package org.spongycastle.openpgp.operator.jcajce; import java.io.OutputStream; import java.security.InvalidKeyException; import java.security.Provider; import java.security.SecureRandom; import java.security.Signature; import java.security.SignatureException; import org.spongycastle.jcajce.DefaultJcaJceHelper; import org.spongycastle.jcajce.NamedJcaJceHelper; import org.spongycastle.jcajce.ProviderJcaJceHelper; import org.spongycastle.openpgp.PGPException; import org.spongycastle.openpgp.PGPPrivateKey; import org.spongycastle.openpgp.operator.PGPContentSigner; import org.spongycastle.openpgp.operator.PGPContentSignerBuilder; import org.spongycastle.openpgp.operator.PGPDigestCalculator; import org.spongycastle.util.io.TeeOutputStream; public class JcaPGPContentSignerBuilder implements PGPContentSignerBuilder { private OperatorHelper helper = new OperatorHelper(new DefaultJcaJceHelper()); private JcaPGPDigestCalculatorProviderBuilder digestCalculatorProviderBuilder = new JcaPGPDigestCalculatorProviderBuilder(); private JcaPGPKeyConverter keyConverter = new JcaPGPKeyConverter(); private int hashAlgorithm; private SecureRandom random; private int keyAlgorithm; public JcaPGPContentSignerBuilder(int keyAlgorithm, int hashAlgorithm) { this.keyAlgorithm = keyAlgorithm; this.hashAlgorithm = hashAlgorithm; } public JcaPGPContentSignerBuilder setSecureRandom(SecureRandom random) { this.random = random; return this; } public JcaPGPContentSignerBuilder setProvider(Provider provider) { this.helper = new OperatorHelper(new ProviderJcaJceHelper(provider)); keyConverter.setProvider(provider); digestCalculatorProviderBuilder.setProvider(provider); return this; } public JcaPGPContentSignerBuilder setProvider(String providerName) { this.helper = new OperatorHelper(new NamedJcaJceHelper(providerName)); keyConverter.setProvider(providerName); digestCalculatorProviderBuilder.setProvider(providerName); return this; } public JcaPGPContentSignerBuilder setDigestProvider(Provider provider) { digestCalculatorProviderBuilder.setProvider(provider); return this; } public JcaPGPContentSignerBuilder setDigestProvider(String providerName) { digestCalculatorProviderBuilder.setProvider(providerName); return this; } public PGPContentSigner build(final int signatureType, final PGPPrivateKey privateKey) throws PGPException { final PGPDigestCalculator digestCalculator = digestCalculatorProviderBuilder.build().get(hashAlgorithm); final Signature signature = helper.createSignature(keyAlgorithm, hashAlgorithm); try { if (random != null) { signature.initSign(keyConverter.getPrivateKey(privateKey), random); } else { signature.initSign(keyConverter.getPrivateKey(privateKey)); } } catch (InvalidKeyException e) { throw new PGPException("invalid key.", e); } return new PGPContentSigner() { public int getType() { return signatureType; } public int getHashAlgorithm() { return hashAlgorithm; } public int getKeyAlgorithm() { return keyAlgorithm; } public long getKeyID() { return privateKey.getKeyID(); } public OutputStream getOutputStream() { return new TeeOutputStream(new SignatureOutputStream(signature), digestCalculator.getOutputStream()); } public byte[] getSignature() { try { return signature.sign(); } catch (SignatureException e) { // TODO: need a specific runtime exception for PGP operators. throw new IllegalStateException("unable to create signature"); } } public byte[] getDigest() { return digestCalculator.getDigest(); } }; } }