diff options
Diffstat (limited to 'bcpkix/src/main/java/org/bouncycastle/operator/jcajce/JcaContentVerifierProviderBuilder.java')
-rw-r--r-- | bcpkix/src/main/java/org/bouncycastle/operator/jcajce/JcaContentVerifierProviderBuilder.java | 207 |
1 files changed, 184 insertions, 23 deletions
diff --git a/bcpkix/src/main/java/org/bouncycastle/operator/jcajce/JcaContentVerifierProviderBuilder.java b/bcpkix/src/main/java/org/bouncycastle/operator/jcajce/JcaContentVerifierProviderBuilder.java index 67150bc0..8f2102b4 100644 --- a/bcpkix/src/main/java/org/bouncycastle/operator/jcajce/JcaContentVerifierProviderBuilder.java +++ b/bcpkix/src/main/java/org/bouncycastle/operator/jcajce/JcaContentVerifierProviderBuilder.java @@ -9,11 +9,16 @@ import java.security.SignatureException; import java.security.cert.CertificateEncodingException; import java.security.cert.CertificateException; import java.security.cert.X509Certificate; +import java.util.List; +import org.bouncycastle.asn1.ASN1Sequence; +import org.bouncycastle.asn1.DERBitString; +import org.bouncycastle.asn1.misc.MiscObjectIdentifiers; import org.bouncycastle.asn1.x509.AlgorithmIdentifier; import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo; import org.bouncycastle.cert.X509CertificateHolder; import org.bouncycastle.cert.jcajce.JcaX509CertificateHolder; +import org.bouncycastle.jcajce.CompositePublicKey; import org.bouncycastle.jcajce.io.OutputStreamFactory; import org.bouncycastle.jcajce.util.DefaultJcaJceHelper; import org.bouncycastle.jcajce.util.NamedJcaJceHelper; @@ -23,6 +28,7 @@ import org.bouncycastle.operator.ContentVerifierProvider; import org.bouncycastle.operator.OperatorCreationException; import org.bouncycastle.operator.RawContentVerifier; import org.bouncycastle.operator.RuntimeOperatorException; +import org.bouncycastle.util.io.TeeOutputStream; public class JcaContentVerifierProviderBuilder { @@ -81,27 +87,34 @@ public class JcaContentVerifierProviderBuilder public ContentVerifier get(AlgorithmIdentifier algorithm) throws OperatorCreationException { - Signature sig; - try - { - sig = helper.createSignature(algorithm); - - sig.initVerify(certificate.getPublicKey()); - } - catch (GeneralSecurityException e) - { - throw new OperatorCreationException("exception on setup: " + e, e); - } - - Signature rawSig = createRawSig(algorithm, certificate.getPublicKey()); - - if (rawSig != null) + if (algorithm.getAlgorithm().equals(MiscObjectIdentifiers.id_alg_composite)) { - return new RawSigVerifier(algorithm, sig, rawSig); + return createCompositeVerifier(algorithm, certificate.getPublicKey()); } else { - return new SigVerifier(algorithm, sig); + Signature sig; + try + { + sig = helper.createSignature(algorithm); + + sig.initVerify(certificate.getPublicKey()); + } + catch (GeneralSecurityException e) + { + throw new OperatorCreationException("exception on setup: " + e, e); + } + + Signature rawSig = createRawSig(algorithm, certificate.getPublicKey()); + + if (rawSig != null) + { + return new RawSigVerifier(algorithm, sig, rawSig); + } + else + { + return new SigVerifier(algorithm, sig); + } } } }; @@ -125,17 +138,54 @@ public class JcaContentVerifierProviderBuilder public ContentVerifier get(AlgorithmIdentifier algorithm) throws OperatorCreationException { - Signature sig = createSignature(algorithm, publicKey); - - Signature rawSig = createRawSig(algorithm, publicKey); + if (algorithm.getAlgorithm().equals(MiscObjectIdentifiers.id_alg_composite)) + { + return createCompositeVerifier(algorithm, publicKey); + } - if (rawSig != null) + if (publicKey instanceof CompositePublicKey) { - return new RawSigVerifier(algorithm, sig, rawSig); + List<PublicKey> keys = ((CompositePublicKey)publicKey).getPublicKeys(); + + for (int i = 0; i != keys.size(); i++) + { + try + { + Signature sig = createSignature(algorithm, (PublicKey)keys.get(i)); + + Signature rawSig = createRawSig(algorithm, (PublicKey)keys.get(i)); + + if (rawSig != null) + { + return new RawSigVerifier(algorithm, sig, rawSig); + } + else + { + return new SigVerifier(algorithm, sig); + } + } + catch (OperatorCreationException e) + { + // skip incorrect keys + } + } + + throw new OperatorCreationException("no matching algorithm found for key"); } else { - return new SigVerifier(algorithm, sig); + Signature sig = createSignature(algorithm, publicKey); + + Signature rawSig = createRawSig(algorithm, publicKey); + + if (rawSig != null) + { + return new RawSigVerifier(algorithm, sig, rawSig); + } + else + { + return new SigVerifier(algorithm, sig); + } } } }; @@ -147,6 +197,51 @@ public class JcaContentVerifierProviderBuilder return this.build(helper.convertPublicKey(publicKey)); } + private ContentVerifier createCompositeVerifier(AlgorithmIdentifier compAlgId, PublicKey publicKey) + throws OperatorCreationException + { + if (publicKey instanceof CompositePublicKey) + { + List<PublicKey> pubKeys = ((CompositePublicKey)publicKey).getPublicKeys(); + ASN1Sequence keySeq = ASN1Sequence.getInstance(compAlgId.getParameters()); + Signature[] sigs = new Signature[keySeq.size()]; + for (int i = 0; i != keySeq.size(); i++) + { + AlgorithmIdentifier sigAlg = AlgorithmIdentifier.getInstance(keySeq.getObjectAt(i)); + if (pubKeys.get(i) != null) + { + sigs[i] = createSignature(sigAlg, (PublicKey)pubKeys.get(i)); + } + else + { + sigs[i] = null; + } + } + + return new CompositeVerifier(sigs); + } + else + { + ASN1Sequence keySeq = ASN1Sequence.getInstance(compAlgId.getParameters()); + Signature[] sigs = new Signature[keySeq.size()]; + for (int i = 0; i != keySeq.size(); i++) + { + AlgorithmIdentifier sigAlg = AlgorithmIdentifier.getInstance(keySeq.getObjectAt(i)); + try + { + sigs[i] = createSignature(sigAlg, publicKey); + } + catch (Exception e) + { + sigs[i] = null; + // continue + } + } + + return new CompositeVerifier(sigs); + } + } + private Signature createSignature(AlgorithmIdentifier algorithm, PublicKey publicKey) throws OperatorCreationException { @@ -286,4 +381,70 @@ public class JcaContentVerifierProviderBuilder } } } + + private class CompositeVerifier + implements ContentVerifier + { + private Signature[] sigs; + private OutputStream stream; + + public CompositeVerifier(Signature[] sigs) + throws OperatorCreationException + { + this.sigs = sigs; + + int start = 0; + while (start < sigs.length && sigs[start] == null) + { + start++; + } + + if (start == sigs.length) + { + throw new OperatorCreationException("no matching signature found in composite"); + } + this.stream = OutputStreamFactory.createStream(sigs[start]); + for (int i = start + 1; i != sigs.length; i++) + { + if (sigs[i] != null) + { + this.stream = new TeeOutputStream(this.stream, OutputStreamFactory.createStream(sigs[i])); + } + } + } + + public AlgorithmIdentifier getAlgorithmIdentifier() + { + return new AlgorithmIdentifier(MiscObjectIdentifiers.id_alg_composite); + } + + public OutputStream getOutputStream() + { + return stream; + } + + public boolean verify(byte[] expected) + { + try + { + ASN1Sequence sigSeq = ASN1Sequence.getInstance(expected); + boolean failed = false; + for (int i = 0; i != sigSeq.size(); i++) + { + if (sigs[i] != null) + { + if (!sigs[i].verify(DERBitString.getInstance(sigSeq.getObjectAt(i)).getBytes())) + { + failed = true; + } + } + } + return !failed; + } + catch (SignatureException e) + { + throw new RuntimeOperatorException("exception obtaining signature: " + e.getMessage(), e); + } + } + } }
\ No newline at end of file |