| package org.bouncycastle.operator.jcajce; |
| |
| import java.io.IOException; |
| import java.io.OutputStream; |
| import java.security.GeneralSecurityException; |
| import java.security.Provider; |
| import java.security.PublicKey; |
| import java.security.Signature; |
| import java.security.SignatureException; |
| import java.security.cert.CertificateEncodingException; |
| import java.security.cert.CertificateException; |
| import java.security.cert.X509Certificate; |
| |
| import org.bouncycastle.asn1.x509.AlgorithmIdentifier; |
| import org.bouncycastle.cert.X509CertificateHolder; |
| import org.bouncycastle.cert.jcajce.JcaX509CertificateHolder; |
| import org.bouncycastle.jcajce.DefaultJcaJceHelper; |
| import org.bouncycastle.jcajce.NamedJcaJceHelper; |
| import org.bouncycastle.jcajce.ProviderJcaJceHelper; |
| import org.bouncycastle.operator.ContentVerifier; |
| import org.bouncycastle.operator.ContentVerifierProvider; |
| import org.bouncycastle.operator.OperatorCreationException; |
| import org.bouncycastle.operator.OperatorStreamException; |
| import org.bouncycastle.operator.RawContentVerifier; |
| import org.bouncycastle.operator.RuntimeOperatorException; |
| |
| public class JcaContentVerifierProviderBuilder |
| { |
| private OperatorHelper helper = new OperatorHelper(new DefaultJcaJceHelper()); |
| |
| public JcaContentVerifierProviderBuilder() |
| { |
| } |
| |
| public JcaContentVerifierProviderBuilder setProvider(Provider provider) |
| { |
| this.helper = new OperatorHelper(new ProviderJcaJceHelper(provider)); |
| |
| return this; |
| } |
| |
| public JcaContentVerifierProviderBuilder setProvider(String providerName) |
| { |
| this.helper = new OperatorHelper(new NamedJcaJceHelper(providerName)); |
| |
| return this; |
| } |
| |
| public ContentVerifierProvider build(X509CertificateHolder certHolder) |
| throws OperatorCreationException, CertificateException |
| { |
| return build(helper.convertCertificate(certHolder)); |
| } |
| |
| public ContentVerifierProvider build(final X509Certificate certificate) |
| throws OperatorCreationException |
| { |
| final X509CertificateHolder certHolder; |
| |
| try |
| { |
| certHolder = new JcaX509CertificateHolder(certificate); |
| } |
| catch (CertificateEncodingException e) |
| { |
| throw new OperatorCreationException("cannot process certificate: " + e.getMessage(), e); |
| } |
| |
| return new ContentVerifierProvider() |
| { |
| private SignatureOutputStream stream; |
| |
| public boolean hasAssociatedCertificate() |
| { |
| return true; |
| } |
| |
| public X509CertificateHolder getAssociatedCertificate() |
| { |
| return certHolder; |
| } |
| |
| public ContentVerifier get(AlgorithmIdentifier algorithm) |
| throws OperatorCreationException |
| { |
| try |
| { |
| Signature sig = helper.createSignature(algorithm); |
| |
| sig.initVerify(certificate.getPublicKey()); |
| |
| stream = new SignatureOutputStream(sig); |
| } |
| catch (GeneralSecurityException e) |
| { |
| throw new OperatorCreationException("exception on setup: " + e, e); |
| } |
| |
| Signature rawSig = createRawSig(algorithm, certificate.getPublicKey()); |
| |
| if (rawSig != null) |
| { |
| return new RawSigVerifier(algorithm, stream, rawSig); |
| } |
| else |
| { |
| return new SigVerifier(algorithm, stream); |
| } |
| } |
| }; |
| } |
| |
| public ContentVerifierProvider build(final PublicKey publicKey) |
| throws OperatorCreationException |
| { |
| return new ContentVerifierProvider() |
| { |
| public boolean hasAssociatedCertificate() |
| { |
| return false; |
| } |
| |
| public X509CertificateHolder getAssociatedCertificate() |
| { |
| return null; |
| } |
| |
| public ContentVerifier get(AlgorithmIdentifier algorithm) |
| throws OperatorCreationException |
| { |
| SignatureOutputStream stream = createSignatureStream(algorithm, publicKey); |
| |
| Signature rawSig = createRawSig(algorithm, publicKey); |
| |
| if (rawSig != null) |
| { |
| return new RawSigVerifier(algorithm, stream, rawSig); |
| } |
| else |
| { |
| return new SigVerifier(algorithm, stream); |
| } |
| } |
| }; |
| } |
| |
| private SignatureOutputStream createSignatureStream(AlgorithmIdentifier algorithm, PublicKey publicKey) |
| throws OperatorCreationException |
| { |
| try |
| { |
| Signature sig = helper.createSignature(algorithm); |
| |
| sig.initVerify(publicKey); |
| |
| return new SignatureOutputStream(sig); |
| } |
| catch (GeneralSecurityException e) |
| { |
| throw new OperatorCreationException("exception on setup: " + e, e); |
| } |
| } |
| |
| private Signature createRawSig(AlgorithmIdentifier algorithm, PublicKey publicKey) |
| { |
| Signature rawSig; |
| try |
| { |
| rawSig = helper.createRawSignature(algorithm); |
| |
| if (rawSig != null) |
| { |
| rawSig.initVerify(publicKey); |
| } |
| } |
| catch (Exception e) |
| { |
| rawSig = null; |
| } |
| return rawSig; |
| } |
| |
| private class SigVerifier |
| implements ContentVerifier |
| { |
| private SignatureOutputStream stream; |
| private AlgorithmIdentifier algorithm; |
| |
| SigVerifier(AlgorithmIdentifier algorithm, SignatureOutputStream stream) |
| { |
| this.algorithm = algorithm; |
| this.stream = stream; |
| } |
| |
| public AlgorithmIdentifier getAlgorithmIdentifier() |
| { |
| return algorithm; |
| } |
| |
| public OutputStream getOutputStream() |
| { |
| if (stream == null) |
| { |
| throw new IllegalStateException("verifier not initialised"); |
| } |
| |
| return stream; |
| } |
| |
| public boolean verify(byte[] expected) |
| { |
| try |
| { |
| return stream.verify(expected); |
| } |
| catch (SignatureException e) |
| { |
| throw new RuntimeOperatorException("exception obtaining signature: " + e.getMessage(), e); |
| } |
| } |
| } |
| |
| private class RawSigVerifier |
| extends SigVerifier |
| implements RawContentVerifier |
| { |
| private Signature rawSignature; |
| |
| RawSigVerifier(AlgorithmIdentifier algorithm, SignatureOutputStream stream, Signature rawSignature) |
| { |
| super(algorithm, stream); |
| this.rawSignature = rawSignature; |
| } |
| |
| public boolean verify(byte[] digest, byte[] expected) |
| { |
| try |
| { |
| rawSignature.update(digest); |
| |
| return rawSignature.verify(expected); |
| } |
| catch (SignatureException e) |
| { |
| throw new RuntimeOperatorException("exception obtaining raw signature: " + e.getMessage(), e); |
| } |
| } |
| } |
| |
| private class SignatureOutputStream |
| extends OutputStream |
| { |
| private Signature sig; |
| |
| SignatureOutputStream(Signature sig) |
| { |
| this.sig = sig; |
| } |
| |
| public void write(byte[] bytes, int off, int len) |
| throws IOException |
| { |
| try |
| { |
| sig.update(bytes, off, len); |
| } |
| catch (SignatureException e) |
| { |
| throw new OperatorStreamException("exception in content signer: " + e.getMessage(), e); |
| } |
| } |
| |
| public void write(byte[] bytes) |
| throws IOException |
| { |
| try |
| { |
| sig.update(bytes); |
| } |
| catch (SignatureException e) |
| { |
| throw new OperatorStreamException("exception in content signer: " + e.getMessage(), e); |
| } |
| } |
| |
| public void write(int b) |
| throws IOException |
| { |
| try |
| { |
| sig.update((byte)b); |
| } |
| catch (SignatureException e) |
| { |
| throw new OperatorStreamException("exception in content signer: " + e.getMessage(), e); |
| } |
| } |
| |
| boolean verify(byte[] expected) |
| throws SignatureException |
| { |
| return sig.verify(expected); |
| } |
| } |
| } |