diff options
Diffstat (limited to 'pkix/src/test/java/org/spongycastle/cms/test/Rfc4134Test.java')
-rw-r--r-- | pkix/src/test/java/org/spongycastle/cms/test/Rfc4134Test.java | 445 |
1 files changed, 445 insertions, 0 deletions
diff --git a/pkix/src/test/java/org/spongycastle/cms/test/Rfc4134Test.java b/pkix/src/test/java/org/spongycastle/cms/test/Rfc4134Test.java new file mode 100644 index 00000000..ab321027 --- /dev/null +++ b/pkix/src/test/java/org/spongycastle/cms/test/Rfc4134Test.java @@ -0,0 +1,445 @@ +package org.spongycastle.cms.test; + +import java.io.ByteArrayInputStream; +import java.io.FileInputStream; +import java.io.IOException; +import java.security.KeyFactory; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import java.security.NoSuchProviderException; +import java.security.PrivateKey; +import java.security.PublicKey; +import java.security.Security; +import java.security.cert.CertificateFactory; +import java.security.cert.X509Certificate; +import java.security.interfaces.DSAParams; +import java.security.interfaces.DSAPublicKey; +import java.security.spec.DSAPublicKeySpec; +import java.security.spec.InvalidKeySpecException; +import java.security.spec.PKCS8EncodedKeySpec; +import java.util.Arrays; +import java.util.Collection; +import java.util.Iterator; + +import junit.framework.Test; +import junit.framework.TestCase; +import junit.framework.TestSuite; +import org.spongycastle.asn1.ASN1EncodableVector; +import org.spongycastle.asn1.DERSequence; +import org.spongycastle.asn1.DERUTF8String; +import org.spongycastle.asn1.cms.Attribute; +import org.spongycastle.asn1.cms.AttributeTable; +import org.spongycastle.asn1.cms.CMSAttributes; +import org.spongycastle.asn1.cms.CMSObjectIdentifiers; +import org.spongycastle.asn1.pkcs.PKCSObjectIdentifiers; +import org.spongycastle.cert.X509CertificateHolder; +import org.spongycastle.cert.jcajce.JcaX509CertificateConverter; +import org.spongycastle.cms.CMSEnvelopedData; +import org.spongycastle.cms.CMSEnvelopedDataGenerator; +import org.spongycastle.cms.CMSEnvelopedDataParser; +import org.spongycastle.cms.CMSException; +import org.spongycastle.cms.CMSProcessableByteArray; +import org.spongycastle.cms.CMSSignedData; +import org.spongycastle.cms.CMSSignedDataParser; +import org.spongycastle.cms.CMSTypedStream; +import org.spongycastle.cms.RecipientInformation; +import org.spongycastle.cms.RecipientInformationStore; +import org.spongycastle.cms.SignerInformation; +import org.spongycastle.cms.SignerInformationStore; +import org.spongycastle.cms.jcajce.JcaSignerInfoVerifierBuilder; +import org.spongycastle.cms.jcajce.JcaX509CertSelectorConverter; +import org.spongycastle.cms.jcajce.JceKeyTransEnvelopedRecipient; +import org.spongycastle.jce.provider.BouncyCastleProvider; +import org.spongycastle.operator.DigestCalculatorProvider; +import org.spongycastle.operator.OperatorCreationException; +import org.spongycastle.operator.jcajce.JcaDigestCalculatorProviderBuilder; +import org.spongycastle.util.Store; +import org.spongycastle.util.encoders.Hex; +import org.spongycastle.util.io.Streams; + +public class Rfc4134Test + extends TestCase +{ + private static final String BC = BouncyCastleProvider.PROVIDER_NAME; + private static final String TEST_DATA_HOME = "bc.test.data.home"; + + private static byte[] exContent = getRfc4134Data("ExContent.bin"); + private static byte[] sha1 = Hex.decode("406aec085279ba6e16022d9e0629c0229687dd48"); + + private static final JcaX509CertSelectorConverter selectorConverter = new JcaX509CertSelectorConverter(); + private static final DigestCalculatorProvider digCalcProv; + + static + { + try + { + digCalcProv = new JcaDigestCalculatorProviderBuilder().build(); + } + catch (OperatorCreationException e) + { + throw new IllegalStateException("can't create default provider!!!"); + } + } + + public Rfc4134Test(String name) + { + super(name); + } + + public static void main(String args[]) + { + Security.addProvider(new BouncyCastleProvider()); + + junit.textui.TestRunner.run(Rfc4134Test.class); + } + + public static Test suite() + throws Exception + { + return new CMSTestSetup(new TestSuite(Rfc4134Test.class)); + } + + public void test4_1() + throws Exception + { + byte[] data = getRfc4134Data("4.1.bin"); + CMSSignedData signedData = new CMSSignedData(data); + + verifySignatures(signedData); + + CMSSignedDataParser parser = new CMSSignedDataParser(digCalcProv, data); + + verifySignatures(parser); + } + + public void test4_2() + throws Exception + { + byte[] data = getRfc4134Data("4.2.bin"); + CMSSignedData signedData = new CMSSignedData(data); + + verifySignatures(signedData); + + CMSSignedDataParser parser = new CMSSignedDataParser(digCalcProv, data); + + verifySignatures(parser); + } + + public void testRfc4_3() + throws Exception + { + byte[] data = getRfc4134Data("4.3.bin"); + CMSSignedData signedData = new CMSSignedData(new CMSProcessableByteArray(exContent), data); + + verifySignatures(signedData, sha1); + + CMSSignedDataParser parser = new CMSSignedDataParser(digCalcProv, + new CMSTypedStream(new ByteArrayInputStream(exContent)), + data); + + verifySignatures(parser); + } + + public void test4_4() + throws Exception + { + byte[] data = getRfc4134Data("4.4.bin"); + byte[] counterSigCert = getRfc4134Data("AliceRSASignByCarl.cer"); + CMSSignedData signedData = new CMSSignedData(data); + + verifySignatures(signedData, sha1); + + verifySignerInfo4_4(getFirstSignerInfo(signedData.getSignerInfos()), counterSigCert); + + CMSSignedDataParser parser = new CMSSignedDataParser(digCalcProv, data); + + verifySignatures(parser); + + verifySignerInfo4_4(getFirstSignerInfo(parser.getSignerInfos()), counterSigCert); + } + + public void test4_5() + throws Exception + { + byte[] data = getRfc4134Data("4.5.bin"); + CMSSignedData signedData = new CMSSignedData(data); + + verifySignatures(signedData); + + CMSSignedDataParser parser = new CMSSignedDataParser(digCalcProv, data); + + verifySignatures(parser); + } + + public void test4_6() + throws Exception + { + byte[] data = getRfc4134Data("4.6.bin"); + CMSSignedData signedData = new CMSSignedData(data); + + verifySignatures(signedData); + + CMSSignedDataParser parser = new CMSSignedDataParser(digCalcProv, data); + + verifySignatures(parser); + } + + public void test4_7() + throws Exception + { + byte[] data = getRfc4134Data("4.7.bin"); + CMSSignedData signedData = new CMSSignedData(data); + + verifySignatures(signedData); + + CMSSignedDataParser parser = new CMSSignedDataParser(digCalcProv, data); + + verifySignatures(parser); + } + + public void test5_1() + throws Exception + { + byte[] data = getRfc4134Data("5.1.bin"); + CMSEnvelopedData envelopedData = new CMSEnvelopedData(data); + + verifyEnvelopedData(envelopedData, CMSEnvelopedDataGenerator.DES_EDE3_CBC); + + CMSEnvelopedDataParser envelopedParser = new CMSEnvelopedDataParser(data); + + verifyEnvelopedData(envelopedParser, CMSEnvelopedDataGenerator.DES_EDE3_CBC); + } + + public void test5_2() + throws Exception + { + byte[] data = getRfc4134Data("5.2.bin"); + CMSEnvelopedData envelopedData = new CMSEnvelopedData(data); + + verifyEnvelopedData(envelopedData, CMSEnvelopedDataGenerator.RC2_CBC); + + CMSEnvelopedDataParser envelopedParser = new CMSEnvelopedDataParser(data); + + verifyEnvelopedData(envelopedParser, CMSEnvelopedDataGenerator.RC2_CBC); + } + + private void verifyEnvelopedData(CMSEnvelopedData envelopedData, String symAlgorithmOID) + throws NoSuchAlgorithmException, NoSuchProviderException, InvalidKeySpecException, CMSException + { + byte[] privKeyData = getRfc4134Data("BobPrivRSAEncrypt.pri"); + PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(privKeyData); + KeyFactory keyFact = KeyFactory.getInstance("RSA", BC); + PrivateKey privKey = keyFact.generatePrivate(keySpec); + + RecipientInformationStore recipients = envelopedData.getRecipientInfos(); + + assertEquals(envelopedData.getEncryptionAlgOID(), symAlgorithmOID); + + Collection c = recipients.getRecipients(); + assertTrue(c.size() >= 1 && c.size() <= 2); + + Iterator it = c.iterator(); + verifyRecipient((RecipientInformation)it.next(), privKey); + + if (c.size() == 2) + { + RecipientInformation recInfo = (RecipientInformation)it.next(); + + assertEquals(PKCSObjectIdentifiers.id_alg_CMSRC2wrap.getId(), recInfo.getKeyEncryptionAlgOID()); + } + } + + private void verifyEnvelopedData(CMSEnvelopedDataParser envelopedParser, String symAlgorithmOID) + throws NoSuchAlgorithmException, NoSuchProviderException, InvalidKeySpecException, CMSException + { + byte[] privKeyData = getRfc4134Data("BobPrivRSAEncrypt.pri"); + PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(privKeyData); + KeyFactory keyFact = KeyFactory.getInstance("RSA", BC); + PrivateKey privKey = keyFact.generatePrivate(keySpec); + + RecipientInformationStore recipients = envelopedParser.getRecipientInfos(); + + assertEquals(envelopedParser.getEncryptionAlgOID(), symAlgorithmOID); + + Collection c = recipients.getRecipients(); + assertTrue(c.size() >= 1 && c.size() <= 2); + + Iterator it = c.iterator(); + verifyRecipient((RecipientInformation)it.next(), privKey); + + if (c.size() == 2) + { + RecipientInformation recInfo = (RecipientInformation)it.next(); + + assertEquals(PKCSObjectIdentifiers.id_alg_CMSRC2wrap.getId(), recInfo.getKeyEncryptionAlgOID()); + } + } + + private void verifyRecipient(RecipientInformation recipient, PrivateKey privKey) + throws CMSException, NoSuchProviderException + { + assertEquals(recipient.getKeyEncryptionAlgOID(), PKCSObjectIdentifiers.rsaEncryption.getId()); + + byte[] recData = recipient.getContent(new JceKeyTransEnvelopedRecipient(privKey).setProvider(BC)); + + assertEquals(true, Arrays.equals(exContent, recData)); + } + + private void verifySignerInfo4_4(SignerInformation signerInfo, byte[] counterSigCert) + throws Exception + { + verifyCounterSignature(signerInfo, counterSigCert); + + verifyContentHint(signerInfo); + } + + private SignerInformation getFirstSignerInfo(SignerInformationStore store) + { + return (SignerInformation)store.getSigners().iterator().next(); + } + + private void verifyCounterSignature(SignerInformation signInfo, byte[] certificate) + throws Exception + { + SignerInformation csi = (SignerInformation)signInfo.getCounterSignatures().getSigners().iterator().next(); + + CertificateFactory certFact = CertificateFactory.getInstance("X.509", BC); + X509Certificate cert = (X509Certificate)certFact.generateCertificate(new ByteArrayInputStream(certificate)); + + assertTrue(csi.verify(new JcaSignerInfoVerifierBuilder(digCalcProv).setProvider(BC).build(cert))); + } + + private void verifyContentHint(SignerInformation signInfo) + { + AttributeTable attrTable = signInfo.getUnsignedAttributes(); + + Attribute attr = attrTable.get(CMSAttributes.contentHint); + + assertEquals(1, attr.getAttrValues().size()); + + ASN1EncodableVector v = new ASN1EncodableVector(); + + v.add(new DERUTF8String("Content Hints Description Buffer")); + v.add(CMSObjectIdentifiers.data); + + assertTrue(attr.getAttrValues().getObjectAt(0).equals(new DERSequence(v))); + } + + private void verifySignatures(CMSSignedData s, byte[] contentDigest) + throws Exception + { + Store certStore = s.getCertificates(); + SignerInformationStore signers = s.getSignerInfos(); + + Collection c = signers.getSigners(); + Iterator it = c.iterator(); + + while (it.hasNext()) + { + SignerInformation signer = (SignerInformation)it.next(); + Collection certCollection = certStore.getMatches(signer.getSID()); + + Iterator certIt = certCollection.iterator(); + X509CertificateHolder cert = (X509CertificateHolder)certIt.next(); + + verifySigner(signer, cert); + + if (contentDigest != null) + { + assertTrue(MessageDigest.isEqual(contentDigest, signer.getContentDigest())); + } + } + } + + private void verifySignatures(CMSSignedData s) + throws Exception + { + verifySignatures(s, null); + } + + private void verifySignatures(CMSSignedDataParser sp) + throws Exception + { + CMSTypedStream sc = sp.getSignedContent(); + if (sc != null) + { + sc.drain(); + } + + Store certs = sp.getCertificates(); + SignerInformationStore signers = sp.getSignerInfos(); + + Collection c = signers.getSigners(); + Iterator it = c.iterator(); + + while (it.hasNext()) + { + SignerInformation signer = (SignerInformation)it.next(); + Collection certCollection = certs.getMatches(signer.getSID()); + + Iterator certIt = certCollection.iterator(); + X509CertificateHolder cert = (X509CertificateHolder)certIt.next(); + + verifySigner(signer, cert); + } + } + + private void verifySigner(SignerInformation signer, X509CertificateHolder certHolder) + throws Exception + { + X509Certificate cert = new JcaX509CertificateConverter().setProvider("SC").getCertificate(certHolder); + if (cert.getPublicKey() instanceof DSAPublicKey) + { + DSAPublicKey key = (DSAPublicKey)cert.getPublicKey(); + + if (key.getParams() == null) + { + assertEquals(true, signer.verify(new JcaSignerInfoVerifierBuilder(digCalcProv).setProvider(BC).build(getInheritedKey(key)))); + } + else + { + assertEquals(true, signer.verify(new JcaSignerInfoVerifierBuilder(digCalcProv).setProvider(BC).build(cert))); + } + } + else + { + assertEquals(true, signer.verify(new JcaSignerInfoVerifierBuilder(digCalcProv).setProvider(BC).build(cert))); + } + } + + private PublicKey getInheritedKey(DSAPublicKey key) + throws Exception + { + CertificateFactory certFact = CertificateFactory.getInstance("X.509", BC); + + X509Certificate cert = (X509Certificate)certFact.generateCertificate(new ByteArrayInputStream(getRfc4134Data("CarlDSSSelf.cer"))); + + DSAParams dsaParams = ((DSAPublicKey)cert.getPublicKey()).getParams(); + + DSAPublicKeySpec dsaPubKeySpec = new DSAPublicKeySpec( + key.getY(), dsaParams.getP(), dsaParams.getQ(), dsaParams.getG()); + + KeyFactory keyFactory = KeyFactory.getInstance("DSA", BC); + + return keyFactory.generatePublic(dsaPubKeySpec); + } + + private static byte[] getRfc4134Data(String name) + { + String dataHome = System.getProperty(TEST_DATA_HOME); + + if (dataHome == null) + { + throw new IllegalStateException(TEST_DATA_HOME + " property not set"); + } + + try + { + return Streams.readAll(new FileInputStream(dataHome + "/rfc4134/" + name)); + } + catch (IOException e) + { + throw new RuntimeException(e.toString()); + } + } +} |