summaryrefslogtreecommitdiff
path: root/bcpkix/src/main/java/org/bouncycastle/operator/jcajce/JcaContentVerifierProviderBuilder.java
diff options
context:
space:
mode:
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.java207
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