diff options
Diffstat (limited to 'pkix/src/test/java/org/spongycastle/cms/test')
20 files changed, 11579 insertions, 0 deletions
diff --git a/pkix/src/test/java/org/spongycastle/cms/test/AllTests.java b/pkix/src/test/java/org/spongycastle/cms/test/AllTests.java new file mode 100644 index 00000000..7ef73a69 --- /dev/null +++ b/pkix/src/test/java/org/spongycastle/cms/test/AllTests.java @@ -0,0 +1,51 @@ +package org.spongycastle.cms.test; + +import javax.crypto.Cipher; + +import junit.framework.Test; +import junit.framework.TestSuite; + +public class AllTests +{ + public static void main (String[] args) + throws Exception + { + junit.textui.TestRunner.run(suite()); + } + + public static Test suite() + throws Exception + { + TestSuite suite = new TestSuite("CMS tests"); + + suite.addTest(NewCompressedDataTest.suite()); + suite.addTest(NewSignedDataTest.suite()); + suite.addTest(NewEnvelopedDataTest.suite()); + suite.addTest(NewAuthenticatedDataTest.suite()); + suite.addTest(NewAuthenticatedDataStreamTest.suite()); + suite.addTest(NewCompressedDataStreamTest.suite()); + suite.addTest(NewSignedDataStreamTest.suite()); + suite.addTest(NewEnvelopedDataStreamTest.suite()); + + suite.addTest(MiscDataStreamTest.suite()); + suite.addTest(Rfc4134Test.suite()); + suite.addTest(ConverterTest.suite()); + + suite.addTest(BcEnvelopedDataTest.suite()); + suite.addTest(BcSignedDataTest.suite()); + + try + { + Cipher.getInstance("RSA", "SunJCE"); + + suite.addTest(SunProviderTest.suite()); + suite.addTest(NullProviderTest.suite()); + } + catch (Exception e) + { + // ignore + } + + return suite; + } +} diff --git a/pkix/src/test/java/org/spongycastle/cms/test/BcEnvelopedDataTest.java b/pkix/src/test/java/org/spongycastle/cms/test/BcEnvelopedDataTest.java new file mode 100644 index 00000000..c7dd42f5 --- /dev/null +++ b/pkix/src/test/java/org/spongycastle/cms/test/BcEnvelopedDataTest.java @@ -0,0 +1,969 @@ +package org.spongycastle.cms.test; + +import java.io.IOException; +import java.security.GeneralSecurityException; +import java.security.Key; +import java.security.KeyFactory; +import java.security.KeyPair; +import java.security.NoSuchAlgorithmException; +import java.security.NoSuchProviderException; +import java.security.PrivateKey; +import java.security.Security; +import java.security.cert.CertificateEncodingException; +import java.security.cert.X509Certificate; +import java.security.spec.PKCS8EncodedKeySpec; +import java.util.Arrays; +import java.util.Collection; +import java.util.Hashtable; +import java.util.Iterator; + +import javax.crypto.SecretKey; + +import junit.framework.Test; +import junit.framework.TestCase; +import junit.framework.TestSuite; +import org.spongycastle.asn1.ASN1ObjectIdentifier; +import org.spongycastle.asn1.DEROctetString; +import org.spongycastle.asn1.DERSet; +import org.spongycastle.asn1.DERUTF8String; +import org.spongycastle.asn1.cms.Attribute; +import org.spongycastle.asn1.cms.AttributeTable; +import org.spongycastle.asn1.nist.NISTObjectIdentifiers; +import org.spongycastle.asn1.pkcs.PKCSObjectIdentifiers; +import org.spongycastle.asn1.pkcs.PrivateKeyInfo; +import org.spongycastle.cert.jcajce.JcaX509CertificateHolder; +import org.spongycastle.cms.CMSAlgorithm; +import org.spongycastle.cms.CMSEnvelopedData; +import org.spongycastle.cms.CMSEnvelopedDataGenerator; +import org.spongycastle.cms.CMSException; +import org.spongycastle.cms.CMSProcessableByteArray; +import org.spongycastle.cms.KeyTransRecipientInformation; +import org.spongycastle.cms.PasswordRecipient; +import org.spongycastle.cms.PasswordRecipientInformation; +import org.spongycastle.cms.RecipientId; +import org.spongycastle.cms.RecipientInformation; +import org.spongycastle.cms.RecipientInformationStore; +import org.spongycastle.cms.SimpleAttributeTableGenerator; +import org.spongycastle.cms.bc.BcCMSContentEncryptorBuilder; +import org.spongycastle.cms.bc.BcKEKEnvelopedRecipient; +import org.spongycastle.cms.bc.BcKEKRecipientInfoGenerator; +import org.spongycastle.cms.bc.BcPasswordEnvelopedRecipient; +import org.spongycastle.cms.bc.BcPasswordRecipientInfoGenerator; +import org.spongycastle.cms.bc.BcRSAKeyTransEnvelopedRecipient; +import org.spongycastle.cms.bc.BcRSAKeyTransRecipientInfoGenerator; +import org.spongycastle.cms.jcajce.JceKeyAgreeEnvelopedRecipient; +import org.spongycastle.cms.jcajce.JceKeyAgreeRecipientId; +import org.spongycastle.cms.jcajce.JceKeyAgreeRecipientInfoGenerator; +import org.spongycastle.crypto.params.KeyParameter; +import org.spongycastle.crypto.util.PrivateKeyFactory; +import org.spongycastle.jce.provider.BouncyCastleProvider; +import org.spongycastle.operator.OutputEncryptor; +import org.spongycastle.operator.bc.BcAESSymmetricKeyUnwrapper; +import org.spongycastle.operator.bc.BcAESSymmetricKeyWrapper; +import org.spongycastle.operator.bc.BcSymmetricKeyUnwrapper; +import org.spongycastle.operator.bc.BcSymmetricKeyWrapper; +import org.spongycastle.util.encoders.Base64; +import org.spongycastle.util.encoders.Hex; + +public class BcEnvelopedDataTest + extends TestCase +{ + private static final String BC = BouncyCastleProvider.PROVIDER_NAME; + + private static String _signDN; + private static KeyPair _signKP; + private static X509Certificate _signCert; + + private static String _origDN; + private static KeyPair _origKP; + private static X509Certificate _origCert; + + private static String _reciDN; + private static String _reciDN2; + private static KeyPair _reciKP; + private static X509Certificate _reciCert; + + private static KeyPair _origEcKP; + private static KeyPair _reciEcKP; + private static X509Certificate _reciEcCert; + private static KeyPair _reciEcKP2; + private static X509Certificate _reciEcCert2; + + private static boolean _initialised = false; + + private byte[] oldKEK = Base64.decode( + "MIAGCSqGSIb3DQEHA6CAMIACAQIxQaI/MD0CAQQwBwQFAQIDBAUwDQYJYIZIAWUDBAEFBQAEI" + + "Fi2eHTPM4bQSjP4DUeDzJZLpfemW2gF1SPq7ZPHJi1mMIAGCSqGSIb3DQEHATAUBggqhkiG9w" + + "0DBwQImtdGyUdGGt6ggAQYk9X9z01YFBkU7IlS3wmsKpm/zpZClTceAAAAAAAAAAAAAA=="); + + private byte[] ecKeyAgreeMsgAES256 = Base64.decode( + "MIAGCSqGSIb3DQEHA6CAMIACAQIxgcShgcECAQOgQ6FBMAsGByqGSM49AgEF" + + "AAMyAAPdXlSTpub+qqno9hUGkUDl+S3/ABhPziIB5yGU4678tgOgU5CiKG9Z" + + "kfnabIJ3nZYwGgYJK4EFEIZIPwACMA0GCWCGSAFlAwQBLQUAMFswWTAtMCgx" + + "EzARBgNVBAMTCkFkbWluLU1EU0UxETAPBgNVBAoTCDRCQ1QtMklEAgEBBCi/" + + "rJRLbFwEVW6PcLLmojjW9lI/xGD7CfZzXrqXFw8iHaf3hTRau1gYMIAGCSqG" + + "SIb3DQEHATAdBglghkgBZQMEASoEEMtCnKKPwccmyrbgeSIlA3qggAQQDLw8" + + "pNJR97bPpj6baG99bQQQwhEDsoj5Xg1oOxojHVcYzAAAAAAAAAAAAAA="); + + private byte[] ecKeyAgreeMsgAES128 = Base64.decode( + "MIAGCSqGSIb3DQEHA6CAMIACAQIxgbShgbECAQOgQ6FBMAsGByqGSM49AgEF" + + "AAMyAAL01JLEgKvKh5rbxI/hOxs/9WEezMIsAbUaZM4l5tn3CzXAN505nr5d" + + "LhrcurMK+tAwGgYJK4EFEIZIPwACMA0GCWCGSAFlAwQBBQUAMEswSTAtMCgx" + + "EzARBgNVBAMTCkFkbWluLU1EU0UxETAPBgNVBAoTCDRCQ1QtMklEAgEBBBhi" + + "FLjc5g6aqDT3f8LomljOwl1WTrplUT8wgAYJKoZIhvcNAQcBMB0GCWCGSAFl" + + "AwQBAgQQzXjms16Y69S/rB0EbHqRMaCABBAFmc/QdVW6LTKdEy97kaZzBBBa" + + "fQuviUS03NycpojELx0bAAAAAAAAAAAAAA=="); + + private byte[] ecKeyAgreeMsgDESEDE = Base64.decode( + "MIAGCSqGSIb3DQEHA6CAMIACAQIxgcahgcMCAQOgQ6FBMAsGByqGSM49AgEF" + + "AAMyAALIici6Nx1WN5f0ThH2A8ht9ovm0thpC5JK54t73E1RDzCifePaoQo0" + + "xd6sUqoyGaYwHAYJK4EFEIZIPwACMA8GCyqGSIb3DQEJEAMGBQAwWzBZMC0w" + + "KDETMBEGA1UEAxMKQWRtaW4tTURTRTERMA8GA1UEChMINEJDVC0ySUQCAQEE" + + "KJuqZQ1NB1vXrKPOnb4TCpYOsdm6GscWdwAAZlm2EHMp444j0s55J9wwgAYJ" + + "KoZIhvcNAQcBMBQGCCqGSIb3DQMHBAjwnsDMsafCrKCABBjyPvqFOVMKxxut" + + "VfTx4fQlNGJN8S2ATRgECMcTQ/dsmeViAAAAAAAAAAAAAA=="); + + private byte[] ecMQVKeyAgreeMsgAES128 = Base64.decode( + "MIAGCSqGSIb3DQEHA6CAMIACAQIxgf2hgfoCAQOgQ6FBMAsGByqGSM49AgEF" + + "AAMyAAPDKU+0H58tsjpoYmYCInMr/FayvCCkupebgsnpaGEB7qS9vzcNVUj6" + + "mrnmiC2grpmhRwRFMEMwQTALBgcqhkjOPQIBBQADMgACZpD13z9c7DzRWx6S" + + "0xdbq3S+EJ7vWO+YcHVjTD8NcQDcZcWASW899l1PkL936zsuMBoGCSuBBRCG" + + "SD8AEDANBglghkgBZQMEAQUFADBLMEkwLTAoMRMwEQYDVQQDEwpBZG1pbi1N" + + "RFNFMREwDwYDVQQKEwg0QkNULTJJRAIBAQQYFq58L71nyMK/70w3nc6zkkRy" + + "RL7DHmpZMIAGCSqGSIb3DQEHATAdBglghkgBZQMEAQIEEDzRUpreBsZXWHBe" + + "onxOtSmggAQQ7csAZXwT1lHUqoazoy8bhAQQq+9Zjj8iGdOWgyebbfj67QAA" + + "AAAAAAAAAAA="); + + + private byte[] ecKeyAgreeKey = Base64.decode( + "MIG2AgEAMBAGByqGSM49AgEGBSuBBAAiBIGeMIGbAgEBBDC8vp7xVTbKSgYVU5Wc" + + "hGkWbzaj+yUFETIWP1Dt7+WSpq3ikSPdl7PpHPqnPVZfoIWhZANiAgSYHTgxf+Dd" + + "Tt84dUvuSKkFy3RhjxJmjwIscK6zbEUzKhcPQG2GHzXhWK5x1kov0I74XpGhVkya" + + "ElH5K6SaOXiXAzcyNGggTOk4+ZFnz5Xl0pBje3zKxPhYu0SnCw7Pcqw="); + + private byte[] bobPrivRsaEncrypt = Base64.decode( + "MIIChQIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAKnhZ5g/OdVf" + + "8qCTQV6meYmFyDVdmpFb+x0B2hlwJhcPvaUi0DWFbXqYZhRBXM+3twg7CcmR" + + "uBlpN235ZR572akzJKN/O7uvRgGGNjQyywcDWVL8hYsxBLjMGAgUSOZPHPtd" + + "YMTgXB9T039T2GkB8QX4enDRvoPGXzjPHCyqaqfrAgMBAAECgYBnzUhMmg2P" + + "mMIbZf8ig5xt8KYGHbztpwOIlPIcaw+LNd4Ogngwy+e6alatd8brUXlweQqg" + + "9P5F4Kmy9Bnah5jWMIR05PxZbMHGd9ypkdB8MKCixQheIXFD/A0HPfD6bRSe" + + "TmPwF1h5HEuYHD09sBvf+iU7o8AsmAX2EAnYh9sDGQJBANDDIsbeopkYdo+N" + + "vKZ11mY/1I1FUox29XLE6/BGmvE+XKpVC5va3Wtt+Pw7PAhDk7Vb/s7q/WiE" + + "I2Kv8zHCueUCQQDQUfweIrdb7bWOAcjXq/JY1PeClPNTqBlFy2bKKBlf4hAr" + + "84/sajB0+E0R9KfEILVHIdxJAfkKICnwJAiEYH2PAkA0umTJSChXdNdVUN5q" + + "SO8bKlocSHseIVnDYDubl6nA7xhmqU5iUjiEzuUJiEiUacUgFJlaV/4jbOSn" + + "I3vQgLeFAkEAni+zN5r7CwZdV+EJBqRd2ZCWBgVfJAZAcpw6iIWchw+dYhKI" + + "FmioNRobQ+g4wJhprwMKSDIETukPj3d9NDAlBwJAVxhn1grStavCunrnVNqc" + + "BU+B1O8BiR4yPWnLMcRSyFRVJQA7HCp8JlDV6abXd8vPFfXuC9WN7rOvTKF8" + + "Y0ZB9qANMAsGA1UdDzEEAwIAEA=="); + + private byte[] rfc4134ex5_1 = Base64.decode( + "MIIBHgYJKoZIhvcNAQcDoIIBDzCCAQsCAQAxgcAwgb0CAQAwJjASMRAwDgYD" + + "VQQDEwdDYXJsUlNBAhBGNGvHgABWvBHTbi7NXXHQMA0GCSqGSIb3DQEBAQUA" + + "BIGAC3EN5nGIiJi2lsGPcP2iJ97a4e8kbKQz36zg6Z2i0yx6zYC4mZ7mX7FB" + + "s3IWg+f6KgCLx3M1eCbWx8+MDFbbpXadCDgO8/nUkUNYeNxJtuzubGgzoyEd" + + "8Ch4H/dd9gdzTd+taTEgS0ipdSJuNnkVY4/M652jKKHRLFf02hosdR8wQwYJ" + + "KoZIhvcNAQcBMBQGCCqGSIb3DQMHBAgtaMXpRwZRNYAgDsiSf8Z9P43LrY4O" + + "xUk660cu1lXeCSFOSOpOJ7FuVyU="); + + private byte[] rfc4134ex5_2 = Base64.decode( + "MIIBZQYJKoZIhvcNAQcDoIIBVjCCAVICAQIxggEAMIG9AgEAMCYwEjEQMA4G" + + "A1UEAxMHQ2FybFJTQQIQRjRrx4AAVrwR024uzV1x0DANBgkqhkiG9w0BAQEF" + + "AASBgJQmQojGi7Z4IP+CVypBmNFoCDoEp87khtgyff2N4SmqD3RxPx+8hbLQ" + + "t9i3YcMwcap+aiOkyqjMalT03VUC0XBOGv+HYI3HBZm/aFzxoq+YOXAWs5xl" + + "GerZwTOc9j6AYlK4qXvnztR5SQ8TBjlzytm4V7zg+TGrnGVNQBNw47Ewoj4C" + + "AQQwDQQLTWFpbExpc3RSQzIwEAYLKoZIhvcNAQkQAwcCAToEGHcUr5MSJ/g9" + + "HnJVHsQ6X56VcwYb+OfojTBJBgkqhkiG9w0BBwEwGgYIKoZIhvcNAwIwDgIC" + + "AKAECJwE0hkuKlWhgCBeKNXhojuej3org9Lt7n+wWxOhnky5V50vSpoYRfRR" + + "yw=="); + + public BcEnvelopedDataTest() + { + } + + private static void init() + throws Exception + { + if (!_initialised) + { + _initialised = true; + + if (Security.getProvider(BC) == null) + { + Security.addProvider(new BouncyCastleProvider()); + } + + _signDN = "O=Bouncy Castle, C=AU"; + _signKP = CMSTestUtil.makeKeyPair(); + _signCert = CMSTestUtil.makeCertificate(_signKP, _signDN, _signKP, _signDN); + + _origDN = "CN=Bob, OU=Sales, O=Bouncy Castle, C=AU"; + _origKP = CMSTestUtil.makeKeyPair(); + _origCert = CMSTestUtil.makeCertificate(_origKP, _origDN, _signKP, _signDN); + + _reciDN = "CN=Doug, OU=Sales, O=Bouncy Castle, C=AU"; + _reciDN2 = "CN=Fred, OU=Sales, O=Bouncy Castle, C=AU"; + _reciKP = CMSTestUtil.makeKeyPair(); + _reciCert = CMSTestUtil.makeCertificate(_reciKP, _reciDN, _signKP, _signDN); + + _origEcKP = CMSTestUtil.makeEcDsaKeyPair(); + _reciEcKP = CMSTestUtil.makeEcDsaKeyPair(); + _reciEcCert = CMSTestUtil.makeCertificate(_reciEcKP, _reciDN, _signKP, _signDN); + _reciEcKP2 = CMSTestUtil.makeEcDsaKeyPair(); + _reciEcCert2 = CMSTestUtil.makeCertificate(_reciEcKP2, _reciDN2, _signKP, _signDN); + } + } + + public static void main( + String args[]) + throws Exception + { + junit.textui.TestRunner.run(BcEnvelopedDataTest.suite()); + } + + public static Test suite() + throws Exception + { + init(); + + return new CMSTestSetup(new TestSuite(BcEnvelopedDataTest.class)); + } + + public void testUnprotectedAttributes() + throws Exception + { + byte[] data = "WallaWallaWashington".getBytes(); + + CMSEnvelopedDataGenerator edGen = new CMSEnvelopedDataGenerator(); + + edGen.addRecipientInfoGenerator(new BcRSAKeyTransRecipientInfoGenerator(new JcaX509CertificateHolder(_reciCert))); + + Hashtable attrs = new Hashtable(); + + attrs.put(PKCSObjectIdentifiers.id_aa_contentHint, new Attribute(PKCSObjectIdentifiers.id_aa_contentHint, new DERSet(new DERUTF8String("Hint")))); + attrs.put(PKCSObjectIdentifiers.id_aa_receiptRequest, new Attribute(PKCSObjectIdentifiers.id_aa_receiptRequest, new DERSet(new DERUTF8String("Request")))); + + AttributeTable attrTable = new AttributeTable(attrs); + + edGen.setUnprotectedAttributeGenerator(new SimpleAttributeTableGenerator(attrTable)); + + CMSEnvelopedData ed = edGen.generate( + new CMSProcessableByteArray(data), + new BcCMSContentEncryptorBuilder(CMSAlgorithm.DES_EDE3_CBC).build()); + + RecipientInformationStore recipients = ed.getRecipientInfos(); + + assertEquals(ed.getEncryptionAlgOID(), CMSAlgorithm.DES_EDE3_CBC.getId()); + + attrTable = ed.getUnprotectedAttributes(); + + assertEquals(attrs.size(), 2); + + assertEquals(new DERUTF8String("Hint"), attrTable.get(PKCSObjectIdentifiers.id_aa_contentHint).getAttrValues().getObjectAt(0)); + assertEquals(new DERUTF8String("Request"), attrTable.get(PKCSObjectIdentifiers.id_aa_receiptRequest).getAttrValues().getObjectAt(0)); + + Collection c = recipients.getRecipients(); + + assertEquals(1, c.size()); + + Iterator it = c.iterator(); + + while (it.hasNext()) + { + RecipientInformation recipient = (RecipientInformation)it.next(); + + assertEquals(recipient.getKeyEncryptionAlgOID(), PKCSObjectIdentifiers.rsaEncryption.getId()); + + byte[] recData = recipient.getContent(new BcRSAKeyTransEnvelopedRecipient(PrivateKeyFactory.createKey(_reciKP.getPrivate().getEncoded()))); + + assertEquals(true, Arrays.equals(data, recData)); + } + } + + public void testKeyTrans() + throws Exception + { + byte[] data = "WallaWallaWashington".getBytes(); + + CMSEnvelopedDataGenerator edGen = new CMSEnvelopedDataGenerator(); + + edGen.addRecipientInfoGenerator(new BcRSAKeyTransRecipientInfoGenerator(new JcaX509CertificateHolder(_reciCert))); + + CMSEnvelopedData ed = edGen.generate( + new CMSProcessableByteArray(data), + new BcCMSContentEncryptorBuilder(CMSAlgorithm.DES_EDE3_CBC).build()); + + RecipientInformationStore recipients = ed.getRecipientInfos(); + + + assertEquals(ed.getEncryptionAlgOID(), CMSAlgorithm.DES_EDE3_CBC.getId()); + + Collection c = recipients.getRecipients(); + + assertEquals(1, c.size()); + + Iterator it = c.iterator(); + + while (it.hasNext()) + { + RecipientInformation recipient = (RecipientInformation)it.next(); + + assertEquals(recipient.getKeyEncryptionAlgOID(), PKCSObjectIdentifiers.rsaEncryption.getId()); + + byte[] recData = recipient.getContent(new BcRSAKeyTransEnvelopedRecipient(PrivateKeyFactory.createKey(PrivateKeyInfo.getInstance(_reciKP.getPrivate().getEncoded())))); + + assertEquals(true, Arrays.equals(data, recData)); + } + } + + public void testKeyTransRC4() + throws Exception + { + byte[] data = "WallaWallaBouncyCastle".getBytes(); + + CMSEnvelopedDataGenerator edGen = new CMSEnvelopedDataGenerator(); + + edGen.addRecipientInfoGenerator(new BcRSAKeyTransRecipientInfoGenerator(new JcaX509CertificateHolder(_reciCert))); + + CMSEnvelopedData ed = edGen.generate( + new CMSProcessableByteArray(data), + new BcCMSContentEncryptorBuilder(new ASN1ObjectIdentifier("1.2.840.113549.3.4")).build()); + + RecipientInformationStore recipients = ed.getRecipientInfos(); + + assertEquals(ed.getEncryptionAlgOID(), new ASN1ObjectIdentifier("1.2.840.113549.3.4").getId()); + + Collection c = recipients.getRecipients(); + + assertEquals(1, c.size()); + + Iterator it = c.iterator(); + + while (it.hasNext()) + { + RecipientInformation recipient = (RecipientInformation)it.next(); + + byte[] recData = recipient.getContent(new BcRSAKeyTransEnvelopedRecipient(PrivateKeyFactory.createKey(PrivateKeyInfo.getInstance(_reciKP.getPrivate().getEncoded())))); + + assertEquals(true, Arrays.equals(data, recData)); + } + } + + public void testKeyTrans128RC4() + throws Exception + { + byte[] data = "WallaWallaBouncyCastle".getBytes(); + + CMSEnvelopedDataGenerator edGen = new CMSEnvelopedDataGenerator(); + + edGen.addRecipientInfoGenerator(new BcRSAKeyTransRecipientInfoGenerator(new JcaX509CertificateHolder(_reciCert))); + + CMSEnvelopedData ed = edGen.generate( + new CMSProcessableByteArray(data), + new BcCMSContentEncryptorBuilder(new ASN1ObjectIdentifier("1.2.840.113549.3.4"), 128).build()); + + RecipientInformationStore recipients = ed.getRecipientInfos(); + + assertEquals(ed.getEncryptionAlgOID(), "1.2.840.113549.3.4"); + + Collection c = recipients.getRecipients(); + Iterator it = c.iterator(); + + if (it.hasNext()) + { + RecipientInformation recipient = (RecipientInformation)it.next(); + + byte[] recData = recipient.getContent(new BcRSAKeyTransEnvelopedRecipient(PrivateKeyFactory.createKey(PrivateKeyInfo.getInstance(_reciKP.getPrivate().getEncoded())))); + + assertEquals(true, Arrays.equals(data, recData)); + } + else + { + fail("no recipient found"); + } + } + + public void testKeyTransLight128RC4() + throws Exception + { + byte[] data = "WallaWallaBouncyCastle".getBytes(); + + CMSEnvelopedDataGenerator edGen = new CMSEnvelopedDataGenerator(); + + edGen.addRecipientInfoGenerator(new BcRSAKeyTransRecipientInfoGenerator(new JcaX509CertificateHolder(_reciCert))); + + CMSEnvelopedData ed = edGen.generate( + new CMSProcessableByteArray(data), + new BcCMSContentEncryptorBuilder(new ASN1ObjectIdentifier("1.2.840.113549.3.4"), 128).build()); + + RecipientInformationStore recipients = ed.getRecipientInfos(); + + assertEquals(ed.getEncryptionAlgOID(), "1.2.840.113549.3.4"); + + Collection c = recipients.getRecipients(); + Iterator it = c.iterator(); + + if (it.hasNext()) + { + RecipientInformation recipient = (RecipientInformation)it.next(); + + byte[] recData = recipient.getContent(new BcRSAKeyTransEnvelopedRecipient(PrivateKeyFactory.createKey(PrivateKeyInfo.getInstance(_reciKP.getPrivate().getEncoded())))); + + assertEquals(true, Arrays.equals(data, recData)); + } + else + { + fail("no recipient found"); + } + } + + public void testKeyTransODES() + throws Exception + { + byte[] data = "WallaWallaBouncyCastle".getBytes(); + + CMSEnvelopedDataGenerator edGen = new CMSEnvelopedDataGenerator(); + + edGen.addRecipientInfoGenerator(new BcRSAKeyTransRecipientInfoGenerator(new JcaX509CertificateHolder(_reciCert))); + + CMSEnvelopedData ed = edGen.generate( + new CMSProcessableByteArray(data), + new BcCMSContentEncryptorBuilder(new ASN1ObjectIdentifier("1.3.14.3.2.7")).build()); + + RecipientInformationStore recipients = ed.getRecipientInfos(); + + assertEquals(ed.getEncryptionAlgOID(), "1.3.14.3.2.7"); + + Collection c = recipients.getRecipients(); + Iterator it = c.iterator(); + + if (it.hasNext()) + { + RecipientInformation recipient = (RecipientInformation)it.next(); + + byte[] recData = recipient.getContent(new BcRSAKeyTransEnvelopedRecipient(PrivateKeyFactory.createKey(PrivateKeyInfo.getInstance(_reciKP.getPrivate().getEncoded())))); + + assertEquals(true, Arrays.equals(data, recData)); + } + else + { + fail("no recipient found"); + } + } + + public void testKeyTransSmallAES() + throws Exception + { + byte[] data = new byte[] { 0, 1, 2, 3 }; + + CMSEnvelopedDataGenerator edGen = new CMSEnvelopedDataGenerator(); + + edGen.addRecipientInfoGenerator(new BcRSAKeyTransRecipientInfoGenerator(new JcaX509CertificateHolder(_reciCert))); + + CMSEnvelopedData ed = edGen.generate( + new CMSProcessableByteArray(data), + new BcCMSContentEncryptorBuilder(CMSAlgorithm.AES128_CBC).build()); + + RecipientInformationStore recipients = ed.getRecipientInfos(); + + assertEquals(ed.getEncryptionAlgOID(), + CMSAlgorithm.AES128_CBC.getId()); + + Collection c = recipients.getRecipients(); + Iterator it = c.iterator(); + + if (it.hasNext()) + { + RecipientInformation recipient = (RecipientInformation)it.next(); + + byte[] recData = recipient.getContent(new BcRSAKeyTransEnvelopedRecipient(PrivateKeyFactory.createKey(PrivateKeyInfo.getInstance(_reciKP.getPrivate().getEncoded())))); + assertEquals(true, Arrays.equals(data, recData)); + } + else + { + fail("no recipient found"); + } + } + + public void testKeyTransAES128() + throws Exception + { + tryKeyTrans(CMSAlgorithm.AES128_CBC, NISTObjectIdentifiers.id_aes128_CBC, 16, DEROctetString.class); + } + + public void testKeyTransAES192() + throws Exception + { + tryKeyTrans(CMSAlgorithm.AES192_CBC, NISTObjectIdentifiers.id_aes192_CBC, 24, DEROctetString.class); + } + + public void testKeyTransAES256() + throws Exception + { + tryKeyTrans(CMSAlgorithm.AES256_CBC, NISTObjectIdentifiers.id_aes256_CBC, 32, DEROctetString.class); + } + + private void tryKeyTrans(ASN1ObjectIdentifier generatorOID, ASN1ObjectIdentifier checkOID, int keySize, Class asn1Params) + throws Exception + { + byte[] data = "WallaWallaWashington".getBytes(); + + CMSEnvelopedDataGenerator edGen = new CMSEnvelopedDataGenerator(); + + edGen.addRecipientInfoGenerator(new BcRSAKeyTransRecipientInfoGenerator(new JcaX509CertificateHolder(_reciCert))); + + OutputEncryptor encryptor = new BcCMSContentEncryptorBuilder(generatorOID).build(); + CMSEnvelopedData ed = edGen.generate( + new CMSProcessableByteArray(data), encryptor); + + RecipientInformationStore recipients = ed.getRecipientInfos(); + + assertEquals(checkOID.getId(), ed.getEncryptionAlgOID()); + assertEquals(keySize, ((byte[])encryptor.getKey().getRepresentation()).length); + + if (asn1Params != null) + { + assertTrue(asn1Params.isAssignableFrom(ed.getContentEncryptionAlgorithm().getParameters().toASN1Primitive().getClass())); + } + + Collection c = recipients.getRecipients(); + + assertEquals(1, c.size()); + + Iterator it = c.iterator(); + + if (!it.hasNext()) + { + fail("no recipients found"); + } + + while (it.hasNext()) + { + RecipientInformation recipient = (RecipientInformation)it.next(); + + assertEquals(recipient.getKeyEncryptionAlgOID(), PKCSObjectIdentifiers.rsaEncryption.getId()); + + byte[] recData = recipient.getContent(new BcRSAKeyTransEnvelopedRecipient(PrivateKeyFactory.createKey(PrivateKeyInfo.getInstance(_reciKP.getPrivate().getEncoded())))); + + assertEquals(true, Arrays.equals(data, recData)); + } + } + + public void testAES128KEK() + throws Exception + { + SecretKey key = CMSTestUtil.makeAESKey(128); + + tryKekAlgorithm(new BcAESSymmetricKeyWrapper(new KeyParameter(key.getEncoded())), new BcAESSymmetricKeyUnwrapper(new KeyParameter(key.getEncoded())), NISTObjectIdentifiers.id_aes128_wrap); + } + + public void testAES192KEK() + throws Exception + { + SecretKey key = CMSTestUtil.makeAESKey(192); + + tryKekAlgorithm(new BcAESSymmetricKeyWrapper(new KeyParameter(key.getEncoded())), new BcAESSymmetricKeyUnwrapper(new KeyParameter(key.getEncoded())), NISTObjectIdentifiers.id_aes192_wrap); + } + + public void testAES256KEK() + throws Exception + { + SecretKey key = CMSTestUtil.makeAESKey(256); + + tryKekAlgorithm(new BcAESSymmetricKeyWrapper(new KeyParameter(key.getEncoded())), new BcAESSymmetricKeyUnwrapper(new KeyParameter(key.getEncoded())), NISTObjectIdentifiers.id_aes256_wrap); + } + + private void tryKekAlgorithm(BcSymmetricKeyWrapper kekWrapper, BcSymmetricKeyUnwrapper kekUnwrapper, ASN1ObjectIdentifier algOid) + throws NoSuchAlgorithmException, NoSuchProviderException, CMSException + { + byte[] data = "WallaWallaWashington".getBytes(); + CMSEnvelopedDataGenerator edGen = new CMSEnvelopedDataGenerator(); + + byte[] kekId = new byte[] { 1, 2, 3, 4, 5 }; + + edGen.addRecipientInfoGenerator(new BcKEKRecipientInfoGenerator(kekId, kekWrapper)); + + CMSEnvelopedData ed = edGen.generate( + new CMSProcessableByteArray(data), + new BcCMSContentEncryptorBuilder(CMSAlgorithm.DES_EDE3_CBC).build()); + + RecipientInformationStore recipients = ed.getRecipientInfos(); + + Collection c = recipients.getRecipients(); + Iterator it = c.iterator(); + + assertEquals(ed.getEncryptionAlgOID(), CMSAlgorithm.DES_EDE3_CBC.getId()); + + if (it.hasNext()) + { + RecipientInformation recipient = (RecipientInformation)it.next(); + + assertEquals(algOid.getId(), recipient.getKeyEncryptionAlgOID()); + + byte[] recData = recipient.getContent(new BcKEKEnvelopedRecipient(kekUnwrapper)); + + assertTrue(Arrays.equals(data, recData)); + } + else + { + fail("no recipient found"); + } + } + + public void testECKeyAgree() + throws Exception + { + byte[] data = Hex.decode("504b492d4320434d5320456e76656c6f706564446174612053616d706c65"); + + CMSEnvelopedDataGenerator edGen = new CMSEnvelopedDataGenerator(); + + edGen.addRecipientInfoGenerator(new JceKeyAgreeRecipientInfoGenerator(CMSAlgorithm.ECDH_SHA1KDF, + _origEcKP.getPrivate(), _origEcKP.getPublic(), + CMSAlgorithm.AES128_WRAP).addRecipient(_reciEcCert).setProvider(BC)); + + CMSEnvelopedData ed = edGen.generate( + new CMSProcessableByteArray(data), + new BcCMSContentEncryptorBuilder(CMSAlgorithm.AES128_CBC).build()); + + assertEquals(ed.getEncryptionAlgOID(), CMSAlgorithm.AES128_CBC.getId()); + + RecipientInformationStore recipients = ed.getRecipientInfos(); + + confirmDataReceived(recipients, data, _reciEcCert, _reciEcKP.getPrivate(), BC); + confirmNumberRecipients(recipients, 1); + } + + public void testECMQVKeyAgree() + throws Exception + { + byte[] data = Hex.decode("504b492d4320434d5320456e76656c6f706564446174612053616d706c65"); + + CMSEnvelopedDataGenerator edGen = new CMSEnvelopedDataGenerator(); + + edGen.addRecipientInfoGenerator(new JceKeyAgreeRecipientInfoGenerator(CMSAlgorithm.ECMQV_SHA1KDF, + _origEcKP.getPrivate(), _origEcKP.getPublic(), + CMSAlgorithm.AES128_WRAP).addRecipient(_reciEcCert).setProvider(BC)); + + CMSEnvelopedData ed = edGen.generate( + new CMSProcessableByteArray(data), + new BcCMSContentEncryptorBuilder(CMSAlgorithm.AES128_CBC).build()); + + assertEquals(ed.getEncryptionAlgOID(), CMSAlgorithm.AES128_CBC.getId()); + + RecipientInformationStore recipients = ed.getRecipientInfos(); + + confirmDataReceived(recipients, data, _reciEcCert, _reciEcKP.getPrivate(), BC); + confirmNumberRecipients(recipients, 1); + } + + public void testECMQVKeyAgreeMultiple() + throws Exception + { + byte[] data = Hex.decode("504b492d4320434d5320456e76656c6f706564446174612053616d706c65"); + + CMSEnvelopedDataGenerator edGen = new CMSEnvelopedDataGenerator(); + + JceKeyAgreeRecipientInfoGenerator recipientGenerator = new JceKeyAgreeRecipientInfoGenerator(CMSAlgorithm.ECMQV_SHA1KDF, + _origEcKP.getPrivate(), _origEcKP.getPublic(), CMSAlgorithm.AES128_WRAP).setProvider(BC); + + recipientGenerator.addRecipient(_reciEcCert); + recipientGenerator.addRecipient(_reciEcCert2); + + edGen.addRecipientInfoGenerator(recipientGenerator); + + CMSEnvelopedData ed = edGen.generate( + new CMSProcessableByteArray(data), + new BcCMSContentEncryptorBuilder(CMSAlgorithm.AES128_CBC).build()); + + assertEquals(ed.getEncryptionAlgOID(), CMSAlgorithm.AES128_CBC.getId()); + + RecipientInformationStore recipients = ed.getRecipientInfos(); + + confirmDataReceived(recipients, data, _reciEcCert, _reciEcKP.getPrivate(), BC); + confirmDataReceived(recipients, data, _reciEcCert2, _reciEcKP2.getPrivate(), BC); + confirmNumberRecipients(recipients, 2); + } + + private static void confirmDataReceived(RecipientInformationStore recipients, + byte[] expectedData, X509Certificate reciCert, PrivateKey reciPrivKey, String provider) + throws CMSException, NoSuchProviderException, CertificateEncodingException, IOException + { + RecipientId rid = new JceKeyAgreeRecipientId(reciCert); + + RecipientInformation recipient = recipients.get(rid); + assertNotNull(recipient); + + byte[] actualData = recipient.getContent(new JceKeyAgreeEnvelopedRecipient(reciPrivKey).setProvider(provider)); + assertEquals(true, Arrays.equals(expectedData, actualData)); + } + + private static void confirmNumberRecipients(RecipientInformationStore recipients, int count) + { + assertEquals(count, recipients.getRecipients().size()); + } + + public void testECKeyAgreeVectors() + throws Exception + { + PKCS8EncodedKeySpec privSpec = new PKCS8EncodedKeySpec(ecKeyAgreeKey); + KeyFactory fact = KeyFactory.getInstance("ECDH", BC); + PrivateKey privKey = fact.generatePrivate(privSpec); + + verifyECKeyAgreeVectors(privKey, "2.16.840.1.101.3.4.1.42", ecKeyAgreeMsgAES256); + verifyECKeyAgreeVectors(privKey, "2.16.840.1.101.3.4.1.2", ecKeyAgreeMsgAES128); + verifyECKeyAgreeVectors(privKey, "1.2.840.113549.3.7", ecKeyAgreeMsgDESEDE); + } + + public void testECMQVKeyAgreeVectors() + throws Exception + { + PKCS8EncodedKeySpec privSpec = new PKCS8EncodedKeySpec(ecKeyAgreeKey); + KeyFactory fact = KeyFactory.getInstance("ECDH", BC); + PrivateKey privKey = fact.generatePrivate(privSpec); + + verifyECMQVKeyAgreeVectors(privKey, "2.16.840.1.101.3.4.1.2", ecMQVKeyAgreeMsgAES128); + } + + public void testPasswordAES256() + throws Exception + { + passwordTest(CMSAlgorithm.AES256_CBC); + passwordUTF8Test(CMSAlgorithm.AES256_CBC); + } + + public void testPasswordDESEDE() + throws Exception + { + passwordTest(CMSAlgorithm.DES_EDE3_CBC); + passwordUTF8Test(CMSAlgorithm.DES_EDE3_CBC); + } + + public void testRFC4134ex5_1() + throws Exception + { + byte[] data = Hex.decode("5468697320697320736f6d652073616d706c6520636f6e74656e742e"); + + KeyFactory kFact = KeyFactory.getInstance("RSA", BC); + Key key = kFact.generatePrivate(new PKCS8EncodedKeySpec(bobPrivRsaEncrypt)); + + CMSEnvelopedData ed = new CMSEnvelopedData(rfc4134ex5_1); + + RecipientInformationStore recipients = ed.getRecipientInfos(); + + assertEquals("1.2.840.113549.3.7", ed.getEncryptionAlgOID()); + + Collection c = recipients.getRecipients(); + Iterator it = c.iterator(); + + if (it.hasNext()) + { + RecipientInformation recipient = (RecipientInformation)it.next(); + + byte[] recData = recipient.getContent(new BcRSAKeyTransEnvelopedRecipient(PrivateKeyFactory.createKey(PrivateKeyInfo.getInstance(key.getEncoded())))); + + assertEquals(true, Arrays.equals(data, recData)); + } + else + { + fail("no recipient found"); + } + } + + public void testRFC4134ex5_2() + throws Exception + { + byte[] data = Hex.decode("5468697320697320736f6d652073616d706c6520636f6e74656e742e"); + + KeyFactory kFact = KeyFactory.getInstance("RSA", BC); + PrivateKey key = kFact.generatePrivate(new PKCS8EncodedKeySpec(bobPrivRsaEncrypt)); + + CMSEnvelopedData ed = new CMSEnvelopedData(rfc4134ex5_2); + + RecipientInformationStore recipients = ed.getRecipientInfos(); + + assertEquals("1.2.840.113549.3.2", ed.getEncryptionAlgOID()); + + Collection c = recipients.getRecipients(); + Iterator it = c.iterator(); + + if (it.hasNext()) + { + while (it.hasNext()) + { + RecipientInformation recipient = (RecipientInformation)it.next(); + byte[] recData; + + if (recipient instanceof KeyTransRecipientInformation) + { + recData = recipient.getContent(new BcRSAKeyTransEnvelopedRecipient(PrivateKeyFactory.createKey(PrivateKeyInfo.getInstance(key.getEncoded())))); + + assertEquals(true, Arrays.equals(data, recData)); + } + } + } + else + { + fail("no recipient found"); + } + } + + public void testOriginatorInfo() + throws Exception + { + CMSEnvelopedData env = new CMSEnvelopedData(CMSSampleMessages.originatorMessage); + + RecipientInformationStore recipients = env.getRecipientInfos(); + + assertEquals(CMSAlgorithm.DES_EDE3_CBC.getId(), env.getEncryptionAlgOID()); + } + + private void passwordTest(ASN1ObjectIdentifier algorithm) + throws Exception + { + byte[] data = Hex.decode("504b492d4320434d5320456e76656c6f706564446174612053616d706c65"); + + CMSEnvelopedDataGenerator edGen = new CMSEnvelopedDataGenerator(); + + edGen.addRecipientInfoGenerator(new BcPasswordRecipientInfoGenerator(algorithm, "password".toCharArray()).setPasswordConversionScheme(PasswordRecipient.PKCS5_SCHEME2).setSaltAndIterationCount(new byte[20], 5)); + + CMSEnvelopedData ed = edGen.generate( + new CMSProcessableByteArray(data), + new BcCMSContentEncryptorBuilder(CMSAlgorithm.AES128_CBC).build()); + + RecipientInformationStore recipients = ed.getRecipientInfos(); + + assertEquals(ed.getEncryptionAlgOID(), + CMSAlgorithm.AES128_CBC.getId()); + + Collection c = recipients.getRecipients(); + Iterator it = c.iterator(); + + if (it.hasNext()) + { + PasswordRecipientInformation recipient = (PasswordRecipientInformation)it.next(); + + byte[] recData = recipient.getContent(new BcPasswordEnvelopedRecipient("password".toCharArray()).setPasswordConversionScheme(PasswordRecipient.PKCS5_SCHEME2)); + + assertEquals(true, Arrays.equals(data, recData)); + } + else + { + fail("no recipient found"); + } + + // + // try algorithm parameters constructor + // + it = c.iterator(); + + RecipientInformation recipient = (RecipientInformation)it.next(); + + byte[] recData = recipient.getContent(new BcPasswordEnvelopedRecipient("password".toCharArray()).setPasswordConversionScheme(PasswordRecipient.PKCS5_SCHEME2)); + assertEquals(true, Arrays.equals(data, recData)); + } + + private void passwordUTF8Test(ASN1ObjectIdentifier algorithm) + throws Exception + { + byte[] data = Hex.decode("504b492d4320434d5320456e76656c6f706564446174612053616d706c65"); + + CMSEnvelopedDataGenerator edGen = new CMSEnvelopedDataGenerator(); + + edGen.addRecipientInfoGenerator(new BcPasswordRecipientInfoGenerator(algorithm, "abc\u5639\u563b".toCharArray()).setSaltAndIterationCount(new byte[20], 5)); + + CMSEnvelopedData ed = edGen.generate( + new CMSProcessableByteArray(data), + new BcCMSContentEncryptorBuilder(CMSAlgorithm.AES128_CBC).build()); + + RecipientInformationStore recipients = ed.getRecipientInfos(); + + assertEquals(ed.getEncryptionAlgOID(), + CMSAlgorithm.AES128_CBC.getId()); + + Collection c = recipients.getRecipients(); + Iterator it = c.iterator(); + + if (it.hasNext()) + { + RecipientInformation recipient = (RecipientInformation)it.next(); + + byte[] recData = recipient.getContent(new BcPasswordEnvelopedRecipient("abc\u5639\u563b".toCharArray())); + assertEquals(true, Arrays.equals(data, recData)); + } + else + { + fail("no recipient found"); + } + + // + // try algorithm parameters constructor + // + it = c.iterator(); + + RecipientInformation recipient = (RecipientInformation)it.next(); + + byte[] recData = recipient.getContent(new BcPasswordEnvelopedRecipient("abc\u5639\u563b".toCharArray())); + assertEquals(true, Arrays.equals(data, recData)); + } + + private void verifyECKeyAgreeVectors(PrivateKey privKey, String wrapAlg, byte[] message) + throws CMSException, GeneralSecurityException + { + byte[] data = Hex.decode("504b492d4320434d5320456e76656c6f706564446174612053616d706c65"); + + CMSEnvelopedData ed = new CMSEnvelopedData(message); + + RecipientInformationStore recipients = ed.getRecipientInfos(); + + Collection c = recipients.getRecipients(); + Iterator it = c.iterator(); + + assertEquals(wrapAlg, ed.getEncryptionAlgOID()); + + if (it.hasNext()) + { + RecipientInformation recipient = (RecipientInformation)it.next(); + + assertEquals("1.3.133.16.840.63.0.2", recipient.getKeyEncryptionAlgOID()); + + byte[] recData = recipient.getContent(new JceKeyAgreeEnvelopedRecipient(privKey).setProvider(BC)); + + assertTrue(Arrays.equals(data, recData)); + } + else + { + fail("no recipient found"); + } + } + + private void verifyECMQVKeyAgreeVectors(PrivateKey privKey, String wrapAlg, byte[] message) + throws CMSException, GeneralSecurityException + { + byte[] data = Hex.decode("504b492d4320434d5320456e76656c6f706564446174612053616d706c65"); + + CMSEnvelopedData ed = new CMSEnvelopedData(message); + + RecipientInformationStore recipients = ed.getRecipientInfos(); + + Collection c = recipients.getRecipients(); + Iterator it = c.iterator(); + + assertEquals(wrapAlg, ed.getEncryptionAlgOID()); + + if (it.hasNext()) + { + RecipientInformation recipient = (RecipientInformation)it.next(); + + assertEquals("1.3.133.16.840.63.0.16", recipient.getKeyEncryptionAlgOID()); + + byte[] recData = recipient.getContent(new JceKeyAgreeEnvelopedRecipient(privKey).setProvider(BC)); + + assertTrue(Arrays.equals(data, recData)); + } + else + { + fail("no recipient found"); + } + } +} diff --git a/pkix/src/test/java/org/spongycastle/cms/test/BcSignedDataTest.java b/pkix/src/test/java/org/spongycastle/cms/test/BcSignedDataTest.java new file mode 100644 index 00000000..e2782ba6 --- /dev/null +++ b/pkix/src/test/java/org/spongycastle/cms/test/BcSignedDataTest.java @@ -0,0 +1,1835 @@ +package org.spongycastle.cms.test; + +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.security.KeyFactory; +import java.security.KeyPair; +import java.security.MessageDigest; +import java.security.Security; +import java.security.cert.X509CRL; +import java.security.cert.X509Certificate; +import java.security.spec.PKCS8EncodedKeySpec; +import java.security.spec.X509EncodedKeySpec; +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +import junit.framework.Test; +import junit.framework.TestCase; +import junit.framework.TestSuite; +import org.spongycastle.asn1.ASN1EncodableVector; +import org.spongycastle.asn1.ASN1InputStream; +import org.spongycastle.asn1.ASN1ObjectIdentifier; +import org.spongycastle.asn1.ASN1OctetString; +import org.spongycastle.asn1.DEROctetString; +import org.spongycastle.asn1.DERSet; +import org.spongycastle.asn1.cms.Attribute; +import org.spongycastle.asn1.cms.AttributeTable; +import org.spongycastle.asn1.cms.CMSAttributes; +import org.spongycastle.asn1.cms.ContentInfo; +import org.spongycastle.asn1.oiw.OIWObjectIdentifiers; +import org.spongycastle.asn1.pkcs.PKCSObjectIdentifiers; +import org.spongycastle.asn1.x509.AlgorithmIdentifier; +import org.spongycastle.cert.X509AttributeCertificateHolder; +import org.spongycastle.cert.X509CertificateHolder; +import org.spongycastle.cert.jcajce.JcaCRLStore; +import org.spongycastle.cert.jcajce.JcaCertStore; +import org.spongycastle.cert.jcajce.JcaX509CRLHolder; +import org.spongycastle.cert.jcajce.JcaX509CertificateHolder; +import org.spongycastle.cms.CMSAbsentContent; +import org.spongycastle.cms.CMSAlgorithm; +import org.spongycastle.cms.CMSException; +import org.spongycastle.cms.CMSProcessableByteArray; +import org.spongycastle.cms.CMSSignedData; +import org.spongycastle.cms.CMSSignedDataGenerator; +import org.spongycastle.cms.CMSSignedDataParser; +import org.spongycastle.cms.CMSTypedData; +import org.spongycastle.cms.DefaultCMSSignatureAlgorithmNameGenerator; +import org.spongycastle.cms.DefaultSignedAttributeTableGenerator; +import org.spongycastle.cms.SignerId; +import org.spongycastle.cms.SignerInfoGeneratorBuilder; +import org.spongycastle.cms.SignerInformation; +import org.spongycastle.cms.SignerInformationStore; +import org.spongycastle.cms.bc.BcRSASignerInfoVerifierBuilder; +import org.spongycastle.cms.jcajce.JcaSignerInfoGeneratorBuilder; +import org.spongycastle.cms.jcajce.JcaSimpleSignerInfoGeneratorBuilder; +import org.spongycastle.cms.jcajce.JcaSimpleSignerInfoVerifierBuilder; +import org.spongycastle.crypto.params.AsymmetricKeyParameter; +import org.spongycastle.crypto.util.PrivateKeyFactory; +import org.spongycastle.jcajce.provider.config.ConfigurableProvider; +import org.spongycastle.jce.provider.BouncyCastleProvider; +import org.spongycastle.operator.BufferingContentSigner; +import org.spongycastle.operator.ContentSigner; +import org.spongycastle.operator.DefaultDigestAlgorithmIdentifierFinder; +import org.spongycastle.operator.DefaultSignatureAlgorithmIdentifierFinder; +import org.spongycastle.operator.DigestCalculatorProvider; +import org.spongycastle.operator.bc.BcContentSignerBuilder; +import org.spongycastle.operator.bc.BcDigestCalculatorProvider; +import org.spongycastle.operator.bc.BcRSAContentSignerBuilder; +import org.spongycastle.operator.jcajce.JcaContentSignerBuilder; +import org.spongycastle.operator.jcajce.JcaDigestCalculatorProviderBuilder; +import org.spongycastle.util.CollectionStore; +import org.spongycastle.util.Store; +import org.spongycastle.util.encoders.Base64; +import org.spongycastle.util.io.Streams; + +public class BcSignedDataTest + extends TestCase +{ + private static final String BC = BouncyCastleProvider.PROVIDER_NAME; + + boolean DEBUG = true; + + private static String _origDN; + private static KeyPair _origKP; + private static X509Certificate _origCert; + + private static String _signDN; + private static KeyPair _signKP; + private static X509Certificate _signCert; + + private static KeyPair _signEcDsaKP; + private static X509Certificate _signEcDsaCert; + + private static KeyPair _signEcGostKP; + private static X509Certificate _signEcGostCert; + + private static KeyPair _signDsaKP; + private static X509Certificate _signDsaCert; + + private static String _reciDN; + private static KeyPair _reciKP; + private static X509Certificate _reciCert; + + private static X509CRL _signCrl; + + private static boolean _initialised = false; + + private byte[] disorderedMessage = Base64.decode( + "SU9fc3RkaW5fdXNlZABfX2xpYmNfc3RhcnRfbWFpbgBnZXRob3N0aWQAX19n" + + "bW9uX3M="); + + private byte[] disorderedSet = Base64.decode( + "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" + + "gQBpSRdnDb6AcNVaXSmGo6+kVPIBhot1LzJOGaPyDNpGXxd7LV4tMBF1U7gr" + + "4k1g9BO6YiMWvw9uiTZmn0CfV8+k4fWEuG/nmafRoGIuay2f+ILuT+C0rnp1" + + "4FgMsEhuVNJJAmb12QV0PZII+UneyhAneZuQQzVUkTcVgYxogxdSOzCCAlUw" + + "ggHBoAMCAQICBACdekowCgYGKyQDAwECBQAwbzELMAkGA1UEBhMCREUxPTA7" + + "BgNVBAoUNFJlZ3VsaWVydW5nc2JlaMhvcmRlIGbIdXIgVGVsZWtvbW11bmlr" + + "YXRpb24gdW5kIFBvc3QxITAMBgcCggYBCgcUEwExMBEGA1UEAxQKNlItQ2Eg" + + "MTpQTjAiGA8yMDAxMDIwMTEzNDcwN1oYDzIwMDUwMzIyMDg1NTUxWjBvMQsw" + + "CQYDVQQGEwJERTE9MDsGA1UEChQ0UmVndWxpZXJ1bmdzYmVoyG9yZGUgZsh1" + + "ciBUZWxla29tbXVuaWthdGlvbiB1bmQgUG9zdDEhMAwGBwKCBgEKBxQTATEw" + + "EQYDVQQDFAo1Ui1DQSAxOlBOMIGhMA0GCSqGSIb3DQEBAQUAA4GPADCBiwKB" + + "gQCKHkFTJx8GmoqFTxEOxpK9XkC3NZ5dBEKiUv0Ife3QMqeGMoCUnyJxwW0k" + + "2/53duHxtv2yHSZpFKjrjvE/uGwdOMqBMTjMzkFg19e9JPv061wyADOucOIa" + + "NAgha/zFt9XUyrHF21knKCvDNExv2MYIAagkTKajLMAw0bu1J0FadQIFAMAA" + + "AAEwCgYGKyQDAwECBQADgYEAV1yTi+2gyB7sUhn4PXmi/tmBxAfe5oBjDW8m" + + "gxtfudxKGZ6l/FUPNcrSc5oqBYxKWtLmf3XX87LcblYsch617jtNTkMzhx9e" + + "qxiD02ufcrxz2EVt0Akdqiz8mdVeqp3oLcNU/IttpSrcA91CAnoUXtDZYwb/" + + "gdQ4FI9l3+qo/0UwggJVMIIBwaADAgECAgQAxIymMAoGBiskAwMBAgUAMG8x" + + "CzAJBgNVBAYTAkRFMT0wOwYDVQQKFDRSZWd1bGllcnVuZ3NiZWjIb3JkZSBm" + + "yHVyIFRlbGVrb21tdW5pa2F0aW9uIHVuZCBQb3N0MSEwDAYHAoIGAQoHFBMB" + + "MTARBgNVBAMUCjZSLUNhIDE6UE4wIhgPMjAwMTEwMTUxMzMxNThaGA8yMDA1" + + "MDYwMTA5NTIxN1owbzELMAkGA1UEBhMCREUxPTA7BgNVBAoUNFJlZ3VsaWVy" + + "dW5nc2JlaMhvcmRlIGbIdXIgVGVsZWtvbW11bmlrYXRpb24gdW5kIFBvc3Qx" + + "ITAMBgcCggYBCgcUEwExMBEGA1UEAxQKN1ItQ0EgMTpQTjCBoTANBgkqhkiG" + + "9w0BAQEFAAOBjwAwgYsCgYEAiokD/j6lEP4FexF356OpU5teUpGGfUKjIrFX" + + "BHc79G0TUzgVxqMoN1PWnWktQvKo8ETaugxLkP9/zfX3aAQzDW4Zki6x6GDq" + + "fy09Agk+RJvhfbbIzRkV4sBBco0n73x7TfG/9NTgVr/96U+I+z/1j30aboM6" + + "9OkLEhjxAr0/GbsCBQDAAAABMAoGBiskAwMBAgUAA4GBAHWRqRixt+EuqHhR" + + "K1kIxKGZL2vZuakYV0R24Gv/0ZR52FE4ECr+I49o8FP1qiGSwnXB0SwjuH2S" + + "iGiSJi+iH/MeY85IHwW1P5e+bOMvEOFhZhQXQixOD7totIoFtdyaj1XGYRef" + + "0f2cPOjNJorXHGV8wuBk+/j++sxbd/Net3FtMIICVTCCAcGgAwIBAgIEAMSM" + + "pzAKBgYrJAMDAQIFADBvMQswCQYDVQQGEwJERTE9MDsGA1UEChQ0UmVndWxp" + + "ZXJ1bmdzYmVoyG9yZGUgZsh1ciBUZWxla29tbXVuaWthdGlvbiB1bmQgUG9z" + + "dDEhMAwGBwKCBgEKBxQTATEwEQYDVQQDFAo3Ui1DQSAxOlBOMCIYDzIwMDEx" + + "MDE1MTMzNDE0WhgPMjAwNTA2MDEwOTUyMTdaMG8xCzAJBgNVBAYTAkRFMT0w" + + "OwYDVQQKFDRSZWd1bGllcnVuZ3NiZWjIb3JkZSBmyHVyIFRlbGVrb21tdW5p" + + "a2F0aW9uIHVuZCBQb3N0MSEwDAYHAoIGAQoHFBMBMTARBgNVBAMUCjZSLUNh" + + "IDE6UE4wgaEwDQYJKoZIhvcNAQEBBQADgY8AMIGLAoGBAIOiqxUkzVyqnvth" + + "ihnltsE5m1Xn5TZKeR/2MQPStc5hJ+V4yptEtIx+Fn5rOoqT5VEVWhcE35wd" + + "bPvgJyQFn5msmhPQT/6XSGOlrWRoFummXN9lQzAjCj1sgTcmoLCVQ5s5WpCA" + + "OXFwVWu16qndz3sPItn3jJ0F3Kh3w79NglvPAgUAwAAAATAKBgYrJAMDAQIF" + + "AAOBgQBi5W96UVDoNIRkCncqr1LLG9vF9SGBIkvFpLDIIbcvp+CXhlvsdCJl" + + "0pt2QEPSDl4cmpOet+CxJTdTuMeBNXxhb7Dvualog69w/+K2JbPhZYxuVFZs" + + "Zh5BkPn2FnbNu3YbJhE60aIkikr72J4XZsI5DxpZCGh6xyV/YPRdKSljFjCC" + + "AlQwggHAoAMCAQICAwyDqzAKBgYrJAMDAQIFADBvMQswCQYDVQQGEwJERTE9" + + "MDsGA1UEChQ0UmVndWxpZXJ1bmdzYmVoyG9yZGUgZsh1ciBUZWxla29tbXVu" + + "aWthdGlvbiB1bmQgUG9zdDEhMAwGBwKCBgEKBxQTATEwEQYDVQQDFAo1Ui1D" + + "QSAxOlBOMCIYDzIwMDAwMzIyMDk0MTI3WhgPMjAwNDAxMjExNjA0NTNaMG8x" + + "CzAJBgNVBAYTAkRFMT0wOwYDVQQKFDRSZWd1bGllcnVuZ3NiZWjIb3JkZSBm" + + "yHVyIFRlbGVrb21tdW5pa2F0aW9uIHVuZCBQb3N0MSEwDAYHAoIGAQoHFBMB" + + "MTARBgNVBAMUCjRSLUNBIDE6UE4wgaEwDQYJKoZIhvcNAQEBBQADgY8AMIGL" + + "AoGBAI8x26tmrFJanlm100B7KGlRemCD1R93PwdnG7svRyf5ZxOsdGrDszNg" + + "xg6ouO8ZHQMT3NC2dH8TvO65Js+8bIyTm51azF6clEg0qeWNMKiiXbBXa+ph" + + "hTkGbXiLYvACZ6/MTJMJ1lcrjpRF7BXtYeYMcEF6znD4pxOqrtbf9z5hAgUA" + + "wAAAATAKBgYrJAMDAQIFAAOBgQB99BjSKlGPbMLQAgXlvA9jUsDNhpnVm3a1" + + "YkfxSqS/dbQlYkbOKvCxkPGA9NBxisBM8l1zFynVjJoy++aysRmcnLY/sHaz" + + "23BF2iU7WERy18H3lMBfYB6sXkfYiZtvQZcWaO48m73ZBySuiV3iXpb2wgs/" + + "Cs20iqroAWxwq/W/9jCCAlMwggG/oAMCAQICBDsFZ9UwCgYGKyQDAwECBQAw" + + "bzELMAkGA1UEBhMCREUxITAMBgcCggYBCgcUEwExMBEGA1UEAxQKNFItQ0Eg" + + "MTpQTjE9MDsGA1UEChQ0UmVndWxpZXJ1bmdzYmVoyG9yZGUgZsh1ciBUZWxl" + + "a29tbXVuaWthdGlvbiB1bmQgUG9zdDAiGA8xOTk5MDEyMTE3MzUzNFoYDzIw" + + "MDQwMTIxMTYwMDAyWjBvMQswCQYDVQQGEwJERTE9MDsGA1UEChQ0UmVndWxp" + + "ZXJ1bmdzYmVoyG9yZGUgZsh1ciBUZWxla29tbXVuaWthdGlvbiB1bmQgUG9z" + + "dDEhMAwGBwKCBgEKBxQTATEwEQYDVQQDFAozUi1DQSAxOlBOMIGfMA0GCSqG" + + "SIb3DQEBAQUAA4GNADCBiQKBgI4B557mbKQg/AqWBXNJhaT/6lwV93HUl4U8" + + "u35udLq2+u9phns1WZkdM3gDfEpL002PeLfHr1ID/96dDYf04lAXQfombils" + + "of1C1k32xOvxjlcrDOuPEMxz9/HDAQZA5MjmmYHAIulGI8Qg4Tc7ERRtg/hd" + + "0QX0/zoOeXoDSEOBAgTAAAABMAoGBiskAwMBAgUAA4GBAIyzwfT3keHI/n2P" + + "LrarRJv96mCohmDZNpUQdZTVjGu5VQjVJwk3hpagU0o/t/FkdzAjOdfEw8Ql" + + "3WXhfIbNLv1YafMm2eWSdeYbLcbB5yJ1od+SYyf9+tm7cwfDAcr22jNRBqx8" + + "wkWKtKDjWKkevaSdy99sAI8jebHtWz7jzydKMIID9TCCA16gAwIBAgICbMcw" + + "DQYJKoZIhvcNAQEFBQAwSzELMAkGA1UEBhMCREUxEjAQBgNVBAoUCVNpZ250" + + "cnVzdDEoMAwGBwKCBgEKBxQTATEwGAYDVQQDFBFDQSBTSUdOVFJVU1QgMTpQ" + + "TjAeFw0wNDA3MzAxMzAyNDZaFw0wNzA3MzAxMzAyNDZaMDwxETAPBgNVBAMM" + + "CFlhY29tOlBOMQ4wDAYDVQRBDAVZYWNvbTELMAkGA1UEBhMCREUxCjAIBgNV" + + "BAUTATEwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAIWzLlYLQApocXIp" + + "pgCCpkkOUVLgcLYKeOd6/bXAnI2dTHQqT2bv7qzfUnYvOqiNgYdF13pOYtKg" + + "XwXMTNFL4ZOI6GoBdNs9TQiZ7KEWnqnr2945HYx7UpgTBclbOK/wGHuCdcwO" + + "x7juZs1ZQPFG0Lv8RoiV9s6HP7POqh1sO0P/AgMBAAGjggH1MIIB8TCBnAYD" + + "VR0jBIGUMIGRgBQcZzNghfnXoXRm8h1+VITC5caNRqFzpHEwbzELMAkGA1UE" + + "BhMCREUxPTA7BgNVBAoUNFJlZ3VsaWVydW5nc2JlaMhvcmRlIGbIdXIgVGVs" + + "ZWtvbW11bmlrYXRpb24gdW5kIFBvc3QxITAMBgcCggYBCgcUEwExMBEGA1UE" + + "AxQKNVItQ0EgMTpQToIEALs8rjAdBgNVHQ4EFgQU2e5KAzkVuKaM9I5heXkz" + + "bcAIuR8wDgYDVR0PAQH/BAQDAgZAMBIGA1UdIAQLMAkwBwYFKyQIAQEwfwYD" + + "VR0fBHgwdjB0oCygKoYobGRhcDovL2Rpci5zaWdudHJ1c3QuZGUvbz1TaWdu" + + "dHJ1c3QsYz1kZaJEpEIwQDEdMBsGA1UEAxMUQ1JMU2lnblNpZ250cnVzdDE6" + + "UE4xEjAQBgNVBAoTCVNpZ250cnVzdDELMAkGA1UEBhMCREUwYgYIKwYBBQUH" + + "AQEEVjBUMFIGCCsGAQUFBzABhkZodHRwOi8vZGlyLnNpZ250cnVzdC5kZS9T" + + "aWdudHJ1c3QvT0NTUC9zZXJ2bGV0L2h0dHBHYXRld2F5LlBvc3RIYW5kbGVy" + + "MBgGCCsGAQUFBwEDBAwwCjAIBgYEAI5GAQEwDgYHAoIGAQoMAAQDAQH/MA0G" + + "CSqGSIb3DQEBBQUAA4GBAHn1m3GcoyD5GBkKUY/OdtD6Sj38LYqYCF+qDbJR" + + "6pqUBjY2wsvXepUppEler+stH8mwpDDSJXrJyuzf7xroDs4dkLl+Rs2x+2tg" + + "BjU+ABkBDMsym2WpwgA8LCdymmXmjdv9tULxY+ec2pjSEzql6nEZNEfrU8nt" + + "ZCSCavgqW4TtMYIBejCCAXYCAQEwUTBLMQswCQYDVQQGEwJERTESMBAGA1UE" + + "ChQJU2lnbnRydXN0MSgwDAYHAoIGAQoHFBMBMTAYBgNVBAMUEUNBIFNJR05U" + + "UlVTVCAxOlBOAgJsxzAJBgUrDgMCGgUAoIGAMBgGCSqGSIb3DQEJAzELBgkq" + + "hkiG9w0BBwEwIwYJKoZIhvcNAQkEMRYEFIYfhPoyfGzkLWWSSLjaHb4HQmaK" + + "MBwGCSqGSIb3DQEJBTEPFw0wNTAzMjQwNzM4MzVaMCEGBSskCAYFMRgWFi92" + + "YXIvZmlsZXMvdG1wXzEvdGVzdDEwDQYJKoZIhvcNAQEFBQAEgYA2IvA8lhVz" + + "VD5e/itUxbFboKxeKnqJ5n/KuO/uBCl1N14+7Z2vtw1sfkIG+bJdp3OY2Cmn" + + "mrQcwsN99Vjal4cXVj8t+DJzFG9tK9dSLvD3q9zT/GQ0kJXfimLVwCa4NaSf" + + "Qsu4xtG0Rav6bCcnzabAkKuNNvKtH8amSRzk870DBg=="); + + public static byte[] xtraCounterSig = Base64.decode( + "MIIR/AYJKoZIhvcNAQcCoIIR7TCCEekCAQExCzAJBgUrDgMCGgUAMBoGCSqG" + + "SIb3DQEHAaANBAtIZWxsbyB3b3JsZKCCDnkwggTPMIIDt6ADAgECAgRDnYD3" + + "MA0GCSqGSIb3DQEBBQUAMFgxCzAJBgNVBAYTAklUMRowGAYDVQQKExFJbi5U" + + "ZS5TLkEuIFMucC5BLjEtMCsGA1UEAxMkSW4uVGUuUy5BLiAtIENlcnRpZmlj" + + "YXRpb24gQXV0aG9yaXR5MB4XDTA4MDkxMjExNDMxMloXDTEwMDkxMjExNDMx" + + "MlowgdgxCzAJBgNVBAYTAklUMSIwIAYDVQQKDBlJbnRlc2EgUy5wLkEuLzA1" + + "MjYyODkwMDE0MSowKAYDVQQLDCFCdXNpbmVzcyBDb2xsYWJvcmF0aW9uICYg" + + "U2VjdXJpdHkxHjAcBgNVBAMMFU1BU1NJTUlMSUFOTyBaSUNDQVJESTERMA8G" + + "A1UEBAwIWklDQ0FSREkxFTATBgNVBCoMDE1BU1NJTUlMSUFOTzEcMBoGA1UE" + + "BRMTSVQ6WkNDTVNNNzZIMTRMMjE5WTERMA8GA1UELhMIMDAwMDI1ODUwgaAw" + + "DQYJKoZIhvcNAQEBBQADgY4AMIGKAoGBALeJTjmyFgx1SIP6c2AuB/kuyHo5" + + "j/prKELTALsFDimre/Hxr3wOSet1TdQfFzU8Lu+EJqgfV9cV+cI1yeH1rZs7" + + "lei7L3tX/VR565IywnguX5xwvteASgWZr537Fkws50bvTEMyYOj1Tf3FZvZU" + + "z4n4OD39KI4mfR9i1eEVIxR3AgQAizpNo4IBoTCCAZ0wHQYDVR0RBBYwFIES" + + "emljY2FyZGlAaW50ZXNhLml0MC8GCCsGAQUFBwEDBCMwITAIBgYEAI5GAQEw" + + "CwYGBACORgEDAgEUMAgGBgQAjkYBBDBZBgNVHSAEUjBQME4GBgQAizABATBE" + + "MEIGCCsGAQUFBwIBFjZodHRwOi8vZS10cnVzdGNvbS5pbnRlc2EuaXQvY2Ff" + + "cHViYmxpY2EvQ1BTX0lOVEVTQS5odG0wDgYDVR0PAQH/BAQDAgZAMIGDBgNV" + + "HSMEfDB6gBQZCQOW0bjFWBt+EORuxPagEgkQqKFcpFowWDELMAkGA1UEBhMC" + + "SVQxGjAYBgNVBAoTEUluLlRlLlMuQS4gUy5wLkEuMS0wKwYDVQQDEyRJbi5U" + + "ZS5TLkEuIC0gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHmCBDzRARMwOwYDVR0f" + + "BDQwMjAwoC6gLIYqaHR0cDovL2UtdHJ1c3Rjb20uaW50ZXNhLml0L0NSTC9J" + + "TlRFU0EuY3JsMB0GA1UdDgQWBBTf5ItL8KmQh541Dxt7YxcWI1254TANBgkq" + + "hkiG9w0BAQUFAAOCAQEAgW+uL1CVWQepbC/wfCmR6PN37Sueb4xiKQj2mTD5" + + "UZ5KQjpivy/Hbuf0NrfKNiDEhAvoHSPC31ebGiKuTMFNyZPHfPEUnyYGSxea" + + "2w837aXJFr6utPNQGBRi89kH90sZDlXtOSrZI+AzJJn5QK3F9gjcayU2NZXQ" + + "MJgRwYmFyn2w4jtox+CwXPQ9E5XgxiMZ4WDL03cWVXDLX00EOJwnDDMUNTRI" + + "m9Zv+4SKTNlfFbi9UTBqWBySkDzAelsfB2U61oqc2h1xKmCtkGMmN9iZT+Qz" + + "ZC/vaaT+hLEBFGAH2gwFrYc4/jTBKyBYeU1vsAxsibIoTs1Apgl6MH75qPDL" + + "BzCCBM8wggO3oAMCAQICBEOdgPcwDQYJKoZIhvcNAQEFBQAwWDELMAkGA1UE" + + "BhMCSVQxGjAYBgNVBAoTEUluLlRlLlMuQS4gUy5wLkEuMS0wKwYDVQQDEyRJ" + + "bi5UZS5TLkEuIC0gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMDgwOTEy" + + "MTE0MzEyWhcNMTAwOTEyMTE0MzEyWjCB2DELMAkGA1UEBhMCSVQxIjAgBgNV" + + "BAoMGUludGVzYSBTLnAuQS4vMDUyNjI4OTAwMTQxKjAoBgNVBAsMIUJ1c2lu" + + "ZXNzIENvbGxhYm9yYXRpb24gJiBTZWN1cml0eTEeMBwGA1UEAwwVTUFTU0lN" + + "SUxJQU5PIFpJQ0NBUkRJMREwDwYDVQQEDAhaSUNDQVJESTEVMBMGA1UEKgwM" + + "TUFTU0lNSUxJQU5PMRwwGgYDVQQFExNJVDpaQ0NNU003NkgxNEwyMTlZMREw" + + "DwYDVQQuEwgwMDAwMjU4NTCBoDANBgkqhkiG9w0BAQEFAAOBjgAwgYoCgYEA" + + "t4lOObIWDHVIg/pzYC4H+S7IejmP+msoQtMAuwUOKat78fGvfA5J63VN1B8X" + + "NTwu74QmqB9X1xX5wjXJ4fWtmzuV6Lsve1f9VHnrkjLCeC5fnHC+14BKBZmv" + + "nfsWTCznRu9MQzJg6PVN/cVm9lTPifg4Pf0ojiZ9H2LV4RUjFHcCBACLOk2j" + + "ggGhMIIBnTAdBgNVHREEFjAUgRJ6aWNjYXJkaUBpbnRlc2EuaXQwLwYIKwYB" + + "BQUHAQMEIzAhMAgGBgQAjkYBATALBgYEAI5GAQMCARQwCAYGBACORgEEMFkG" + + "A1UdIARSMFAwTgYGBACLMAEBMEQwQgYIKwYBBQUHAgEWNmh0dHA6Ly9lLXRy" + + "dXN0Y29tLmludGVzYS5pdC9jYV9wdWJibGljYS9DUFNfSU5URVNBLmh0bTAO" + + "BgNVHQ8BAf8EBAMCBkAwgYMGA1UdIwR8MHqAFBkJA5bRuMVYG34Q5G7E9qAS" + + "CRCooVykWjBYMQswCQYDVQQGEwJJVDEaMBgGA1UEChMRSW4uVGUuUy5BLiBT" + + "LnAuQS4xLTArBgNVBAMTJEluLlRlLlMuQS4gLSBDZXJ0aWZpY2F0aW9uIEF1" + + "dGhvcml0eYIEPNEBEzA7BgNVHR8ENDAyMDCgLqAshipodHRwOi8vZS10cnVz" + + "dGNvbS5pbnRlc2EuaXQvQ1JML0lOVEVTQS5jcmwwHQYDVR0OBBYEFN/ki0vw" + + "qZCHnjUPG3tjFxYjXbnhMA0GCSqGSIb3DQEBBQUAA4IBAQCBb64vUJVZB6ls" + + "L/B8KZHo83ftK55vjGIpCPaZMPlRnkpCOmK/L8du5/Q2t8o2IMSEC+gdI8Lf" + + "V5saIq5MwU3Jk8d88RSfJgZLF5rbDzftpckWvq6081AYFGLz2Qf3SxkOVe05" + + "Ktkj4DMkmflArcX2CNxrJTY1ldAwmBHBiYXKfbDiO2jH4LBc9D0TleDGIxnh" + + "YMvTdxZVcMtfTQQ4nCcMMxQ1NEib1m/7hIpM2V8VuL1RMGpYHJKQPMB6Wx8H" + + "ZTrWipzaHXEqYK2QYyY32JlP5DNkL+9ppP6EsQEUYAfaDAWthzj+NMErIFh5" + + "TW+wDGyJsihOzUCmCXowfvmo8MsHMIIEzzCCA7egAwIBAgIEQ52A9zANBgkq" + + "hkiG9w0BAQUFADBYMQswCQYDVQQGEwJJVDEaMBgGA1UEChMRSW4uVGUuUy5B" + + "LiBTLnAuQS4xLTArBgNVBAMTJEluLlRlLlMuQS4gLSBDZXJ0aWZpY2F0aW9u" + + "IEF1dGhvcml0eTAeFw0wODA5MTIxMTQzMTJaFw0xMDA5MTIxMTQzMTJaMIHY" + + "MQswCQYDVQQGEwJJVDEiMCAGA1UECgwZSW50ZXNhIFMucC5BLi8wNTI2Mjg5" + + "MDAxNDEqMCgGA1UECwwhQnVzaW5lc3MgQ29sbGFib3JhdGlvbiAmIFNlY3Vy" + + "aXR5MR4wHAYDVQQDDBVNQVNTSU1JTElBTk8gWklDQ0FSREkxETAPBgNVBAQM" + + "CFpJQ0NBUkRJMRUwEwYDVQQqDAxNQVNTSU1JTElBTk8xHDAaBgNVBAUTE0lU" + + "OlpDQ01TTTc2SDE0TDIxOVkxETAPBgNVBC4TCDAwMDAyNTg1MIGgMA0GCSqG" + + "SIb3DQEBAQUAA4GOADCBigKBgQC3iU45shYMdUiD+nNgLgf5Lsh6OY/6ayhC" + + "0wC7BQ4pq3vx8a98DknrdU3UHxc1PC7vhCaoH1fXFfnCNcnh9a2bO5Xouy97" + + "V/1UeeuSMsJ4Ll+ccL7XgEoFma+d+xZMLOdG70xDMmDo9U39xWb2VM+J+Dg9" + + "/SiOJn0fYtXhFSMUdwIEAIs6TaOCAaEwggGdMB0GA1UdEQQWMBSBEnppY2Nh" + + "cmRpQGludGVzYS5pdDAvBggrBgEFBQcBAwQjMCEwCAYGBACORgEBMAsGBgQA" + + "jkYBAwIBFDAIBgYEAI5GAQQwWQYDVR0gBFIwUDBOBgYEAIswAQEwRDBCBggr" + + "BgEFBQcCARY2aHR0cDovL2UtdHJ1c3Rjb20uaW50ZXNhLml0L2NhX3B1YmJs" + + "aWNhL0NQU19JTlRFU0EuaHRtMA4GA1UdDwEB/wQEAwIGQDCBgwYDVR0jBHww" + + "eoAUGQkDltG4xVgbfhDkbsT2oBIJEKihXKRaMFgxCzAJBgNVBAYTAklUMRow" + + "GAYDVQQKExFJbi5UZS5TLkEuIFMucC5BLjEtMCsGA1UEAxMkSW4uVGUuUy5B" + + "LiAtIENlcnRpZmljYXRpb24gQXV0aG9yaXR5ggQ80QETMDsGA1UdHwQ0MDIw" + + "MKAuoCyGKmh0dHA6Ly9lLXRydXN0Y29tLmludGVzYS5pdC9DUkwvSU5URVNB" + + "LmNybDAdBgNVHQ4EFgQU3+SLS/CpkIeeNQ8be2MXFiNdueEwDQYJKoZIhvcN" + + "AQEFBQADggEBAIFvri9QlVkHqWwv8Hwpkejzd+0rnm+MYikI9pkw+VGeSkI6" + + "Yr8vx27n9Da3yjYgxIQL6B0jwt9XmxoirkzBTcmTx3zxFJ8mBksXmtsPN+2l" + + "yRa+rrTzUBgUYvPZB/dLGQ5V7Tkq2SPgMySZ+UCtxfYI3GslNjWV0DCYEcGJ" + + "hcp9sOI7aMfgsFz0PROV4MYjGeFgy9N3FlVwy19NBDicJwwzFDU0SJvWb/uE" + + "ikzZXxW4vVEwalgckpA8wHpbHwdlOtaKnNodcSpgrZBjJjfYmU/kM2Qv72mk" + + "/oSxARRgB9oMBa2HOP40wSsgWHlNb7AMbImyKE7NQKYJejB++ajwywcxggM8" + + "MIIDOAIBATBgMFgxCzAJBgNVBAYTAklUMRowGAYDVQQKExFJbi5UZS5TLkEu" + + "IFMucC5BLjEtMCsGA1UEAxMkSW4uVGUuUy5BLiAtIENlcnRpZmljYXRpb24g" + + "QXV0aG9yaXR5AgRDnYD3MAkGBSsOAwIaBQAwDQYJKoZIhvcNAQEBBQAEgYB+" + + "lH2cwLqc91mP8prvgSV+RRzk13dJdZvdoVjgQoFrPhBiZCNIEoHvIhMMA/sM" + + "X6euSRZk7EjD24FasCEGYyd0mJVLEy6TSPmuW+wWz/28w3a6IWXBGrbb/ild" + + "/CJMkPgLPGgOVD1WDwiNKwfasiQSFtySf5DPn3jFevdLeMmEY6GCAjIwggEV" + + "BgkqhkiG9w0BCQYxggEGMIIBAgIBATBgMFgxCzAJBgNVBAYTAklUMRowGAYD" + + "VQQKExFJbi5UZS5TLkEuIFMucC5BLjEtMCsGA1UEAxMkSW4uVGUuUy5BLiAt" + + "IENlcnRpZmljYXRpb24gQXV0aG9yaXR5AgRDnYD3MAkGBSsOAwIaBQAwDQYJ" + + "KoZIhvcNAQEBBQAEgYBHlOULfT5GDigIvxP0qZOy8VbpntmzaPF55VV4buKV" + + "35J+uHp98gXKp0LrHM69V5IRKuyuQzHHFBqsXxsRI9o6KoOfgliD9Xc+BeMg" + + "dKzQhBhBYoFREq8hQM0nSbqDNHYAQyNHMzUA/ZQUO5dlFuH8Dw3iDYAhNtfd" + + "PrlchKJthDCCARUGCSqGSIb3DQEJBjGCAQYwggECAgEBMGAwWDELMAkGA1UE" + + "BhMCSVQxGjAYBgNVBAoTEUluLlRlLlMuQS4gUy5wLkEuMS0wKwYDVQQDEyRJ" + + "bi5UZS5TLkEuIC0gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkCBEOdgPcwCQYF" + + "Kw4DAhoFADANBgkqhkiG9w0BAQEFAASBgEeU5Qt9PkYOKAi/E/Spk7LxVume" + + "2bNo8XnlVXhu4pXfkn64en3yBcqnQusczr1XkhEq7K5DMccUGqxfGxEj2joq" + + "g5+CWIP1dz4F4yB0rNCEGEFigVESryFAzSdJuoM0dgBDI0czNQD9lBQ7l2UW" + + "4fwPDeINgCE2190+uVyEom2E"); + + byte[] noSignedAttrSample2 = Base64.decode( + "MIIIlAYJKoZIhvcNAQcCoIIIhTCCCIECAQExCzAJBgUrDgMCGgUAMAsGCSqG" + + "SIb3DQEHAaCCB3UwggOtMIIDa6ADAgECAgEzMAsGByqGSM44BAMFADCBkDEL" + + "MAkGA1UEBhMCVVMxCzAJBgNVBAgTAkNBMRIwEAYDVQQHEwlQYWxvIEFsdG8x" + + "HTAbBgNVBAoTFFN1biBNaWNyb3N5c3RlbXMgSW5jMSMwIQYDVQQLExpKYXZh" + + "IFNvZnR3YXJlIENvZGUgU2lnbmluZzEcMBoGA1UEAxMTSkNFIENvZGUgU2ln" + + "bmluZyBDQTAeFw0wMTA1MjkxNjQ3MTFaFw0wNjA1MjgxNjQ3MTFaMG4xHTAb" + + "BgNVBAoTFFN1biBNaWNyb3N5c3RlbXMgSW5jMSMwIQYDVQQLExpKYXZhIFNv" + + "ZnR3YXJlIENvZGUgU2lnbmluZzEoMCYGA1UEAxMfVGhlIExlZ2lvbiBvZiB0" + + "aGUgQm91bmN5IENhc3RsZTCCAbcwggEsBgcqhkjOOAQBMIIBHwKBgQD9f1OB" + + "HXUSKVLfSpwu7OTn9hG3UjzvRADDHj+AtlEmaUVdQCJR+1k9jVj6v8X1ujD2" + + "y5tVbNeBO4AdNG/yZmC3a5lQpaSfn+gEexAiwk+7qdf+t8Yb+DtX58aophUP" + + "BPuD9tPFHsMCNVQTWhaRMvZ1864rYdcq7/IiAxmd0UgBxwIVAJdgUI8VIwvM" + + "spK5gqLrhAvwWBz1AoGBAPfhoIXWmz3ey7yrXDa4V7l5lK+7+jrqgvlXTAs9" + + "B4JnUVlXjrrUWU/mcQcQgYC0SRZxI+hMKBYTt88JMozIpuE8FnqLVHyNKOCj" + + "rh4rs6Z1kW6jfwv6ITVi8ftiegEkO8yk8b6oUZCJqIPf4VrlnwaSi2ZegHtV" + + "JWQBTDv+z0kqA4GEAAKBgBWry/FCAZ6miyy39+ftsa+h9lxoL+JtV0MJcUyQ" + + "E4VAhpAwWb8vyjba9AwOylYQTktHX5sAkFvjBiU0LOYDbFSTVZSHMRJgfjxB" + + "SHtICjOEvr1BJrrOrdzqdxcOUge5n7El124BCrv91x5Ol8UTwtiO9LrRXF/d" + + "SyK+RT5n1klRo3YwdDARBglghkgBhvhCAQEEBAMCAIcwDgYDVR0PAQH/BAQD" + + "AgHGMB0GA1UdDgQWBBQwMY4NRcco1AO3w1YsokfDLVseEjAPBgNVHRMBAf8E" + + "BTADAQH/MB8GA1UdIwQYMBaAFGXi9IbJ007wkU5Yomr12HhamsGmMAsGByqG" + + "SM44BAMFAAMvADAsAhRmigTu6QV0sTfEkVljgij/hhdVfAIUQZvMxAnIHc30" + + "y/u0C1T5UEG9glUwggPAMIIDfqADAgECAgEQMAsGByqGSM44BAMFADCBkDEL" + + "MAkGA1UEBhMCVVMxCzAJBgNVBAgTAkNBMRIwEAYDVQQHEwlQYWxvIEFsdG8x" + + "HTAbBgNVBAoTFFN1biBNaWNyb3N5c3RlbXMgSW5jMSMwIQYDVQQLExpKYXZh" + + "IFNvZnR3YXJlIENvZGUgU2lnbmluZzEcMBoGA1UEAxMTSkNFIENvZGUgU2ln" + + "bmluZyBDQTAeFw0wMTA0MjUwNzAwMDBaFw0yMDA0MjUwNzAwMDBaMIGQMQsw" + + "CQYDVQQGEwJVUzELMAkGA1UECBMCQ0ExEjAQBgNVBAcTCVBhbG8gQWx0bzEd" + + "MBsGA1UEChMUU3VuIE1pY3Jvc3lzdGVtcyBJbmMxIzAhBgNVBAsTGkphdmEg" + + "U29mdHdhcmUgQ29kZSBTaWduaW5nMRwwGgYDVQQDExNKQ0UgQ29kZSBTaWdu" + + "aW5nIENBMIIBtzCCASwGByqGSM44BAEwggEfAoGBAOuvNwQeylEeaV2w8o/2" + + "tUkfxqSZBdcpv3S3avUZ2B7kG/gKAZqY/3Cr4kpWhmxTs/zhyIGMMfDE87CL" + + "5nAG7PdpaNuDTHIpiSk2F1w7SgegIAIqRpdRHXDICBgLzgxum3b3BePn+9Nh" + + "eeFgmiSNBpWDPFEg4TDPOFeCphpyDc7TAhUAhCVF4bq5qWKreehbMLiJaxv/" + + "e3UCgYEAq8l0e3Tv7kK1alNNO92QBnJokQ8LpCl2LlU71a5NZVx+KjoEpmem" + + "0HGqpde34sFyDaTRqh6SVEwgAAmisAlBGTMAssNcrkL4sYvKfJbYEH83RFuq" + + "zHjI13J2N2tAmahVZvqoAx6LShECactMuCUGHKB30sms0j3pChD6dnC3+9wD" + + "gYQAAoGALQmYXKy4nMeZfu4gGSo0kPnXq6uu3WtylQ1m+O8nj0Sy7ShEx/6v" + + "sKYnbwBnRYJbB6hWVjvSKVFhXmk51y50dxLPGUr1LcjLcmHETm/6R0M/FLv6" + + "vBhmKMLZZot6LS/CYJJLFP5YPiF/aGK+bEhJ+aBLXoWdGRD5FUVRG3HU9wuj" + + "ZjBkMBEGCWCGSAGG+EIBAQQEAwIABzAPBgNVHRMBAf8EBTADAQH/MB8GA1Ud" + + "IwQYMBaAFGXi9IbJ007wkU5Yomr12HhamsGmMB0GA1UdDgQWBBRl4vSGydNO" + + "8JFOWKJq9dh4WprBpjALBgcqhkjOOAQDBQADLwAwLAIUKvfPPJdd+Xi2CNdB" + + "tNkNRUzktJwCFEXNdWkOIfod1rMpsun3Mx0z/fxJMYHoMIHlAgEBMIGWMIGQ" + + "MQswCQYDVQQGEwJVUzELMAkGA1UECBMCQ0ExEjAQBgNVBAcTCVBhbG8gQWx0" + + "bzEdMBsGA1UEChMUU3VuIE1pY3Jvc3lzdGVtcyBJbmMxIzAhBgNVBAsTGkph" + + "dmEgU29mdHdhcmUgQ29kZSBTaWduaW5nMRwwGgYDVQQDExNKQ0UgQ29kZSBT" + + "aWduaW5nIENBAgEzMAkGBSsOAwIaBQAwCwYHKoZIzjgEAQUABC8wLQIVAIGV" + + "khm+kbV4a/+EP45PHcq0hIViAhR4M9os6IrJnoEDS3Y3l7O6zrSosA=="); + + /* + * + * INFRASTRUCTURE + * + */ + + public BcSignedDataTest(String name) + { + super(name); + } + + public static void main(String args[]) + { + + junit.textui.TestRunner.run(BcSignedDataTest.class); + } + + public static Test suite() + throws Exception + { + init(); + + return new CMSTestSetup(new TestSuite(BcSignedDataTest.class)); + } + + private static void init() + throws Exception + { + if (!_initialised) + { + _initialised = true; + + if (Security.getProvider(BC) == null) + { + Security.addProvider(new BouncyCastleProvider()); + } + + _origDN = "O=Bouncy Castle, C=AU"; + _origKP = CMSTestUtil.makeKeyPair(); + _origCert = CMSTestUtil.makeCertificate(_origKP, _origDN, _origKP, _origDN); + + _signDN = "CN=Bob, OU=Sales, O=Bouncy Castle, C=AU"; + _signKP = CMSTestUtil.makeKeyPair(); + _signCert = CMSTestUtil.makeCertificate(_signKP, _signDN, _origKP, _origDN); + + _signDsaKP = CMSTestUtil.makeDsaKeyPair(); + _signDsaCert = CMSTestUtil.makeCertificate(_signDsaKP, _signDN, _origKP, _origDN); + + _signEcDsaKP = CMSTestUtil.makeEcDsaKeyPair(); + _signEcDsaCert = CMSTestUtil.makeCertificate(_signEcDsaKP, _signDN, _origKP, _origDN); + + _reciDN = "CN=Doug, OU=Sales, O=Bouncy Castle, C=AU"; + _reciKP = CMSTestUtil.makeKeyPair(); + _reciCert = CMSTestUtil.makeCertificate(_reciKP, _reciDN, _signKP, _signDN); + + _signCrl = CMSTestUtil.makeCrl(_signKP); + } + } + + private void verifyRSASignatures(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(); + + assertEquals(true, signer.verify(new BcRSASignerInfoVerifierBuilder(new DefaultCMSSignatureAlgorithmNameGenerator(), new DefaultSignatureAlgorithmIdentifierFinder(), new DefaultDigestAlgorithmIdentifierFinder(), new BcDigestCalculatorProvider()).build(cert))); + + if (contentDigest != null) + { + assertTrue(MessageDigest.isEqual(contentDigest, signer.getContentDigest())); + } + } + } + + private void verifySignatures(CMSSignedData s, byte[] contentDigest) + throws Exception + { + Store certStore = s.getCertificates(); + Store crlStore = s.getCRLs(); + 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(); + + assertEquals(true, signer.verify(new JcaSimpleSignerInfoVerifierBuilder().setProvider(BC).build(cert))); + + if (contentDigest != null) + { + assertTrue(MessageDigest.isEqual(contentDigest, signer.getContentDigest())); + } + } + + Collection certColl = certStore.getMatches(null); + Collection crlColl = crlStore.getMatches(null); + + assertEquals(certColl.size(), s.getCertificates().getMatches(null).size()); + assertEquals(crlColl.size(), s.getCRLs().getMatches(null).size()); + } + + private void verifySignatures(CMSSignedData s) + throws Exception + { + verifySignatures(s, null); + } + + public void testDetachedVerification() + throws Exception + { + byte[] data = "Hello World!".getBytes(); + List certList = new ArrayList(); + CMSTypedData msg = new CMSProcessableByteArray(data); + + certList.add(_origCert); + certList.add(_signCert); + + Store certs = new JcaCertStore(certList); + + CMSSignedDataGenerator gen = new CMSSignedDataGenerator(); + + DigestCalculatorProvider digProvider = new JcaDigestCalculatorProviderBuilder().setProvider(BC).build(); + JcaSignerInfoGeneratorBuilder signerInfoGeneratorBuilder = new JcaSignerInfoGeneratorBuilder(digProvider); + ContentSigner sha1Signer = new JcaContentSignerBuilder("SHA1withRSA").setProvider(BC).build(_origKP.getPrivate()); + ContentSigner md5Signer = new JcaContentSignerBuilder("MD5withRSA").setProvider(BC).build(_origKP.getPrivate()); + + gen.addSignerInfoGenerator(signerInfoGeneratorBuilder.build(sha1Signer, _origCert)); + gen.addSignerInfoGenerator(signerInfoGeneratorBuilder.build(md5Signer, _origCert)); + + gen.addCertificates(certs); + + CMSSignedData s = gen.generate(msg); + + MessageDigest sha1 = MessageDigest.getInstance("SHA1", BC); + MessageDigest md5 = MessageDigest.getInstance("MD5", BC); + Map hashes = new HashMap(); + byte[] sha1Hash = sha1.digest(data); + byte[] md5Hash = md5.digest(data); + + hashes.put(CMSAlgorithm.SHA1, sha1Hash); + hashes.put(CMSAlgorithm.MD5, md5Hash); + + s = new CMSSignedData(hashes, s.getEncoded()); + + verifySignatures(s, null); + } + + public void testDetachedVerificationWithBufferingContentSigner() + throws Exception + { + byte[] data = "Hello World!".getBytes(); + List certList = new ArrayList(); + CMSTypedData msg = new CMSProcessableByteArray(data); + + certList.add(_origCert); + certList.add(_signCert); + + Store certs = new JcaCertStore(certList); + + CMSSignedDataGenerator gen = new CMSSignedDataGenerator(); + + DigestCalculatorProvider digProvider = new JcaDigestCalculatorProviderBuilder().setProvider(BC).build(); + JcaSignerInfoGeneratorBuilder signerInfoGeneratorBuilder = new JcaSignerInfoGeneratorBuilder(digProvider); + ContentSigner sha1Signer = new JcaContentSignerBuilder("SHA1withRSA").setProvider(BC).build(_origKP.getPrivate()); + ContentSigner md5Signer = new JcaContentSignerBuilder("MD5withRSA").setProvider(BC).build(_origKP.getPrivate()); + + gen.addSignerInfoGenerator(signerInfoGeneratorBuilder.build(new BufferingContentSigner(sha1Signer), _origCert)); + gen.addSignerInfoGenerator(signerInfoGeneratorBuilder.build(new BufferingContentSigner(md5Signer), _origCert)); + + gen.addCertificates(certs); + + CMSSignedData s = gen.generate(msg); + + MessageDigest sha1 = MessageDigest.getInstance("SHA1", BC); + MessageDigest md5 = MessageDigest.getInstance("MD5", BC); + Map hashes = new HashMap(); + byte[] sha1Hash = sha1.digest(data); + byte[] md5Hash = md5.digest(data); + + hashes.put(CMSAlgorithm.SHA1, sha1Hash); + hashes.put(CMSAlgorithm.MD5, md5Hash); + + s = new CMSSignedData(hashes, s.getEncoded()); + + verifySignatures(s, null); + } + + public void testSHA1AndMD5WithRSAEncapsulatedRepeated() + throws Exception + { + List certList = new ArrayList(); + CMSTypedData msg = new CMSProcessableByteArray("Hello World!".getBytes()); + + certList.add(_origCert); + certList.add(_signCert); + + Store certs = new JcaCertStore(certList); + + CMSSignedDataGenerator gen = new CMSSignedDataGenerator(); + + DigestCalculatorProvider digCalcProv = new JcaDigestCalculatorProviderBuilder().setProvider(BC).build(); + + gen.addSignerInfoGenerator(new JcaSignerInfoGeneratorBuilder(digCalcProv).build(new JcaContentSignerBuilder("SHA1withRSA").setProvider(BC).build(_origKP.getPrivate()), _origCert)); + + gen.addSignerInfoGenerator(new JcaSignerInfoGeneratorBuilder(digCalcProv).build(new JcaContentSignerBuilder("MD5withRSA").setProvider(BC).build(_origKP.getPrivate()), _origCert)); + + gen.addCertificates(certs); + + CMSSignedData s = gen.generate(msg, true); + + ByteArrayInputStream bIn = new ByteArrayInputStream(s.getEncoded()); + ASN1InputStream aIn = new ASN1InputStream(bIn); + + s = new CMSSignedData(ContentInfo.getInstance(aIn.readObject())); + + certs = s.getCertificates(); + + SignerInformationStore signers = s.getSignerInfos(); + + assertEquals(2, signers.size()); + + Collection c = signers.getSigners(); + Iterator it = c.iterator(); + SignerId sid = null; + + while (it.hasNext()) + { + SignerInformation signer = (SignerInformation)it.next(); + Collection certCollection = certs.getMatches(signer.getSID()); + + Iterator certIt = certCollection.iterator(); + X509CertificateHolder cert = (X509CertificateHolder)certIt.next(); + + sid = signer.getSID(); + + assertEquals(true, signer.verify(new JcaSimpleSignerInfoVerifierBuilder().setProvider(BC).build(cert))); + + // + // check content digest + // + + byte[] contentDigest = (byte[])gen.getGeneratedDigests().get(signer.getDigestAlgOID()); + + AttributeTable table = signer.getSignedAttributes(); + Attribute hash = table.get(CMSAttributes.messageDigest); + + assertTrue(MessageDigest.isEqual(contentDigest, ((ASN1OctetString)hash.getAttrValues().getObjectAt(0)).getOctets())); + } + + c = signers.getSigners(sid); + + assertEquals(2, c.size()); + + + // + // try using existing signer + // + + gen = new CMSSignedDataGenerator(); + + gen.addSigners(s.getSignerInfos()); + + gen.addCertificates(s.getCertificates()); + + s = gen.generate(msg, true); + + bIn = new ByteArrayInputStream(s.getEncoded()); + aIn = new ASN1InputStream(bIn); + + s = new CMSSignedData(ContentInfo.getInstance(aIn.readObject())); + + certs = s.getCertificates(); + + signers = s.getSignerInfos(); + c = signers.getSigners(); + it = c.iterator(); + + assertEquals(2, c.size()); + + while (it.hasNext()) + { + SignerInformation signer = (SignerInformation)it.next(); + Collection certCollection = certs.getMatches(signer.getSID()); + + Iterator certIt = certCollection.iterator(); + X509CertificateHolder cert = (X509CertificateHolder)certIt.next(); + + assertEquals(true, signer.verify(new JcaSimpleSignerInfoVerifierBuilder().setProvider(BC).build(cert))); + } + + checkSignerStoreReplacement(s, signers); + } + + public void testSHA1WithRSANoAttributes() + throws Exception + { + List certList = new ArrayList(); + CMSTypedData msg = new CMSProcessableByteArray("Hello world!".getBytes()); + + certList.add(_origCert); + certList.add(_signCert); + + Store certs = new JcaCertStore(certList); + + CMSSignedDataGenerator gen = new CMSSignedDataGenerator(); + ContentSigner sha1Signer = new JcaContentSignerBuilder("SHA1withRSA").setProvider(BC).build(_origKP.getPrivate()); + + JcaSignerInfoGeneratorBuilder builder = new JcaSignerInfoGeneratorBuilder(new JcaDigestCalculatorProviderBuilder().setProvider(BC).build()); + + builder.setDirectSignature(true); + + gen.addSignerInfoGenerator(builder.build(sha1Signer, _origCert)); + + gen.addCertificates(certs); + + CMSSignedData s = gen.generate(msg, false); + + // + // compute expected content digest + // + MessageDigest md = MessageDigest.getInstance("SHA1", BC); + + verifySignatures(s, md.digest("Hello world!".getBytes())); + } + + public void testSHA1WithRSANoAttributesSimple() + throws Exception + { + List certList = new ArrayList(); + CMSTypedData msg = new CMSProcessableByteArray("Hello world!".getBytes()); + + certList.add(_origCert); + certList.add(_signCert); + + Store certs = new JcaCertStore(certList); + + CMSSignedDataGenerator gen = new CMSSignedDataGenerator(); + + JcaSimpleSignerInfoGeneratorBuilder builder = new JcaSimpleSignerInfoGeneratorBuilder().setProvider(BC).setDirectSignature(true); + + gen.addSignerInfoGenerator(builder.build("SHA1withRSA", _origKP.getPrivate(), _origCert)); + + gen.addCertificates(certs); + + CMSSignedData s = gen.generate(msg, false); + + // + // compute expected content digest + // + MessageDigest md = MessageDigest.getInstance("SHA1", BC); + + verifySignatures(s, md.digest("Hello world!".getBytes())); + } + + public void testSHA1WithRSAViaConfig() + throws Exception + { + List certList = new ArrayList(); + CMSTypedData msg = new CMSProcessableByteArray("Hello world!".getBytes()); + + certList.add(_origCert); + certList.add(_signCert); + + Store certs = new JcaCertStore(certList); + + // set some bogus mappings. + TestCMSSignatureAlgorithmNameGenerator sigAlgNameGen = new TestCMSSignatureAlgorithmNameGenerator(); + + sigAlgNameGen.setEncryptionAlgorithmMapping(PKCSObjectIdentifiers.rsaEncryption, "XXXX"); + sigAlgNameGen.setDigestAlgorithmMapping(OIWObjectIdentifiers.idSHA1, "YYYY"); + + CMSSignedDataGenerator gen = new CMSSignedDataGenerator(); + + ContentSigner sha1Signer = new JcaContentSignerBuilder("SHA1withRSA").setProvider(BC).build(_origKP.getPrivate()); + + gen.addSignerInfoGenerator(new JcaSignerInfoGeneratorBuilder(new JcaDigestCalculatorProviderBuilder().setProvider(BC).build()).build(sha1Signer, _origCert)); + + gen.addCertificates(certs); + + CMSSignedData s; + + try + { + // try the bogus mappings + s = gen.generate(msg, false); + } + catch (CMSException e) + { + if (!e.getMessage().startsWith("no such algorithm: YYYYwithXXXX")) + { + throw e; + } + } + finally + { + // reset to the real ones + sigAlgNameGen.setEncryptionAlgorithmMapping(PKCSObjectIdentifiers.rsaEncryption, "RSA"); + sigAlgNameGen.setDigestAlgorithmMapping(OIWObjectIdentifiers.idSHA1, "SHA1"); + } + + s = gen.generate(msg, false); + + // + // compute expected content digest + // + MessageDigest md = MessageDigest.getInstance("SHA1", BC); + + verifySignatures(s, md.digest("Hello world!".getBytes())); + } + + public void testSHA1WithRSAAndAttributeTableSimple() + throws Exception + { + MessageDigest md = MessageDigest.getInstance("SHA1", BC); + List certList = new ArrayList(); + CMSTypedData msg = new CMSProcessableByteArray("Hello world!".getBytes()); + + certList.add(_origCert); + certList.add(_signCert); + + Store certs = new JcaCertStore(certList); + + CMSSignedDataGenerator gen = new CMSSignedDataGenerator(); + + Attribute attr = new Attribute(CMSAttributes.messageDigest, + new DERSet( + new DEROctetString( + md.digest("Hello world!".getBytes())))); + + ASN1EncodableVector v = new ASN1EncodableVector(); + + v.add(attr); + + SignerInfoGeneratorBuilder builder = new SignerInfoGeneratorBuilder(new BcDigestCalculatorProvider()).setSignedAttributeGenerator(new DefaultSignedAttributeTableGenerator(new AttributeTable(v))); + + AlgorithmIdentifier sha1withRSA = new DefaultSignatureAlgorithmIdentifierFinder().find("SHA1withRSA"); + gen.addSignerInfoGenerator(builder.build(new BcRSAContentSignerBuilder(sha1withRSA, new DefaultDigestAlgorithmIdentifierFinder().find(sha1withRSA)).build(PrivateKeyFactory.createKey(_origKP.getPrivate().getEncoded())), new JcaX509CertificateHolder(_origCert))); + + gen.addCertificates(certs); + + CMSSignedData s = gen.generate(new CMSAbsentContent(), false); + + // + // the signature is detached, so need to add msg before passing on + // + s = new CMSSignedData(msg, s.getEncoded()); + // + // compute expected content digest + // + + verifySignatures(s, md.digest("Hello world!".getBytes())); + verifyRSASignatures(s, md.digest("Hello world!".getBytes())); + } + + public void testSHA1WithRSAAndAttributeTable() + throws Exception + { + MessageDigest md = MessageDigest.getInstance("SHA1", BC); + List certList = new ArrayList(); + CMSTypedData msg = new CMSProcessableByteArray("Hello world!".getBytes()); + + certList.add(_origCert); + certList.add(_signCert); + + Store certs = new JcaCertStore(certList); + + CMSSignedDataGenerator gen = new CMSSignedDataGenerator(); + + Attribute attr = new Attribute(CMSAttributes.messageDigest, + new DERSet( + new DEROctetString( + md.digest("Hello world!".getBytes())))); + + ASN1EncodableVector v = new ASN1EncodableVector(); + + v.add(attr); + + JcaSignerInfoGeneratorBuilder builder = new JcaSignerInfoGeneratorBuilder(new JcaDigestCalculatorProviderBuilder().setProvider(BC).build()); + + builder.setSignedAttributeGenerator(new DefaultSignedAttributeTableGenerator(new AttributeTable(v))); + + ContentSigner sha1Signer = new JcaContentSignerBuilder("SHA1withRSA").setProvider(BC).build(_origKP.getPrivate()); + + gen.addSignerInfoGenerator(builder.build(sha1Signer, _origCert)); + + gen.addCertificates(certs); + + CMSSignedData s = gen.generate(new CMSAbsentContent(), false); + + // + // the signature is detached, so need to add msg before passing on + // + s = new CMSSignedData(msg, s.getEncoded()); + // + // compute expected content digest + // + + verifySignatures(s, md.digest("Hello world!".getBytes())); + verifyRSASignatures(s, md.digest("Hello world!".getBytes())); + } + + public void testLwSHA1WithRSAAndAttributeTable() + throws Exception + { + MessageDigest md = MessageDigest.getInstance("SHA1", BC); + List certList = new ArrayList(); + CMSTypedData msg = new CMSProcessableByteArray("Hello world!".getBytes()); + + certList.add(_origCert); + certList.add(_signCert); + + Store certs = new JcaCertStore(certList); + + CMSSignedDataGenerator gen = new CMSSignedDataGenerator(); + + Attribute attr = new Attribute(CMSAttributes.messageDigest, + new DERSet( + new DEROctetString( + md.digest("Hello world!".getBytes())))); + + ASN1EncodableVector v = new ASN1EncodableVector(); + + v.add(attr); + + AsymmetricKeyParameter privKey = PrivateKeyFactory.createKey(_origKP.getPrivate().getEncoded()); + + AlgorithmIdentifier sigAlgId = new DefaultSignatureAlgorithmIdentifierFinder().find("SHA1withRSA"); + AlgorithmIdentifier digAlgId = new DefaultDigestAlgorithmIdentifierFinder().find(sigAlgId); + + BcContentSignerBuilder contentSignerBuilder = new BcRSAContentSignerBuilder(sigAlgId, digAlgId); + + gen.addSignerInfoGenerator( + new SignerInfoGeneratorBuilder(new BcDigestCalculatorProvider()) + .setSignedAttributeGenerator(new DefaultSignedAttributeTableGenerator(new AttributeTable(v))) + .build(contentSignerBuilder.build(privKey), new JcaX509CertificateHolder(_origCert))); + + gen.addCertificates(certs); + + CMSSignedData s = gen.generate(new CMSAbsentContent(), false); + + // + // the signature is detached, so need to add msg before passing on + // + s = new CMSSignedData(msg, s.getEncoded()); + // + // compute expected content digest + // + + verifySignatures(s, md.digest("Hello world!".getBytes())); + verifyRSASignatures(s, md.digest("Hello world!".getBytes())); + } + + public void testSHA1WithRSAEncapsulated() + throws Exception + { + encapsulatedTest(_signKP, _signCert, "SHA1withRSA"); + } + + public void testSHA1WithRSAEncapsulatedSubjectKeyID() + throws Exception + { + subjectKeyIDTest(_signKP, _signCert, "SHA1withRSA"); + } + + public void testSHA1WithRSAPSS() + throws Exception + { + rsaPSSTest("SHA1withRSAandMGF1"); + } + + public void testSHA224WithRSAPSS() + throws Exception + { + rsaPSSTest("SHA224withRSAandMGF1"); + } + + public void testSHA256WithRSAPSS() + throws Exception + { + rsaPSSTest("SHA256withRSAandMGF1"); + } + + public void testSHA384WithRSAPSS() + throws Exception + { + rsaPSSTest("SHA384withRSAandMGF1"); + } + + public void testSHA224WithRSAEncapsulated() + throws Exception + { + encapsulatedTest(_signKP, _signCert, "SHA224withRSA"); + } + + public void testSHA256WithRSAEncapsulated() + throws Exception + { + encapsulatedTest(_signKP, _signCert, "SHA256withRSA"); + } + + public void testRIPEMD128WithRSAEncapsulated() + throws Exception + { + encapsulatedTest(_signKP, _signCert, "RIPEMD128withRSA"); + } + + public void testRIPEMD160WithRSAEncapsulated() + throws Exception + { + encapsulatedTest(_signKP, _signCert, "RIPEMD160withRSA"); + } + + public void testRIPEMD256WithRSAEncapsulated() + throws Exception + { + encapsulatedTest(_signKP, _signCert, "RIPEMD256withRSA"); + } + + public void testECDSAEncapsulated() + throws Exception + { + encapsulatedTest(_signEcDsaKP, _signEcDsaCert, "SHA1withECDSA"); + } + + public void testECDSAEncapsulatedSubjectKeyID() + throws Exception + { + subjectKeyIDTest(_signEcDsaKP, _signEcDsaCert, "SHA1withECDSA"); + } + + public void testECDSASHA224Encapsulated() + throws Exception + { + encapsulatedTest(_signEcDsaKP, _signEcDsaCert, "SHA224withECDSA"); + } + + public void testECDSASHA256Encapsulated() + throws Exception + { + encapsulatedTest(_signEcDsaKP, _signEcDsaCert, "SHA256withECDSA"); + } + + public void testECDSASHA384Encapsulated() + throws Exception + { + encapsulatedTest(_signEcDsaKP, _signEcDsaCert, "SHA384withECDSA"); + } + + public void testECDSASHA512Encapsulated() + throws Exception + { + encapsulatedTest(_signEcDsaKP, _signEcDsaCert, "SHA512withECDSA"); + } + + public void testECDSASHA512EncapsulatedWithKeyFactoryAsEC() + throws Exception + { + X509EncodedKeySpec pubSpec = new X509EncodedKeySpec(_signEcDsaKP.getPublic().getEncoded()); + PKCS8EncodedKeySpec privSpec = new PKCS8EncodedKeySpec(_signEcDsaKP.getPrivate().getEncoded()); + KeyFactory keyFact = KeyFactory.getInstance("EC", BC); + KeyPair kp = new KeyPair(keyFact.generatePublic(pubSpec), keyFact.generatePrivate(privSpec)); + + encapsulatedTest(kp, _signEcDsaCert, "SHA512withECDSA"); + } + + public void testDSAEncapsulated() + throws Exception + { + encapsulatedTest(_signDsaKP, _signDsaCert, "SHA1withDSA"); + } + + public void testDSAEncapsulatedSubjectKeyID() + throws Exception + { + subjectKeyIDTest(_signDsaKP, _signDsaCert, "SHA1withDSA"); + } + + public void testSHA1WithRSACounterSignature() + throws Exception + { + List certList = new ArrayList(); + List crlList = new ArrayList(); + CMSTypedData msg = new CMSProcessableByteArray("Hello World!".getBytes()); + + certList.add(_signCert); + certList.add(_origCert); + + crlList.add(_signCrl); + + Store certStore = new JcaCertStore(certList); + Store crlStore = new JcaCRLStore(crlList); + + CMSSignedDataGenerator gen = new CMSSignedDataGenerator(); + + ContentSigner sha1Signer = new JcaContentSignerBuilder("SHA1withRSA").setProvider(BC).build(_signKP.getPrivate()); + + gen.addSignerInfoGenerator(new JcaSignerInfoGeneratorBuilder(new JcaDigestCalculatorProviderBuilder().setProvider(BC).build()).build(sha1Signer, _signCert)); + + gen.addCertificates(certStore); + gen.addCRLs(crlStore); + + CMSSignedData s = gen.generate(msg, true); + SignerInformation origSigner = (SignerInformation)s.getSignerInfos().getSigners().toArray()[0]; + SignerInformationStore counterSigners1 = gen.generateCounterSigners(origSigner); + SignerInformationStore counterSigners2 = gen.generateCounterSigners(origSigner); + + SignerInformation signer1 = SignerInformation.addCounterSigners(origSigner, counterSigners1); + SignerInformation signer2 = SignerInformation.addCounterSigners(signer1, counterSigners2); + + SignerInformationStore cs = signer2.getCounterSignatures(); + Collection csSigners = cs.getSigners(); + assertEquals(2, csSigners.size()); + + Iterator it = csSigners.iterator(); + while (it.hasNext()) + { + SignerInformation cSigner = (SignerInformation)it.next(); + Collection certCollection = certStore.getMatches(cSigner.getSID()); + + Iterator certIt = certCollection.iterator(); + X509CertificateHolder cert = (X509CertificateHolder)certIt.next(); + + assertTrue(cSigner.isCounterSignature()); + assertNull(cSigner.getSignedAttributes().get(PKCSObjectIdentifiers.pkcs_9_at_contentType)); + assertEquals(true, cSigner.verify(new JcaSimpleSignerInfoVerifierBuilder().setProvider(BC).build(cert))); + } + } + + private void rsaPSSTest(String signatureAlgorithmName) + throws Exception + { + List certList = new ArrayList(); + CMSTypedData msg = new CMSProcessableByteArray("Hello world!".getBytes()); + + certList.add(_origCert); + certList.add(_signCert); + + Store certs = new JcaCertStore(certList); + + CMSSignedDataGenerator gen = new CMSSignedDataGenerator(); + + ContentSigner contentSigner = new JcaContentSignerBuilder(signatureAlgorithmName).setProvider(BC).build(_origKP.getPrivate()); + + JcaSignerInfoGeneratorBuilder siBuilder = new JcaSignerInfoGeneratorBuilder(new JcaDigestCalculatorProviderBuilder().setProvider(BC).build()); + + siBuilder.setDirectSignature(true); + + gen.addSignerInfoGenerator(siBuilder.build(contentSigner, _origCert)); + + gen.addCertificates(certs); + + CMSSignedData s = gen.generate(msg, false); + + // + // compute expected content digest + // + String digestName = signatureAlgorithmName.substring(0, signatureAlgorithmName.indexOf('w')); + MessageDigest md = MessageDigest.getInstance(digestName, BC); + + verifySignatures(s, md.digest("Hello world!".getBytes())); + } + + private void subjectKeyIDTest( + KeyPair signaturePair, + X509Certificate signatureCert, + String signatureAlgorithm) + throws Exception + { + List certList = new ArrayList(); + List crlList = new ArrayList(); + CMSTypedData msg = new CMSProcessableByteArray("Hello World!".getBytes()); + + certList.add(signatureCert); + certList.add(_origCert); + + crlList.add(_signCrl); + + Store certStore = new JcaCertStore(certList); + Store crlStore = new JcaCRLStore(crlList); + + CMSSignedDataGenerator gen = new CMSSignedDataGenerator(); + + ContentSigner contentSigner = new JcaContentSignerBuilder(signatureAlgorithm).setProvider(BC).build(signaturePair.getPrivate()); + + gen.addSignerInfoGenerator(new JcaSignerInfoGeneratorBuilder(new JcaDigestCalculatorProviderBuilder().setProvider(BC).build()).build(contentSigner, CMSTestUtil.createSubjectKeyId(signatureCert.getPublicKey()).getKeyIdentifier())); + + gen.addCertificates(certStore); + gen.addCRLs(crlStore); + + CMSSignedData s = gen.generate(msg, true); + + assertEquals(3, s.getVersion()); + + ByteArrayInputStream bIn = new ByteArrayInputStream(s.getEncoded()); + ASN1InputStream aIn = new ASN1InputStream(bIn); + + s = new CMSSignedData(ContentInfo.getInstance(aIn.readObject())); + + 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(); + + assertEquals(true, signer.verify(new JcaSimpleSignerInfoVerifierBuilder().setProvider(BC).build(cert))); + } + + // + // check for CRLs + // + Collection crls = crlStore.getMatches(null); + + assertEquals(1, crls.size()); + + assertTrue(crls.contains(new JcaX509CRLHolder(_signCrl))); + + // + // try using existing signer + // + + gen = new CMSSignedDataGenerator(); + + gen.addSigners(s.getSignerInfos()); + + gen.addCertificates(s.getCertificates()); + + s = gen.generate(msg, true); + + bIn = new ByteArrayInputStream(s.getEncoded()); + aIn = new ASN1InputStream(bIn); + + s = new CMSSignedData(ContentInfo.getInstance(aIn.readObject())); + + certStore = s.getCertificates(); + + signers = s.getSignerInfos(); + c = signers.getSigners(); + 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(); + + assertEquals(true, signer.verify(new JcaSimpleSignerInfoVerifierBuilder().setProvider(BC).build(cert))); + } + + checkSignerStoreReplacement(s, signers); + } + + private void encapsulatedTest( + KeyPair signaturePair, + X509Certificate signatureCert, + String signatureAlgorithm) + throws Exception + { + ConfigurableProvider provider = (ConfigurableProvider)Security.getProvider(BC); + + if (!provider.hasAlgorithm("Signature", signatureAlgorithm)) + { + return; + } + + List certList = new ArrayList(); + List crlList = new ArrayList(); + CMSTypedData msg = new CMSProcessableByteArray("Hello World!".getBytes()); + + certList.add(signatureCert); + certList.add(_origCert); + + crlList.add(_signCrl); + + Store certs = new JcaCertStore(certList); + Store crlStore = new JcaCRLStore(crlList); + + CMSSignedDataGenerator gen = new CMSSignedDataGenerator(); + + ContentSigner contentSigner = new JcaContentSignerBuilder(signatureAlgorithm).setProvider(BC).build(signaturePair.getPrivate()); + + gen.addSignerInfoGenerator(new JcaSignerInfoGeneratorBuilder(new JcaDigestCalculatorProviderBuilder().setProvider(BC).build()).build(contentSigner, signatureCert)); + + gen.addCertificates(certs); + + CMSSignedData s = gen.generate(msg, true); + + ByteArrayInputStream bIn = new ByteArrayInputStream(s.getEncoded()); + ASN1InputStream aIn = new ASN1InputStream(bIn); + + s = new CMSSignedData(ContentInfo.getInstance(aIn.readObject())); + + certs = s.getCertificates(); + + SignerInformationStore signers = s.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(); + + assertEquals(true, signer.verify(new JcaSimpleSignerInfoVerifierBuilder().setProvider(BC).build(cert))); + } + + // + // check for CRLs + // + Collection crls = crlStore.getMatches(null); + + assertEquals(1, crls.size()); + + assertTrue(crls.contains(new JcaX509CRLHolder(_signCrl))); + + // + // try using existing signer + // + + gen = new CMSSignedDataGenerator(); + + gen.addSigners(s.getSignerInfos()); + + gen.addCertificates(s.getCertificates()); + + s = gen.generate(msg, true); + + bIn = new ByteArrayInputStream(s.getEncoded()); + aIn = new ASN1InputStream(bIn); + + s = new CMSSignedData(ContentInfo.getInstance(aIn.readObject())); + + certs = s.getCertificates(); + + signers = s.getSignerInfos(); + c = signers.getSigners(); + 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(); + + assertEquals(true, signer.verify(new JcaSimpleSignerInfoVerifierBuilder().setProvider(BC).build(cert))); + } + + checkSignerStoreReplacement(s, signers); + } + + // + // signerInformation store replacement test. + // + private void checkSignerStoreReplacement( + CMSSignedData orig, + SignerInformationStore signers) + throws Exception + { + CMSSignedData s = CMSSignedData.replaceSigners(orig, signers); + + Store certs = s.getCertificates(); + + signers = s.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(); + + assertEquals(true, signer.verify(new JcaSimpleSignerInfoVerifierBuilder().setProvider(BC).build(cert))); + } + } + + public void testUnsortedAttributes() + throws Exception + { + CMSSignedData s = new CMSSignedData(new CMSProcessableByteArray(disorderedMessage), disorderedSet); + + Store certs = s.getCertificates(); + + SignerInformationStore signers = s.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(); + + assertEquals(true, signer.verify(new JcaSimpleSignerInfoVerifierBuilder().setProvider(BC).build(cert))); + } + } + + public void testNullContentWithSigner() + throws Exception + { + List certList = new ArrayList(); + + certList.add(_origCert); + certList.add(_signCert); + + Store certs = new JcaCertStore(certList); + + CMSSignedDataGenerator gen = new CMSSignedDataGenerator(); + + ContentSigner sha1Signer = new JcaContentSignerBuilder("SHA1withRSA").setProvider(BC).build(_origKP.getPrivate()); + + gen.addSignerInfoGenerator(new JcaSignerInfoGeneratorBuilder(new JcaDigestCalculatorProviderBuilder().setProvider(BC).build()).build(sha1Signer, _origCert)); + + gen.addCertificates(certs); + + CMSSignedData s = gen.generate(new CMSAbsentContent(), false); + + ByteArrayInputStream bIn = new ByteArrayInputStream(s.getEncoded()); + ASN1InputStream aIn = new ASN1InputStream(bIn); + + s = new CMSSignedData(ContentInfo.getInstance(aIn.readObject())); + + verifySignatures(s); + } + + public void testWithAttributeCertificate() + throws Exception + { + List certList = new ArrayList(); + CMSTypedData msg = new CMSProcessableByteArray("Hello World!".getBytes()); + + + certList.add(_signDsaCert); + + Store certs = new JcaCertStore(certList); + + CMSSignedDataGenerator gen = new CMSSignedDataGenerator(); + + JcaSignerInfoGeneratorBuilder builder = new JcaSignerInfoGeneratorBuilder(new JcaDigestCalculatorProviderBuilder().setProvider(BC).build()); + ContentSigner sha1Signer = new JcaContentSignerBuilder("SHA1withRSA").setProvider(BC).build(_origKP.getPrivate()); + + gen.addSignerInfoGenerator(builder.build(sha1Signer, _origCert)); + + gen.addCertificates(certs); + + X509AttributeCertificateHolder attrCert = new X509AttributeCertificateHolder(CMSTestUtil.getAttributeCertificate().getEncoded()); + List attrList = new ArrayList(); + + attrList.add(new X509AttributeCertificateHolder(attrCert.getEncoded())); + + Store store = new CollectionStore(attrList); + + gen.addAttributeCertificates(store); + + CMSSignedData sd = gen.generate(msg); + + assertEquals(4, sd.getVersion()); + + store = sd.getAttributeCertificates(); + + Collection coll = store.getMatches(null); + + assertEquals(1, coll.size()); + + assertTrue(coll.contains(new X509AttributeCertificateHolder(attrCert.getEncoded()))); + + // + // create new certstore + // + certList = new ArrayList(); + certList.add(_origCert); + certList.add(_signCert); + + certs = new JcaCertStore(certList); + + + // + // replace certs + // + sd = CMSSignedData.replaceCertificatesAndCRLs(sd, certs, null, null); + + verifySignatures(sd); + } + + public void testCertStoreReplacement() + throws Exception + { + List certList = new ArrayList(); + CMSTypedData msg = new CMSProcessableByteArray("Hello World!".getBytes()); + + + certList.add(_signDsaCert); + + Store certs = new JcaCertStore(certList); + + CMSSignedDataGenerator gen = new CMSSignedDataGenerator(); + + ContentSigner sha1Signer = new JcaContentSignerBuilder("SHA1withRSA").setProvider(BC).build(_origKP.getPrivate()); + + gen.addSignerInfoGenerator(new JcaSignerInfoGeneratorBuilder(new JcaDigestCalculatorProviderBuilder().setProvider(BC).build()).build(sha1Signer, _origCert)); + + gen.addCertificates(certs); + + CMSSignedData sd = gen.generate(msg); + + // + // create new certstore + // + certList = new ArrayList(); + certList.add(_origCert); + certList.add(_signCert); + + certs = new JcaCertStore(certList); + + // + // replace certs + // + sd = CMSSignedData.replaceCertificatesAndCRLs(sd, certs, null, null); + + verifySignatures(sd); + } + + public void testEncapsulatedCertStoreReplacement() + throws Exception + { + List certList = new ArrayList(); + CMSTypedData msg = new CMSProcessableByteArray("Hello World!".getBytes()); + + + certList.add(_signDsaCert); + + Store certs = new JcaCertStore(certList); + + CMSSignedDataGenerator gen = new CMSSignedDataGenerator(); + ContentSigner sha1Signer = new JcaContentSignerBuilder("SHA1withRSA").setProvider(BC).build(_origKP.getPrivate()); + + gen.addSignerInfoGenerator(new JcaSignerInfoGeneratorBuilder(new JcaDigestCalculatorProviderBuilder().setProvider(BC).build()).build(sha1Signer, _origCert)); + + gen.addCertificates(certs); + + CMSSignedData sd = gen.generate(msg, true); + + // + // create new certstore + // + certList = new ArrayList(); + certList.add(_origCert); + certList.add(_signCert); + + certs = new JcaCertStore(certList); + + + // + // replace certs + // + sd = CMSSignedData.replaceCertificatesAndCRLs(sd, certs, null, null); + + verifySignatures(sd); + } + + public void testCertOrdering1() + throws Exception + { + List certList = new ArrayList(); + CMSTypedData msg = new CMSProcessableByteArray("Hello World!".getBytes()); + + certList.add(_origCert); + certList.add(_signCert); + certList.add(_signDsaCert); + + Store certs = new JcaCertStore(certList); + + CMSSignedDataGenerator gen = new CMSSignedDataGenerator(); + + ContentSigner sha1Signer = new JcaContentSignerBuilder("SHA1withRSA").setProvider(BC).build(_origKP.getPrivate()); + + gen.addSignerInfoGenerator(new JcaSignerInfoGeneratorBuilder(new JcaDigestCalculatorProviderBuilder().setProvider(BC).build()).build(sha1Signer, _origCert)); + + gen.addCertificates(certs); + + CMSSignedData sd = gen.generate(msg, true); + + certs = sd.getCertificates(); + Iterator it = certs.getMatches(null).iterator(); + + assertEquals(new JcaX509CertificateHolder(_origCert), it.next()); + assertEquals(new JcaX509CertificateHolder(_signCert), it.next()); + assertEquals(new JcaX509CertificateHolder(_signDsaCert), it.next()); + } + + public void testCertOrdering2() + throws Exception + { + List certList = new ArrayList(); + CMSTypedData msg = new CMSProcessableByteArray("Hello World!".getBytes()); + + certList.add(_signCert); + certList.add(_signDsaCert); + certList.add(_origCert); + + Store certs = new JcaCertStore(certList); + + CMSSignedDataGenerator gen = new CMSSignedDataGenerator(); + + ContentSigner sha1Signer = new JcaContentSignerBuilder("SHA1withRSA").setProvider(BC).build(_origKP.getPrivate()); + + gen.addSignerInfoGenerator(new JcaSignerInfoGeneratorBuilder(new JcaDigestCalculatorProviderBuilder().setProvider(BC).build()).build(sha1Signer, _origCert)); + + gen.addCertificates(certs); + + CMSSignedData sd = gen.generate(msg, true); + + certs = sd.getCertificates(); + Iterator it = certs.getMatches(null).iterator(); + + assertEquals(new JcaX509CertificateHolder(_signCert), it.next()); + assertEquals(new JcaX509CertificateHolder(_signDsaCert), it.next()); + assertEquals(new JcaX509CertificateHolder(_origCert), it.next()); + } + + public void testSignerStoreReplacement() + throws Exception + { + List certList = new ArrayList(); + CMSTypedData msg = new CMSProcessableByteArray("Hello World!".getBytes()); + + certList.add(_origCert); + certList.add(_signCert); + + Store certs = new JcaCertStore(certList); + + CMSSignedDataGenerator gen = new CMSSignedDataGenerator(); + + ContentSigner sha1Signer = new JcaContentSignerBuilder("SHA1withRSA").setProvider(BC).build(_origKP.getPrivate()); + + gen.addSignerInfoGenerator(new JcaSignerInfoGeneratorBuilder(new JcaDigestCalculatorProviderBuilder().setProvider(BC).build()).build(sha1Signer, _origCert)); + + gen.addCertificates(certs); + + CMSSignedData original = gen.generate(msg, true); + + // + // create new Signer + // + gen = new CMSSignedDataGenerator(); + + ContentSigner sha224Signer = new JcaContentSignerBuilder("SHA224withRSA").setProvider(BC).build(_origKP.getPrivate()); + + gen.addSignerInfoGenerator(new JcaSignerInfoGeneratorBuilder(new JcaDigestCalculatorProviderBuilder().setProvider(BC).build()).build(sha224Signer, _origCert)); + + gen.addCertificates(certs); + + CMSSignedData newSD = gen.generate(msg, true); + + // + // replace signer + // + CMSSignedData sd = CMSSignedData.replaceSigners(original, newSD.getSignerInfos()); + + SignerInformation signer = (SignerInformation)sd.getSignerInfos().getSigners().iterator().next(); + + assertEquals(CMSAlgorithm.SHA224.getId(), signer.getDigestAlgOID()); + + // we use a parser here as it requires the digests to be correct in the digest set, if it + // isn't we'll get a NullPointerException + CMSSignedDataParser sp = new CMSSignedDataParser(new JcaDigestCalculatorProviderBuilder().setProvider(BC).build(), sd.getEncoded()); + + sp.getSignedContent().drain(); + + verifySignatures(sp); + } + + public void testEncapsulatedSamples() + throws Exception + { + testSample("PSSSignDataSHA1Enc.sig"); + testSample("PSSSignDataSHA256Enc.sig"); + testSample("PSSSignDataSHA512Enc.sig"); + } + + public void testSamples() + throws Exception + { + testSample("PSSSignData.data", "PSSSignDataSHA1.sig"); + testSample("PSSSignData.data", "PSSSignDataSHA256.sig"); + testSample("PSSSignData.data", "PSSSignDataSHA512.sig"); + } + + public void testCounterSig() + throws Exception + { + CMSSignedData sig = new CMSSignedData(getInput("counterSig.p7m")); + + SignerInformationStore ss = sig.getSignerInfos(); + Collection signers = ss.getSigners(); + + SignerInformationStore cs = ((SignerInformation)signers.iterator().next()).getCounterSignatures(); + Collection csSigners = cs.getSigners(); + assertEquals(1, csSigners.size()); + + Iterator it = csSigners.iterator(); + while (it.hasNext()) + { + SignerInformation cSigner = (SignerInformation)it.next(); + Collection certCollection = sig.getCertificates().getMatches(cSigner.getSID()); + + Iterator certIt = certCollection.iterator(); + X509CertificateHolder cert = (X509CertificateHolder)certIt.next(); + + assertTrue(cSigner.isCounterSignature()); + assertNull(cSigner.getSignedAttributes().get(PKCSObjectIdentifiers.pkcs_9_at_contentType)); + assertEquals(true, cSigner.verify(new JcaSimpleSignerInfoVerifierBuilder().setProvider(BC).build(cert))); + } + + verifySignatures(sig); + } + + private void testSample(String sigName) + throws Exception + { + CMSSignedData sig = new CMSSignedData(getInput(sigName)); + + verifySignatures(sig); + } + + private void testSample(String messageName, String sigName) + throws Exception + { + CMSSignedData sig = new CMSSignedData(new CMSProcessableByteArray(getInput(messageName)), getInput(sigName)); + + verifySignatures(sig); + } + + private byte[] getInput(String name) + throws IOException + { + return Streams.readAll(getClass().getResourceAsStream(name)); + } + + public void testForMultipleCounterSignatures() + throws Exception + { + CMSSignedData sd = new CMSSignedData(xtraCounterSig); + + for (Iterator sI = sd.getSignerInfos().getSigners().iterator(); sI.hasNext();) + { + SignerInformation sigI = (SignerInformation)sI.next(); + + SignerInformationStore counter = sigI.getCounterSignatures(); + List sigs = new ArrayList(counter.getSigners()); + + assertEquals(2, sigs.size()); + } + } + + private void verifySignatures(CMSSignedDataParser sp) + throws Exception + { + 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(); + + assertEquals(true, signer.verify(new JcaSimpleSignerInfoVerifierBuilder().setProvider(BC).build(cert))); + } + } + + private class TestCMSSignatureAlgorithmNameGenerator + extends DefaultCMSSignatureAlgorithmNameGenerator + { + void setDigestAlgorithmMapping(ASN1ObjectIdentifier oid, String algName) + { + super.setSigningDigestAlgorithmMapping(oid, algName); + } + + void setEncryptionAlgorithmMapping(ASN1ObjectIdentifier oid, String algName) + { + super.setSigningEncryptionAlgorithmMapping(oid, algName); + } + } +} diff --git a/pkix/src/test/java/org/spongycastle/cms/test/CMSSampleMessages.java b/pkix/src/test/java/org/spongycastle/cms/test/CMSSampleMessages.java new file mode 100644 index 00000000..a9609df7 --- /dev/null +++ b/pkix/src/test/java/org/spongycastle/cms/test/CMSSampleMessages.java @@ -0,0 +1,147 @@ +package org.spongycastle.cms.test; + +import org.spongycastle.util.encoders.Base64; + +public class CMSSampleMessages +{ + static byte[] originatorMessage = Base64.decode( + "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" + + "k9HhGwwsgiR+"); + +} diff --git a/pkix/src/test/java/org/spongycastle/cms/test/CMSTestSetup.java b/pkix/src/test/java/org/spongycastle/cms/test/CMSTestSetup.java new file mode 100644 index 00000000..644d3d3b --- /dev/null +++ b/pkix/src/test/java/org/spongycastle/cms/test/CMSTestSetup.java @@ -0,0 +1,24 @@ +package org.spongycastle.cms.test; + +import junit.extensions.TestSetup; +import junit.framework.Test; + +import java.security.Security; + +class CMSTestSetup extends TestSetup +{ + public CMSTestSetup(Test test) + { + super(test); + } + + protected void setUp() + { + Security.addProvider(new org.spongycastle.jce.provider.BouncyCastleProvider()); + } + + protected void tearDown() + { + Security.removeProvider("SC"); + } +} diff --git a/pkix/src/test/java/org/spongycastle/cms/test/CMSTestUtil.java b/pkix/src/test/java/org/spongycastle/cms/test/CMSTestUtil.java new file mode 100644 index 00000000..90c42e74 --- /dev/null +++ b/pkix/src/test/java/org/spongycastle/cms/test/CMSTestUtil.java @@ -0,0 +1,503 @@ +package org.spongycastle.cms.test; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.math.BigInteger; +import java.security.GeneralSecurityException; +import java.security.KeyPair; +import java.security.KeyPairGenerator; +import java.security.PrivateKey; +import java.security.PublicKey; +import java.security.SecureRandom; +import java.security.cert.X509CRL; +import java.security.cert.X509Certificate; +import java.security.interfaces.RSAPublicKey; +import java.security.spec.DSAParameterSpec; +import java.util.Date; + +import javax.crypto.KeyGenerator; +import javax.crypto.SecretKey; + +import org.spongycastle.asn1.cryptopro.CryptoProObjectIdentifiers; +import org.spongycastle.asn1.pkcs.PKCSObjectIdentifiers; +import org.spongycastle.asn1.pkcs.RSAESOAEPparams; +import org.spongycastle.asn1.x500.X500Name; +import org.spongycastle.asn1.x509.AlgorithmIdentifier; +import org.spongycastle.asn1.x509.AuthorityKeyIdentifier; +import org.spongycastle.asn1.x509.BasicConstraints; +import org.spongycastle.asn1.x509.CRLReason; +import org.spongycastle.asn1.x509.Extension; +import org.spongycastle.asn1.x509.SubjectKeyIdentifier; +import org.spongycastle.asn1.x509.SubjectPublicKeyInfo; +import org.spongycastle.cert.X509AttributeCertificateHolder; +import org.spongycastle.cert.X509ExtensionUtils; +import org.spongycastle.cert.X509v1CertificateBuilder; +import org.spongycastle.cert.X509v2CRLBuilder; +import org.spongycastle.cert.X509v3CertificateBuilder; +import org.spongycastle.cert.jcajce.JcaX509CRLConverter; +import org.spongycastle.cert.jcajce.JcaX509CertificateConverter; +import org.spongycastle.cert.jcajce.JcaX509ExtensionUtils; +import org.spongycastle.cert.jcajce.JcaX509v1CertificateBuilder; +import org.spongycastle.cert.jcajce.JcaX509v3CertificateBuilder; +import org.spongycastle.jce.ECGOST3410NamedCurveTable; +import org.spongycastle.jce.provider.BouncyCastleProvider; +import org.spongycastle.jce.spec.GOST3410ParameterSpec; +import org.spongycastle.operator.OperatorCreationException; +import org.spongycastle.operator.jcajce.JcaContentSignerBuilder; +import org.spongycastle.util.encoders.Base64; + +public class CMSTestUtil +{ + public static SecureRandom rand; + public static KeyPairGenerator kpg; + + public static KeyPairGenerator gostKpg; + public static KeyPairGenerator dsaKpg; + public static KeyPairGenerator ecGostKpg; + public static KeyPairGenerator ecDsaKpg; + public static KeyGenerator aes192kg; + public static KeyGenerator desede128kg; + public static KeyGenerator desede192kg; + public static KeyGenerator rc240kg; + public static KeyGenerator rc264kg; + public static KeyGenerator rc2128kg; + public static KeyGenerator aesKg; + public static KeyGenerator seedKg; + public static KeyGenerator camelliaKg; + public static BigInteger serialNumber; + + public static final boolean DEBUG = true; + + private static byte[] attrCert = Base64.decode( + "MIIHQDCCBqkCAQEwgZChgY2kgYowgYcxHDAaBgkqhkiG9w0BCQEWDW1sb3JjaEB2" + + "dC5lZHUxHjAcBgNVBAMTFU1hcmt1cyBMb3JjaCAobWxvcmNoKTEbMBkGA1UECxMS" + + "VmlyZ2luaWEgVGVjaCBVc2VyMRAwDgYDVQQLEwdDbGFzcyAyMQswCQYDVQQKEwJ2" + + "dDELMAkGA1UEBhMCVVMwgYmkgYYwgYMxGzAZBgkqhkiG9w0BCQEWDHNzaGFoQHZ0" + + "LmVkdTEbMBkGA1UEAxMSU3VtaXQgU2hhaCAoc3NoYWgpMRswGQYDVQQLExJWaXJn" + + "aW5pYSBUZWNoIFVzZXIxEDAOBgNVBAsTB0NsYXNzIDExCzAJBgNVBAoTAnZ0MQsw" + + "CQYDVQQGEwJVUzANBgkqhkiG9w0BAQQFAAIBBTAiGA8yMDAzMDcxODE2MDgwMloY" + + "DzIwMDMwNzI1MTYwODAyWjCCBU0wggVJBgorBgEEAbRoCAEBMYIFORaCBTU8UnVs" + + "ZSBSdWxlSWQ9IkZpbGUtUHJpdmlsZWdlLVJ1bGUiIEVmZmVjdD0iUGVybWl0Ij4K" + + "IDxUYXJnZXQ+CiAgPFN1YmplY3RzPgogICA8U3ViamVjdD4KICAgIDxTdWJqZWN0" + + "TWF0Y2ggTWF0Y2hJZD0idXJuOm9hc2lzOm5hbWVzOnRjOnhhY21sOjEuMDpmdW5j" + + "dGlvbjpzdHJpbmctZXF1YWwiPgogICAgIDxBdHRyaWJ1dGVWYWx1ZSBEYXRhVHlw" + + "ZT0iaHR0cDovL3d3dy53My5vcmcvMjAwMS9YTUxTY2hlbWEjc3RyaW5nIj4KICAg" + + "ICAgIENOPU1hcmt1cyBMb3JjaDwvQXR0cmlidXRlVmFsdWU+CiAgICAgPFN1Ympl" + + "Y3RBdHRyaWJ1dGVEZXNpZ25hdG9yIEF0dHJpYnV0ZUlkPSJ1cm46b2FzaXM6bmFt" + + "ZXM6dGM6eGFjbWw6MS4wOnN1YmplY3Q6c3ViamVjdC1pZCIgRGF0YVR5cGU9Imh0" + + "dHA6Ly93d3cudzMub3JnLzIwMDEvWE1MU2NoZW1hI3N0cmluZyIgLz4gCiAgICA8" + + "L1N1YmplY3RNYXRjaD4KICAgPC9TdWJqZWN0PgogIDwvU3ViamVjdHM+CiAgPFJl" + + "c291cmNlcz4KICAgPFJlc291cmNlPgogICAgPFJlc291cmNlTWF0Y2ggTWF0Y2hJ" + + "ZD0idXJuOm9hc2lzOm5hbWVzOnRjOnhhY21sOjEuMDpmdW5jdGlvbjpzdHJpbmct" + + "ZXF1YWwiPgogICAgIDxBdHRyaWJ1dGVWYWx1ZSBEYXRhVHlwZT0iaHR0cDovL3d3" + + "dy53My5vcmcvMjAwMS9YTUxTY2hlbWEjYW55VVJJIj4KICAgICAgaHR0cDovL3p1" + + "bmkuY3MudnQuZWR1PC9BdHRyaWJ1dGVWYWx1ZT4KICAgICA8UmVzb3VyY2VBdHRy" + + "aWJ1dGVEZXNpZ25hdG9yIEF0dHJpYnV0ZUlkPSJ1cm46b2FzaXM6bmFtZXM6dGM6" + + "eGFjbWw6MS4wOnJlc291cmNlOnJlc291cmNlLWlkIiBEYXRhVHlwZT0iaHR0cDov" + + "L3d3dy53My5vcmcvMjAwMS9YTUxTY2hlbWEjYW55VVJJIiAvPiAKICAgIDwvUmVz" + + "b3VyY2VNYXRjaD4KICAgPC9SZXNvdXJjZT4KICA8L1Jlc291cmNlcz4KICA8QWN0" + + "aW9ucz4KICAgPEFjdGlvbj4KICAgIDxBY3Rpb25NYXRjaCBNYXRjaElkPSJ1cm46" + + "b2FzaXM6bmFtZXM6dGM6eGFjbWw6MS4wOmZ1bmN0aW9uOnN0cmluZy1lcXVhbCI+" + + "CiAgICAgPEF0dHJpYnV0ZVZhbHVlIERhdGFUeXBlPSJodHRwOi8vd3d3LnczLm9y" + + "Zy8yMDAxL1hNTFNjaGVtYSNzdHJpbmciPgpEZWxlZ2F0ZSBBY2Nlc3MgICAgIDwv" + + "QXR0cmlidXRlVmFsdWU+CgkgIDxBY3Rpb25BdHRyaWJ1dGVEZXNpZ25hdG9yIEF0" + + "dHJpYnV0ZUlkPSJ1cm46b2FzaXM6bmFtZXM6dGM6eGFjbWw6MS4wOmFjdGlvbjph" + + "Y3Rpb24taWQiIERhdGFUeXBlPSJodHRwOi8vd3d3LnczLm9yZy8yMDAxL1hNTFNj" + + "aGVtYSNzdHJpbmciIC8+IAogICAgPC9BY3Rpb25NYXRjaD4KICAgPC9BY3Rpb24+" + + "CiAgPC9BY3Rpb25zPgogPC9UYXJnZXQ+CjwvUnVsZT4KMA0GCSqGSIb3DQEBBAUA" + + "A4GBAGiJSM48XsY90HlYxGmGVSmNR6ZW2As+bot3KAfiCIkUIOAqhcphBS23egTr" + + "6asYwy151HshbPNYz+Cgeqs45KkVzh7bL/0e1r8sDVIaaGIkjHK3CqBABnfSayr3" + + "Rd1yBoDdEv8Qb+3eEPH6ab9021AsLEnJ6LWTmybbOpMNZ3tv"); + + static + { + try + { + java.security.Security.addProvider(new BouncyCastleProvider()); + + rand = new SecureRandom(); + + kpg = KeyPairGenerator.getInstance("RSA", "SC"); + kpg.initialize(1024, rand); + + kpg = KeyPairGenerator.getInstance("RSA", "SC"); + kpg.initialize(1024, rand); + + gostKpg = KeyPairGenerator.getInstance("GOST3410", "SC"); + GOST3410ParameterSpec gost3410P = new GOST3410ParameterSpec(CryptoProObjectIdentifiers.gostR3410_94_CryptoPro_A.getId()); + + gostKpg.initialize(gost3410P, new SecureRandom()); + + dsaKpg = KeyPairGenerator.getInstance("DSA", "SC"); + DSAParameterSpec dsaSpec = new DSAParameterSpec( + new BigInteger("7434410770759874867539421675728577177024889699586189000788950934679315164676852047058354758883833299702695428196962057871264685291775577130504050839126673"), + new BigInteger("1138656671590261728308283492178581223478058193247"), + new BigInteger("4182906737723181805517018315469082619513954319976782448649747742951189003482834321192692620856488639629011570381138542789803819092529658402611668375788410")); + + dsaKpg.initialize(dsaSpec, new SecureRandom()); + + ecGostKpg = KeyPairGenerator.getInstance("ECGOST3410", "SC"); + ecGostKpg.initialize(ECGOST3410NamedCurveTable.getParameterSpec("GostR3410-2001-CryptoPro-A"), new SecureRandom()); + + ecDsaKpg = KeyPairGenerator.getInstance("ECDSA", "SC"); + ecDsaKpg.initialize(239, new SecureRandom()); + + aes192kg = KeyGenerator.getInstance("AES", "SC"); + aes192kg.init(192, rand); + + desede128kg = KeyGenerator.getInstance("DESEDE", "SC"); + desede128kg.init(112, rand); + + desede192kg = KeyGenerator.getInstance("DESEDE", "SC"); + desede192kg.init(168, rand); + + rc240kg = KeyGenerator.getInstance("RC2", "SC"); + rc240kg.init(40, rand); + + rc264kg = KeyGenerator.getInstance("RC2", "SC"); + rc264kg.init(64, rand); + + rc2128kg = KeyGenerator.getInstance("RC2", "SC"); + rc2128kg.init(128, rand); + + aesKg = KeyGenerator.getInstance("AES", "SC"); + + seedKg = KeyGenerator.getInstance("SEED", "SC"); + + camelliaKg = KeyGenerator.getInstance("Camellia", "SC"); + + serialNumber = new BigInteger("1"); + } + catch (Exception ex) + { + throw new RuntimeException(ex.toString()); + } + } + + public static String dumpBase64( + byte[] data) + { + StringBuffer buf = new StringBuffer(); + + data = Base64.encode(data); + + for (int i = 0; i < data.length; i += 64) + { + if (i + 64 < data.length) + { + buf.append(new String(data, i, 64)); + } + else + { + buf.append(new String(data, i, data.length - i)); + } + buf.append('\n'); + } + + return buf.toString(); + } + + public static X509AttributeCertificateHolder getAttributeCertificate() + throws Exception + { + return new X509AttributeCertificateHolder(CMSTestUtil.attrCert); + } + + public static KeyPair makeKeyPair() + { + return kpg.generateKeyPair(); + } + + public static KeyPair makeGostKeyPair() + { + return gostKpg.generateKeyPair(); + } + + public static KeyPair makeDsaKeyPair() + { + return dsaKpg.generateKeyPair(); + } + + public static KeyPair makeEcDsaKeyPair() + { + return ecDsaKpg.generateKeyPair(); + } + + public static KeyPair makeEcGostKeyPair() + { + return ecGostKpg.generateKeyPair(); + } + + public static SecretKey makeDesede128Key() + { + return desede128kg.generateKey(); + } + + public static SecretKey makeAES192Key() + { + return aes192kg.generateKey(); + } + + public static SecretKey makeDesede192Key() + { + return desede192kg.generateKey(); + } + + public static SecretKey makeRC240Key() + { + return rc240kg.generateKey(); + } + + public static SecretKey makeRC264Key() + { + return rc264kg.generateKey(); + } + + public static SecretKey makeRC2128Key() + { + return rc2128kg.generateKey(); + } + + public static SecretKey makeSEEDKey() + { + return seedKg.generateKey(); + } + + public static SecretKey makeAESKey(int keySize) + { + aesKg.init(keySize); + return aesKg.generateKey(); + } + + public static SecretKey makeCamelliaKey(int keySize) + { + camelliaKg.init(keySize); + return camelliaKg.generateKey(); + } + + public static X509Certificate makeCertificate(KeyPair _subKP, + String _subDN, KeyPair _issKP, String _issDN) + throws GeneralSecurityException, IOException, OperatorCreationException + { + return makeCertificate(_subKP, _subDN, _issKP, _issDN, false); + } + + public static X509Certificate makeOaepCertificate(KeyPair _subKP, + String _subDN, KeyPair _issKP, String _issDN) + throws GeneralSecurityException, IOException, OperatorCreationException + { + return makeOaepCertificate(_subKP, _subDN, _issKP, _issDN, false); + } + + public static X509Certificate makeCACertificate(KeyPair _subKP, + String _subDN, KeyPair _issKP, String _issDN) + throws GeneralSecurityException, IOException, OperatorCreationException + { + return makeCertificate(_subKP, _subDN, _issKP, _issDN, true); + } + + public static X509Certificate makeV1Certificate(KeyPair subKP, String _subDN, KeyPair issKP, String _issDN) + throws GeneralSecurityException, IOException, OperatorCreationException + { + + PublicKey subPub = subKP.getPublic(); + PrivateKey issPriv = issKP.getPrivate(); + PublicKey issPub = issKP.getPublic(); + + X509v1CertificateBuilder v1CertGen = new JcaX509v1CertificateBuilder( + new X500Name(_issDN), + allocateSerialNumber(), + new Date(System.currentTimeMillis()), + new Date(System.currentTimeMillis() + (1000L * 60 * 60 * 24 * 100)), + new X500Name(_subDN), + subPub); + + JcaContentSignerBuilder contentSignerBuilder = makeContentSignerBuilder(issPub); + + X509Certificate _cert = new JcaX509CertificateConverter().setProvider("SC").getCertificate(v1CertGen.build(contentSignerBuilder.build(issPriv))); + + _cert.checkValidity(new Date()); + _cert.verify(issPub); + + return _cert; + } + + public static X509Certificate makeCertificate(KeyPair subKP, String _subDN, KeyPair issKP, String _issDN, boolean _ca) + throws GeneralSecurityException, IOException, OperatorCreationException + { + + PublicKey subPub = subKP.getPublic(); + PrivateKey issPriv = issKP.getPrivate(); + PublicKey issPub = issKP.getPublic(); + + X509v3CertificateBuilder v3CertGen = new JcaX509v3CertificateBuilder( + new X500Name(_issDN), + allocateSerialNumber(), + new Date(System.currentTimeMillis()), + new Date(System.currentTimeMillis() + (1000L * 60 * 60 * 24 * 100)), + new X500Name(_subDN), + subPub); + + JcaContentSignerBuilder contentSignerBuilder = makeContentSignerBuilder(issPub); + + v3CertGen.addExtension( + Extension.subjectKeyIdentifier, + false, + createSubjectKeyId(subPub)); + + v3CertGen.addExtension( + Extension.authorityKeyIdentifier, + false, + createAuthorityKeyId(issPub)); + + v3CertGen.addExtension( + Extension.basicConstraints, + false, + new BasicConstraints(_ca)); + + X509Certificate _cert = new JcaX509CertificateConverter().setProvider("SC").getCertificate(v3CertGen.build(contentSignerBuilder.build(issPriv))); + + _cert.checkValidity(new Date()); + _cert.verify(issPub); + + return _cert; + } + + public static X509Certificate makeOaepCertificate(KeyPair subKP, String _subDN, KeyPair issKP, String _issDN, boolean _ca) + throws GeneralSecurityException, IOException, OperatorCreationException + { + + SubjectPublicKeyInfo subPub = SubjectPublicKeyInfo.getInstance(subKP.getPublic().getEncoded()); + PrivateKey issPriv = issKP.getPrivate(); + PublicKey issPub = issKP.getPublic(); + + X509v3CertificateBuilder v3CertGen = new X509v3CertificateBuilder( + new X500Name(_issDN), + allocateSerialNumber(), + new Date(System.currentTimeMillis()), + new Date(System.currentTimeMillis() + (1000L * 60 * 60 * 24 * 100)), + new X500Name(_subDN), + new SubjectPublicKeyInfo(new AlgorithmIdentifier(PKCSObjectIdentifiers.id_RSAES_OAEP, new RSAESOAEPparams()), subPub.parsePublicKey())); + + JcaContentSignerBuilder contentSignerBuilder = makeContentSignerBuilder(issPub); + + v3CertGen.addExtension( + Extension.subjectKeyIdentifier, + false, + createSubjectKeyId(subPub)); + + v3CertGen.addExtension( + Extension.authorityKeyIdentifier, + false, + createAuthorityKeyId(issPub)); + + v3CertGen.addExtension( + Extension.basicConstraints, + false, + new BasicConstraints(_ca)); + + X509Certificate _cert = new JcaX509CertificateConverter().setProvider("SC").getCertificate(v3CertGen.build(contentSignerBuilder.build(issPriv))); + + _cert.checkValidity(new Date()); + _cert.verify(issPub); + + return _cert; + } + + private static JcaContentSignerBuilder makeContentSignerBuilder(PublicKey issPub) + { + JcaContentSignerBuilder contentSignerBuilder; + if (issPub instanceof RSAPublicKey) + { + contentSignerBuilder = new JcaContentSignerBuilder("SHA1WithRSA"); + } + else if (issPub.getAlgorithm().equals("DSA")) + { + contentSignerBuilder = new JcaContentSignerBuilder("SHA1withDSA"); + } + else if (issPub.getAlgorithm().equals("ECDSA")) + { + contentSignerBuilder = new JcaContentSignerBuilder("SHA1withECDSA"); + } + else if (issPub.getAlgorithm().equals("ECGOST3410")) + { + contentSignerBuilder = new JcaContentSignerBuilder("GOST3411withECGOST3410"); + } + else + { + contentSignerBuilder = new JcaContentSignerBuilder("GOST3411WithGOST3410"); + } + + contentSignerBuilder.setProvider(BouncyCastleProvider.PROVIDER_NAME); + + return contentSignerBuilder; + } + + public static X509CRL makeCrl(KeyPair pair) + throws Exception + { + Date now = new Date(); + X509v2CRLBuilder crlGen = new X509v2CRLBuilder(new X500Name("CN=Test CA"), now); + JcaX509ExtensionUtils extensionUtils = new JcaX509ExtensionUtils(); + + crlGen.setNextUpdate(new Date(now.getTime() + 100000)); + + crlGen.addCRLEntry(BigInteger.ONE, now, CRLReason.privilegeWithdrawn); + + crlGen.addExtension(Extension.authorityKeyIdentifier, false, extensionUtils.createAuthorityKeyIdentifier(pair.getPublic())); + + return new JcaX509CRLConverter().setProvider("SC").getCRL(crlGen.build(new JcaContentSignerBuilder("SHA256WithRSAEncryption").setProvider("SC").build(pair.getPrivate()))); + } + + /* + * + * INTERNAL METHODS + * + */ + + private static final X509ExtensionUtils extUtils = new X509ExtensionUtils(new SHA1DigestCalculator()); + + private static AuthorityKeyIdentifier createAuthorityKeyId( + PublicKey _pubKey) + throws IOException + { + return extUtils.createAuthorityKeyIdentifier(SubjectPublicKeyInfo.getInstance(_pubKey.getEncoded())); + } + + static SubjectKeyIdentifier createSubjectKeyId( + SubjectPublicKeyInfo _pubKey) + throws IOException + { + return extUtils.createSubjectKeyIdentifier(_pubKey); + } + + static SubjectKeyIdentifier createSubjectKeyId( + PublicKey _pubKey) + throws IOException + { + return extUtils.createSubjectKeyIdentifier(SubjectPublicKeyInfo.getInstance(_pubKey.getEncoded())); + } + + private static BigInteger allocateSerialNumber() + { + BigInteger _tmp = serialNumber; + serialNumber = serialNumber.add(BigInteger.ONE); + return _tmp; + } + + public static byte[] streamToByteArray( + InputStream in) + throws IOException + { + ByteArrayOutputStream bOut = new ByteArrayOutputStream(); + int ch; + + while ((ch = in.read()) >= 0) + { + bOut.write(ch); + } + + return bOut.toByteArray(); + } +} diff --git a/pkix/src/test/java/org/spongycastle/cms/test/ConverterTest.java b/pkix/src/test/java/org/spongycastle/cms/test/ConverterTest.java new file mode 100644 index 00000000..cf08054d --- /dev/null +++ b/pkix/src/test/java/org/spongycastle/cms/test/ConverterTest.java @@ -0,0 +1,111 @@ +package org.spongycastle.cms.test; + +import java.math.BigInteger; +import java.security.cert.X509CertSelector; + +import junit.framework.Test; +import junit.framework.TestCase; +import junit.framework.TestSuite; +import org.spongycastle.asn1.DEROctetString; +import org.spongycastle.asn1.x500.X500Name; +import org.spongycastle.cms.KeyTransRecipientId; +import org.spongycastle.cms.SignerId; +import org.spongycastle.cms.jcajce.JcaSelectorConverter; +import org.spongycastle.cms.jcajce.JcaX509CertSelectorConverter; +import org.spongycastle.util.Arrays; + +public class ConverterTest + extends TestCase +{ + public void testSignerIdConversion() + throws Exception + { + JcaX509CertSelectorConverter converter = new JcaX509CertSelectorConverter(); + JcaSelectorConverter toSelector = new JcaSelectorConverter(); + + SignerId sid1 = new SignerId(new X500Name("CN=Test"), BigInteger.valueOf(1), new byte[20]); + + X509CertSelector conv = converter.getCertSelector(sid1); + + assertTrue(conv.getIssuerAsString().equals("CN=Test")); + assertTrue(Arrays.areEqual(conv.getSubjectKeyIdentifier(), new DEROctetString(new byte[20]).getEncoded())); + assertEquals(conv.getSerialNumber(), sid1.getSerialNumber()); + + SignerId sid2 = toSelector.getSignerId(conv); + + assertEquals(sid1, sid2); + + sid1 = new SignerId(new X500Name("CN=Test"), BigInteger.valueOf(1)); + + conv = converter.getCertSelector(sid1); + + assertTrue(conv.getIssuerAsString().equals("CN=Test")); + assertNull(conv.getSubjectKeyIdentifier()); + assertEquals(conv.getSerialNumber(), sid1.getSerialNumber()); + + sid2 = toSelector.getSignerId(conv); + + assertEquals(sid1, sid2); + + sid1 = new SignerId(new byte[20]); + + conv = converter.getCertSelector(sid1); + + assertNull(conv.getIssuerAsString()); + assertTrue(Arrays.areEqual(conv.getSubjectKeyIdentifier(), new DEROctetString(new byte[20]).getEncoded())); + assertNull(conv.getSerialNumber()); + + sid2 = toSelector.getSignerId(conv); + + assertEquals(sid1, sid2); + } + + public void testRecipientIdConversion() + throws Exception + { + JcaX509CertSelectorConverter converter = new JcaX509CertSelectorConverter(); + JcaSelectorConverter toSelector = new JcaSelectorConverter(); + + KeyTransRecipientId ktid1 = new KeyTransRecipientId(new X500Name("CN=Test"), BigInteger.valueOf(1), new byte[20]); + + X509CertSelector conv = converter.getCertSelector(ktid1); + + assertTrue(conv.getIssuerAsString().equals("CN=Test")); + assertTrue(Arrays.areEqual(conv.getSubjectKeyIdentifier(), new DEROctetString(new byte[20]).getEncoded())); + assertEquals(conv.getSerialNumber(), ktid1.getSerialNumber()); + + KeyTransRecipientId ktid2 = toSelector.getKeyTransRecipientId(conv); + + assertEquals(ktid1, ktid2); + + ktid1 = new KeyTransRecipientId(new X500Name("CN=Test"), BigInteger.valueOf(1)); + + conv = converter.getCertSelector(ktid1); + + assertTrue(conv.getIssuerAsString().equals("CN=Test")); + assertNull(conv.getSubjectKeyIdentifier()); + assertEquals(conv.getSerialNumber(), ktid1.getSerialNumber()); + + ktid2 = toSelector.getKeyTransRecipientId(conv); + + assertEquals(ktid1, ktid2); + + ktid1 = new KeyTransRecipientId(new byte[20]); + + conv = converter.getCertSelector(ktid1); + + assertNull(conv.getIssuerAsString()); + assertTrue(Arrays.areEqual(conv.getSubjectKeyIdentifier(), new DEROctetString(new byte[20]).getEncoded())); + assertNull(conv.getSerialNumber()); + + ktid2 = toSelector.getKeyTransRecipientId(conv); + + assertEquals(ktid1, ktid2); + } + + public static Test suite() + throws Exception + { + return new TestSuite(ConverterTest.class); + } +} diff --git a/pkix/src/test/java/org/spongycastle/cms/test/MiscDataStreamTest.java b/pkix/src/test/java/org/spongycastle/cms/test/MiscDataStreamTest.java new file mode 100644 index 00000000..d01b68e3 --- /dev/null +++ b/pkix/src/test/java/org/spongycastle/cms/test/MiscDataStreamTest.java @@ -0,0 +1,265 @@ +package org.spongycastle.cms.test; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.OutputStream; +import java.security.KeyPair; +import java.security.MessageDigest; +import java.security.Security; +import java.security.cert.X509CRL; +import java.security.cert.X509Certificate; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Iterator; +import java.util.List; + +import junit.framework.Test; +import junit.framework.TestCase; +import junit.framework.TestSuite; +import org.spongycastle.cert.X509CertificateHolder; +import org.spongycastle.cert.jcajce.JcaCRLStore; +import org.spongycastle.cert.jcajce.JcaCertStore; +import org.spongycastle.cms.CMSCompressedDataStreamGenerator; +import org.spongycastle.cms.CMSDigestedData; +import org.spongycastle.cms.CMSSignedDataParser; +import org.spongycastle.cms.CMSSignedDataStreamGenerator; +import org.spongycastle.cms.CMSTypedStream; +import org.spongycastle.cms.SignerInformation; +import org.spongycastle.cms.SignerInformationStore; +import org.spongycastle.cms.jcajce.JcaSignerInfoVerifierBuilder; +import org.spongycastle.cms.jcajce.JcaSimpleSignerInfoGeneratorBuilder; +import org.spongycastle.cms.jcajce.JcaX509CertSelectorConverter; +import org.spongycastle.cms.jcajce.ZlibCompressor; +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.Arrays; +import org.spongycastle.util.Store; +import org.spongycastle.util.encoders.Base64; + +public class MiscDataStreamTest + extends TestCase +{ + private static final String BC = BouncyCastleProvider.PROVIDER_NAME; + + private static byte[] data = Base64.decode( + "TUlNRS1WZXJzaW9uOiAxLjAKQ29udGVudC1UeXBlOiBhcHBsaWNhdGlvbi9v" + + "Y3RldC1zdHJlYW0KQ29udGVudC1UcmFuc2Zlci1FbmNvZGluZzogYmluYXJ5" + + "CkNvbnRlbnQtRGlzcG9zaXRpb246IGF0dGFjaG1lbnQ7IGZpbGVuYW1lPWRv" + + "Yy5iaW4KClRoaXMgaXMgYSB2ZXJ5IGh1Z2Ugc2VjcmV0LCBtYWRlIHdpdGgg" + + "b3BlbnNzbAoKCgo="); + + private static byte[] digestedData = Base64.decode( + "MIIBGAYJKoZIhvcNAQcFoIIBCTCCAQUCAQAwCwYJYIZIAWUDBAIBMIHQBgkq" + + "hkiG9w0BBwGggcIEgb9NSU1FLVZlcnNpb246IDEuMApDb250ZW50LVR5cGU6" + + "IGFwcGxpY2F0aW9uL29jdGV0LXN0cmVhbQpDb250ZW50LVRyYW5zZmVyLUVu" + + "Y29kaW5nOiBiaW5hcnkKQ29udGVudC1EaXNwb3NpdGlvbjogYXR0YWNobWVu" + + "dDsgZmlsZW5hbWU9ZG9jLmJpbgoKVGhpcyBpcyBhIHZlcnkgaHVnZSBzZWNy" + + "ZXQsIG1hZGUgd2l0aCBvcGVuc3NsCgoKCgQgHLG72tSYW0LgcxOA474iwdCv" + + "KyhnaV4RloWTAvkq+do="); + + private static final String TEST_MESSAGE = "Hello World!"; + private static String _signDN; + private static KeyPair _signKP; + private static X509Certificate _signCert; + + private static String _origDN; + private static KeyPair _origKP; + private static X509Certificate _origCert; + + private static String _reciDN; + private static KeyPair _reciKP; + private static X509Certificate _reciCert; + + private static KeyPair _origDsaKP; + private static X509Certificate _origDsaCert; + + private static X509CRL _signCrl; + private static X509CRL _origCrl; + + private static boolean _initialised = false; + + 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 MiscDataStreamTest(String name) + { + super(name); + } + + private static void init() + throws Exception + { + if (!_initialised) + { + _initialised = true; + Security.addProvider(new org.spongycastle.jce.provider.BouncyCastleProvider()); + + _signDN = "O=Bouncy Castle, C=AU"; + _signKP = CMSTestUtil.makeKeyPair(); + _signCert = CMSTestUtil.makeCertificate(_signKP, _signDN, _signKP, _signDN); + + _origDN = "CN=Bob, OU=Sales, O=Bouncy Castle, C=AU"; + _origKP = CMSTestUtil.makeKeyPair(); + _origCert = CMSTestUtil.makeCertificate(_origKP, _origDN, _signKP, _signDN); + + _origDsaKP = CMSTestUtil.makeDsaKeyPair(); + _origDsaCert = CMSTestUtil.makeCertificate(_origDsaKP, _origDN, _signKP, _signDN); + + _reciDN = "CN=Doug, OU=Sales, O=Bouncy Castle, C=AU"; + _reciKP = CMSTestUtil.makeKeyPair(); + _reciCert = CMSTestUtil.makeCertificate(_reciKP, _reciDN, _signKP, _signDN); + + _signCrl = CMSTestUtil.makeCrl(_signKP); + _origCrl = CMSTestUtil.makeCrl(_origKP); + } + } + + private void verifySignatures(CMSSignedDataParser sp, byte[] contentDigest) + throws Exception + { + Store certStore = sp.getCertificates(); + SignerInformationStore signers = sp.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(); + + assertEquals(true, signer.verify(new JcaSignerInfoVerifierBuilder(digCalcProv).setProvider(BC).build(cert))); + + if (contentDigest != null) + { + assertTrue(MessageDigest.isEqual(contentDigest, signer.getContentDigest())); + } + } + } + + private void verifySignatures(CMSSignedDataParser sp) + throws Exception + { + verifySignatures(sp, null); + } + + private void verifyEncodedData(ByteArrayOutputStream bOut) + throws Exception + { + CMSSignedDataParser sp; + sp = new CMSSignedDataParser(digCalcProv, bOut.toByteArray()); + + sp.getSignedContent().drain(); + + verifySignatures(sp); + + sp.close(); + } + + private void checkSigParseable(byte[] sig) + throws Exception + { + CMSSignedDataParser sp = new CMSSignedDataParser(digCalcProv, sig); + sp.getVersion(); + CMSTypedStream sc = sp.getSignedContent(); + if (sc != null) + { + sc.drain(); + } + sp.getCertificates(); + sp.getSignerInfos(); + sp.close(); + } + + public void testSHA1WithRSA() + throws Exception + { + List certList = new ArrayList(); + List crlList = new ArrayList(); + ByteArrayOutputStream bOut = new ByteArrayOutputStream(); + + certList.add(_origCert); + certList.add(_signCert); + + crlList.add(_signCrl); + crlList.add(_origCrl); + + CMSSignedDataStreamGenerator gen = new CMSSignedDataStreamGenerator(); + + gen.addSignerInfoGenerator(new JcaSimpleSignerInfoGeneratorBuilder().setProvider(BC).build("SHA1withRSA", _origKP.getPrivate(), _origCert)); + + gen.addCertificates(new JcaCertStore(certList)); + gen.addCRLs(new JcaCRLStore(crlList)); + + OutputStream sigOut = gen.open(bOut); + + CMSCompressedDataStreamGenerator cGen = new CMSCompressedDataStreamGenerator(); + + OutputStream cOut = cGen.open(sigOut, new ZlibCompressor()); + + cOut.write(TEST_MESSAGE.getBytes()); + + cOut.close(); + + sigOut.close(); + + checkSigParseable(bOut.toByteArray()); + + // generate compressed stream + ByteArrayOutputStream cDataOut = new ByteArrayOutputStream(); + + cOut = cGen.open(cDataOut, new ZlibCompressor()); + + cOut.write(TEST_MESSAGE.getBytes()); + + cOut.close(); + + CMSSignedDataParser sp = new CMSSignedDataParser(digCalcProv, + new CMSTypedStream(new ByteArrayInputStream(cDataOut.toByteArray())), bOut.toByteArray()); + + sp.getSignedContent().drain(); + + // + // compute expected content digest + // + MessageDigest md = MessageDigest.getInstance("SHA1", BC); + + verifySignatures(sp, md.digest(cDataOut.toByteArray())); + } + + public void testDigestedData() + throws Exception + { + CMSDigestedData digData = new CMSDigestedData(digestedData); + + assertTrue(Arrays.areEqual(data, (byte[])digData.getDigestedContent().getContent())); + + assertTrue(digData.verify(new JcaDigestCalculatorProviderBuilder().setProvider(BC).build())); + } + + public static Test suite() + throws Exception + { + init(); + + return new CMSTestSetup(new TestSuite(MiscDataStreamTest.class)); + } +}
\ No newline at end of file diff --git a/pkix/src/test/java/org/spongycastle/cms/test/NewAuthenticatedDataStreamTest.java b/pkix/src/test/java/org/spongycastle/cms/test/NewAuthenticatedDataStreamTest.java new file mode 100644 index 00000000..589c64e4 --- /dev/null +++ b/pkix/src/test/java/org/spongycastle/cms/test/NewAuthenticatedDataStreamTest.java @@ -0,0 +1,251 @@ +package org.spongycastle.cms.test; + +import java.io.ByteArrayOutputStream; +import java.io.OutputStream; +import java.security.KeyPair; +import java.security.Security; +import java.security.cert.X509Certificate; +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.ASN1ObjectIdentifier; +import org.spongycastle.asn1.oiw.OIWObjectIdentifiers; +import org.spongycastle.asn1.pkcs.PKCSObjectIdentifiers; +import org.spongycastle.asn1.x509.AlgorithmIdentifier; +import org.spongycastle.cert.X509CertificateHolder; +import org.spongycastle.cms.CMSAlgorithm; +import org.spongycastle.cms.CMSAuthenticatedDataParser; +import org.spongycastle.cms.CMSAuthenticatedDataStreamGenerator; +import org.spongycastle.cms.OriginatorInfoGenerator; +import org.spongycastle.cms.RecipientInformation; +import org.spongycastle.cms.RecipientInformationStore; +import org.spongycastle.cms.jcajce.JceCMSMacCalculatorBuilder; +import org.spongycastle.cms.jcajce.JceKeyTransAuthenticatedRecipient; +import org.spongycastle.cms.jcajce.JceKeyTransRecipientInfoGenerator; +import org.spongycastle.jce.provider.BouncyCastleProvider; +import org.spongycastle.operator.DigestCalculatorProvider; +import org.spongycastle.operator.jcajce.JcaDigestCalculatorProviderBuilder; + +public class NewAuthenticatedDataStreamTest + extends TestCase +{ + private static final String BC = BouncyCastleProvider.PROVIDER_NAME; + + private static String _signDN; + private static KeyPair _signKP; + private static X509Certificate _signCert; + + private static String _origDN; + private static KeyPair _origKP; + private static X509Certificate _origCert; + + private static String _reciDN; + private static KeyPair _reciKP; + private static X509Certificate _reciCert; + + private static KeyPair _origEcKP; + private static KeyPair _reciEcKP; + private static X509Certificate _reciEcCert; + + private static boolean _initialised = false; + + public boolean DEBUG = true; + + private static void init() + throws Exception + { + if (!_initialised) + { + _initialised = true; + Security.addProvider(new org.spongycastle.jce.provider.BouncyCastleProvider()); + + _signDN = "O=Bouncy Castle, C=AU"; + _signKP = CMSTestUtil.makeKeyPair(); + _signCert = CMSTestUtil.makeCertificate(_signKP, _signDN, _signKP, _signDN); + + _origDN = "CN=Bob, OU=Sales, O=Bouncy Castle, C=AU"; + _origKP = CMSTestUtil.makeKeyPair(); + _origCert = CMSTestUtil.makeCertificate(_origKP, _origDN, _signKP, _signDN); + + _reciDN = "CN=Doug, OU=Sales, O=Bouncy Castle, C=AU"; + _reciKP = CMSTestUtil.makeKeyPair(); + _reciCert = CMSTestUtil.makeCertificate(_reciKP, _reciDN, _signKP, _signDN); + + _origEcKP = CMSTestUtil.makeEcDsaKeyPair(); + _reciEcKP = CMSTestUtil.makeEcDsaKeyPair(); + _reciEcCert = CMSTestUtil.makeCertificate(_reciEcKP, _reciDN, _signKP, _signDN); + } + } + + public void setUp() + throws Exception + { + init(); + } + + public NewAuthenticatedDataStreamTest(String name) + { + super(name); + } + + public static void main(String args[]) + { + junit.textui.TestRunner.run(NewAuthenticatedDataStreamTest.class); + } + + public static Test suite() + throws Exception + { + init(); + + return new CMSTestSetup(new TestSuite(NewAuthenticatedDataStreamTest.class)); + } + + public void testKeyTransDESede() + throws Exception + { + tryKeyTrans(CMSAlgorithm.DES_EDE3_CBC); + } + + public void testKeyTransDESedeWithDigest() + throws Exception + { + tryKeyTransWithDigest(CMSAlgorithm.DES_EDE3_CBC); + } + + public void testOriginatorInfo() + throws Exception + { + ASN1ObjectIdentifier macAlg = CMSAlgorithm.DES_EDE3_CBC; + byte[] data = "Eric H. Echidna".getBytes(); + + CMSAuthenticatedDataStreamGenerator adGen = new CMSAuthenticatedDataStreamGenerator(); + ByteArrayOutputStream bOut = new ByteArrayOutputStream(); + + X509CertificateHolder origCert = new X509CertificateHolder(_origCert.getEncoded()); + + adGen.setOriginatorInfo(new OriginatorInfoGenerator(origCert).generate()); + + adGen.addRecipientInfoGenerator(new JceKeyTransRecipientInfoGenerator(_reciCert).setProvider(BC)); + + OutputStream aOut = adGen.open(bOut, new JceCMSMacCalculatorBuilder(macAlg).setProvider(BC).build()); + + aOut.write(data); + + aOut.close(); + + CMSAuthenticatedDataParser ad = new CMSAuthenticatedDataParser(bOut.toByteArray()); + + assertTrue(ad.getOriginatorInfo().getCertificates().getMatches(null).contains(origCert)); + + RecipientInformationStore recipients = ad.getRecipientInfos(); + + assertEquals(ad.getMacAlgOID(), macAlg.getId()); + + Collection c = recipients.getRecipients(); + + assertEquals(1, c.size()); + + Iterator it = c.iterator(); + + while (it.hasNext()) + { + RecipientInformation recipient = (RecipientInformation)it.next(); + + assertEquals(recipient.getKeyEncryptionAlgOID(), PKCSObjectIdentifiers.rsaEncryption.getId()); + + byte[] recData = recipient.getContent(new JceKeyTransAuthenticatedRecipient(_reciKP.getPrivate()).setProvider(BC)); + + assertTrue(Arrays.equals(data, recData)); + assertTrue(Arrays.equals(ad.getMac(), recipient.getMac())); + } + } + + private void tryKeyTrans(ASN1ObjectIdentifier macAlg) + throws Exception + { + byte[] data = "Eric H. Echidna".getBytes(); + + CMSAuthenticatedDataStreamGenerator adGen = new CMSAuthenticatedDataStreamGenerator(); + ByteArrayOutputStream bOut = new ByteArrayOutputStream(); + + adGen.addRecipientInfoGenerator(new JceKeyTransRecipientInfoGenerator(_reciCert).setProvider(BC)); + + OutputStream aOut = adGen.open(bOut, new JceCMSMacCalculatorBuilder(macAlg).setProvider(BC).build()); + + aOut.write(data); + + aOut.close(); + + CMSAuthenticatedDataParser ad = new CMSAuthenticatedDataParser(bOut.toByteArray()); + + RecipientInformationStore recipients = ad.getRecipientInfos(); + + assertEquals(ad.getMacAlgOID(), macAlg.getId()); + + Collection c = recipients.getRecipients(); + + assertEquals(1, c.size()); + + Iterator it = c.iterator(); + + while (it.hasNext()) + { + RecipientInformation recipient = (RecipientInformation)it.next(); + + assertEquals(recipient.getKeyEncryptionAlgOID(), PKCSObjectIdentifiers.rsaEncryption.getId()); + + byte[] recData = recipient.getContent(new JceKeyTransAuthenticatedRecipient(_reciKP.getPrivate()).setProvider(BC)); + + assertTrue(Arrays.equals(data, recData)); + assertTrue(Arrays.equals(ad.getMac(), recipient.getMac())); + } + } + + private void tryKeyTransWithDigest(ASN1ObjectIdentifier macAlg) + throws Exception + { + byte[] data = "Eric H. Echidna".getBytes(); + + CMSAuthenticatedDataStreamGenerator adGen = new CMSAuthenticatedDataStreamGenerator(); + ByteArrayOutputStream bOut = new ByteArrayOutputStream(); + DigestCalculatorProvider calcProvider = new JcaDigestCalculatorProviderBuilder().setProvider(BC).build(); + + adGen.addRecipientInfoGenerator(new JceKeyTransRecipientInfoGenerator(_reciCert).setProvider(BC)); + + OutputStream aOut = adGen.open(bOut, new JceCMSMacCalculatorBuilder(macAlg).setProvider(BC).build(), calcProvider.get(new AlgorithmIdentifier(OIWObjectIdentifiers.idSHA1))); + + aOut.write(data); + + aOut.close(); + + CMSAuthenticatedDataParser ad = new CMSAuthenticatedDataParser(bOut.toByteArray(), calcProvider); + + RecipientInformationStore recipients = ad.getRecipientInfos(); + + assertEquals(ad.getMacAlgOID(), macAlg.getId()); + + Collection c = recipients.getRecipients(); + + assertEquals(1, c.size()); + + Iterator it = c.iterator(); + + while (it.hasNext()) + { + RecipientInformation recipient = (RecipientInformation)it.next(); + + assertEquals(recipient.getKeyEncryptionAlgOID(), PKCSObjectIdentifiers.rsaEncryption.getId()); + + byte[] recData = recipient.getContent(new JceKeyTransAuthenticatedRecipient(_reciKP.getPrivate()).setProvider(BC)); + + assertTrue(Arrays.equals(data, recData)); + assertTrue(Arrays.equals(ad.getMac(), recipient.getMac())); + assertTrue(Arrays.equals(ad.getContentDigest(), recipient.getContentDigest())); + } + } +}
\ No newline at end of file diff --git a/pkix/src/test/java/org/spongycastle/cms/test/NewAuthenticatedDataTest.java b/pkix/src/test/java/org/spongycastle/cms/test/NewAuthenticatedDataTest.java new file mode 100644 index 00000000..326748fe --- /dev/null +++ b/pkix/src/test/java/org/spongycastle/cms/test/NewAuthenticatedDataTest.java @@ -0,0 +1,472 @@ +package org.spongycastle.cms.test; + +import java.security.KeyPair; +import java.security.NoSuchAlgorithmException; +import java.security.NoSuchProviderException; +import java.security.Security; +import java.security.cert.X509Certificate; +import java.util.Arrays; +import java.util.Collection; +import java.util.Iterator; + +import javax.crypto.SecretKey; + +import junit.framework.Test; +import junit.framework.TestCase; +import junit.framework.TestSuite; +import org.spongycastle.asn1.ASN1ObjectIdentifier; +import org.spongycastle.asn1.oiw.OIWObjectIdentifiers; +import org.spongycastle.asn1.pkcs.PKCSObjectIdentifiers; +import org.spongycastle.asn1.x509.AlgorithmIdentifier; +import org.spongycastle.cert.X509CertificateHolder; +import org.spongycastle.cms.CMSAlgorithm; +import org.spongycastle.cms.CMSAuthenticatedData; +import org.spongycastle.cms.CMSAuthenticatedDataGenerator; +import org.spongycastle.cms.CMSException; +import org.spongycastle.cms.CMSProcessableByteArray; +import org.spongycastle.cms.OriginatorInfoGenerator; +import org.spongycastle.cms.PasswordRecipient; +import org.spongycastle.cms.PasswordRecipientInformation; +import org.spongycastle.cms.RecipientInformation; +import org.spongycastle.cms.RecipientInformationStore; +import org.spongycastle.cms.jcajce.JceCMSMacCalculatorBuilder; +import org.spongycastle.cms.jcajce.JceKEKAuthenticatedRecipient; +import org.spongycastle.cms.jcajce.JceKEKRecipientInfoGenerator; +import org.spongycastle.cms.jcajce.JceKeyAgreeAuthenticatedRecipient; +import org.spongycastle.cms.jcajce.JceKeyAgreeRecipientInfoGenerator; +import org.spongycastle.cms.jcajce.JceKeyTransAuthenticatedRecipient; +import org.spongycastle.cms.jcajce.JceKeyTransRecipientInfoGenerator; +import org.spongycastle.cms.jcajce.JcePasswordAuthenticatedRecipient; +import org.spongycastle.cms.jcajce.JcePasswordRecipientInfoGenerator; +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.encoders.Hex; + +public class NewAuthenticatedDataTest + extends TestCase +{ + private static final String BC = BouncyCastleProvider.PROVIDER_NAME; + + private static String _signDN; + private static KeyPair _signKP; + private static X509Certificate _signCert; + + private static String _origDN; + private static KeyPair _origKP; + private static X509Certificate _origCert; + + private static String _reciDN; + private static KeyPair _reciKP; + private static X509Certificate _reciCert; + + private static KeyPair _origEcKP; + private static KeyPair _reciEcKP; + private static X509Certificate _reciEcCert; + + private static boolean _initialised = false; + + public boolean DEBUG = true; + + private static void init() + throws Exception + { + if (!_initialised) + { + _initialised = true; + Security.addProvider(new org.spongycastle.jce.provider.BouncyCastleProvider()); + + _signDN = "O=Bouncy Castle, C=AU"; + _signKP = CMSTestUtil.makeKeyPair(); + _signCert = CMSTestUtil.makeCertificate(_signKP, _signDN, _signKP, _signDN); + + _origDN = "CN=Bob, OU=Sales, O=Bouncy Castle, C=AU"; + _origKP = CMSTestUtil.makeKeyPair(); + _origCert = CMSTestUtil.makeCertificate(_origKP, _origDN, _signKP, _signDN); + + _reciDN = "CN=Doug, OU=Sales, O=Bouncy Castle, C=AU"; + _reciKP = CMSTestUtil.makeKeyPair(); + _reciCert = CMSTestUtil.makeCertificate(_reciKP, _reciDN, _signKP, _signDN); + + _origEcKP = CMSTestUtil.makeEcDsaKeyPair(); + _reciEcKP = CMSTestUtil.makeEcDsaKeyPair(); + _reciEcCert = CMSTestUtil.makeCertificate(_reciEcKP, _reciDN, _signKP, _signDN); + } + } + + public void setUp() + throws Exception + { + init(); + } + + public NewAuthenticatedDataTest(String name) + { + super(name); + } + + public static void main(String args[]) + { + junit.textui.TestRunner.run(NewAuthenticatedDataTest.class); + } + + public static Test suite() + throws Exception + { + init(); + + return new CMSTestSetup(new TestSuite(NewAuthenticatedDataTest.class)); + } + + public void testKeyTransDESede() + throws Exception + { + tryKeyTrans(CMSAlgorithm.DES_EDE3_CBC); + } + + public void testKeyTransDESedeWithDigest() + throws Exception + { + tryKeyTransWithDigest(CMSAlgorithm.DES_EDE3_CBC); + } + + public void testKeyTransRC2() + throws Exception + { + tryKeyTrans(CMSAlgorithm.RC2_CBC); + } + + public void testKEKDESede() + throws Exception + { + tryKekAlgorithm(CMSTestUtil.makeDesede192Key(), new ASN1ObjectIdentifier("1.2.840.113549.1.9.16.3.6")); + } + + public void testKEKDESedeWithDigest() + throws Exception + { + tryKekAlgorithmWithDigest(CMSTestUtil.makeDesede192Key(), new ASN1ObjectIdentifier("1.2.840.113549.1.9.16.3.6")); + } + + public void testPasswordAES256() + throws Exception + { + passwordTest(CMSAuthenticatedDataGenerator.AES256_CBC); + } + + public void testECKeyAgree() + throws Exception + { + byte[] data = Hex.decode("504b492d4320434d5320456e76656c6f706564446174612053616d706c65"); + + CMSAuthenticatedDataGenerator adGen = new CMSAuthenticatedDataGenerator(); + + JceKeyAgreeRecipientInfoGenerator recipientGenerator = new JceKeyAgreeRecipientInfoGenerator(CMSAlgorithm.ECDH_SHA1KDF, _origEcKP.getPrivate(), _origEcKP.getPublic(), CMSAlgorithm.AES128_WRAP).setProvider(BC); + + recipientGenerator.addRecipient(_reciEcCert); + + adGen.addRecipientInfoGenerator(recipientGenerator); + + CMSAuthenticatedData ad = adGen.generate( + new CMSProcessableByteArray(data), + new JceCMSMacCalculatorBuilder(CMSAlgorithm.DES_EDE3_CBC).setProvider(BC).build()); + + RecipientInformationStore recipients = ad.getRecipientInfos(); + + assertEquals(ad.getMacAlgOID(), + CMSAuthenticatedDataGenerator.DES_EDE3_CBC); + + Collection c = recipients.getRecipients(); + Iterator it = c.iterator(); + + if (it.hasNext()) + { + RecipientInformation recipient = (RecipientInformation)it.next(); + + byte[] recData = recipient.getContent(new JceKeyAgreeAuthenticatedRecipient(_reciEcKP.getPrivate()).setProvider(BC)); + assertTrue(Arrays.equals(data, recData)); + assertTrue(Arrays.equals(ad.getMac(), recipient.getMac())); + } + else + { + fail("no recipient found"); + } + } + + public void testEncoding() + throws Exception + { + byte[] data = "Eric H. Echidna".getBytes(); + + CMSAuthenticatedDataGenerator adGen = new CMSAuthenticatedDataGenerator(); + + adGen.addRecipientInfoGenerator(new JceKeyTransRecipientInfoGenerator(_reciCert).setProvider(BC)); + + CMSAuthenticatedData ad = adGen.generate( + new CMSProcessableByteArray(data), + new JceCMSMacCalculatorBuilder(CMSAlgorithm.DES_EDE3_CBC).setProvider(BC).build()); + + ad = new CMSAuthenticatedData(ad.getEncoded()); + + RecipientInformationStore recipients = ad.getRecipientInfos(); + + assertEquals(CMSAuthenticatedDataGenerator.DES_EDE3_CBC, ad.getMacAlgOID()); + + Collection c = recipients.getRecipients(); + + assertEquals(1, c.size()); + + Iterator it = c.iterator(); + + while (it.hasNext()) + { + RecipientInformation recipient = (RecipientInformation)it.next(); + + assertEquals(recipient.getKeyEncryptionAlgOID(), PKCSObjectIdentifiers.rsaEncryption.getId()); + + byte[] recData = recipient.getContent(new JceKeyTransAuthenticatedRecipient(_reciKP.getPrivate()).setProvider(BC)); + + assertTrue(Arrays.equals(data, recData)); + assertTrue(Arrays.equals(ad.getMac(), recipient.getMac())); + } + } + + public void testOriginatorInfo() + throws Exception + { + byte[] data = "Eric H. Echidna".getBytes(); + ASN1ObjectIdentifier macAlg = CMSAlgorithm.DES_EDE3_CBC; + + CMSAuthenticatedDataGenerator adGen = new CMSAuthenticatedDataGenerator(); + + X509CertificateHolder origCert = new X509CertificateHolder(_origCert.getEncoded()); + + adGen.setOriginatorInfo(new OriginatorInfoGenerator(origCert).generate()); + + adGen.addRecipientInfoGenerator(new JceKeyTransRecipientInfoGenerator(_reciCert).setProvider(BC)); + + CMSAuthenticatedData ad = adGen.generate( + new CMSProcessableByteArray(data), + new JceCMSMacCalculatorBuilder(macAlg).setProvider(BC).build()); + + assertTrue(ad.getOriginatorInfo().getCertificates().getMatches(null).contains(origCert)); + + RecipientInformationStore recipients = ad.getRecipientInfos(); + + assertEquals(ad.getMacAlgOID(), macAlg.getId()); + + Collection c = recipients.getRecipients(); + + assertEquals(1, c.size()); + + Iterator it = c.iterator(); + + while (it.hasNext()) + { + RecipientInformation recipient = (RecipientInformation)it.next(); + + assertEquals(recipient.getKeyEncryptionAlgOID(), PKCSObjectIdentifiers.rsaEncryption.getId()); + + byte[] recData = recipient.getContent(new JceKeyTransAuthenticatedRecipient(_reciKP.getPrivate()).setProvider(BC)); + + assertTrue(Arrays.equals(data, recData)); + assertTrue(Arrays.equals(ad.getMac(), recipient.getMac())); + } + } + + private void tryKeyTrans(ASN1ObjectIdentifier macAlg) + throws Exception + { + byte[] data = "Eric H. Echidna".getBytes(); + + CMSAuthenticatedDataGenerator adGen = new CMSAuthenticatedDataGenerator(); + + adGen.addRecipientInfoGenerator(new JceKeyTransRecipientInfoGenerator(_reciCert).setProvider(BC)); + + CMSAuthenticatedData ad = adGen.generate( + new CMSProcessableByteArray(data), + new JceCMSMacCalculatorBuilder(macAlg).setProvider(BC).build()); + + RecipientInformationStore recipients = ad.getRecipientInfos(); + + assertEquals(ad.getMacAlgOID(), macAlg.getId()); + + Collection c = recipients.getRecipients(); + + assertEquals(1, c.size()); + + Iterator it = c.iterator(); + + while (it.hasNext()) + { + RecipientInformation recipient = (RecipientInformation)it.next(); + + assertEquals(recipient.getKeyEncryptionAlgOID(), PKCSObjectIdentifiers.rsaEncryption.getId()); + + byte[] recData = recipient.getContent(new JceKeyTransAuthenticatedRecipient(_reciKP.getPrivate()).setProvider(BC)); + + assertTrue(Arrays.equals(data, recData)); + assertTrue(Arrays.equals(ad.getMac(), recipient.getMac())); + } + } + + private void tryKeyTransWithDigest(ASN1ObjectIdentifier macAlg) + throws Exception + { + byte[] data = "Eric H. Echidna".getBytes(); + + CMSAuthenticatedDataGenerator adGen = new CMSAuthenticatedDataGenerator(); + DigestCalculatorProvider calcProvider = new JcaDigestCalculatorProviderBuilder().setProvider(BC).build(); + + adGen.addRecipientInfoGenerator(new JceKeyTransRecipientInfoGenerator(_reciCert).setProvider(BC)); + + CMSAuthenticatedData ad = adGen.generate( + new CMSProcessableByteArray(data), + new JceCMSMacCalculatorBuilder(macAlg).setProvider(BC).build(), + calcProvider.get(new AlgorithmIdentifier(OIWObjectIdentifiers.idSHA1))); + + RecipientInformationStore recipients = ad.getRecipientInfos(); + + assertEquals(ad.getMacAlgOID(), macAlg.getId()); + + Collection c = recipients.getRecipients(); + + assertEquals(1, c.size()); + + Iterator it = c.iterator(); + + while (it.hasNext()) + { + RecipientInformation recipient = (RecipientInformation)it.next(); + + assertEquals(recipient.getKeyEncryptionAlgOID(), PKCSObjectIdentifiers.rsaEncryption.getId()); + + byte[] recData = recipient.getContent(new JceKeyTransAuthenticatedRecipient(_reciKP.getPrivate()).setProvider(BC)); + + assertTrue(Arrays.equals(data, recData)); + assertTrue(Arrays.equals(ad.getMac(), recipient.getMac())); + assertTrue(Arrays.equals(ad.getContentDigest(), recipient.getContentDigest())); + } + } + + private void tryKekAlgorithm(SecretKey kek, ASN1ObjectIdentifier algOid) + throws NoSuchAlgorithmException, NoSuchProviderException, CMSException, OperatorCreationException + { + byte[] data = "Eric H. Echidna".getBytes(); + + CMSAuthenticatedDataGenerator adGen = new CMSAuthenticatedDataGenerator(); + + byte[] kekId = new byte[] { 1, 2, 3, 4, 5 }; + + adGen.addRecipientInfoGenerator(new JceKEKRecipientInfoGenerator(kekId, kek).setProvider(BC)); + + CMSAuthenticatedData ad = adGen.generate( + new CMSProcessableByteArray(data), + new JceCMSMacCalculatorBuilder(CMSAlgorithm.DES_EDE3_CBC).setProvider(BC).build()); + + RecipientInformationStore recipients = ad.getRecipientInfos(); + + Collection c = recipients.getRecipients(); + Iterator it = c.iterator(); + + assertEquals(ad.getMacAlgOID(), CMSAuthenticatedDataGenerator.DES_EDE3_CBC); + + if (it.hasNext()) + { + RecipientInformation recipient = (RecipientInformation)it.next(); + + assertEquals(recipient.getKeyEncryptionAlgOID(), algOid.getId()); + + byte[] recData = recipient.getContent(new JceKEKAuthenticatedRecipient(kek).setProvider(BC)); + + assertTrue(Arrays.equals(data, recData)); + assertTrue(Arrays.equals(ad.getMac(), recipient.getMac())); + } + else + { + fail("no recipient found"); + } + } + + private void tryKekAlgorithmWithDigest(SecretKey kek, ASN1ObjectIdentifier algOid) + throws NoSuchAlgorithmException, NoSuchProviderException, CMSException, OperatorCreationException + { + byte[] data = "Eric H. Echidna".getBytes(); + + CMSAuthenticatedDataGenerator adGen = new CMSAuthenticatedDataGenerator(); + DigestCalculatorProvider calcProvider = new JcaDigestCalculatorProviderBuilder().setProvider(BC).build(); + + byte[] kekId = new byte[] { 1, 2, 3, 4, 5 }; + + adGen.addRecipientInfoGenerator(new JceKEKRecipientInfoGenerator(kekId, kek).setProvider(BC)); + + CMSAuthenticatedData ad = adGen.generate( + new CMSProcessableByteArray(data), + new JceCMSMacCalculatorBuilder(CMSAlgorithm.DES_EDE3_CBC).setProvider(BC).build(), + calcProvider.get(new AlgorithmIdentifier(OIWObjectIdentifiers.idSHA1))); + + RecipientInformationStore recipients = ad.getRecipientInfos(); + + Collection c = recipients.getRecipients(); + Iterator it = c.iterator(); + + assertEquals(ad.getMacAlgOID(), CMSAuthenticatedDataGenerator.DES_EDE3_CBC); + + if (it.hasNext()) + { + RecipientInformation recipient = (RecipientInformation)it.next(); + + assertEquals(recipient.getKeyEncryptionAlgOID(), algOid.getId()); + + byte[] recData = recipient.getContent(new JceKEKAuthenticatedRecipient(kek).setProvider(BC)); + + assertTrue(Arrays.equals(data, recData)); + assertTrue(Arrays.equals(ad.getMac(), recipient.getMac())); + assertTrue(Arrays.equals(ad.getContentDigest(), recipient.getContentDigest())); + } + else + { + fail("no recipient found"); + } + } + + + private void passwordTest(String algorithm) + throws Exception + { + byte[] data = Hex.decode("504b492d4320434d5320456e76656c6f706564446174612053616d706c65"); + + CMSAuthenticatedDataGenerator adGen = new CMSAuthenticatedDataGenerator(); + + adGen.addRecipientInfoGenerator(new JcePasswordRecipientInfoGenerator(new ASN1ObjectIdentifier(algorithm), "password".toCharArray()).setProvider(BC).setSaltAndIterationCount(new byte[20], 5)); + + CMSAuthenticatedData ad = adGen.generate( + new CMSProcessableByteArray(data), + new JceCMSMacCalculatorBuilder(CMSAlgorithm.DES_EDE3_CBC).setProvider(BC).build()); + + RecipientInformationStore recipients = ad.getRecipientInfos(); + + assertEquals(ad.getMacAlgOID(), + CMSAuthenticatedDataGenerator.DES_EDE3_CBC); + + Collection c = recipients.getRecipients(); + Iterator it = c.iterator(); + + if (it.hasNext()) + { + PasswordRecipientInformation recipient = (PasswordRecipientInformation)it.next(); + + PasswordRecipient pbeRep = new JcePasswordAuthenticatedRecipient("password".toCharArray()).setProvider(BC); + + byte[] recData = recipient.getContent(pbeRep); + + assertTrue(Arrays.equals(data, recData)); + assertTrue(Arrays.equals(ad.getMac(), recipient.getMac())); + } + else + { + fail("no recipient found"); + } + } +}
\ No newline at end of file diff --git a/pkix/src/test/java/org/spongycastle/cms/test/NewCompressedDataStreamTest.java b/pkix/src/test/java/org/spongycastle/cms/test/NewCompressedDataStreamTest.java new file mode 100644 index 00000000..f2edfbe9 --- /dev/null +++ b/pkix/src/test/java/org/spongycastle/cms/test/NewCompressedDataStreamTest.java @@ -0,0 +1,127 @@ +package org.spongycastle.cms.test; + +import java.io.ByteArrayOutputStream; +import java.io.OutputStream; +import java.util.Arrays; +import java.util.Random; + +import junit.framework.Test; +import junit.framework.TestCase; +import junit.framework.TestSuite; +import org.spongycastle.cms.CMSCompressedDataParser; +import org.spongycastle.cms.CMSCompressedDataStreamGenerator; +import org.spongycastle.cms.jcajce.ZlibCompressor; +import org.spongycastle.cms.jcajce.ZlibExpanderProvider; +import org.spongycastle.util.encoders.Base64; + +public class NewCompressedDataStreamTest + extends TestCase +{ + public NewCompressedDataStreamTest(String name) + { + super(name); + } + + public void testWorkingData() + throws Exception + { + byte[] compData = Base64.decode( + "MIAGCyqGSIb3DQEJEAEJoIAwgAIBADANBgsqhkiG9w0BCRADCDCABgkqhkiG9w0BBwGggCSABIIC" + + "Hnic7ZRdb9owFIbvK/k/5PqVYPFXGK12YYyboVFASSp1vQtZGiLRACZE49/XHoUW7S/0tXP8Efux" + + "fU5ivWnasml72XFb3gb5druui7ytN803M570nii7C5r8tfwR281hy/p/KSM3+jzH5s3+pbQ90xSb" + + "P3VT3QbLusnt8WPIuN5vN/vaA2+DulnXTXkXvNTr8j8ouZmkCmGI/UW+ZS/C8zP0bz2dz0zwLt+1" + + "UEk2M8mlaxjRMByAhZTj0RGYg4TvogiRASROsZgjpVcJCb1KV6QzQeDJ1XkoQ5Jm+C5PbOHZZGRi" + + "v+ORAcshOGeCcdFJyfgFxdtCdEcmOrbinc/+BBMzRThEYpwl+jEBpciSGWQkI0TSlREmD/eOHb2D" + + "SGLuESm/iKUFt1y4XHBO2a5oq0IKJKWLS9kUZTA7vC5LSxYmgVL46SIWxIfWBQd6AdrnjLmH94UT" + + "vGxVibLqRCtIpp4g2qpdtqK1LiOeolpVK5wVQ5P7+QjZAlrh0cePYTx/gNZuB9Vhndtgujl9T/tg" + + "W9ogK+3rnmg3YWygnTuF5GDS+Q/jIVLnCcYZFc6Kk/+c80wKwZjwdZIqDYWRH68MuBQSXLgXYXj2" + + "3CAaYOBNJMliTl0X7eV5DnoKIFSKYdj3cRpD/cK/JWTHJRe76MUXnfBW8m7Hd5zhQ4ri2NrVF/WL" + + "+kV1/3AGSlJ32bFPd2BsQD8uSzIx6lObkjdz95c0AAAAAAAAAAAAAAAA"); + + byte[] uncompData = Base64.decode( + "Q29udGVudC1UeXBlOiBhcHBsaWNhdGlvbi9FREktWDEyOyBuYW1lPUdyb3VwMi54MTINCkNvbnRl" + + "bnQtVHJhbnNmZXItRW5jb2Rpbmc6IGJpbmFyeQ0KQ29udGVudC1EaXNwb3NpdGlvbjogaW5saW5l" + + "OyBmaWxlbmFtZT1Hcm91cDIueDEyDQoNCklTQSowMCpzc3Nzc3Nzc3NzKjAwKnJycnJycnJycnIqW" + + "loqQ1lDTE9ORSAgICAgICAgKlpaKlBBUlRORVIgICAgICAgICo5NjEwMDcqMjAxMypVKjAwMjAwKj" + + "AwMDAwMDAwMSowKlQqKg1HUypQTypTMVMxUzFTMVMxUzFTMVMqUjFSMVIxUjFSMVIxUjFSKjk2MTA" + + "wNyoyMDEzKjAwMDAwMDAwNCpYKjAwMzA1MA1TVCo4NTAqMDAwMDQwMDAxDUJFRyowMCpCRSoyYSo0" + + "MzMyNDIzNHY1NTIzKjk2MTAwNyoyM3RjNHZ5MjR2MmgzdmgzdmgqWloqSUVMKjA5KlJFKjA5DUNVU" + + "ioxMSpUUk4qNTY1Nio2NSo1NjYqSU1GKjAwNio5NjEwMDcNUkVGKjZBKjQzM3IxYzNyMzRyMzRjMz" + + "MxMnFjdGdjNTQqUmVmZXJlbmNlIE51bWJlcg1QRVIqQUEqSGFucyBHdXR0ZW4qQ1AqMS4zMjIuMzI" + + "zLjQ0NDQqKioqKnJnZzRlZ3Y0dDQNVEFYKjR0Z3RidDR0cjR0cipHTCpnaGdoKioqKioqKioqRypD" + + "DUZPQipUUCpDQSpVU0EqMDIqRE9NKkNDKlJlZ3VsYXIgTG9jYXRpb25zIHBlciBUZXJtcw1DVFAqR" + + "EUqQzA0KjQ1MyoyNTAwMCpEOSpTRUwqMjMyMTQqMjM0MzI0MjM0MjMqRVMqNDIyNDM0MjMNU0FDKk" + + "EqQjAwMCpBRSozNTQ1KjM0NDIzMDANQ1VSKjExKjc2Nyo3NzY3KjY1DVBPMSoxMTEtYWFhKjEwMDA" + + "wMDAqQVMqOTAuMDAqQkQqQUsqMjM0MjM1djM1MzRxNmYzNTM0djQzNTM0NTN2cTNxMzIqKioqKioq" + + "KioqKkExKnl0cmgNUE8xKjExMS1hYWEqMTAwMDAwMCpBUyo5MC4wMCpCRCpBSyoyMzQyMzV2MzUzN" + + "HE2ZjM1MzR2NDM1MzQ1M3ZxM3EzMioqKioqKioqKioqQTEqeXRyaA1QTzEqMTExLWFhYSoxMDAwMD" + + "AwKkFTKjkwLjAwKkJEKkFLKjIzNDIzNXYzNTM0cTZmMzUzNHY0MzUzNDUzdnEzcTMyKioqKioqKio" + + "qKipBMSp5dHJoDVBPMSoxMTEtYWFhKjEwMDAwMDAqQVMqOTAuMDAqQkQqQUsqMjM0MjM1djM1MzRx" + + "NmYzNTM0djQzNTM0NTN2cTNxMzIqKioqKioqKioqKkExKnl0cmgNUE8xKjExMS1hYWEqMTAwMDAwM" + + "CpBUyo5MC4wMCpCRCpBSyoyMzQyMzV2MzUzNHE2ZjM1MzR2NDM1MzQ1M3ZxM3EzMioqKioqKioqKi" + + "oqQTEqeXRyaA1QTzEqMTExLWFhYSoxMDAwMDAwKkFTKjkwLjAwKkJEKkFLKjIzNDIzNXYzNTM0cTZ" + + "mMzUzNHY0MzUzNDUzdnEzcTMyKioqKioqKioqKipBMSp5dHJoDVBPMSoxMTEtYWFhKjEwMDAwMDAq" + + "QVMqOTAuMDAqQkQqQUsqMjM0MjM1djM1MzRxNmYzNTM0djQzNTM0NTN2cTNxMzIqKioqKioqKioqK" + + "kExKnl0cmgNUE8xKjExMS1hYWEqMTAwMDAwMCpBUyo5MC4wMCpCRCpBSyoyMzQyMzV2MzUzNHE2Zj" + + "M1MzR2NDM1MzQ1M3ZxM3EzMioqKioqKioqKioqQTEqeXRyaA1QTzEqMTExLWFhYSoxMDAwMDAwKkF" + + "TKjkwLjAwKkJEKkFLKjIzNDIzNXYzNTM0cTZmMzUzNHY0MzUzNDUzdnEzcTMyKioqKioqKioqKipB" + + "MSp5dHJoDVBPMSoxMTEtYWFhKjEwMDAwMDAqQVMqOTAuMDAqQkQqQUsqMjM0MjM1djM1MzRxNmYzN" + + "TM0djQzNTM0NTN2cTNxMzIqKioqKioqKioqKkExKnl0cmgNQ1RUKjENU0UqMjIqMDAwMDQwMDAxDU" + + "dFKjEqMDAwMDAwMDA0DUlFQSoxKjAwMDAwMDAwMQ0="); + + CMSCompressedDataParser ed = new CMSCompressedDataParser(compData); + + assertEquals(true, Arrays.equals(uncompData, CMSTestUtil.streamToByteArray(ed.getContent(new ZlibExpanderProvider()).getContentStream()))); + } + + public void testEach() + throws Exception + { + byte[] testData = "Hello world!".getBytes(); + + CMSCompressedDataStreamGenerator gen = new CMSCompressedDataStreamGenerator(); + ByteArrayOutputStream bOut = new ByteArrayOutputStream(); + + OutputStream cOut = gen.open(bOut, new ZlibCompressor()); + + cOut.write(testData); + + cOut.close(); + + CMSCompressedDataParser ed = new CMSCompressedDataParser(bOut.toByteArray()); + + assertEquals(true, Arrays.equals(testData, CMSTestUtil.streamToByteArray(ed.getContent(new ZlibExpanderProvider()).getContentStream()))); + } + + public void test1000() + throws Exception + { + byte[] testData = new byte[10000]; + Random rand = new Random(); + + rand.setSeed(0); + + for (int i = 0; i != 10; i++) + { + CMSCompressedDataStreamGenerator gen = new CMSCompressedDataStreamGenerator(); + ByteArrayOutputStream bOut = new ByteArrayOutputStream(); + + OutputStream cOut = gen.open(bOut, new ZlibCompressor()); + + rand.nextBytes(testData); + + cOut.write(testData); + + cOut.close(); + + CMSCompressedDataParser ed = new CMSCompressedDataParser(bOut.toByteArray()); + + assertEquals(true, Arrays.equals(testData, CMSTestUtil.streamToByteArray(ed.getContent(new ZlibExpanderProvider()).getContentStream()))); + } + } + + public static Test suite() + { + return new TestSuite(NewCompressedDataStreamTest.class); + } +} diff --git a/pkix/src/test/java/org/spongycastle/cms/test/NewCompressedDataTest.java b/pkix/src/test/java/org/spongycastle/cms/test/NewCompressedDataTest.java new file mode 100644 index 00000000..13600e72 --- /dev/null +++ b/pkix/src/test/java/org/spongycastle/cms/test/NewCompressedDataTest.java @@ -0,0 +1,151 @@ +package org.spongycastle.cms.test; + +import java.util.Arrays; + +import junit.framework.Test; +import junit.framework.TestCase; +import junit.framework.TestSuite; +import org.spongycastle.cms.CMSCompressedData; +import org.spongycastle.cms.CMSCompressedDataGenerator; +import org.spongycastle.cms.CMSException; +import org.spongycastle.cms.CMSProcessableByteArray; +import org.spongycastle.cms.jcajce.ZlibCompressor; +import org.spongycastle.cms.jcajce.ZlibExpanderProvider; +import org.spongycastle.util.encoders.Base64; +import org.spongycastle.util.io.StreamOverflowException; + +public class NewCompressedDataTest + extends TestCase +{ + private static final byte[] TEST_DATA = "Hello world!".getBytes(); + + /* + * + * INFRASTRUCTURE + * + */ + + public NewCompressedDataTest(String name) + { + super(name); + } + + public static void main(String args[]) + { + junit.textui.TestRunner.run(NewCompressedDataTest.class); + } + + public static Test suite() + { + return new CMSTestSetup(new TestSuite(NewCompressedDataTest.class)); + } + + public void setUp() + { + + } + + public void tearDown() + { + + } + + public void testWorkingData() + throws Exception + { + byte[] compData = Base64 + .decode("MIAGCyqGSIb3DQEJEAEJoIAwgAIBADANBgsqhkiG9w0BCRADCDCABgkqhkiG9w0BBwGggCSABIIC" + + "Hnic7ZRdb9owFIbvK/k/5PqVYPFXGK12YYyboVFASSp1vQtZGiLRACZE49/XHoUW7S/0tXP8Efux" + + "fU5ivWnasml72XFb3gb5druui7ytN803M570nii7C5r8tfwR281hy/p/KSM3+jzH5s3+pbQ90xSb" + + "P3VT3QbLusnt8WPIuN5vN/vaA2+DulnXTXkXvNTr8j8ouZmkCmGI/UW+ZS/C8zP0bz2dz0zwLt+1" + + "UEk2M8mlaxjRMByAhZTj0RGYg4TvogiRASROsZgjpVcJCb1KV6QzQeDJ1XkoQ5Jm+C5PbOHZZGRi" + + "v+ORAcshOGeCcdFJyfgFxdtCdEcmOrbinc/+BBMzRThEYpwl+jEBpciSGWQkI0TSlREmD/eOHb2D" + + "SGLuESm/iKUFt1y4XHBO2a5oq0IKJKWLS9kUZTA7vC5LSxYmgVL46SIWxIfWBQd6AdrnjLmH94UT" + + "vGxVibLqRCtIpp4g2qpdtqK1LiOeolpVK5wVQ5P7+QjZAlrh0cePYTx/gNZuB9Vhndtgujl9T/tg" + + "W9ogK+3rnmg3YWygnTuF5GDS+Q/jIVLnCcYZFc6Kk/+c80wKwZjwdZIqDYWRH68MuBQSXLgXYXj2" + + "3CAaYOBNJMliTl0X7eV5DnoKIFSKYdj3cRpD/cK/JWTHJRe76MUXnfBW8m7Hd5zhQ4ri2NrVF/WL" + + "+kV1/3AGSlJ32bFPd2BsQD8uSzIx6lObkjdz95c0AAAAAAAAAAAAAAAA"); + + byte[] uncompData = Base64 + .decode("Q29udGVudC1UeXBlOiBhcHBsaWNhdGlvbi9FREktWDEyOyBuYW1lPUdyb3VwMi54MTINCkNvbnRl" + + "bnQtVHJhbnNmZXItRW5jb2Rpbmc6IGJpbmFyeQ0KQ29udGVudC1EaXNwb3NpdGlvbjogaW5saW5l" + + "OyBmaWxlbmFtZT1Hcm91cDIueDEyDQoNCklTQSowMCpzc3Nzc3Nzc3NzKjAwKnJycnJycnJycnIqW" + + "loqQ1lDTE9ORSAgICAgICAgKlpaKlBBUlRORVIgICAgICAgICo5NjEwMDcqMjAxMypVKjAwMjAwKj" + + "AwMDAwMDAwMSowKlQqKg1HUypQTypTMVMxUzFTMVMxUzFTMVMqUjFSMVIxUjFSMVIxUjFSKjk2MTA" + + "wNyoyMDEzKjAwMDAwMDAwNCpYKjAwMzA1MA1TVCo4NTAqMDAwMDQwMDAxDUJFRyowMCpCRSoyYSo0" + + "MzMyNDIzNHY1NTIzKjk2MTAwNyoyM3RjNHZ5MjR2MmgzdmgzdmgqWloqSUVMKjA5KlJFKjA5DUNVU" + + "ioxMSpUUk4qNTY1Nio2NSo1NjYqSU1GKjAwNio5NjEwMDcNUkVGKjZBKjQzM3IxYzNyMzRyMzRjMz" + + "MxMnFjdGdjNTQqUmVmZXJlbmNlIE51bWJlcg1QRVIqQUEqSGFucyBHdXR0ZW4qQ1AqMS4zMjIuMzI" + + "zLjQ0NDQqKioqKnJnZzRlZ3Y0dDQNVEFYKjR0Z3RidDR0cjR0cipHTCpnaGdoKioqKioqKioqRypD" + + "DUZPQipUUCpDQSpVU0EqMDIqRE9NKkNDKlJlZ3VsYXIgTG9jYXRpb25zIHBlciBUZXJtcw1DVFAqR" + + "EUqQzA0KjQ1MyoyNTAwMCpEOSpTRUwqMjMyMTQqMjM0MzI0MjM0MjMqRVMqNDIyNDM0MjMNU0FDKk" + + "EqQjAwMCpBRSozNTQ1KjM0NDIzMDANQ1VSKjExKjc2Nyo3NzY3KjY1DVBPMSoxMTEtYWFhKjEwMDA" + + "wMDAqQVMqOTAuMDAqQkQqQUsqMjM0MjM1djM1MzRxNmYzNTM0djQzNTM0NTN2cTNxMzIqKioqKioq" + + "KioqKkExKnl0cmgNUE8xKjExMS1hYWEqMTAwMDAwMCpBUyo5MC4wMCpCRCpBSyoyMzQyMzV2MzUzN" + + "HE2ZjM1MzR2NDM1MzQ1M3ZxM3EzMioqKioqKioqKioqQTEqeXRyaA1QTzEqMTExLWFhYSoxMDAwMD" + + "AwKkFTKjkwLjAwKkJEKkFLKjIzNDIzNXYzNTM0cTZmMzUzNHY0MzUzNDUzdnEzcTMyKioqKioqKio" + + "qKipBMSp5dHJoDVBPMSoxMTEtYWFhKjEwMDAwMDAqQVMqOTAuMDAqQkQqQUsqMjM0MjM1djM1MzRx" + + "NmYzNTM0djQzNTM0NTN2cTNxMzIqKioqKioqKioqKkExKnl0cmgNUE8xKjExMS1hYWEqMTAwMDAwM" + + "CpBUyo5MC4wMCpCRCpBSyoyMzQyMzV2MzUzNHE2ZjM1MzR2NDM1MzQ1M3ZxM3EzMioqKioqKioqKi" + + "oqQTEqeXRyaA1QTzEqMTExLWFhYSoxMDAwMDAwKkFTKjkwLjAwKkJEKkFLKjIzNDIzNXYzNTM0cTZ" + + "mMzUzNHY0MzUzNDUzdnEzcTMyKioqKioqKioqKipBMSp5dHJoDVBPMSoxMTEtYWFhKjEwMDAwMDAq" + + "QVMqOTAuMDAqQkQqQUsqMjM0MjM1djM1MzRxNmYzNTM0djQzNTM0NTN2cTNxMzIqKioqKioqKioqK" + + "kExKnl0cmgNUE8xKjExMS1hYWEqMTAwMDAwMCpBUyo5MC4wMCpCRCpBSyoyMzQyMzV2MzUzNHE2Zj" + + "M1MzR2NDM1MzQ1M3ZxM3EzMioqKioqKioqKioqQTEqeXRyaA1QTzEqMTExLWFhYSoxMDAwMDAwKkF" + + "TKjkwLjAwKkJEKkFLKjIzNDIzNXYzNTM0cTZmMzUzNHY0MzUzNDUzdnEzcTMyKioqKioqKioqKipB" + + "MSp5dHJoDVBPMSoxMTEtYWFhKjEwMDAwMDAqQVMqOTAuMDAqQkQqQUsqMjM0MjM1djM1MzRxNmYzN" + + "TM0djQzNTM0NTN2cTNxMzIqKioqKioqKioqKkExKnl0cmgNQ1RUKjENU0UqMjIqMDAwMDQwMDAxDUdFKjEqMDAwMDAwMDA0DUlFQSoxKjAwMDAwMDAwMQ0="); + + CMSCompressedData ed = new CMSCompressedData(compData); + + assertEquals(true, Arrays.equals(uncompData, ed.getContent(new ZlibExpanderProvider()))); + } + + public void testEach() + throws Exception + { + CMSCompressedData cd = getStdData(); + + assertEquals(true, Arrays.equals(TEST_DATA, cd.getContent(new ZlibExpanderProvider()))); + } + + public void testLimitUnder() + throws Exception + { + CMSCompressedData cd = getStdData(); + + try + { + cd.getContent(new ZlibExpanderProvider(TEST_DATA.length / 2)); + } + catch (CMSException e) + { + assertEquals(true, e.getCause() instanceof StreamOverflowException); + } + } + + public void testLimitOver() + throws Exception + { + CMSCompressedData cd = getStdData(); + + assertEquals(true, Arrays.equals(TEST_DATA, cd.getContent(new ZlibExpanderProvider(TEST_DATA.length * 2)))); + } + + public void testLimitEqual() + throws Exception + { + CMSCompressedData cd = getStdData(); + + assertEquals(true, Arrays.equals(TEST_DATA, cd.getContent(new ZlibExpanderProvider(TEST_DATA.length)))); + } + + private CMSCompressedData getStdData() + throws CMSException + { + CMSProcessableByteArray testData = new CMSProcessableByteArray(TEST_DATA); + CMSCompressedDataGenerator gen = new CMSCompressedDataGenerator(); + + return gen.generate(testData, new ZlibCompressor()); + } +} diff --git a/pkix/src/test/java/org/spongycastle/cms/test/NewEnvelopedDataStreamTest.java b/pkix/src/test/java/org/spongycastle/cms/test/NewEnvelopedDataStreamTest.java new file mode 100644 index 00000000..3a86a67a --- /dev/null +++ b/pkix/src/test/java/org/spongycastle/cms/test/NewEnvelopedDataStreamTest.java @@ -0,0 +1,760 @@ +package org.spongycastle.cms.test; + +import java.io.BufferedOutputStream; +import java.io.ByteArrayOutputStream; +import java.io.InputStream; +import java.io.OutputStream; +import java.security.KeyFactory; +import java.security.KeyPair; +import java.security.PrivateKey; +import java.security.Security; +import java.security.cert.X509Certificate; +import java.security.spec.PKCS8EncodedKeySpec; +import java.util.Arrays; +import java.util.Collection; +import java.util.Hashtable; +import java.util.Iterator; + +import javax.crypto.SecretKey; + +import junit.framework.Test; +import junit.framework.TestCase; +import junit.framework.TestSuite; +import org.spongycastle.asn1.ASN1InputStream; +import org.spongycastle.asn1.DEROutputStream; +import org.spongycastle.asn1.DERSet; +import org.spongycastle.asn1.DERUTF8String; +import org.spongycastle.asn1.cms.Attribute; +import org.spongycastle.asn1.cms.AttributeTable; +import org.spongycastle.asn1.pkcs.PKCSObjectIdentifiers; +import org.spongycastle.asn1.x500.X500Name; +import org.spongycastle.cert.X509CertificateHolder; +import org.spongycastle.cms.CMSAlgorithm; +import org.spongycastle.cms.CMSEnvelopedDataGenerator; +import org.spongycastle.cms.CMSEnvelopedDataParser; +import org.spongycastle.cms.CMSEnvelopedDataStreamGenerator; +import org.spongycastle.cms.CMSTypedStream; +import org.spongycastle.cms.KEKRecipientId; +import org.spongycastle.cms.OriginatorInfoGenerator; +import org.spongycastle.cms.OriginatorInformation; +import org.spongycastle.cms.RecipientId; +import org.spongycastle.cms.RecipientInformation; +import org.spongycastle.cms.RecipientInformationStore; +import org.spongycastle.cms.SimpleAttributeTableGenerator; +import org.spongycastle.cms.jcajce.JceCMSContentEncryptorBuilder; +import org.spongycastle.cms.jcajce.JceKEKEnvelopedRecipient; +import org.spongycastle.cms.jcajce.JceKEKRecipientInfoGenerator; +import org.spongycastle.cms.jcajce.JceKeyAgreeEnvelopedRecipient; +import org.spongycastle.cms.jcajce.JceKeyAgreeRecipientId; +import org.spongycastle.cms.jcajce.JceKeyAgreeRecipientInfoGenerator; +import org.spongycastle.cms.jcajce.JceKeyTransEnvelopedRecipient; +import org.spongycastle.cms.jcajce.JceKeyTransRecipientInfoGenerator; +import org.spongycastle.jce.provider.BouncyCastleProvider; +import org.spongycastle.util.encoders.Base64; +import org.spongycastle.util.encoders.Hex; + +public class NewEnvelopedDataStreamTest + extends TestCase +{ + private static final String BC = BouncyCastleProvider.PROVIDER_NAME; + + private static final int BUFFER_SIZE = 4000; + private static String _signDN; + private static KeyPair _signKP; + private static X509Certificate _signCert; + + private static String _origDN; + private static KeyPair _origKP; + private static X509Certificate _origCert; + + private static String _reciDN; + private static KeyPair _reciKP; + private static X509Certificate _reciCert; + + private static KeyPair _origEcKP; + private static KeyPair _reciEcKP; + private static X509Certificate _reciEcCert; + + private static boolean _initialised = false; + + public NewEnvelopedDataStreamTest() + { + } + + private static void init() + throws Exception + { + if (!_initialised) + { + _initialised = true; + + _signDN = "O=Bouncy Castle, C=AU"; + _signKP = CMSTestUtil.makeKeyPair(); + _signCert = CMSTestUtil.makeCertificate(_signKP, _signDN, _signKP, _signDN); + + _origDN = "CN=Bob, OU=Sales, O=Bouncy Castle, C=AU"; + _origKP = CMSTestUtil.makeKeyPair(); + _origCert = CMSTestUtil.makeCertificate(_origKP, _origDN, _signKP, _signDN); + + _reciDN = "CN=Doug, OU=Sales, O=Bouncy Castle, C=AU"; + _reciKP = CMSTestUtil.makeKeyPair(); + _reciCert = CMSTestUtil.makeCertificate(_reciKP, _reciDN, _signKP, _signDN); + + _origEcKP = CMSTestUtil.makeEcDsaKeyPair(); + _reciEcKP = CMSTestUtil.makeEcDsaKeyPair(); + _reciEcCert = CMSTestUtil.makeCertificate(_reciEcKP, _reciDN, _signKP, _signDN); + } + } + + public void setUp() + throws Exception + { + init(); + } + + public void testWorkingData() + throws Exception + { + byte[] keyData = Base64.decode( + "MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAKrAz/SQKrcQ" + + "nj9IxHIfKDbuXsMqUpI06s2gps6fp7RDNvtUDDMOciWGFhD45YSy8GO0mPx3" + + "Nkc7vKBqX4TLcqLUz7kXGOHGOwiPZoNF+9jBMPNROe/B0My0PkWg9tuq+nxN" + + "64oD47+JvDwrpNOS5wsYavXeAW8Anv9ZzHLU7KwZAgMBAAECgYA/fqdVt+5K" + + "WKGfwr1Z+oAHvSf7xtchiw/tGtosZ24DOCNP3fcTXUHQ9kVqVkNyzt9ZFCT3" + + "bJUAdBQ2SpfuV4DusVeQZVzcROKeA09nPkxBpTefWbSDQGhb+eZq9L8JDRSW" + + "HyYqs+MBoUpLw7GKtZiJkZyY6CsYkAnQ+uYVWq/TIQJBAP5zafO4HUV/w4KD" + + "VJi+ua+GYF1Sg1t/dYL1kXO9GP1p75YAmtm6LdnOCas7wj70/G1YlPGkOP0V" + + "GFzeG5KAmAUCQQCryvKU9nwWA+kypcQT9Yr1P4vGS0APYoBThnZq7jEPc5Cm" + + "ZI82yseSxSeea0+8KQbZ5mvh1p3qImDLEH/iNSQFAkAghS+tboKPN10NeSt+" + + "uiGRRWNbiggv0YJ7Uldcq3ZeLQPp7/naiekCRUsHD4Qr97OrZf7jQ1HlRqTu" + + "eZScjMLhAkBNUMZCQnhwFAyEzdPkQ7LpU1MdyEopYmRssuxijZao5JLqQAGw" + + "YCzXokGFa7hz72b09F4DQurJL/WuDlvvu4jdAkEAxwT9lylvfSfEQw4/qQgZ" + + "MFB26gqB6Gqs1pHIZCzdliKx5BO3VDeUGfXMI8yOkbXoWbYx5xPid/+N8R//" + + "+sxLBw=="); + + byte[] envData = Base64.decode( + "MIAGCSqGSIb3DQEHA6CAMIACAQAxgcQwgcECAQAwKjAlMRYwFAYDVQQKEw1C" + + "b3VuY3kgQ2FzdGxlMQswCQYDVQQGEwJBVQIBHjANBgkqhkiG9w0BAQEFAASB" + + "gDmnaDZ0vDJNlaUSYyEXsgbaUH+itNTjCOgv77QTX2ImXj+kTctM19PQF2I1" + + "0/NL0fjakvCgBTHKmk13a7jqB6cX3bysenHNrglHsgNGgeXQ7ggAq5fV/JQQ" + + "T7rSxEtuwpbuHQnoVUZahOHVKy/a0uLr9iIh1A3y+yZTZaG505ZJMIAGCSqG" + + "SIb3DQEHATAdBglghkgBZQMEAQIEENmkYNbDXiZxJWtq82qIRZKggAQgkOGr" + + "1JcTsADStez1eY4+rO4DtyBIyUYQ3pilnbirfPkAAAAAAAAAAAAA"); + + + CMSEnvelopedDataParser ep = new CMSEnvelopedDataParser(envData); + + RecipientInformationStore recipients = ep.getRecipientInfos(); + + assertEquals(ep.getEncryptionAlgOID(), CMSEnvelopedDataGenerator.AES128_CBC); + + Collection c = recipients.getRecipients(); + Iterator it = c.iterator(); + + PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(keyData); + KeyFactory keyFact = KeyFactory.getInstance("RSA", BC); + PrivateKey priKey = keyFact.generatePrivate(keySpec); + byte[] data = Hex.decode("57616c6c6157616c6c6157617368696e67746f6e"); + + while (it.hasNext()) + { + RecipientInformation recipient = (RecipientInformation)it.next(); + + assertEquals(recipient.getKeyEncryptionAlgOID(), PKCSObjectIdentifiers.rsaEncryption.getId()); + + CMSTypedStream recData = recipient.getContentStream(new JceKeyTransEnvelopedRecipient(priKey).setProvider(BC)); + + assertEquals(true, Arrays.equals(data, CMSTestUtil.streamToByteArray(recData.getContentStream()))); + } + } + + private void verifyData( + ByteArrayOutputStream encodedStream, + String expectedOid, + byte[] expectedData) + throws Exception + { + CMSEnvelopedDataParser ep = new CMSEnvelopedDataParser(encodedStream.toByteArray()); + RecipientInformationStore recipients = ep.getRecipientInfos(); + + assertEquals(ep.getEncryptionAlgOID(), expectedOid); + + Collection c = recipients.getRecipients(); + Iterator it = c.iterator(); + + while (it.hasNext()) + { + RecipientInformation recipient = (RecipientInformation)it.next(); + + assertEquals(recipient.getKeyEncryptionAlgOID(), PKCSObjectIdentifiers.rsaEncryption.getId()); + + CMSTypedStream recData = recipient.getContentStream(new JceKeyTransEnvelopedRecipient(_reciKP.getPrivate()).setProvider(BC)); + + assertEquals(true, Arrays.equals(expectedData, CMSTestUtil.streamToByteArray(recData.getContentStream()))); + } + } + + public void testUnprotectedAttributes() + throws Exception + { + byte[] data = "WallaWallaWashington".getBytes(); + + CMSEnvelopedDataStreamGenerator edGen = new CMSEnvelopedDataStreamGenerator(); + + edGen.addRecipientInfoGenerator(new JceKeyTransRecipientInfoGenerator(_reciCert).setProvider(BC)); + + Hashtable attrs = new Hashtable(); + + attrs.put(PKCSObjectIdentifiers.id_aa_contentHint, new Attribute(PKCSObjectIdentifiers.id_aa_contentHint, new DERSet(new DERUTF8String("Hint")))); + attrs.put(PKCSObjectIdentifiers.id_aa_receiptRequest, new Attribute(PKCSObjectIdentifiers.id_aa_receiptRequest, new DERSet(new DERUTF8String("Request")))); + + AttributeTable attrTable = new AttributeTable(attrs); + + edGen.setUnprotectedAttributeGenerator(new SimpleAttributeTableGenerator(attrTable)); + + ByteArrayOutputStream bOut = new ByteArrayOutputStream(); + + OutputStream out = edGen.open( + bOut, new JceCMSContentEncryptorBuilder(CMSAlgorithm.AES128_CBC).setProvider(BC).build()); + + out.write(data); + + out.close(); + + CMSEnvelopedDataParser ed = new CMSEnvelopedDataParser(bOut.toByteArray()); + + RecipientInformationStore recipients = ed.getRecipientInfos(); + + Collection c = recipients.getRecipients(); + + assertEquals(1, c.size()); + + Iterator it = c.iterator(); + + while (it.hasNext()) + { + RecipientInformation recipient = (RecipientInformation)it.next(); + + assertEquals(recipient.getKeyEncryptionAlgOID(), PKCSObjectIdentifiers.rsaEncryption.getId()); + + byte[] recData = recipient.getContent(new JceKeyTransEnvelopedRecipient(_reciKP.getPrivate()).setProvider(BC)); + + assertEquals(true, Arrays.equals(data, recData)); + } + + attrTable = ed.getUnprotectedAttributes(); + + assertEquals(attrs.size(), 2); + + assertEquals(new DERUTF8String("Hint"), attrTable.get(PKCSObjectIdentifiers.id_aa_contentHint).getAttrValues().getObjectAt(0)); + assertEquals(new DERUTF8String("Request"), attrTable.get(PKCSObjectIdentifiers.id_aa_receiptRequest).getAttrValues().getObjectAt(0)); + + } + + public void testKeyTransAES128BufferedStream() + throws Exception + { + byte[] data = new byte[2000]; + + for (int i = 0; i != 2000; i++) + { + data[i] = (byte)(i & 0xff); + } + + // + // unbuffered + // + CMSEnvelopedDataStreamGenerator edGen = new CMSEnvelopedDataStreamGenerator(); + + edGen.addRecipientInfoGenerator(new JceKeyTransRecipientInfoGenerator(_reciCert).setProvider(BC)); + + ByteArrayOutputStream bOut = new ByteArrayOutputStream(); + + OutputStream out = edGen.open( + bOut, new JceCMSContentEncryptorBuilder(CMSAlgorithm.AES128_CBC).setProvider(BC).build()); + + for (int i = 0; i != 2000; i++) + { + out.write(data[i]); + } + + out.close(); + + verifyData(bOut, CMSEnvelopedDataGenerator.AES128_CBC, data); + + int unbufferedLength = bOut.toByteArray().length; + + // + // Using buffered output - should be == to unbuffered + // + edGen = new CMSEnvelopedDataStreamGenerator(); + + edGen.addRecipientInfoGenerator(new JceKeyTransRecipientInfoGenerator(_reciCert).setProvider(BC)); + + bOut = new ByteArrayOutputStream(); + + out = edGen.open(bOut, new JceCMSContentEncryptorBuilder(CMSAlgorithm.AES128_CBC).setProvider(BC).build()); + + BufferedOutputStream bfOut = new BufferedOutputStream(out, 300); + + for (int i = 0; i != 2000; i++) + { + bfOut.write(data[i]); + } + + bfOut.close(); + + verifyData(bOut, CMSEnvelopedDataGenerator.AES128_CBC, data); + + assertTrue(bOut.toByteArray().length == unbufferedLength); + } + + public void testKeyTransAES128Buffered() + throws Exception + { + byte[] data = new byte[2000]; + + for (int i = 0; i != 2000; i++) + { + data[i] = (byte)(i & 0xff); + } + + // + // unbuffered + // + CMSEnvelopedDataStreamGenerator edGen = new CMSEnvelopedDataStreamGenerator(); + + edGen.addRecipientInfoGenerator(new JceKeyTransRecipientInfoGenerator(_reciCert).setProvider(BC)); + + ByteArrayOutputStream bOut = new ByteArrayOutputStream(); + + OutputStream out = edGen.open( + bOut, new JceCMSContentEncryptorBuilder(CMSAlgorithm.AES128_CBC).setProvider(BC).build()); + + for (int i = 0; i != 2000; i++) + { + out.write(data[i]); + } + + out.close(); + + verifyData(bOut, CMSEnvelopedDataGenerator.AES128_CBC, data); + + int unbufferedLength = bOut.toByteArray().length; + + // + // buffered - less than default of 1000 + // + edGen = new CMSEnvelopedDataStreamGenerator(); + + edGen.setBufferSize(300); + + edGen.addRecipientInfoGenerator(new JceKeyTransRecipientInfoGenerator(_reciCert).setProvider(BC)); + + bOut = new ByteArrayOutputStream(); + + out = edGen.open(bOut, new JceCMSContentEncryptorBuilder(CMSAlgorithm.AES128_CBC).setProvider(BC).build()); + + for (int i = 0; i != 2000; i++) + { + out.write(data[i]); + } + + out.close(); + + verifyData(bOut, CMSEnvelopedDataGenerator.AES128_CBC, data); + + assertTrue(bOut.toByteArray().length > unbufferedLength); + } + + public void testKeyTransAES128Der() + throws Exception + { + byte[] data = new byte[2000]; + + for (int i = 0; i != 2000; i++) + { + data[i] = (byte)(i & 0xff); + } + + CMSEnvelopedDataStreamGenerator edGen = new CMSEnvelopedDataStreamGenerator(); + + edGen.addRecipientInfoGenerator(new JceKeyTransRecipientInfoGenerator(_reciCert).setProvider(BC)); + + ByteArrayOutputStream bOut = new ByteArrayOutputStream(); + + OutputStream out = edGen.open( + bOut, new JceCMSContentEncryptorBuilder(CMSAlgorithm.AES128_CBC).setProvider(BC).build()); + + for (int i = 0; i != 2000; i++) + { + out.write(data[i]); + } + + out.close(); + + // convert to DER + ASN1InputStream aIn = new ASN1InputStream(bOut.toByteArray()); + + bOut.reset(); + + DEROutputStream dOut = new DEROutputStream(bOut); + + dOut.writeObject(aIn.readObject()); + + verifyData(bOut, CMSEnvelopedDataGenerator.AES128_CBC, data); + } + + public void testKeyTransAES128Throughput() + throws Exception + { + byte[] data = new byte[40001]; + + for (int i = 0; i != data.length; i++) + { + data[i] = (byte)(i & 0xff); + } + + // + // buffered + // + CMSEnvelopedDataStreamGenerator edGen = new CMSEnvelopedDataStreamGenerator(); + + edGen.setBufferSize(BUFFER_SIZE); + + edGen.addRecipientInfoGenerator(new JceKeyTransRecipientInfoGenerator(_reciCert).setProvider(BC)); + + ByteArrayOutputStream bOut = new ByteArrayOutputStream(); + + OutputStream out = edGen.open(bOut, new JceCMSContentEncryptorBuilder(CMSAlgorithm.AES128_CBC).setProvider(BC).build()); + + for (int i = 0; i != data.length; i++) + { + out.write(data[i]); + } + + out.close(); + + CMSEnvelopedDataParser ep = new CMSEnvelopedDataParser(bOut.toByteArray()); + RecipientInformationStore recipients = ep.getRecipientInfos(); + Collection c = recipients.getRecipients(); + Iterator it = c.iterator(); + + if (it.hasNext()) + { + RecipientInformation recipient = (RecipientInformation)it.next(); + + assertEquals(recipient.getKeyEncryptionAlgOID(), PKCSObjectIdentifiers.rsaEncryption.getId()); + + CMSTypedStream recData = recipient.getContentStream(new JceKeyTransEnvelopedRecipient(_reciKP.getPrivate()).setProvider(BC)); + + InputStream dataStream = recData.getContentStream(); + ByteArrayOutputStream dataOut = new ByteArrayOutputStream(); + int len; + byte[] buf = new byte[BUFFER_SIZE]; + int count = 0; + + while (count != 10 && (len = dataStream.read(buf)) > 0) + { + assertEquals(buf.length, len); + + dataOut.write(buf); + count++; + } + + len = dataStream.read(buf); + dataOut.write(buf, 0, len); + + assertEquals(true, Arrays.equals(data, dataOut.toByteArray())); + } + else + { + fail("recipient not found."); + } + } + + public void testKeyTransAES128AndOriginatorInfo() + throws Exception + { + byte[] data = "WallaWallaWashington".getBytes(); + + CMSEnvelopedDataStreamGenerator edGen = new CMSEnvelopedDataStreamGenerator(); + + X509CertificateHolder origCert = new X509CertificateHolder(_origCert.getEncoded()); + + edGen.setOriginatorInfo(new OriginatorInfoGenerator(origCert).generate()); + + edGen.addRecipientInfoGenerator(new JceKeyTransRecipientInfoGenerator(_reciCert).setProvider(BC)); + + ByteArrayOutputStream bOut = new ByteArrayOutputStream(); + + OutputStream out = edGen.open( + bOut, new JceCMSContentEncryptorBuilder(CMSAlgorithm.AES128_CBC).setProvider(BC).build()); + + out.write(data); + + out.close(); + + CMSEnvelopedDataParser ep = new CMSEnvelopedDataParser(bOut.toByteArray()); + + assertTrue(ep.getOriginatorInfo().getCertificates().getMatches(null).contains(origCert)); + + RecipientInformationStore recipients = ep.getRecipientInfos(); + + assertEquals(ep.getEncryptionAlgOID(), CMSEnvelopedDataGenerator.AES128_CBC); + + Collection c = recipients.getRecipients(); + Iterator it = c.iterator(); + + while (it.hasNext()) + { + RecipientInformation recipient = (RecipientInformation)it.next(); + + assertEquals(recipient.getKeyEncryptionAlgOID(), PKCSObjectIdentifiers.rsaEncryption.getId()); + + CMSTypedStream recData = recipient.getContentStream(new JceKeyTransEnvelopedRecipient(_reciKP.getPrivate()).setProvider(BC)); + + assertEquals(true, Arrays.equals(data, CMSTestUtil.streamToByteArray(recData.getContentStream()))); + } + + ep.close(); + } + + public void testKeyTransAES128() + throws Exception + { + byte[] data = "WallaWallaWashington".getBytes(); + + CMSEnvelopedDataStreamGenerator edGen = new CMSEnvelopedDataStreamGenerator(); + + edGen.addRecipientInfoGenerator(new JceKeyTransRecipientInfoGenerator(_reciCert).setProvider(BC)); + + ByteArrayOutputStream bOut = new ByteArrayOutputStream(); + + OutputStream out = edGen.open( + bOut, new JceCMSContentEncryptorBuilder(CMSAlgorithm.AES128_CBC).setProvider(BC).build()); + + out.write(data); + + out.close(); + + CMSEnvelopedDataParser ep = new CMSEnvelopedDataParser(bOut.toByteArray()); + + RecipientInformationStore recipients = ep.getRecipientInfos(); + + assertEquals(ep.getEncryptionAlgOID(), CMSEnvelopedDataGenerator.AES128_CBC); + + Collection c = recipients.getRecipients(); + Iterator it = c.iterator(); + + while (it.hasNext()) + { + RecipientInformation recipient = (RecipientInformation)it.next(); + + assertEquals(recipient.getKeyEncryptionAlgOID(), PKCSObjectIdentifiers.rsaEncryption.getId()); + + CMSTypedStream recData = recipient.getContentStream(new JceKeyTransEnvelopedRecipient(_reciKP.getPrivate()).setProvider(BC)); + + assertEquals(true, Arrays.equals(data, CMSTestUtil.streamToByteArray(recData.getContentStream()))); + } + + ep.close(); + } + + public void testKeyTransCAST5SunJCE() + throws Exception + { + if (Security.getProvider("SunJCE") == null) + { + return; + } + + String version = System.getProperty("java.version"); + if (version.startsWith("1.4") || version.startsWith("1.3")) + { + return; + } + + byte[] data = "WallaWallaWashington".getBytes(); + + CMSEnvelopedDataStreamGenerator edGen = new CMSEnvelopedDataStreamGenerator(); + + edGen.addRecipientInfoGenerator(new JceKeyTransRecipientInfoGenerator(_reciCert).setProvider("SunJCE")); + + ByteArrayOutputStream bOut = new ByteArrayOutputStream(); + + OutputStream out = edGen.open( + bOut, new JceCMSContentEncryptorBuilder(CMSAlgorithm.CAST5_CBC).setProvider(BC).build()); + + out.write(data); + + out.close(); + + CMSEnvelopedDataParser ep = new CMSEnvelopedDataParser(bOut.toByteArray()); + + RecipientInformationStore recipients = ep.getRecipientInfos(); + + assertEquals(ep.getEncryptionAlgOID(), CMSEnvelopedDataGenerator.CAST5_CBC); + + Collection c = recipients.getRecipients(); + Iterator it = c.iterator(); + + while (it.hasNext()) + { + RecipientInformation recipient = (RecipientInformation)it.next(); + + assertEquals(recipient.getKeyEncryptionAlgOID(), PKCSObjectIdentifiers.rsaEncryption.getId()); + + CMSTypedStream recData = recipient.getContentStream(new JceKeyTransEnvelopedRecipient(_reciKP.getPrivate()).setProvider("SunJCE").setContentProvider(BC)); + + assertEquals(true, Arrays.equals(data, CMSTestUtil.streamToByteArray(recData.getContentStream()))); + } + + ep.close(); + } + + public void testAESKEK() + throws Exception + { + byte[] data = "WallaWallaWashington".getBytes(); + SecretKey kek = CMSTestUtil.makeAES192Key(); + + CMSEnvelopedDataStreamGenerator edGen = new CMSEnvelopedDataStreamGenerator(); + + byte[] kekId = new byte[] { 1, 2, 3, 4, 5 }; + + edGen.addRecipientInfoGenerator(new JceKEKRecipientInfoGenerator(kekId, kek).setProvider(BC)); + + ByteArrayOutputStream bOut = new ByteArrayOutputStream(); + + OutputStream out = edGen.open( + bOut, + new JceCMSContentEncryptorBuilder(CMSAlgorithm.DES_EDE3_CBC).setProvider(BC).build()); + out.write(data); + + out.close(); + + CMSEnvelopedDataParser ep = new CMSEnvelopedDataParser(bOut.toByteArray()); + + RecipientInformationStore recipients = ep.getRecipientInfos(); + + assertEquals(ep.getEncryptionAlgOID(), CMSEnvelopedDataGenerator.DES_EDE3_CBC); + + Collection c = recipients.getRecipients(); + Iterator it = c.iterator(); + + while (it.hasNext()) + { + RecipientInformation recipient = (RecipientInformation)it.next(); + + assertEquals(recipient.getKeyEncryptionAlgOID(), "2.16.840.1.101.3.4.1.25"); + + CMSTypedStream recData = recipient.getContentStream(new JceKEKEnvelopedRecipient(kek).setProvider(BC)); + + assertEquals(true, Arrays.equals(data, CMSTestUtil.streamToByteArray(recData.getContentStream()))); + } + + ep.close(); + } + + public void testTwoAESKEK() + throws Exception + { + byte[] data = "WallaWallaWashington".getBytes(); + SecretKey kek1 = CMSTestUtil.makeAES192Key(); + SecretKey kek2 = CMSTestUtil.makeAES192Key(); + + CMSEnvelopedDataStreamGenerator edGen = new CMSEnvelopedDataStreamGenerator(); + + byte[] kekId1 = new byte[] { 1, 2, 3, 4, 5 }; + byte[] kekId2 = new byte[] { 5, 4, 3, 2, 1 }; + + edGen.addRecipientInfoGenerator(new JceKEKRecipientInfoGenerator(kekId1, kek1).setProvider(BC)); + edGen.addRecipientInfoGenerator(new JceKEKRecipientInfoGenerator(kekId2, kek2).setProvider(BC)); + + ByteArrayOutputStream bOut = new ByteArrayOutputStream(); + + OutputStream out = edGen.open( + bOut, + new JceCMSContentEncryptorBuilder(CMSAlgorithm.DES_EDE3_CBC).setProvider(BC).build()); + out.write(data); + + out.close(); + + CMSEnvelopedDataParser ep = new CMSEnvelopedDataParser(bOut.toByteArray()); + + RecipientInformationStore recipients = ep.getRecipientInfos(); + + assertEquals(ep.getEncryptionAlgOID(), CMSEnvelopedDataGenerator.DES_EDE3_CBC); + + RecipientId recSel = new KEKRecipientId(kekId2); + + RecipientInformation recipient = recipients.get(recSel); + + assertEquals(recipient.getKeyEncryptionAlgOID(), "2.16.840.1.101.3.4.1.25"); + + CMSTypedStream recData = recipient.getContentStream(new JceKEKEnvelopedRecipient(kek2).setProvider(BC)); + + assertEquals(true, Arrays.equals(data, CMSTestUtil.streamToByteArray(recData.getContentStream()))); + + ep.close(); + } + + public void testECKeyAgree() + throws Exception + { + byte[] data = Hex.decode("504b492d4320434d5320456e76656c6f706564446174612053616d706c65"); + + CMSEnvelopedDataStreamGenerator edGen = new CMSEnvelopedDataStreamGenerator(); + + JceKeyAgreeRecipientInfoGenerator recipientGenerator = new JceKeyAgreeRecipientInfoGenerator(CMSAlgorithm.ECDH_SHA1KDF, _origEcKP.getPrivate(), _origEcKP.getPublic(), CMSAlgorithm.AES128_WRAP).setProvider(BC); + + recipientGenerator.addRecipient(_reciEcCert); + + edGen.addRecipientInfoGenerator(recipientGenerator); + + ByteArrayOutputStream bOut = new ByteArrayOutputStream(); + + OutputStream out = edGen.open( + bOut, + new JceCMSContentEncryptorBuilder(CMSAlgorithm.AES128_CBC).setProvider(BC).build()); + out.write(data); + + out.close(); + + CMSEnvelopedDataParser ep = new CMSEnvelopedDataParser(bOut.toByteArray()); + + RecipientInformationStore recipients = ep.getRecipientInfos(); + + assertEquals(ep.getEncryptionAlgOID(), CMSEnvelopedDataGenerator.AES128_CBC); + + RecipientId recSel = new JceKeyAgreeRecipientId(_reciEcCert); + + RecipientInformation recipient = recipients.get(recSel); + + CMSTypedStream recData = recipient.getContentStream(new JceKeyAgreeEnvelopedRecipient(_reciEcKP.getPrivate()).setProvider(BC)); + + assertEquals(true, Arrays.equals(data, CMSTestUtil.streamToByteArray(recData.getContentStream()))); + + ep.close(); + } + + public void testOriginatorInfo() + throws Exception + { + CMSEnvelopedDataParser env = new CMSEnvelopedDataParser(CMSSampleMessages.originatorMessage); + + OriginatorInformation origInfo = env.getOriginatorInfo(); + + RecipientInformationStore recipients = env.getRecipientInfos(); + + assertEquals(new X500Name("C=US,O=U.S. Government,OU=HSPD12Lab,OU=Agents,CN=user1"), ((X509CertificateHolder)origInfo.getCertificates().getMatches(null).iterator().next()).getSubject()); + assertEquals(CMSEnvelopedDataGenerator.DES_EDE3_CBC, env.getEncryptionAlgOID()); + } + + public static Test suite() + throws Exception + { + return new CMSTestSetup(new TestSuite(NewEnvelopedDataStreamTest.class)); + } +} diff --git a/pkix/src/test/java/org/spongycastle/cms/test/NewEnvelopedDataTest.java b/pkix/src/test/java/org/spongycastle/cms/test/NewEnvelopedDataTest.java new file mode 100644 index 00000000..f68ed383 --- /dev/null +++ b/pkix/src/test/java/org/spongycastle/cms/test/NewEnvelopedDataTest.java @@ -0,0 +1,1488 @@ +package org.spongycastle.cms.test; + +import java.io.IOException; +import java.security.*; +import java.security.cert.CertificateEncodingException; +import java.security.cert.X509Certificate; +import java.security.spec.MGF1ParameterSpec; +import java.security.spec.PKCS8EncodedKeySpec; +import java.util.Arrays; +import java.util.Collection; +import java.util.Hashtable; +import java.util.Iterator; + +import javax.crypto.SecretKey; +import javax.crypto.spec.OAEPParameterSpec; +import javax.crypto.spec.PSource; +import javax.crypto.spec.SecretKeySpec; + +import junit.framework.Test; +import junit.framework.TestCase; +import junit.framework.TestSuite; +import org.spongycastle.asn1.ASN1InputStream; +import org.spongycastle.asn1.ASN1ObjectIdentifier; +import org.spongycastle.asn1.ASN1OctetString; +import org.spongycastle.asn1.ASN1Sequence; +import org.spongycastle.asn1.DEROctetString; +import org.spongycastle.asn1.DERSet; +import org.spongycastle.asn1.DERUTF8String; +import org.spongycastle.asn1.cms.Attribute; +import org.spongycastle.asn1.cms.AttributeTable; +import org.spongycastle.asn1.kisa.KISAObjectIdentifiers; +import org.spongycastle.asn1.nist.NISTObjectIdentifiers; +import org.spongycastle.asn1.ntt.NTTObjectIdentifiers; +import org.spongycastle.asn1.pkcs.PKCSObjectIdentifiers; +import org.spongycastle.asn1.pkcs.RC2CBCParameter; +import org.spongycastle.asn1.x500.X500Name; +import org.spongycastle.asn1.x509.AlgorithmIdentifier; +import org.spongycastle.asn1.x509.Extension; +import org.spongycastle.cert.X509CertificateHolder; +import org.spongycastle.cert.jcajce.JcaX509CertificateHolder; +import org.spongycastle.cms.CMSAlgorithm; +import org.spongycastle.cms.CMSEnvelopedData; +import org.spongycastle.cms.CMSEnvelopedDataGenerator; +import org.spongycastle.cms.CMSException; +import org.spongycastle.cms.CMSProcessableByteArray; +import org.spongycastle.cms.KeyTransRecipientInformation; +import org.spongycastle.cms.OriginatorInfoGenerator; +import org.spongycastle.cms.OriginatorInformation; +import org.spongycastle.cms.PasswordRecipient; +import org.spongycastle.cms.PasswordRecipientInformation; +import org.spongycastle.cms.RecipientId; +import org.spongycastle.cms.RecipientInformation; +import org.spongycastle.cms.RecipientInformationStore; +import org.spongycastle.cms.SimpleAttributeTableGenerator; +import org.spongycastle.cms.bc.BcCMSContentEncryptorBuilder; +import org.spongycastle.cms.bc.BcRSAKeyTransRecipientInfoGenerator; +import org.spongycastle.cms.jcajce.JceCMSContentEncryptorBuilder; +import org.spongycastle.cms.jcajce.JceKEKEnvelopedRecipient; +import org.spongycastle.cms.jcajce.JceKEKRecipientInfoGenerator; +import org.spongycastle.cms.jcajce.JceKeyAgreeEnvelopedRecipient; +import org.spongycastle.cms.jcajce.JceKeyAgreeRecipientId; +import org.spongycastle.cms.jcajce.JceKeyAgreeRecipientInfoGenerator; +import org.spongycastle.cms.jcajce.JceKeyTransEnvelopedRecipient; +import org.spongycastle.cms.jcajce.JceKeyTransRecipientId; +import org.spongycastle.cms.jcajce.JceKeyTransRecipientInfoGenerator; +import org.spongycastle.cms.jcajce.JcePasswordEnvelopedRecipient; +import org.spongycastle.cms.jcajce.JcePasswordRecipientInfoGenerator; +import org.spongycastle.jce.provider.BouncyCastleProvider; +import org.spongycastle.operator.OutputEncryptor; +import org.spongycastle.operator.jcajce.JcaAlgorithmParametersConverter; +import org.spongycastle.util.encoders.Base64; +import org.spongycastle.util.encoders.Hex; + +public class NewEnvelopedDataTest + extends TestCase +{ + private static final String BC = BouncyCastleProvider.PROVIDER_NAME; + + private static String _signDN; + private static KeyPair _signKP; + private static X509Certificate _signCert; + + private static String _origDN; + private static KeyPair _origKP; + private static X509Certificate _origCert; + + private static String _reciDN; + private static String _reciDN2; + private static KeyPair _reciKP; + private static KeyPair _reciOaepKP; + private static X509Certificate _reciCert; + private static X509Certificate _reciCertOaep; + + private static KeyPair _origEcKP; + private static KeyPair _reciEcKP; + private static X509Certificate _reciEcCert; + private static KeyPair _reciEcKP2; + private static X509Certificate _reciEcCert2; + + private static boolean _initialised = false; + + private byte[] oldKEK = Base64.decode( + "MIAGCSqGSIb3DQEHA6CAMIACAQIxQaI/MD0CAQQwBwQFAQIDBAUwDQYJYIZIAWUDBAEFBQAEI" + + "Fi2eHTPM4bQSjP4DUeDzJZLpfemW2gF1SPq7ZPHJi1mMIAGCSqGSIb3DQEHATAUBggqhkiG9w" + + "0DBwQImtdGyUdGGt6ggAQYk9X9z01YFBkU7IlS3wmsKpm/zpZClTceAAAAAAAAAAAAAA=="); + + private byte[] ecKeyAgreeMsgAES256 = Base64.decode( + "MIAGCSqGSIb3DQEHA6CAMIACAQIxgcShgcECAQOgQ6FBMAsGByqGSM49AgEF" + + "AAMyAAPdXlSTpub+qqno9hUGkUDl+S3/ABhPziIB5yGU4678tgOgU5CiKG9Z" + + "kfnabIJ3nZYwGgYJK4EFEIZIPwACMA0GCWCGSAFlAwQBLQUAMFswWTAtMCgx" + + "EzARBgNVBAMTCkFkbWluLU1EU0UxETAPBgNVBAoTCDRCQ1QtMklEAgEBBCi/" + + "rJRLbFwEVW6PcLLmojjW9lI/xGD7CfZzXrqXFw8iHaf3hTRau1gYMIAGCSqG" + + "SIb3DQEHATAdBglghkgBZQMEASoEEMtCnKKPwccmyrbgeSIlA3qggAQQDLw8" + + "pNJR97bPpj6baG99bQQQwhEDsoj5Xg1oOxojHVcYzAAAAAAAAAAAAAA="); + + private byte[] ecKeyAgreeMsgAES128 = Base64.decode( + "MIAGCSqGSIb3DQEHA6CAMIACAQIxgbShgbECAQOgQ6FBMAsGByqGSM49AgEF" + + "AAMyAAL01JLEgKvKh5rbxI/hOxs/9WEezMIsAbUaZM4l5tn3CzXAN505nr5d" + + "LhrcurMK+tAwGgYJK4EFEIZIPwACMA0GCWCGSAFlAwQBBQUAMEswSTAtMCgx" + + "EzARBgNVBAMTCkFkbWluLU1EU0UxETAPBgNVBAoTCDRCQ1QtMklEAgEBBBhi" + + "FLjc5g6aqDT3f8LomljOwl1WTrplUT8wgAYJKoZIhvcNAQcBMB0GCWCGSAFl" + + "AwQBAgQQzXjms16Y69S/rB0EbHqRMaCABBAFmc/QdVW6LTKdEy97kaZzBBBa" + + "fQuviUS03NycpojELx0bAAAAAAAAAAAAAA=="); + + private byte[] ecKeyAgreeMsgDESEDE = Base64.decode( + "MIAGCSqGSIb3DQEHA6CAMIACAQIxgcahgcMCAQOgQ6FBMAsGByqGSM49AgEF" + + "AAMyAALIici6Nx1WN5f0ThH2A8ht9ovm0thpC5JK54t73E1RDzCifePaoQo0" + + "xd6sUqoyGaYwHAYJK4EFEIZIPwACMA8GCyqGSIb3DQEJEAMGBQAwWzBZMC0w" + + "KDETMBEGA1UEAxMKQWRtaW4tTURTRTERMA8GA1UEChMINEJDVC0ySUQCAQEE" + + "KJuqZQ1NB1vXrKPOnb4TCpYOsdm6GscWdwAAZlm2EHMp444j0s55J9wwgAYJ" + + "KoZIhvcNAQcBMBQGCCqGSIb3DQMHBAjwnsDMsafCrKCABBjyPvqFOVMKxxut" + + "VfTx4fQlNGJN8S2ATRgECMcTQ/dsmeViAAAAAAAAAAAAAA=="); + + private byte[] ecMQVKeyAgreeMsgAES128 = Base64.decode( + "MIAGCSqGSIb3DQEHA6CAMIACAQIxgf2hgfoCAQOgQ6FBMAsGByqGSM49AgEF" + + "AAMyAAPDKU+0H58tsjpoYmYCInMr/FayvCCkupebgsnpaGEB7qS9vzcNVUj6" + + "mrnmiC2grpmhRwRFMEMwQTALBgcqhkjOPQIBBQADMgACZpD13z9c7DzRWx6S" + + "0xdbq3S+EJ7vWO+YcHVjTD8NcQDcZcWASW899l1PkL936zsuMBoGCSuBBRCG" + + "SD8AEDANBglghkgBZQMEAQUFADBLMEkwLTAoMRMwEQYDVQQDEwpBZG1pbi1N" + + "RFNFMREwDwYDVQQKEwg0QkNULTJJRAIBAQQYFq58L71nyMK/70w3nc6zkkRy" + + "RL7DHmpZMIAGCSqGSIb3DQEHATAdBglghkgBZQMEAQIEEDzRUpreBsZXWHBe" + + "onxOtSmggAQQ7csAZXwT1lHUqoazoy8bhAQQq+9Zjj8iGdOWgyebbfj67QAA" + + "AAAAAAAAAAA="); + + + private byte[] ecKeyAgreeKey = Base64.decode( + "MIG2AgEAMBAGByqGSM49AgEGBSuBBAAiBIGeMIGbAgEBBDC8vp7xVTbKSgYVU5Wc" + + "hGkWbzaj+yUFETIWP1Dt7+WSpq3ikSPdl7PpHPqnPVZfoIWhZANiAgSYHTgxf+Dd" + + "Tt84dUvuSKkFy3RhjxJmjwIscK6zbEUzKhcPQG2GHzXhWK5x1kov0I74XpGhVkya" + + "ElH5K6SaOXiXAzcyNGggTOk4+ZFnz5Xl0pBje3zKxPhYu0SnCw7Pcqw="); + + private byte[] bobPrivRsaEncrypt = Base64.decode( + "MIIChQIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAKnhZ5g/OdVf" + + "8qCTQV6meYmFyDVdmpFb+x0B2hlwJhcPvaUi0DWFbXqYZhRBXM+3twg7CcmR" + + "uBlpN235ZR572akzJKN/O7uvRgGGNjQyywcDWVL8hYsxBLjMGAgUSOZPHPtd" + + "YMTgXB9T039T2GkB8QX4enDRvoPGXzjPHCyqaqfrAgMBAAECgYBnzUhMmg2P" + + "mMIbZf8ig5xt8KYGHbztpwOIlPIcaw+LNd4Ogngwy+e6alatd8brUXlweQqg" + + "9P5F4Kmy9Bnah5jWMIR05PxZbMHGd9ypkdB8MKCixQheIXFD/A0HPfD6bRSe" + + "TmPwF1h5HEuYHD09sBvf+iU7o8AsmAX2EAnYh9sDGQJBANDDIsbeopkYdo+N" + + "vKZ11mY/1I1FUox29XLE6/BGmvE+XKpVC5va3Wtt+Pw7PAhDk7Vb/s7q/WiE" + + "I2Kv8zHCueUCQQDQUfweIrdb7bWOAcjXq/JY1PeClPNTqBlFy2bKKBlf4hAr" + + "84/sajB0+E0R9KfEILVHIdxJAfkKICnwJAiEYH2PAkA0umTJSChXdNdVUN5q" + + "SO8bKlocSHseIVnDYDubl6nA7xhmqU5iUjiEzuUJiEiUacUgFJlaV/4jbOSn" + + "I3vQgLeFAkEAni+zN5r7CwZdV+EJBqRd2ZCWBgVfJAZAcpw6iIWchw+dYhKI" + + "FmioNRobQ+g4wJhprwMKSDIETukPj3d9NDAlBwJAVxhn1grStavCunrnVNqc" + + "BU+B1O8BiR4yPWnLMcRSyFRVJQA7HCp8JlDV6abXd8vPFfXuC9WN7rOvTKF8" + + "Y0ZB9qANMAsGA1UdDzEEAwIAEA=="); + + private byte[] rfc4134ex5_1 = Base64.decode( + "MIIBHgYJKoZIhvcNAQcDoIIBDzCCAQsCAQAxgcAwgb0CAQAwJjASMRAwDgYD" + + "VQQDEwdDYXJsUlNBAhBGNGvHgABWvBHTbi7NXXHQMA0GCSqGSIb3DQEBAQUA" + + "BIGAC3EN5nGIiJi2lsGPcP2iJ97a4e8kbKQz36zg6Z2i0yx6zYC4mZ7mX7FB" + + "s3IWg+f6KgCLx3M1eCbWx8+MDFbbpXadCDgO8/nUkUNYeNxJtuzubGgzoyEd" + + "8Ch4H/dd9gdzTd+taTEgS0ipdSJuNnkVY4/M652jKKHRLFf02hosdR8wQwYJ" + + "KoZIhvcNAQcBMBQGCCqGSIb3DQMHBAgtaMXpRwZRNYAgDsiSf8Z9P43LrY4O" + + "xUk660cu1lXeCSFOSOpOJ7FuVyU="); + + private byte[] rfc4134ex5_2 = Base64.decode( + "MIIBZQYJKoZIhvcNAQcDoIIBVjCCAVICAQIxggEAMIG9AgEAMCYwEjEQMA4G" + + "A1UEAxMHQ2FybFJTQQIQRjRrx4AAVrwR024uzV1x0DANBgkqhkiG9w0BAQEF" + + "AASBgJQmQojGi7Z4IP+CVypBmNFoCDoEp87khtgyff2N4SmqD3RxPx+8hbLQ" + + "t9i3YcMwcap+aiOkyqjMalT03VUC0XBOGv+HYI3HBZm/aFzxoq+YOXAWs5xl" + + "GerZwTOc9j6AYlK4qXvnztR5SQ8TBjlzytm4V7zg+TGrnGVNQBNw47Ewoj4C" + + "AQQwDQQLTWFpbExpc3RSQzIwEAYLKoZIhvcNAQkQAwcCAToEGHcUr5MSJ/g9" + + "HnJVHsQ6X56VcwYb+OfojTBJBgkqhkiG9w0BBwEwGgYIKoZIhvcNAwIwDgIC" + + "AKAECJwE0hkuKlWhgCBeKNXhojuej3org9Lt7n+wWxOhnky5V50vSpoYRfRR" + + "yw=="); + + private byte[] tooShort3DES = Base64.decode( + "MIAGCSqGSIb3DQEHA6CAMIACAQAxgcQwgcECAQAwKjAlMRYwFAYDVQQKDA1C" + + "b3VuY3kgQ2FzdGxlMQswCQYDVQQGEwJBVQIBCjANBgkqhkiG9w0BAQEFAASB" + + "gJIM2QN0o6iv8Ux018pVCJ8js+ROV4t6+KoMwLJ4DzRKLU8XCAb9BS+crP+F" + + "ghNTxTpTX8TaxPrO4wV0USgVHu2SvFnxNaWZjBDVIyZI2HR4QkSTqFMhsUB2" + + "6CuZIWBZkhqQ6ruDfvn9UuBWVnfsBD4iryZ1idr713sDeVo5TyvTMIAGCSqG" + + "SIb3DQEHATAUBggqhkiG9w0DBwQIQq9e4+WB3CqggAQIwU4cOlmkWUcAAAAA" + + "AAAAAAAA"); + + private byte[] tooShort3DESKey = Base64.decode( + "MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBAODZDCj0nQdV" + + "f0GGeFsPjjvPx1Vem0V6IkJ4SzazGKfddk0pX58ZDCnG+S+OPiXmPDqValiu" + + "9FtNy2/r9rrf/6qtcVQJkfSJv9E5Y7HgI98L/Y9lKxZWsfRqu/SlYO5zx0Dc" + + "2rzDvvZRtrtaq0uuHXWJlbWda2L9S65sv/Le/zvjAgMBAAECgYEAnn+iGMTG" + + "ZMMaH6Cg+t/uTa9cPougPMuplt2hd3+sY7izihUeONK5RkHiqmlE2gaAcnOd" + + "McKysiIWxGC73mPEnsOObPkaFlneVb5CtjTaTMdptuLNEQkwvtKhuW2HnMra" + + "4afEgFZdll3FyRpvW/CDooe4Bppjd4aGn/Sr/o9nOzECQQD4QKLwZssuclji" + + "nD/8gU1CqGMMnGNogTMpHm1269HUOE7r1y3MuapUqSWsVhpuEQ8P/Tko0haJ" + + "jeZn2eWTbZu/AkEA591snui8FMeGvkRgvyMFNvXZWDEjsh+N74XEL1lykTgZ" + + "FQJ+cmThnrdM/8yj1dKkdASYrk5kFJ4PVE6CzDI43QJAFS22eNncJZc9u/9m" + + "eg0x4SjqYk4JMQYsripZXlbZ7Mfs+7O8xYVlYZmYjC5ATPmJlmyc7r2VjKCd" + + "cmilbEFikwJBAMh7yf8BaBdjitubzjeW9VxXaa37F01eQWD5PfBfHFP6uJ1V" + + "AbayCfAtuHN6I7OwJih3DPmyqJC3NrQECs67IjUCQAb4TfVE/2G1s66SGnb4" + + "no34BspoV/i4f0uLhJap84bTHcF/ZRSXCmQOCRGdSvQkXHeNPI5Lus6lOHuU" + + "vUDbQC8="); + + public NewEnvelopedDataTest() + { + } + + private static void init() + throws Exception + { + if (!_initialised) + { + _initialised = true; + Security.addProvider(new org.spongycastle.jce.provider.BouncyCastleProvider()); + + _signDN = "O=Bouncy Castle, C=AU"; + _signKP = CMSTestUtil.makeKeyPair(); + _signCert = CMSTestUtil.makeCertificate(_signKP, _signDN, _signKP, _signDN); + + _origDN = "CN=Bob, OU=Sales, O=Bouncy Castle, C=AU"; + _origKP = CMSTestUtil.makeKeyPair(); + _origCert = CMSTestUtil.makeCertificate(_origKP, _origDN, _signKP, _signDN); + + _reciDN = "CN=Doug, OU=Sales, O=Bouncy Castle, C=AU"; + _reciDN2 = "CN=Fred, OU=Sales, O=Bouncy Castle, C=AU"; + _reciKP = CMSTestUtil.makeKeyPair(); + _reciCert = CMSTestUtil.makeCertificate(_reciKP, _reciDN, _signKP, _signDN); + _reciCertOaep = CMSTestUtil.makeOaepCertificate(_reciKP, _reciDN, _signKP, _signDN); + + _origEcKP = CMSTestUtil.makeEcDsaKeyPair(); + _reciEcKP = CMSTestUtil.makeEcDsaKeyPair(); + _reciEcCert = CMSTestUtil.makeCertificate(_reciEcKP, _reciDN, _signKP, _signDN); + _reciEcKP2 = CMSTestUtil.makeEcDsaKeyPair(); + _reciEcCert2 = CMSTestUtil.makeCertificate(_reciEcKP2, _reciDN2, _signKP, _signDN); + } + } + + public static void main( + String args[]) + throws Exception + { + junit.textui.TestRunner.run(NewEnvelopedDataTest.suite()); + } + + public static Test suite() + throws Exception + { + init(); + + return new CMSTestSetup(new TestSuite(NewEnvelopedDataTest.class)); + } + + public void testUnprotectedAttributes() + throws Exception + { + byte[] data = "WallaWallaWashington".getBytes(); + + CMSEnvelopedDataGenerator edGen = new CMSEnvelopedDataGenerator(); + + edGen.addRecipientInfoGenerator(new JceKeyTransRecipientInfoGenerator(_reciCert).setProvider(BC)); + + Hashtable attrs = new Hashtable(); + + attrs.put(PKCSObjectIdentifiers.id_aa_contentHint, new Attribute(PKCSObjectIdentifiers.id_aa_contentHint, new DERSet(new DERUTF8String("Hint")))); + attrs.put(PKCSObjectIdentifiers.id_aa_receiptRequest, new Attribute(PKCSObjectIdentifiers.id_aa_receiptRequest, new DERSet(new DERUTF8String("Request")))); + + AttributeTable attrTable = new AttributeTable(attrs); + + edGen.setUnprotectedAttributeGenerator(new SimpleAttributeTableGenerator(attrTable)); + + CMSEnvelopedData ed = edGen.generate( + new CMSProcessableByteArray(data), + new JceCMSContentEncryptorBuilder(CMSAlgorithm.DES_EDE3_CBC).setProvider(BC).build()); + + RecipientInformationStore recipients = ed.getRecipientInfos(); + + assertEquals(ed.getEncryptionAlgOID(), CMSEnvelopedDataGenerator.DES_EDE3_CBC); + + attrTable = ed.getUnprotectedAttributes(); + + assertEquals(attrs.size(), 2); + + assertEquals(new DERUTF8String("Hint"), attrTable.get(PKCSObjectIdentifiers.id_aa_contentHint).getAttrValues().getObjectAt(0)); + assertEquals(new DERUTF8String("Request"), attrTable.get(PKCSObjectIdentifiers.id_aa_receiptRequest).getAttrValues().getObjectAt(0)); + + Collection c = recipients.getRecipients(); + + assertEquals(1, c.size()); + + Iterator it = c.iterator(); + + while (it.hasNext()) + { + RecipientInformation recipient = (RecipientInformation)it.next(); + + assertEquals(recipient.getKeyEncryptionAlgOID(), PKCSObjectIdentifiers.rsaEncryption.getId()); + + byte[] recData = recipient.getContent(new JceKeyTransEnvelopedRecipient(_reciKP.getPrivate()).setProvider(BC)); + + assertEquals(true, Arrays.equals(data, recData)); + } + } + + public void testKeyTrans() + throws Exception + { + byte[] data = "WallaWallaWashington".getBytes(); + + CMSEnvelopedDataGenerator edGen = new CMSEnvelopedDataGenerator(); + + edGen.addRecipientInfoGenerator(new JceKeyTransRecipientInfoGenerator(_reciCert).setProvider(BC)); + edGen.addRecipientInfoGenerator(new JceKeyTransRecipientInfoGenerator(ASN1OctetString.getInstance(ASN1OctetString.getInstance(_reciCert.getExtensionValue(Extension.subjectKeyIdentifier.getId())).getOctets()).getOctets(), _reciCert.getPublicKey()).setProvider(BC)); + + CMSEnvelopedData ed = edGen.generate( + new CMSProcessableByteArray(data), + new JceCMSContentEncryptorBuilder(CMSAlgorithm.DES_EDE3_CBC).setProvider(BC).build()); + + RecipientInformationStore recipients = ed.getRecipientInfos(); + + + assertEquals(ed.getEncryptionAlgOID(), CMSEnvelopedDataGenerator.DES_EDE3_CBC); + + Collection c = recipients.getRecipients(); + + assertEquals(2, c.size()); + + Iterator it = c.iterator(); + + while (it.hasNext()) + { + RecipientInformation recipient = (RecipientInformation)it.next(); + + assertEquals(recipient.getKeyEncryptionAlgOID(), PKCSObjectIdentifiers.rsaEncryption.getId()); + + byte[] recData = recipient.getContent(new JceKeyTransEnvelopedRecipient(_reciKP.getPrivate()).setProvider(BC)); + + assertEquals(true, Arrays.equals(data, recData)); + } + + RecipientId id = new JceKeyTransRecipientId(_reciCert); + + Collection collection = recipients.getRecipients(id); + if (collection.size() != 2) + { + fail("recipients not matched using general recipient ID."); + } + assertTrue(collection.iterator().next() instanceof RecipientInformation); + } + + public void testKeyTransOAEPDefault() + throws Exception + { + byte[] data = "WallaWallaWashington".getBytes(); + + CMSEnvelopedDataGenerator edGen = new CMSEnvelopedDataGenerator(); + JcaAlgorithmParametersConverter paramsConverter = new JcaAlgorithmParametersConverter(); + + edGen.addRecipientInfoGenerator(new JceKeyTransRecipientInfoGenerator(_reciCert, paramsConverter.getAlgorithmIdentifier(PKCSObjectIdentifiers.id_RSAES_OAEP, OAEPParameterSpec.DEFAULT)).setProvider(BC)); + edGen.addRecipientInfoGenerator(new JceKeyTransRecipientInfoGenerator(ASN1OctetString.getInstance(ASN1OctetString.getInstance(_reciCert.getExtensionValue(Extension.subjectKeyIdentifier.getId())).getOctets()).getOctets(), paramsConverter.getAlgorithmIdentifier(PKCSObjectIdentifiers.id_RSAES_OAEP, OAEPParameterSpec.DEFAULT), _reciCert.getPublicKey()).setProvider(BC)); + + CMSEnvelopedData ed = edGen.generate( + new CMSProcessableByteArray(data), + new JceCMSContentEncryptorBuilder(CMSAlgorithm.DES_EDE3_CBC).setProvider(BC).build()); + + RecipientInformationStore recipients = ed.getRecipientInfos(); + + + assertEquals(ed.getEncryptionAlgOID(), CMSEnvelopedDataGenerator.DES_EDE3_CBC); + + Collection c = recipients.getRecipients(); + + assertEquals(2, c.size()); + + Iterator it = c.iterator(); + + while (it.hasNext()) + { + RecipientInformation recipient = (RecipientInformation)it.next(); + + assertEquals(PKCSObjectIdentifiers.id_RSAES_OAEP, recipient.getKeyEncryptionAlgorithm().getAlgorithm()); + + byte[] recData = recipient.getContent(new JceKeyTransEnvelopedRecipient(_reciKP.getPrivate()).setProvider(BC)); + + assertEquals(true, Arrays.equals(data, recData)); + } + + RecipientId id = new JceKeyTransRecipientId(_reciCert); + + Collection collection = recipients.getRecipients(id); + if (collection.size() != 2) + { + fail("recipients not matched using general recipient ID."); + } + assertTrue(collection.iterator().next() instanceof RecipientInformation); + } + + public void testKeyTransOAEPSHA1() + throws Exception + { + doTestKeyTransOAEPDefaultNamed("SHA-1"); + } + + public void testKeyTransOAEPSHA224() + throws Exception + { + doTestKeyTransOAEPDefaultNamed("SHA-224"); + } + + public void testKeyTransOAEPSHA256() + throws Exception + { + doTestKeyTransOAEPDefaultNamed("SHA-256"); + } + + public void testKeyTransOAEPSHA1AndSHA256() + throws Exception + { + doTestKeyTransOAEPDefaultNamed("SHA-1", "SHA-256"); + } + + private void doTestKeyTransOAEPDefaultNamed(String digest) + throws Exception + { + doTestKeyTransOAEPDefaultNamed(digest, digest); + } + + private void doTestKeyTransOAEPDefaultNamed(String digest, String mgfDigest) + throws Exception + { + byte[] data = "WallaWallaWashington".getBytes(); + + CMSEnvelopedDataGenerator edGen = new CMSEnvelopedDataGenerator(); + JcaAlgorithmParametersConverter paramsConverter = new JcaAlgorithmParametersConverter(); + + OAEPParameterSpec oaepSpec = new OAEPParameterSpec(digest, "MGF1", new MGF1ParameterSpec(mgfDigest), new PSource.PSpecified(new byte[]{1, 2, 3, 4, 5})); + AlgorithmIdentifier oaepAlgId = paramsConverter.getAlgorithmIdentifier(PKCSObjectIdentifiers.id_RSAES_OAEP, oaepSpec); + + edGen.addRecipientInfoGenerator(new JceKeyTransRecipientInfoGenerator(_reciCert, oaepAlgId).setProvider(BC)); + edGen.addRecipientInfoGenerator(new JceKeyTransRecipientInfoGenerator(ASN1OctetString.getInstance(ASN1OctetString.getInstance(_reciCert.getExtensionValue(Extension.subjectKeyIdentifier.getId())).getOctets()).getOctets(), oaepAlgId, _reciCert.getPublicKey()).setProvider(BC)); + + CMSEnvelopedData ed = edGen.generate( + new CMSProcessableByteArray(data), + new JceCMSContentEncryptorBuilder(CMSAlgorithm.DES_EDE3_CBC).setProvider(BC).build()); + + RecipientInformationStore recipients = ed.getRecipientInfos(); + + + assertEquals(ed.getEncryptionAlgOID(), CMSEnvelopedDataGenerator.DES_EDE3_CBC); + + Collection c = recipients.getRecipients(); + + assertEquals(2, c.size()); + + Iterator it = c.iterator(); + + while (it.hasNext()) + { + RecipientInformation recipient = (RecipientInformation)it.next(); + + assertEquals(PKCSObjectIdentifiers.id_RSAES_OAEP, recipient.getKeyEncryptionAlgorithm().getAlgorithm()); + + byte[] recData = recipient.getContent(new JceKeyTransEnvelopedRecipient(_reciKP.getPrivate()).setProvider(BC)); + + assertEquals(true, Arrays.equals(data, recData)); + } + + RecipientId id = new JceKeyTransRecipientId(_reciCert); + + Collection collection = recipients.getRecipients(id); + if (collection.size() != 2) + { + fail("recipients not matched using general recipient ID."); + } + assertTrue(collection.iterator().next() instanceof RecipientInformation); + } + + public void testKeyTransOAEPInCert() + throws Exception + { + byte[] data = "WallaWallaWashington".getBytes(); + + CMSEnvelopedDataGenerator edGen = new CMSEnvelopedDataGenerator(); + + edGen.addRecipientInfoGenerator(new JceKeyTransRecipientInfoGenerator(_reciCertOaep).setProvider(BC)); + edGen.addRecipientInfoGenerator(new JceKeyTransRecipientInfoGenerator(ASN1OctetString.getInstance(ASN1OctetString.getInstance(_reciCertOaep.getExtensionValue(Extension.subjectKeyIdentifier.getId())).getOctets()).getOctets(), _reciCertOaep.getPublicKey()).setProvider(BC)); + + CMSEnvelopedData ed = edGen.generate( + new CMSProcessableByteArray(data), + new JceCMSContentEncryptorBuilder(CMSAlgorithm.DES_EDE3_CBC).setProvider(BC).build()); + + RecipientInformationStore recipients = ed.getRecipientInfos(); + + + assertEquals(ed.getEncryptionAlgOID(), CMSEnvelopedDataGenerator.DES_EDE3_CBC); + + Collection c = recipients.getRecipients(); + + assertEquals(2, c.size()); + + Iterator it = c.iterator(); + + while (it.hasNext()) + { + RecipientInformation recipient = (RecipientInformation)it.next(); + + assertEquals(PKCSObjectIdentifiers.id_RSAES_OAEP, recipient.getKeyEncryptionAlgorithm().getAlgorithm()); + + byte[] recData = recipient.getContent(new JceKeyTransEnvelopedRecipient(_reciKP.getPrivate()).setProvider(BC)); + + assertEquals(true, Arrays.equals(data, recData)); + } + + RecipientId id = new JceKeyTransRecipientId(_reciCertOaep); + + Collection collection = recipients.getRecipients(id); + if (collection.size() != 2) + { + fail("recipients not matched using general recipient ID."); + } + assertTrue(collection.iterator().next() instanceof RecipientInformation); + } + + public void testKeyTransWithAlgMapping() + throws Exception + { + byte[] data = "WallaWallaWashington".getBytes(); + + CMSEnvelopedDataGenerator edGen = new CMSEnvelopedDataGenerator(); + + edGen.addRecipientInfoGenerator(new JceKeyTransRecipientInfoGenerator(_reciCert).setAlgorithmMapping(PKCSObjectIdentifiers.rsaEncryption, "RSA/2/PKCS1Padding").setProvider(BC)); + + CMSEnvelopedData ed = edGen.generate( + new CMSProcessableByteArray(data), + new JceCMSContentEncryptorBuilder(CMSAlgorithm.DES_EDE3_CBC).setProvider(BC).build()); + + RecipientInformationStore recipients = ed.getRecipientInfos(); + + assertEquals(ed.getEncryptionAlgOID(), CMSEnvelopedDataGenerator.DES_EDE3_CBC); + + Collection c = recipients.getRecipients(); + + assertEquals(1, c.size()); + + Iterator it = c.iterator(); + + while (it.hasNext()) + { + RecipientInformation recipient = (RecipientInformation)it.next(); + + assertEquals(recipient.getKeyEncryptionAlgOID(), PKCSObjectIdentifiers.rsaEncryption.getId()); + + byte[] recData = recipient.getContent(new JceKeyTransEnvelopedRecipient(_reciKP.getPrivate()).setAlgorithmMapping(PKCSObjectIdentifiers.rsaEncryption, "RSA/2/PKCS1Padding").setProvider(BC)); + + assertEquals(true, Arrays.equals(data, recData)); + } + + RecipientId id = new JceKeyTransRecipientId(_reciCert); + + Collection collection = recipients.getRecipients(id); + if (collection.size() != 1) + { + fail("recipients not matched using general recipient ID."); + } + assertTrue(collection.iterator().next() instanceof RecipientInformation); + } + + public void testOriginatorInfoGeneration() + throws Exception + { + byte[] data = "WallaWallaWashington".getBytes(); + + CMSEnvelopedDataGenerator edGen = new CMSEnvelopedDataGenerator(); + + X509CertificateHolder origCert = new X509CertificateHolder(_origCert.getEncoded()); + + edGen.setOriginatorInfo(new OriginatorInfoGenerator(origCert).generate()); + + edGen.addRecipientInfoGenerator(new JceKeyTransRecipientInfoGenerator(_reciCert).setProvider(BC)); + edGen.addRecipientInfoGenerator(new JceKeyTransRecipientInfoGenerator(ASN1OctetString.getInstance(ASN1OctetString.getInstance(_reciCert.getExtensionValue(Extension.subjectKeyIdentifier.getId())).getOctets()).getOctets(), _reciCert.getPublicKey()).setProvider(BC)); + + CMSEnvelopedData ed = edGen.generate( + new CMSProcessableByteArray(data), + new JceCMSContentEncryptorBuilder(CMSAlgorithm.DES_EDE3_CBC).setProvider(BC).build()); + + RecipientInformationStore recipients = ed.getRecipientInfos(); + + + assertEquals(ed.getEncryptionAlgOID(), CMSEnvelopedDataGenerator.DES_EDE3_CBC); + + assertTrue(ed.getOriginatorInfo().getCertificates().getMatches(null).contains(origCert)); + + Collection c = recipients.getRecipients(); + + assertEquals(2, c.size()); + + Iterator it = c.iterator(); + + while (it.hasNext()) + { + RecipientInformation recipient = (RecipientInformation)it.next(); + + assertEquals(recipient.getKeyEncryptionAlgOID(), PKCSObjectIdentifiers.rsaEncryption.getId()); + + byte[] recData = recipient.getContent(new JceKeyTransEnvelopedRecipient(_reciKP.getPrivate()).setProvider(BC)); + + assertEquals(true, Arrays.equals(data, recData)); + } + + RecipientId id = new JceKeyTransRecipientId(_reciCert); + + Collection collection = recipients.getRecipients(id); + if (collection.size() != 2) + { + fail("recipients not matched using general recipient ID."); + } + assertTrue(collection.iterator().next() instanceof RecipientInformation); + } + + public void testKeyTransRC2bit40() + throws Exception + { + byte[] data = "WallaWallaBouncyCastle".getBytes(); + + CMSEnvelopedDataGenerator edGen = new CMSEnvelopedDataGenerator(); + + edGen.addRecipientInfoGenerator(new JceKeyTransRecipientInfoGenerator(_reciCert).setProvider(BC)); + + CMSEnvelopedData ed = edGen.generate( + new CMSProcessableByteArray(data), + new JceCMSContentEncryptorBuilder(CMSAlgorithm.RC2_CBC, 40).setProvider(BC).build()); + + RecipientInformationStore recipients = ed.getRecipientInfos(); + + assertEquals(ed.getContentEncryptionAlgorithm().getAlgorithm(), CMSAlgorithm.RC2_CBC); + + RC2CBCParameter rc2P = RC2CBCParameter.getInstance(ed.getContentEncryptionAlgorithm().getParameters()); + assertEquals(160, rc2P.getRC2ParameterVersion().intValue()); + + Collection c = recipients.getRecipients(); + + assertEquals(1, c.size()); + + Iterator it = c.iterator(); + + while (it.hasNext()) + { + RecipientInformation recipient = (RecipientInformation)it.next(); + + byte[] recData = recipient.getContent(new JceKeyTransEnvelopedRecipient(_reciKP.getPrivate()).setProvider(BC)); + + assertEquals(true, Arrays.equals(data, recData)); + } + } + + public void testKeyTransRC4() + throws Exception + { + byte[] data = "WallaWallaBouncyCastle".getBytes(); + + CMSEnvelopedDataGenerator edGen = new CMSEnvelopedDataGenerator(); + + edGen.addRecipientInfoGenerator(new JceKeyTransRecipientInfoGenerator(_reciCert).setProvider(BC)); + + CMSEnvelopedData ed = edGen.generate( + new CMSProcessableByteArray(data), + new JceCMSContentEncryptorBuilder(new ASN1ObjectIdentifier("1.2.840.113549.3.4")).setProvider(BC).build()); + + RecipientInformationStore recipients = ed.getRecipientInfos(); + + assertEquals(ed.getEncryptionAlgOID(), "1.2.840.113549.3.4"); + + Collection c = recipients.getRecipients(); + + assertEquals(1, c.size()); + + Iterator it = c.iterator(); + + while (it.hasNext()) + { + RecipientInformation recipient = (RecipientInformation)it.next(); + + byte[] recData = recipient.getContent(new JceKeyTransEnvelopedRecipient(_reciKP.getPrivate()).setProvider(BC)); + + assertEquals(true, Arrays.equals(data, recData)); + } + } + + public void testKeyTrans128RC4() + throws Exception + { + byte[] data = "WallaWallaBouncyCastle".getBytes(); + + CMSEnvelopedDataGenerator edGen = new CMSEnvelopedDataGenerator(); + + edGen.addRecipientInfoGenerator(new JceKeyTransRecipientInfoGenerator(_reciCert).setProvider(BC)); + + CMSEnvelopedData ed = edGen.generate( + new CMSProcessableByteArray(data), + new JceCMSContentEncryptorBuilder(new ASN1ObjectIdentifier("1.2.840.113549.3.4"), 128).setProvider(BC).build()); + + RecipientInformationStore recipients = ed.getRecipientInfos(); + + assertEquals(ed.getEncryptionAlgOID(), "1.2.840.113549.3.4"); + + Collection c = recipients.getRecipients(); + Iterator it = c.iterator(); + + if (it.hasNext()) + { + RecipientInformation recipient = (RecipientInformation)it.next(); + + byte[] recData = recipient.getContent(new JceKeyTransEnvelopedRecipient(_reciKP.getPrivate()).setProvider(BC)); + + assertEquals(true, Arrays.equals(data, recData)); + } + else + { + fail("no recipient found"); + } + } + + public void testKeyTransLight128RC4() + throws Exception + { + byte[] data = "WallaWallaBouncyCastle".getBytes(); + + CMSEnvelopedDataGenerator edGen = new CMSEnvelopedDataGenerator(); + + edGen.addRecipientInfoGenerator(new BcRSAKeyTransRecipientInfoGenerator(new JcaX509CertificateHolder(_reciCert))); + + CMSEnvelopedData ed = edGen.generate( + new CMSProcessableByteArray(data), + new JceCMSContentEncryptorBuilder(new ASN1ObjectIdentifier("1.2.840.113549.3.4"), 128).setProvider(BC).build()); + + RecipientInformationStore recipients = ed.getRecipientInfos(); + + assertEquals(ed.getEncryptionAlgOID(), "1.2.840.113549.3.4"); + + Collection c = recipients.getRecipients(); + Iterator it = c.iterator(); + + if (it.hasNext()) + { + RecipientInformation recipient = (RecipientInformation)it.next(); + + byte[] recData = recipient.getContent(new JceKeyTransEnvelopedRecipient(_reciKP.getPrivate()).setProvider(BC)); + + assertEquals(true, Arrays.equals(data, recData)); + } + else + { + fail("no recipient found"); + } + } + + public void testKeyTransODES() + throws Exception + { + byte[] data = "WallaWallaBouncyCastle".getBytes(); + + CMSEnvelopedDataGenerator edGen = new CMSEnvelopedDataGenerator(); + + edGen.addRecipientInfoGenerator(new JceKeyTransRecipientInfoGenerator(_reciCert).setProvider(BC)); + + CMSEnvelopedData ed = edGen.generate( + new CMSProcessableByteArray(data), + new JceCMSContentEncryptorBuilder(new ASN1ObjectIdentifier("1.3.14.3.2.7")).setProvider(BC).build()); + + RecipientInformationStore recipients = ed.getRecipientInfos(); + + assertEquals(ed.getEncryptionAlgOID(), "1.3.14.3.2.7"); + + Collection c = recipients.getRecipients(); + Iterator it = c.iterator(); + + if (it.hasNext()) + { + RecipientInformation recipient = (RecipientInformation)it.next(); + + byte[] recData = recipient.getContent(new JceKeyTransEnvelopedRecipient(_reciKP.getPrivate()).setProvider(BC)); + + assertEquals(true, Arrays.equals(data, recData)); + } + else + { + fail("no recipient found"); + } + } + + public void testKeyTransSmallAES() + throws Exception + { + byte[] data = new byte[] { 0, 1, 2, 3 }; + + CMSEnvelopedDataGenerator edGen = new CMSEnvelopedDataGenerator(); + + edGen.addRecipientInfoGenerator(new JceKeyTransRecipientInfoGenerator(_reciCert).setProvider(BC)); + + CMSEnvelopedData ed = edGen.generate( + new CMSProcessableByteArray(data), + new JceCMSContentEncryptorBuilder(CMSAlgorithm.AES128_CBC).setProvider(BC).build()); + + RecipientInformationStore recipients = ed.getRecipientInfos(); + + assertEquals(ed.getEncryptionAlgOID(), + CMSEnvelopedDataGenerator.AES128_CBC); + + Collection c = recipients.getRecipients(); + Iterator it = c.iterator(); + + if (it.hasNext()) + { + RecipientInformation recipient = (RecipientInformation)it.next(); + + byte[] recData = recipient.getContent(new JceKeyTransEnvelopedRecipient(_reciKP.getPrivate()).setProvider(BC)); + assertEquals(true, Arrays.equals(data, recData)); + } + else + { + fail("no recipient found"); + } + } + + public void testKeyTransDESEDE3Short() + throws Exception + { + byte[] data = new byte[] { 0, 1, 2, 3 }; + KeyFactory kf = KeyFactory.getInstance("RSA", BC); + PrivateKey kPriv = kf.generatePrivate(new PKCS8EncodedKeySpec(tooShort3DESKey)); + + CMSEnvelopedData ed = new CMSEnvelopedData(tooShort3DES); + + RecipientInformationStore recipients = ed.getRecipientInfos(); + + assertEquals(ed.getEncryptionAlgOID(), CMSEnvelopedDataGenerator.DES_EDE3_CBC); + + Collection c = recipients.getRecipients(); + Iterator it = c.iterator(); + + if (it.hasNext()) + { + RecipientInformation recipient = (RecipientInformation)it.next(); + try + { + byte[] recData = recipient.getContent(new JceKeyTransEnvelopedRecipient(kPriv).setKeySizeValidation(true).setProvider(BC)); + fail("invalid 3DES-EDE key not picked up"); + } + catch (CMSException e) + { + assertEquals("Expected key size for algorithm OID not found in recipient.", e.getMessage()); + } + + byte[] recData = recipient.getContent(new JceKeyTransEnvelopedRecipient(kPriv).setKeySizeValidation(false).setProvider(BC)); + assertEquals(true, Arrays.equals(data, recData)); + } + else + { + fail("no recipient found"); + } + } + + public void testKeyTransDESEDE3Light() + throws Exception + { + byte[] data = new byte[] { 0, 1, 2, 3 }; + + CMSEnvelopedDataGenerator edGen = new CMSEnvelopedDataGenerator(); + + edGen.addRecipientInfoGenerator(new BcRSAKeyTransRecipientInfoGenerator(new JcaX509CertificateHolder(_reciCert))); + + CMSEnvelopedData ed = edGen.generate( + new CMSProcessableByteArray(data), + new BcCMSContentEncryptorBuilder(CMSAlgorithm.DES_EDE3_CBC, 192).build()); + + RecipientInformationStore recipients = ed.getRecipientInfos(); + + assertEquals(ed.getEncryptionAlgOID(), CMSEnvelopedDataGenerator.DES_EDE3_CBC); + + Collection c = recipients.getRecipients(); + Iterator it = c.iterator(); + + if (it.hasNext()) + { + RecipientInformation recipient = (RecipientInformation)it.next(); + + byte[] recData = recipient.getContent(new JceKeyTransEnvelopedRecipient(_reciKP.getPrivate()).setKeySizeValidation(true).setProvider(BC)); + assertEquals(true, Arrays.equals(data, recData)); + } + else + { + fail("no recipient found"); + } + } + + public void testKeyTransDES() + throws Exception + { + tryKeyTrans(CMSAlgorithm.DES_CBC, CMSAlgorithm.DES_CBC, 8, DEROctetString.class); + } + + public void testKeyTransCAST5() + throws Exception + { + tryKeyTrans(CMSAlgorithm.CAST5_CBC, CMSAlgorithm.CAST5_CBC, 16, ASN1Sequence.class); + } + + public void testKeyTransAES128() + throws Exception + { + tryKeyTrans(CMSAlgorithm.AES128_CBC, NISTObjectIdentifiers.id_aes128_CBC, 16, DEROctetString.class); + } + + public void testKeyTransAES192() + throws Exception + { + tryKeyTrans(CMSAlgorithm.AES192_CBC, NISTObjectIdentifiers.id_aes192_CBC, 24, DEROctetString.class); + } + + public void testKeyTransAES256() + throws Exception + { + tryKeyTrans(CMSAlgorithm.AES256_CBC, NISTObjectIdentifiers.id_aes256_CBC, 32, DEROctetString.class); + } + + public void testKeyTransSEED() + throws Exception + { + tryKeyTrans(CMSAlgorithm.SEED_CBC, KISAObjectIdentifiers.id_seedCBC, 16, DEROctetString.class); + } + + public void testKeyTransCamellia128() + throws Exception + { + tryKeyTrans(CMSAlgorithm.CAMELLIA128_CBC, NTTObjectIdentifiers.id_camellia128_cbc, 16, DEROctetString.class); + } + + public void testKeyTransCamellia192() + throws Exception + { + tryKeyTrans(CMSAlgorithm.CAMELLIA192_CBC, NTTObjectIdentifiers.id_camellia192_cbc, 24, DEROctetString.class); + } + + public void testKeyTransCamellia256() + throws Exception + { + tryKeyTrans(CMSAlgorithm.CAMELLIA256_CBC, NTTObjectIdentifiers.id_camellia256_cbc, 32, DEROctetString.class); + } + + private void tryKeyTrans(ASN1ObjectIdentifier generatorOID, ASN1ObjectIdentifier checkOID, int keySize, Class asn1Params) + throws Exception + { + byte[] data = "WallaWallaWashington".getBytes(); + + CMSEnvelopedDataGenerator edGen = new CMSEnvelopedDataGenerator(); + + edGen.addRecipientInfoGenerator(new JceKeyTransRecipientInfoGenerator(_reciCert).setProvider(BC)); + + OutputEncryptor encryptor = new JceCMSContentEncryptorBuilder(generatorOID).setProvider(BC).build(); + CMSEnvelopedData ed = edGen.generate( + new CMSProcessableByteArray(data), + encryptor); + + RecipientInformationStore recipients = ed.getRecipientInfos(); + + assertEquals(checkOID.getId(), ed.getEncryptionAlgOID()); + assertEquals(keySize, ((byte[])encryptor.getKey().getRepresentation()).length); + + if (asn1Params != null) + { + ASN1InputStream aIn = new ASN1InputStream(ed.getEncryptionAlgParams()); + + assertTrue(asn1Params.isAssignableFrom(aIn.readObject().getClass())); + } + + Collection c = recipients.getRecipients(); + + assertEquals(1, c.size()); + + Iterator it = c.iterator(); + + if (!it.hasNext()) + { + fail("no recipients found"); + } + + while (it.hasNext()) + { + RecipientInformation recipient = (RecipientInformation)it.next(); + + assertEquals(recipient.getKeyEncryptionAlgOID(), PKCSObjectIdentifiers.rsaEncryption.getId()); + + byte[] recData = recipient.getContent(new JceKeyTransEnvelopedRecipient(_reciKP.getPrivate()).setKeySizeValidation(true).setProvider(BC)); + + assertEquals(true, Arrays.equals(data, recData)); + } + } + + public void testErroneousKEK() + throws Exception + { + byte[] data = "WallaWallaWashington".getBytes(); + SecretKey kek = new SecretKeySpec(new byte[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 }, "AES"); + + CMSEnvelopedData ed = new CMSEnvelopedData(oldKEK); + + RecipientInformationStore recipients = ed.getRecipientInfos(); + + assertEquals(ed.getEncryptionAlgOID(), CMSEnvelopedDataGenerator.DES_EDE3_CBC); + + Collection c = recipients.getRecipients(); + Iterator it = c.iterator(); + + if (it.hasNext()) + { + RecipientInformation recipient = (RecipientInformation)it.next(); + + assertEquals(recipient.getKeyEncryptionAlgOID(), NISTObjectIdentifiers.id_aes128_wrap.getId()); + + byte[] recData = recipient.getContent(new JceKEKEnvelopedRecipient(kek).setProvider(BC)); + + assertEquals(true, Arrays.equals(data, recData)); + } + else + { + fail("no recipient found"); + } + } + + public void testDESKEK() + throws Exception + { + tryKekAlgorithm(CMSTestUtil.makeDesede192Key(), new ASN1ObjectIdentifier("1.2.840.113549.1.9.16.3.6")); + } + public void testRC2128KEK() + throws Exception + { + tryKekAlgorithm(CMSTestUtil.makeRC2128Key(), new ASN1ObjectIdentifier("1.2.840.113549.1.9.16.3.7")); + } + + public void testAES128KEK() + throws Exception + { + tryKekAlgorithm(CMSTestUtil.makeAESKey(128), NISTObjectIdentifiers.id_aes128_wrap); + } + + public void testAES192KEK() + throws Exception + { + tryKekAlgorithm(CMSTestUtil.makeAESKey(192), NISTObjectIdentifiers.id_aes192_wrap); + } + + public void testAES256KEK() + throws Exception + { + tryKekAlgorithm(CMSTestUtil.makeAESKey(256), NISTObjectIdentifiers.id_aes256_wrap); + } + + public void testSEED128KEK() + throws Exception + { + tryKekAlgorithm(CMSTestUtil.makeSEEDKey(), KISAObjectIdentifiers.id_npki_app_cmsSeed_wrap); + } + + public void testCamellia128KEK() + throws Exception + { + tryKekAlgorithm(CMSTestUtil.makeCamelliaKey(128), NTTObjectIdentifiers.id_camellia128_wrap); + } + + public void testCamellia192KEK() + throws Exception + { + tryKekAlgorithm(CMSTestUtil.makeCamelliaKey(192), NTTObjectIdentifiers.id_camellia192_wrap); + } + + public void testCamellia256KEK() + throws Exception + { + tryKekAlgorithm(CMSTestUtil.makeCamelliaKey(256), NTTObjectIdentifiers.id_camellia256_wrap); + } + + private void tryKekAlgorithm(SecretKey kek, ASN1ObjectIdentifier algOid) + throws NoSuchAlgorithmException, NoSuchProviderException, CMSException + { + byte[] data = "WallaWallaWashington".getBytes(); + CMSEnvelopedDataGenerator edGen = new CMSEnvelopedDataGenerator(); + + byte[] kekId = new byte[] { 1, 2, 3, 4, 5 }; + + edGen.addRecipientInfoGenerator(new JceKEKRecipientInfoGenerator(kekId, kek).setProvider(BC)); + + CMSEnvelopedData ed = edGen.generate( + new CMSProcessableByteArray(data), + new JceCMSContentEncryptorBuilder(CMSAlgorithm.DES_EDE3_CBC).setProvider(BC).build()); + + RecipientInformationStore recipients = ed.getRecipientInfos(); + + Collection c = recipients.getRecipients(); + Iterator it = c.iterator(); + + assertEquals(ed.getEncryptionAlgOID(), CMSEnvelopedDataGenerator.DES_EDE3_CBC); + + if (it.hasNext()) + { + RecipientInformation recipient = (RecipientInformation)it.next(); + + assertEquals(algOid.getId(), recipient.getKeyEncryptionAlgOID()); + + byte[] recData = recipient.getContent(new JceKEKEnvelopedRecipient(kek).setKeySizeValidation(true).setProvider(BC)); + + assertTrue(Arrays.equals(data, recData)); + } + else + { + fail("no recipient found"); + } + } + + public void testECKeyAgree() + throws Exception + { + byte[] data = Hex.decode("504b492d4320434d5320456e76656c6f706564446174612053616d706c65"); + + CMSEnvelopedDataGenerator edGen = new CMSEnvelopedDataGenerator(); + + edGen.addRecipientInfoGenerator(new JceKeyAgreeRecipientInfoGenerator(CMSAlgorithm.ECDH_SHA1KDF, + _origEcKP.getPrivate(), _origEcKP.getPublic(), + CMSAlgorithm.AES128_WRAP).addRecipient(_reciEcCert).setProvider(BC)); + + CMSEnvelopedData ed = edGen.generate( + new CMSProcessableByteArray(data), + new JceCMSContentEncryptorBuilder(CMSAlgorithm.AES128_CBC).setProvider(BC).build()); + + assertEquals(ed.getEncryptionAlgOID(), CMSEnvelopedDataGenerator.AES128_CBC); + + RecipientInformationStore recipients = ed.getRecipientInfos(); + + confirmDataReceived(recipients, data, _reciEcCert, _reciEcKP.getPrivate(), BC); + confirmNumberRecipients(recipients, 1); + } + + public void testECMQVKeyAgree() + throws Exception + { + byte[] data = Hex.decode("504b492d4320434d5320456e76656c6f706564446174612053616d706c65"); + + CMSEnvelopedDataGenerator edGen = new CMSEnvelopedDataGenerator(); + + edGen.addRecipientInfoGenerator(new JceKeyAgreeRecipientInfoGenerator(CMSAlgorithm.ECMQV_SHA1KDF, + _origEcKP.getPrivate(), _origEcKP.getPublic(), + CMSAlgorithm.AES128_WRAP).addRecipient(_reciEcCert).setProvider(BC)); + + CMSEnvelopedData ed = edGen.generate( + new CMSProcessableByteArray(data), + new JceCMSContentEncryptorBuilder(CMSAlgorithm.AES128_CBC).setProvider(BC).build()); + + assertEquals(ed.getEncryptionAlgOID(), CMSEnvelopedDataGenerator.AES128_CBC); + + RecipientInformationStore recipients = ed.getRecipientInfos(); + + confirmDataReceived(recipients, data, _reciEcCert, _reciEcKP.getPrivate(), BC); + confirmNumberRecipients(recipients, 1); + } + + public void testECMQVKeyAgreeMultiple() + throws Exception + { + byte[] data = Hex.decode("504b492d4320434d5320456e76656c6f706564446174612053616d706c65"); + + CMSEnvelopedDataGenerator edGen = new CMSEnvelopedDataGenerator(); + + JceKeyAgreeRecipientInfoGenerator recipientGenerator = new JceKeyAgreeRecipientInfoGenerator(CMSAlgorithm.ECMQV_SHA1KDF, + _origEcKP.getPrivate(), _origEcKP.getPublic(), CMSAlgorithm.AES128_WRAP).setProvider(BC); + + recipientGenerator.addRecipient(_reciEcCert); + recipientGenerator.addRecipient(_reciEcCert2); + + edGen.addRecipientInfoGenerator(recipientGenerator); + + CMSEnvelopedData ed = edGen.generate( + new CMSProcessableByteArray(data), + new JceCMSContentEncryptorBuilder(CMSAlgorithm.AES128_CBC).setProvider(BC).build()); + + assertEquals(ed.getEncryptionAlgOID(), CMSEnvelopedDataGenerator.AES128_CBC); + + RecipientInformationStore recipients = ed.getRecipientInfos(); + + confirmDataReceived(recipients, data, _reciEcCert, _reciEcKP.getPrivate(), BC); + confirmDataReceived(recipients, data, _reciEcCert2, _reciEcKP2.getPrivate(), BC); + confirmNumberRecipients(recipients, 2); + } + + private static void confirmDataReceived(RecipientInformationStore recipients, + byte[] expectedData, X509Certificate reciCert, PrivateKey reciPrivKey, String provider) + throws CMSException, NoSuchProviderException, CertificateEncodingException, IOException + { + RecipientId rid = new JceKeyAgreeRecipientId(reciCert); + + RecipientInformation recipient = recipients.get(rid); + assertNotNull(recipient); + + byte[] actualData = recipient.getContent(new JceKeyAgreeEnvelopedRecipient(reciPrivKey).setProvider(provider)); + assertEquals(true, Arrays.equals(expectedData, actualData)); + } + + private static void confirmNumberRecipients(RecipientInformationStore recipients, int count) + { + assertEquals(count, recipients.getRecipients().size()); + } + + public void testECKeyAgreeVectors() + throws Exception + { + PKCS8EncodedKeySpec privSpec = new PKCS8EncodedKeySpec(ecKeyAgreeKey); + KeyFactory fact = KeyFactory.getInstance("ECDH", BC); + PrivateKey privKey = fact.generatePrivate(privSpec); + + verifyECKeyAgreeVectors(privKey, "2.16.840.1.101.3.4.1.42", ecKeyAgreeMsgAES256); + verifyECKeyAgreeVectors(privKey, "2.16.840.1.101.3.4.1.2", ecKeyAgreeMsgAES128); + verifyECKeyAgreeVectors(privKey, "1.2.840.113549.3.7", ecKeyAgreeMsgDESEDE); + } + + public void testECMQVKeyAgreeVectors() + throws Exception + { + PKCS8EncodedKeySpec privSpec = new PKCS8EncodedKeySpec(ecKeyAgreeKey); + KeyFactory fact = KeyFactory.getInstance("ECDH", BC); + PrivateKey privKey = fact.generatePrivate(privSpec); + + verifyECMQVKeyAgreeVectors(privKey, "2.16.840.1.101.3.4.1.2", ecMQVKeyAgreeMsgAES128); + } + + public void testPasswordAES256() + throws Exception + { + passwordTest(CMSEnvelopedDataGenerator.AES256_CBC); + passwordUTF8Test(CMSEnvelopedDataGenerator.AES256_CBC); + } + + public void testPasswordDESEDE() + throws Exception + { + passwordTest(CMSEnvelopedDataGenerator.DES_EDE3_CBC); + passwordUTF8Test(CMSEnvelopedDataGenerator.DES_EDE3_CBC); + } + + public void testRFC4134ex5_1() + throws Exception + { + byte[] data = Hex.decode("5468697320697320736f6d652073616d706c6520636f6e74656e742e"); + + KeyFactory kFact = KeyFactory.getInstance("RSA", BC); + Key key = kFact.generatePrivate(new PKCS8EncodedKeySpec(bobPrivRsaEncrypt)); + + CMSEnvelopedData ed = new CMSEnvelopedData(rfc4134ex5_1); + + RecipientInformationStore recipients = ed.getRecipientInfos(); + + assertEquals("1.2.840.113549.3.7", ed.getEncryptionAlgOID()); + + Collection c = recipients.getRecipients(); + Iterator it = c.iterator(); + + if (it.hasNext()) + { + RecipientInformation recipient = (RecipientInformation)it.next(); + + byte[] recData = recipient.getContent(new JceKeyTransEnvelopedRecipient((PrivateKey)key).setProvider(BC)); + + assertEquals(true, Arrays.equals(data, recData)); + } + else + { + fail("no recipient found"); + } + } + + public void testRFC4134ex5_2() + throws Exception + { + byte[] data = Hex.decode("5468697320697320736f6d652073616d706c6520636f6e74656e742e"); + + KeyFactory kFact = KeyFactory.getInstance("RSA", BC); + PrivateKey key = kFact.generatePrivate(new PKCS8EncodedKeySpec(bobPrivRsaEncrypt)); + + CMSEnvelopedData ed = new CMSEnvelopedData(rfc4134ex5_2); + + RecipientInformationStore recipients = ed.getRecipientInfos(); + + assertEquals("1.2.840.113549.3.2", ed.getEncryptionAlgOID()); + + Collection c = recipients.getRecipients(); + Iterator it = c.iterator(); + + if (it.hasNext()) + { + while (it.hasNext()) + { + RecipientInformation recipient = (RecipientInformation)it.next(); + byte[] recData; + + if (recipient instanceof KeyTransRecipientInformation) + { + recData = recipient.getContent(new JceKeyTransEnvelopedRecipient(key).setProvider(BC)); + + assertEquals(true, Arrays.equals(data, recData)); + } + } + } + else + { + fail("no recipient found"); + } + } + + public void testOriginatorInfo() + throws Exception + { + CMSEnvelopedData env = new CMSEnvelopedData(CMSSampleMessages.originatorMessage); + + RecipientInformationStore recipients = env.getRecipientInfos(); + + OriginatorInformation origInfo = env.getOriginatorInfo(); + + assertEquals(new X500Name("C=US,O=U.S. Government,OU=HSPD12Lab,OU=Agents,CN=user1"), ((X509CertificateHolder)origInfo.getCertificates().getMatches(null).iterator().next()).getSubject()); + assertEquals(CMSEnvelopedDataGenerator.DES_EDE3_CBC, env.getEncryptionAlgOID()); + } + + private void passwordTest(String algorithm) + throws Exception + { + byte[] data = Hex.decode("504b492d4320434d5320456e76656c6f706564446174612053616d706c65"); + + CMSEnvelopedDataGenerator edGen = new CMSEnvelopedDataGenerator(); + + edGen.addRecipientInfoGenerator(new JcePasswordRecipientInfoGenerator(new ASN1ObjectIdentifier(algorithm), "password".toCharArray()).setProvider(BC).setPasswordConversionScheme(PasswordRecipient.PKCS5_SCHEME2).setSaltAndIterationCount(new byte[20], 5)); + + CMSEnvelopedData ed = edGen.generate( + new CMSProcessableByteArray(data), + new JceCMSContentEncryptorBuilder(CMSAlgorithm.AES128_CBC).setProvider(BC).build()); + + RecipientInformationStore recipients = ed.getRecipientInfos(); + + assertEquals(ed.getEncryptionAlgOID(), + CMSEnvelopedDataGenerator.AES128_CBC); + + Collection c = recipients.getRecipients(); + Iterator it = c.iterator(); + + if (it.hasNext()) + { + PasswordRecipientInformation recipient = (PasswordRecipientInformation)it.next(); + + byte[] recData = recipient.getContent(new JcePasswordEnvelopedRecipient("password".toCharArray()).setPasswordConversionScheme(PasswordRecipient.PKCS5_SCHEME2).setProvider(BC)); + + assertEquals(true, Arrays.equals(data, recData)); + } + else + { + fail("no recipient found"); + } + + // + // try algorithm parameters constructor + // + it = c.iterator(); + + RecipientInformation recipient = (RecipientInformation)it.next(); + + byte[] recData = recipient.getContent(new JcePasswordEnvelopedRecipient("password".toCharArray()).setPasswordConversionScheme(PasswordRecipient.PKCS5_SCHEME2).setProvider(BC)); + assertEquals(true, Arrays.equals(data, recData)); + } + + private void passwordUTF8Test(String algorithm) + throws Exception + { + byte[] data = Hex.decode("504b492d4320434d5320456e76656c6f706564446174612053616d706c65"); + + CMSEnvelopedDataGenerator edGen = new CMSEnvelopedDataGenerator(); + + edGen.addRecipientInfoGenerator(new JcePasswordRecipientInfoGenerator(new ASN1ObjectIdentifier(algorithm), "abc\u5639\u563b".toCharArray()).setProvider(BC).setSaltAndIterationCount(new byte[20], 5)); + + CMSEnvelopedData ed = edGen.generate( + new CMSProcessableByteArray(data), + new JceCMSContentEncryptorBuilder(CMSAlgorithm.AES128_CBC).setProvider(BC).build()); + + RecipientInformationStore recipients = ed.getRecipientInfos(); + + assertEquals(ed.getEncryptionAlgOID(), + CMSEnvelopedDataGenerator.AES128_CBC); + + Collection c = recipients.getRecipients(); + Iterator it = c.iterator(); + + if (it.hasNext()) + { + RecipientInformation recipient = (RecipientInformation)it.next(); + + byte[] recData = recipient.getContent(new JcePasswordEnvelopedRecipient("abc\u5639\u563b".toCharArray()).setProvider(BC)); + assertEquals(true, Arrays.equals(data, recData)); + } + else + { + fail("no recipient found"); + } + + // + // try algorithm parameters constructor + // + it = c.iterator(); + + RecipientInformation recipient = (RecipientInformation)it.next(); + + byte[] recData = recipient.getContent(new JcePasswordEnvelopedRecipient("abc\u5639\u563b".toCharArray()).setProvider(BC)); + assertEquals(true, Arrays.equals(data, recData)); + } + + private void verifyECKeyAgreeVectors(PrivateKey privKey, String wrapAlg, byte[] message) + throws CMSException, GeneralSecurityException + { + byte[] data = Hex.decode("504b492d4320434d5320456e76656c6f706564446174612053616d706c65"); + + CMSEnvelopedData ed = new CMSEnvelopedData(message); + + RecipientInformationStore recipients = ed.getRecipientInfos(); + + Collection c = recipients.getRecipients(); + Iterator it = c.iterator(); + + assertEquals(wrapAlg, ed.getEncryptionAlgOID()); + + if (it.hasNext()) + { + RecipientInformation recipient = (RecipientInformation)it.next(); + + assertEquals("1.3.133.16.840.63.0.2", recipient.getKeyEncryptionAlgOID()); + + byte[] recData = recipient.getContent(new JceKeyAgreeEnvelopedRecipient(privKey).setProvider(BC)); + + assertTrue(Arrays.equals(data, recData)); + } + else + { + fail("no recipient found"); + } + } + + private void verifyECMQVKeyAgreeVectors(PrivateKey privKey, String wrapAlg, byte[] message) + throws CMSException, GeneralSecurityException + { + byte[] data = Hex.decode("504b492d4320434d5320456e76656c6f706564446174612053616d706c65"); + + CMSEnvelopedData ed = new CMSEnvelopedData(message); + + RecipientInformationStore recipients = ed.getRecipientInfos(); + + Collection c = recipients.getRecipients(); + Iterator it = c.iterator(); + + assertEquals(wrapAlg, ed.getEncryptionAlgOID()); + + if (it.hasNext()) + { + RecipientInformation recipient = (RecipientInformation)it.next(); + + assertEquals("1.3.133.16.840.63.0.16", recipient.getKeyEncryptionAlgOID()); + + byte[] recData = recipient.getContent(new JceKeyAgreeEnvelopedRecipient(privKey).setProvider(BC)); + + assertTrue(Arrays.equals(data, recData)); + } + else + { + fail("no recipient found"); + } + } +}
\ No newline at end of file diff --git a/pkix/src/test/java/org/spongycastle/cms/test/NewSignedDataStreamTest.java b/pkix/src/test/java/org/spongycastle/cms/test/NewSignedDataStreamTest.java new file mode 100644 index 00000000..8032b71c --- /dev/null +++ b/pkix/src/test/java/org/spongycastle/cms/test/NewSignedDataStreamTest.java @@ -0,0 +1,1311 @@ +package org.spongycastle.cms.test; + +import java.io.BufferedOutputStream; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.OutputStream; +import java.security.KeyPair; +import java.security.MessageDigest; +import java.security.Security; +import java.security.cert.X509CRL; +import java.security.cert.X509Certificate; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.Hashtable; +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +import junit.framework.Test; +import junit.framework.TestCase; +import junit.framework.TestSuite; +import org.spongycastle.asn1.ASN1ObjectIdentifier; +import org.spongycastle.asn1.ASN1OctetString; +import org.spongycastle.asn1.DEROctetString; +import org.spongycastle.asn1.DERSet; +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.ocsp.OCSPResponse; +import org.spongycastle.cert.X509AttributeCertificateHolder; +import org.spongycastle.cert.X509CertificateHolder; +import org.spongycastle.cert.jcajce.JcaCRLStore; +import org.spongycastle.cert.jcajce.JcaCertStore; +import org.spongycastle.cert.jcajce.JcaX509CRLHolder; +import org.spongycastle.cert.jcajce.JcaX509CertificateHolder; +import org.spongycastle.cert.ocsp.OCSPResp; +import org.spongycastle.cms.CMSAlgorithm; +import org.spongycastle.cms.CMSAttributeTableGenerator; +import org.spongycastle.cms.CMSProcessableByteArray; +import org.spongycastle.cms.CMSSignedData; +import org.spongycastle.cms.CMSSignedDataGenerator; +import org.spongycastle.cms.CMSSignedDataParser; +import org.spongycastle.cms.CMSSignedDataStreamGenerator; +import org.spongycastle.cms.CMSTypedData; +import org.spongycastle.cms.CMSTypedStream; +import org.spongycastle.cms.DefaultSignedAttributeTableGenerator; +import org.spongycastle.cms.SignerInformation; +import org.spongycastle.cms.SignerInformationStore; +import org.spongycastle.cms.jcajce.JcaSignerInfoGeneratorBuilder; +import org.spongycastle.cms.jcajce.JcaSimpleSignerInfoGeneratorBuilder; +import org.spongycastle.cms.jcajce.JcaSimpleSignerInfoVerifierBuilder; +import org.spongycastle.jce.provider.BouncyCastleProvider; +import org.spongycastle.operator.ContentSigner; +import org.spongycastle.operator.jcajce.JcaContentSignerBuilder; +import org.spongycastle.operator.jcajce.JcaDigestCalculatorProviderBuilder; +import org.spongycastle.util.CollectionStore; +import org.spongycastle.util.Store; +import org.spongycastle.util.encoders.Base64; + +public class NewSignedDataStreamTest + extends TestCase +{ + + byte[] successResp = Base64.decode( + "MIIFnAoBAKCCBZUwggWRBgkrBgEFBQcwAQEEggWCMIIFfjCCARehgZ8wgZwx" + + "CzAJBgNVBAYTAklOMRcwFQYDVQQIEw5BbmRocmEgcHJhZGVzaDESMBAGA1UE" + + "BxMJSHlkZXJhYmFkMQwwCgYDVQQKEwNUQ1MxDDAKBgNVBAsTA0FUQzEeMBwG" + + "A1UEAxMVVENTLUNBIE9DU1AgUmVzcG9uZGVyMSQwIgYJKoZIhvcNAQkBFhVv" + + "Y3NwQHRjcy1jYS50Y3MuY28uaW4YDzIwMDMwNDAyMTIzNDU4WjBiMGAwOjAJ" + + "BgUrDgMCGgUABBRs07IuoCWNmcEl1oHwIak1BPnX8QQUtGyl/iL9WJ1VxjxF" + + "j0hAwJ/s1AcCAQKhERgPMjAwMjA4MjkwNzA5MjZaGA8yMDAzMDQwMjEyMzQ1" + + "OFowDQYJKoZIhvcNAQEFBQADgYEAfbN0TCRFKdhsmvOdUoiJ+qvygGBzDxD/" + + "VWhXYA+16AphHLIWNABR3CgHB3zWtdy2j7DJmQ/R7qKj7dUhWLSqclAiPgFt" + + "QQ1YvSJAYfEIdyHkxv4NP0LSogxrumANcDyC9yt/W9yHjD2ICPBIqCsZLuLk" + + "OHYi5DlwWe9Zm9VFwCGgggPMMIIDyDCCA8QwggKsoAMCAQICAQYwDQYJKoZI" + + "hvcNAQEFBQAwgZQxFDASBgNVBAMTC1RDUy1DQSBPQ1NQMSYwJAYJKoZIhvcN" + + "AQkBFhd0Y3MtY2FAdGNzLWNhLnRjcy5jby5pbjEMMAoGA1UEChMDVENTMQww" + + "CgYDVQQLEwNBVEMxEjAQBgNVBAcTCUh5ZGVyYWJhZDEXMBUGA1UECBMOQW5k" + + "aHJhIHByYWRlc2gxCzAJBgNVBAYTAklOMB4XDTAyMDgyOTA3MTE0M1oXDTAz" + + "MDgyOTA3MTE0M1owgZwxCzAJBgNVBAYTAklOMRcwFQYDVQQIEw5BbmRocmEg" + + "cHJhZGVzaDESMBAGA1UEBxMJSHlkZXJhYmFkMQwwCgYDVQQKEwNUQ1MxDDAK" + + "BgNVBAsTA0FUQzEeMBwGA1UEAxMVVENTLUNBIE9DU1AgUmVzcG9uZGVyMSQw" + + "IgYJKoZIhvcNAQkBFhVvY3NwQHRjcy1jYS50Y3MuY28uaW4wgZ8wDQYJKoZI" + + "hvcNAQEBBQADgY0AMIGJAoGBAM+XWW4caMRv46D7L6Bv8iwtKgmQu0SAybmF" + + "RJiz12qXzdvTLt8C75OdgmUomxp0+gW/4XlTPUqOMQWv463aZRv9Ust4f8MH" + + "EJh4ekP/NS9+d8vEO3P40ntQkmSMcFmtA9E1koUtQ3MSJlcs441JjbgUaVnm" + + "jDmmniQnZY4bU3tVAgMBAAGjgZowgZcwDAYDVR0TAQH/BAIwADALBgNVHQ8E" + + "BAMCB4AwEwYDVR0lBAwwCgYIKwYBBQUHAwkwNgYIKwYBBQUHAQEEKjAoMCYG" + + "CCsGAQUFBzABhhpodHRwOi8vMTcyLjE5LjQwLjExMDo3NzAwLzAtBgNVHR8E" + + "JjAkMCKgIKAehhxodHRwOi8vMTcyLjE5LjQwLjExMC9jcmwuY3JsMA0GCSqG" + + "SIb3DQEBBQUAA4IBAQB6FovM3B4VDDZ15o12gnADZsIk9fTAczLlcrmXLNN4" + + "PgmqgnwF0Ymj3bD5SavDOXxbA65AZJ7rBNAguLUo+xVkgxmoBH7R2sBxjTCc" + + "r07NEadxM3HQkt0aX5XYEl8eRoifwqYAI9h0ziZfTNes8elNfb3DoPPjqq6V" + + "mMg0f0iMS4W8LjNPorjRB+kIosa1deAGPhq0eJ8yr0/s2QR2/WFD5P4aXc8I" + + "KWleklnIImS3zqiPrq6tl2Bm8DZj7vXlTOwmraSQxUwzCKwYob1yGvNOUQTq" + + "pG6jxn7jgDawHU1+WjWQe4Q34/pWeGLysxTraMa+Ug9kPe+jy/qRX2xwvKBZ"); + + private static final String BC = BouncyCastleProvider.PROVIDER_NAME; + + private static final String TEST_MESSAGE = "Hello World!"; + private static String _signDN; + private static KeyPair _signKP; + private static X509Certificate _signCert; + + private static String _origDN; + private static KeyPair _origKP; + private static X509Certificate _origCert; + + private static String _reciDN; + private static KeyPair _reciKP; + private static X509Certificate _reciCert; + + private static KeyPair _origDsaKP; + private static X509Certificate _origDsaCert; + + private static X509CRL _signCrl; + private static X509CRL _origCrl; + + private static boolean _initialised = false; + + public NewSignedDataStreamTest(String name) + { + super(name); + } + + private static void init() + throws Exception + { + if (!_initialised) + { + _initialised = true; + + if (Security.getProvider(BC) == null) + { + Security.addProvider(new BouncyCastleProvider()); + } + + _signDN = "O=Bouncy Castle, C=AU"; + _signKP = CMSTestUtil.makeKeyPair(); + _signCert = CMSTestUtil.makeCertificate(_signKP, _signDN, _signKP, _signDN); + + _origDN = "CN=Bob, OU=Sales, O=Bouncy Castle, C=AU"; + _origKP = CMSTestUtil.makeKeyPair(); + _origCert = CMSTestUtil.makeCertificate(_origKP, _origDN, _signKP, _signDN); + + _origDsaKP = CMSTestUtil.makeDsaKeyPair(); + _origDsaCert = CMSTestUtil.makeCertificate(_origDsaKP, _origDN, _signKP, _signDN); + + _reciDN = "CN=Doug, OU=Sales, O=Bouncy Castle, C=AU"; + _reciKP = CMSTestUtil.makeKeyPair(); + _reciCert = CMSTestUtil.makeCertificate(_reciKP, _reciDN, _signKP, _signDN); + + _signCrl = CMSTestUtil.makeCrl(_signKP); + _origCrl = CMSTestUtil.makeCrl(_origKP); + } + } + + private void verifySignatures(CMSSignedDataParser sp, byte[] contentDigest) + throws Exception + { + Store certStore = sp.getCertificates(); + Store crlStore = sp.getCRLs(); + SignerInformationStore signers = sp.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(); + + assertEquals(true, signer.verify(new JcaSimpleSignerInfoVerifierBuilder().setProvider(BC).build(cert))); + + if (contentDigest != null) + { + assertTrue(MessageDigest.isEqual(contentDigest, signer.getContentDigest())); + } + } + + assertEquals(certStore.getMatches(null).size(), sp.getCertificates().getMatches(null).size()); + assertEquals(crlStore.getMatches(null).size(), sp.getCRLs().getMatches(null).size()); + } + + private void verifySignatures(CMSSignedDataParser sp) + throws Exception + { + verifySignatures(sp, null); + } + + private void verifyEncodedData(ByteArrayOutputStream bOut) + throws Exception + { + CMSSignedDataParser sp; + sp = new CMSSignedDataParser(new JcaDigestCalculatorProviderBuilder().setProvider(BC).build(), bOut.toByteArray()); + + sp.getSignedContent().drain(); + + verifySignatures(sp); + + sp.close(); + } + + private void checkSigParseable(byte[] sig) + throws Exception + { + CMSSignedDataParser sp = new CMSSignedDataParser(new JcaDigestCalculatorProviderBuilder().setProvider(BC).build(), sig); + sp.getVersion(); + CMSTypedStream sc = sp.getSignedContent(); + if (sc != null) + { + sc.drain(); + } + sp.getCertificates(); + sp.getCRLs(); + sp.getSignerInfos(); + sp.close(); + } + +// public void testEarlyInvalidKeyException() throws Exception +// { +// try +// { +// CMSSignedDataStreamGenerator gen = new CMSSignedDataStreamGenerator(); +// gen.addSigner( _origKP.getPrivate(), _origCert, +// "DSA", // DOESN'T MATCH KEY ALG +// CMSSignedDataStreamGenerator.DIGEST_SHA1, BC); +// +// fail("Expected InvalidKeyException in addSigner"); +// } +// catch (InvalidKeyException e) +// { +// // Ignore +// } +// } + +// public void testEarlyNoSuchAlgorithmException() throws Exception +// { +// try +// { +// CMSSignedDataStreamGenerator gen = new CMSSignedDataStreamGenerator(); +// gen.addSigner( _origKP.getPrivate(), _origCert, +// CMSSignedDataStreamGenerator.DIGEST_SHA1, // BAD OID! +// CMSSignedDataStreamGenerator.DIGEST_SHA1, BC); +// +// fail("Expected NoSuchAlgorithmException in addSigner"); +// } +// catch (NoSuchAlgorithmException e) +// { +// // Ignore +// } +// } + + public void testSha1EncapsulatedSignature() + throws Exception + { + byte[] encapSigData = Base64.decode( + "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" + + "n7MsJMoKN3Kd2Vzh6s10PFgeAAAAAAAA"); + + CMSSignedDataParser sp = new CMSSignedDataParser(new JcaDigestCalculatorProviderBuilder().setProvider(BC).build(), encapSigData); + + sp.getSignedContent().drain(); + + verifySignatures(sp); + } + + public void testSHA1WithRSANoAttributes() + throws Exception + { + List certList = new ArrayList(); + CMSTypedData msg = new CMSProcessableByteArray(TEST_MESSAGE.getBytes()); + + certList.add(_origCert); + certList.add(_signCert); + + Store certs = new JcaCertStore(certList); + + CMSSignedDataGenerator gen = new CMSSignedDataGenerator(); + + ContentSigner sha1Signer = new JcaContentSignerBuilder("SHA1withRSA").setProvider(BC).build(_origKP.getPrivate()); + + JcaSignerInfoGeneratorBuilder siBuilder = new JcaSignerInfoGeneratorBuilder(new JcaDigestCalculatorProviderBuilder().setProvider(BC).build()); + + siBuilder.setDirectSignature(true); + + gen.addSignerInfoGenerator(siBuilder.build(sha1Signer, _origCert)); + + gen.addCertificates(certs); + + CMSSignedData s = gen.generate(msg, false); + + CMSSignedDataParser sp = new CMSSignedDataParser(new JcaDigestCalculatorProviderBuilder().setProvider(BC).build(), + new CMSTypedStream(new ByteArrayInputStream(TEST_MESSAGE.getBytes())), s.getEncoded()); + + sp.getSignedContent().drain(); + + // + // compute expected content digest + // + MessageDigest md = MessageDigest.getInstance("SHA1", BC); + + verifySignatures(sp, md.digest(TEST_MESSAGE.getBytes())); + } + + public void testDSANoAttributes() + throws Exception + { + List certList = new ArrayList(); + CMSTypedData msg = new CMSProcessableByteArray(TEST_MESSAGE.getBytes()); + + certList.add(_origDsaCert); + certList.add(_signCert); + + JcaCertStore certs = new JcaCertStore(certList); + + CMSSignedDataGenerator gen = new CMSSignedDataGenerator(); + + JcaSignerInfoGeneratorBuilder builder = new JcaSignerInfoGeneratorBuilder(new JcaDigestCalculatorProviderBuilder().setProvider(BC).build()); + + builder.setDirectSignature(true); + + gen.addSignerInfoGenerator(builder.build(new JcaContentSignerBuilder("SHA1withDSA").setProvider(BC).build(_origDsaKP.getPrivate()), _origDsaCert)); + + gen.addCertificates(certs); + + CMSSignedData s = gen.generate(msg); + + CMSSignedDataParser sp = new CMSSignedDataParser(new JcaDigestCalculatorProviderBuilder().setProvider(BC).build(), + new CMSTypedStream(new ByteArrayInputStream(TEST_MESSAGE.getBytes())), s.getEncoded()); + + sp.getSignedContent().drain(); + + // + // compute expected content digest + // + MessageDigest md = MessageDigest.getInstance("SHA1", BC); + + verifySignatures(sp, md.digest(TEST_MESSAGE.getBytes())); + } + + public void testSHA1WithRSA() + throws Exception + { + List certList = new ArrayList(); + List crlList = new ArrayList(); + ByteArrayOutputStream bOut = new ByteArrayOutputStream(); + + certList.add(_origCert); + certList.add(_signCert); + + crlList.add(_signCrl); + crlList.add(_origCrl); + + Store certs = new JcaCertStore(certList); + Store crls = new JcaCRLStore(crlList); + + CMSSignedDataStreamGenerator gen = new CMSSignedDataStreamGenerator(); + + ContentSigner sha1Signer = new JcaContentSignerBuilder("SHA1withRSA").setProvider(BC).build(_origKP.getPrivate()); + + gen.addSignerInfoGenerator(new JcaSignerInfoGeneratorBuilder(new JcaDigestCalculatorProviderBuilder().setProvider(BC).build()).build(sha1Signer, _origCert)); + + gen.addCertificates(certs); + + gen.addCRLs(crls); + + OutputStream sigOut = gen.open(bOut); + + sigOut.write(TEST_MESSAGE.getBytes()); + + sigOut.close(); + + checkSigParseable(bOut.toByteArray()); + + CMSSignedDataParser sp = new CMSSignedDataParser(new JcaDigestCalculatorProviderBuilder().setProvider(BC).build(), + new CMSTypedStream(new ByteArrayInputStream(TEST_MESSAGE.getBytes())), bOut.toByteArray()); + + sp.getSignedContent().drain(); + + // + // compute expected content digest + // + MessageDigest md = MessageDigest.getInstance("SHA1", BC); + + verifySignatures(sp, md.digest(TEST_MESSAGE.getBytes())); + + // + // try using existing signer + // + gen = new CMSSignedDataStreamGenerator(); + + gen.addSigners(sp.getSignerInfos()); + + gen.addCertificates(sp.getCertificates()); + gen.addCRLs(sp.getCRLs()); + + bOut.reset(); + + sigOut = gen.open(bOut, true); + + sigOut.write(TEST_MESSAGE.getBytes()); + + sigOut.close(); + + verifyEncodedData(bOut); + + // + // look for the CRLs + // + Collection col = sp.getCRLs().getMatches(null); + + assertEquals(2, col.size()); + assertTrue(col.contains(new JcaX509CRLHolder(_signCrl))); + assertTrue(col.contains(new JcaX509CRLHolder(_origCrl))); + } + + public void testSHA1WithRSAAndOtherRevocation() + throws Exception + { + List certList = new ArrayList(); + CMSTypedData msg = new CMSProcessableByteArray("Hello world!".getBytes()); + ByteArrayOutputStream bOut = new ByteArrayOutputStream(); + + certList.add(_origCert); + certList.add(_signCert); + + Store certs = new JcaCertStore(certList); + + CMSSignedDataStreamGenerator gen = new CMSSignedDataStreamGenerator(); + + ContentSigner sha1Signer = new JcaContentSignerBuilder("SHA1withRSA").setProvider(BC).build(_origKP.getPrivate()); + + gen.addSignerInfoGenerator(new JcaSignerInfoGeneratorBuilder(new JcaDigestCalculatorProviderBuilder().setProvider(BC).build()).build(sha1Signer, _origCert)); + + gen.addCertificates(certs); + + List otherInfo = new ArrayList(); + OCSPResp response = new OCSPResp(successResp); + + otherInfo.add(response.toASN1Structure()); + + gen.addOtherRevocationInfo(CMSObjectIdentifiers.id_ri_ocsp_response, new CollectionStore(otherInfo)); + + OutputStream sigOut = gen.open(bOut, true); + + sigOut.write(TEST_MESSAGE.getBytes()); + + sigOut.close(); + + CMSSignedDataParser sp = new CMSSignedDataParser(new JcaDigestCalculatorProviderBuilder().setProvider(BC).build(), bOut.toByteArray()); + + CMSTypedStream stream = sp.getSignedContent(); + + assertEquals(CMSObjectIdentifiers.data, stream.getContentType()); + + stream.drain(); + + // + // check version + // + assertEquals(5, sp.getVersion()); + + // + // compute expected content digest + // + MessageDigest md = MessageDigest.getInstance("SHA1", BC); + + verifySignatures(sp, md.digest(TEST_MESSAGE.getBytes())); + + Store dataOtherInfo = sp.getOtherRevocationInfo(CMSObjectIdentifiers.id_ri_ocsp_response); + + assertEquals(1, dataOtherInfo.getMatches(null).size()); + + OCSPResp dataResponse = new OCSPResp(OCSPResponse.getInstance(dataOtherInfo.getMatches(null).iterator().next())); + + assertEquals(response, dataResponse); + } + + public void testSHA1WithRSANonData() + throws Exception + { + List certList = new ArrayList(); + List crlList = new ArrayList(); + ByteArrayOutputStream bOut = new ByteArrayOutputStream(); + + certList.add(new JcaX509CertificateHolder(_origCert)); + certList.add(new JcaX509CertificateHolder(_signCert)); + + crlList.add(new JcaX509CRLHolder(_signCrl)); + crlList.add(new JcaX509CRLHolder(_origCrl)); + + Store certs = new JcaCertStore(certList); + Store crls = new JcaCRLStore(crlList); + + CMSSignedDataStreamGenerator gen = new CMSSignedDataStreamGenerator(); + ContentSigner sha1Signer = new JcaContentSignerBuilder("SHA1withRSA").setProvider(BC).build(_origKP.getPrivate()); + + gen.addSignerInfoGenerator(new JcaSignerInfoGeneratorBuilder(new JcaDigestCalculatorProviderBuilder().setProvider(BC).build()).build(sha1Signer, _origCert)); + + gen.addCertificates(certs); + gen.addCRLs(crls); + + OutputStream sigOut = gen.open(new ASN1ObjectIdentifier("1.2.3.4"), bOut, true); + + sigOut.write(TEST_MESSAGE.getBytes()); + + sigOut.close(); + + CMSSignedDataParser sp = new CMSSignedDataParser(new JcaDigestCalculatorProviderBuilder().setProvider(BC).build(), bOut.toByteArray()); + + CMSTypedStream stream = sp.getSignedContent(); + + assertEquals(new ASN1ObjectIdentifier("1.2.3.4"), stream.getContentType()); + + stream.drain(); + + // + // compute expected content digest + // + MessageDigest md = MessageDigest.getInstance("SHA1", BC); + + verifySignatures(sp, md.digest(TEST_MESSAGE.getBytes())); + } + + public void testSHA1AndMD5WithRSA() + throws Exception + { + List certList = new ArrayList(); + ByteArrayOutputStream bOut = new ByteArrayOutputStream(); + + certList.add(_origCert); + certList.add(_signCert); + + Store certs = new JcaCertStore(certList); + + CMSSignedDataStreamGenerator gen = new CMSSignedDataStreamGenerator(); + JcaSignerInfoGeneratorBuilder signerInfoGeneratorBuilder = new JcaSignerInfoGeneratorBuilder(new JcaDigestCalculatorProviderBuilder().setProvider(BC).build()); + ContentSigner sha1Signer = new JcaContentSignerBuilder("SHA1withRSA").setProvider(BC).build(_origKP.getPrivate()); + ContentSigner md5Signer = new JcaContentSignerBuilder("MD5withRSA").setProvider(BC).build(_origKP.getPrivate()); + + gen.addSignerInfoGenerator(signerInfoGeneratorBuilder.build(sha1Signer, _origCert)); + + gen.addSignerInfoGenerator(signerInfoGeneratorBuilder.build(md5Signer, _origCert)); + + gen.addCertificates(certs); + + OutputStream sigOut = gen.open(bOut); + + sigOut.write(TEST_MESSAGE.getBytes()); + + sigOut.close(); + + checkSigParseable(bOut.toByteArray()); + + CMSSignedDataParser sp = new CMSSignedDataParser(new JcaDigestCalculatorProviderBuilder().setProvider(BC).build(), + new CMSTypedStream(new ByteArrayInputStream(TEST_MESSAGE.getBytes())), bOut.toByteArray()); + + sp.getSignedContent().drain(); + + verifySignatures(sp); + } + + public void testSHA1WithRSAEncapsulatedBufferedStream() + throws Exception + { + List certList = new ArrayList(); + ByteArrayOutputStream bOut = new ByteArrayOutputStream(); + + certList.add(_origCert); + certList.add(_signCert); + + Store certs = new JcaCertStore(certList); + + // + // find unbuffered length + // + CMSSignedDataStreamGenerator gen = new CMSSignedDataStreamGenerator(); + + ContentSigner sha1Signer = new JcaContentSignerBuilder("SHA1withRSA").setProvider(BC).build(_origKP.getPrivate()); + + gen.addSignerInfoGenerator(new JcaSignerInfoGeneratorBuilder(new JcaDigestCalculatorProviderBuilder().setProvider(BC).build()).build(sha1Signer, _origCert)); + + gen.addCertificates(certs); + + OutputStream sigOut = gen.open(bOut, true); + + for (int i = 0; i != 2000; i++) + { + sigOut.write(i & 0xff); + } + + sigOut.close(); + + CMSSignedDataParser sp = new CMSSignedDataParser(new JcaDigestCalculatorProviderBuilder().setProvider(BC).build(), bOut.toByteArray()); + + sp.getSignedContent().drain(); + + verifySignatures(sp); + + int unbufferedLength = bOut.toByteArray().length; + + // + // find buffered length with buffered stream - should be equal + // + bOut = new ByteArrayOutputStream(); + + gen = new CMSSignedDataStreamGenerator(); + + gen.addSignerInfoGenerator(new JcaSignerInfoGeneratorBuilder(new JcaDigestCalculatorProviderBuilder().setProvider(BC).build()).build(sha1Signer, _origCert)); + + gen.addCertificates(certs); + + sigOut = gen.open(bOut, true); + + BufferedOutputStream bfOut = new BufferedOutputStream(sigOut, 300); + + for (int i = 0; i != 2000; i++) + { + bfOut.write(i & 0xff); + } + + bfOut.close(); + + verifyEncodedData(bOut); + + assertTrue(bOut.toByteArray().length == unbufferedLength); + } + + public void testSHA1WithRSAEncapsulatedBuffered() + throws Exception + { + List certList = new ArrayList(); + ByteArrayOutputStream bOut = new ByteArrayOutputStream(); + + certList.add(_origCert); + certList.add(_signCert); + + Store certs = new JcaCertStore(certList); + + // + // find unbuffered length + // + CMSSignedDataStreamGenerator gen = new CMSSignedDataStreamGenerator(); + + ContentSigner sha1Signer = new JcaContentSignerBuilder("SHA1withRSA").setProvider(BC).build(_origKP.getPrivate()); + + gen.addSignerInfoGenerator(new JcaSignerInfoGeneratorBuilder(new JcaDigestCalculatorProviderBuilder().setProvider(BC).build()).build(sha1Signer, _origCert)); + + gen.addCertificates(certs); + + OutputStream sigOut = gen.open(bOut, true); + + for (int i = 0; i != 2000; i++) + { + sigOut.write(i & 0xff); + } + + sigOut.close(); + + CMSSignedDataParser sp = new CMSSignedDataParser(new JcaDigestCalculatorProviderBuilder().setProvider(BC).build(), bOut.toByteArray()); + + sp.getSignedContent().drain(); + + verifySignatures(sp); + + int unbufferedLength = bOut.toByteArray().length; + + // + // find buffered length - buffer size less than default + // + bOut = new ByteArrayOutputStream(); + + gen = new CMSSignedDataStreamGenerator(); + + gen.setBufferSize(300); + + gen.addSignerInfoGenerator(new JcaSignerInfoGeneratorBuilder(new JcaDigestCalculatorProviderBuilder().setProvider(BC).build()).build(sha1Signer, _origCert)); + + gen.addCertificates(certs); + + sigOut = gen.open(bOut, true); + + for (int i = 0; i != 2000; i++) + { + sigOut.write(i & 0xff); + } + + sigOut.close(); + + verifyEncodedData(bOut); + + assertTrue(bOut.toByteArray().length > unbufferedLength); + } + + public void testSHA1WithRSAEncapsulated() + throws Exception + { + List certList = new ArrayList(); + ByteArrayOutputStream bOut = new ByteArrayOutputStream(); + + certList.add(_origCert); + certList.add(_signCert); + + Store certs = new JcaCertStore(certList); + + CMSSignedDataStreamGenerator gen = new CMSSignedDataStreamGenerator(); + + ContentSigner sha1Signer = new JcaContentSignerBuilder("SHA1withRSA").setProvider(BC).build(_origKP.getPrivate()); + + gen.addSignerInfoGenerator(new JcaSignerInfoGeneratorBuilder(new JcaDigestCalculatorProviderBuilder().setProvider(BC).build()).build(sha1Signer, _origCert)); + + gen.addCertificates(certs); + + OutputStream sigOut = gen.open(bOut, true); + + sigOut.write(TEST_MESSAGE.getBytes()); + + sigOut.close(); + + CMSSignedDataParser sp = new CMSSignedDataParser(new JcaDigestCalculatorProviderBuilder().setProvider(BC).build(), bOut.toByteArray()); + + sp.getSignedContent().drain(); + + verifySignatures(sp); + + byte[] contentDigest = (byte[])gen.getGeneratedDigests().get(CMSAlgorithm.SHA1.getId()); + + AttributeTable table = ((SignerInformation)sp.getSignerInfos().getSigners().iterator().next()).getSignedAttributes(); + Attribute hash = table.get(CMSAttributes.messageDigest); + + assertTrue(MessageDigest.isEqual(contentDigest, ((ASN1OctetString)hash.getAttrValues().getObjectAt(0)).getOctets())); + + // + // try using existing signer + // + gen = new CMSSignedDataStreamGenerator(); + + gen.addSigners(sp.getSignerInfos()); + + gen.addCertificates(sp.getCertificates()); + + bOut.reset(); + + sigOut = gen.open(bOut, true); + + sigOut.write(TEST_MESSAGE.getBytes()); + + sigOut.close(); + + CMSSignedData sd = new CMSSignedData(new CMSProcessableByteArray(TEST_MESSAGE.getBytes()), bOut.toByteArray()); + + assertEquals(1, sd.getSignerInfos().getSigners().size()); + + verifyEncodedData(bOut); + } + + public void testSHA1WithRSAEncapsulatedSubjectKeyID() + throws Exception + { + List certList = new ArrayList(); + ByteArrayOutputStream bOut = new ByteArrayOutputStream(); + + certList.add(_origCert); + certList.add(_signCert); + + Store certs = new JcaCertStore(certList); + + CMSSignedDataStreamGenerator gen = new CMSSignedDataStreamGenerator(); + + ContentSigner sha1Signer = new JcaContentSignerBuilder("SHA1withRSA").setProvider(BC).build(_origKP.getPrivate()); + + gen.addSignerInfoGenerator(new JcaSignerInfoGeneratorBuilder(new JcaDigestCalculatorProviderBuilder().setProvider(BC).build()).build(sha1Signer, CMSTestUtil.createSubjectKeyId(_origCert.getPublicKey()).getKeyIdentifier())); + + gen.addCertificates(certs); + + OutputStream sigOut = gen.open(bOut, true); + + sigOut.write(TEST_MESSAGE.getBytes()); + + sigOut.close(); + + CMSSignedDataParser sp = new CMSSignedDataParser(new JcaDigestCalculatorProviderBuilder().setProvider(BC).build(), bOut.toByteArray()); + + sp.getSignedContent().drain(); + + verifySignatures(sp); + + byte[] contentDigest = (byte[])gen.getGeneratedDigests().get(CMSAlgorithm.SHA1.getId()); + + AttributeTable table = ((SignerInformation)sp.getSignerInfos().getSigners().iterator().next()).getSignedAttributes(); + Attribute hash = table.get(CMSAttributes.messageDigest); + + assertTrue(MessageDigest.isEqual(contentDigest, ((ASN1OctetString)hash.getAttrValues().getObjectAt(0)).getOctets())); + + // + // try using existing signer + // + gen = new CMSSignedDataStreamGenerator(); + + gen.addSigners(sp.getSignerInfos()); + + gen.addCertificates(sp.getCertificates()); + + bOut.reset(); + + sigOut = gen.open(bOut, true); + + sigOut.write(TEST_MESSAGE.getBytes()); + + sigOut.close(); + + CMSSignedData sd = new CMSSignedData(new CMSProcessableByteArray(TEST_MESSAGE.getBytes()), bOut.toByteArray()); + + assertEquals(1, sd.getSignerInfos().getSigners().size()); + + verifyEncodedData(bOut); + } + + public void testAttributeGenerators() + throws Exception + { + final ASN1ObjectIdentifier dummyOid1 = new ASN1ObjectIdentifier("1.2.3"); + final ASN1ObjectIdentifier dummyOid2 = new ASN1ObjectIdentifier("1.2.3.4"); + List certList = new ArrayList(); + ByteArrayOutputStream bOut = new ByteArrayOutputStream(); + + certList.add(_origCert); + certList.add(_signCert); + + JcaCertStore certs = new JcaCertStore(certList); + + CMSSignedDataStreamGenerator gen = new CMSSignedDataStreamGenerator(); + + CMSAttributeTableGenerator signedGen = new DefaultSignedAttributeTableGenerator() + { + public AttributeTable getAttributes(Map parameters) + { + Hashtable table = createStandardAttributeTable(parameters); + + DEROctetString val = new DEROctetString((byte[])parameters.get(CMSAttributeTableGenerator.DIGEST)); + Attribute attr = new Attribute(dummyOid1, new DERSet(val)); + + table.put(attr.getAttrType(), attr); + + return new AttributeTable(table); + } + }; + + CMSAttributeTableGenerator unsignedGen = new CMSAttributeTableGenerator() + { + public AttributeTable getAttributes(Map parameters) + { + DEROctetString val = new DEROctetString((byte[])parameters.get(CMSAttributeTableGenerator.SIGNATURE)); + Attribute attr = new Attribute(dummyOid2, new DERSet(val)); + + return new AttributeTable(new DERSet(attr)); + } + }; + ContentSigner sha1Signer = new JcaContentSignerBuilder("SHA1withRSA").setProvider(BC).build(_origKP.getPrivate()); + + JcaSignerInfoGeneratorBuilder siBuilder = new JcaSignerInfoGeneratorBuilder(new JcaDigestCalculatorProviderBuilder().setProvider(BC).build()); + + siBuilder.setSignedAttributeGenerator(signedGen).setUnsignedAttributeGenerator(unsignedGen); + + gen.addSignerInfoGenerator(siBuilder.build(sha1Signer, _origCert)); + + gen.addCertificates(certs); + + OutputStream sigOut = gen.open(bOut, true); + + sigOut.write(TEST_MESSAGE.getBytes()); + + sigOut.close(); + + CMSSignedDataParser sp = new CMSSignedDataParser(new JcaDigestCalculatorProviderBuilder().setProvider(BC).build(), bOut.toByteArray()); + + sp.getSignedContent().drain(); + + verifySignatures(sp); + + // + // check attributes + // + SignerInformationStore signers = sp.getSignerInfos(); + + Collection c = signers.getSigners(); + Iterator it = c.iterator(); + + while (it.hasNext()) + { + SignerInformation signer = (SignerInformation)it.next(); + checkAttribute(signer.getContentDigest(), signer.getSignedAttributes().get(dummyOid1)); + checkAttribute(signer.getSignature(), signer.getUnsignedAttributes().get(dummyOid2)); + } + } + + private void checkAttribute(byte[] expected, Attribute attr) + { + DEROctetString value = (DEROctetString)attr.getAttrValues().getObjectAt(0); + + assertEquals(new DEROctetString(expected), value); + } + + public void testWithAttributeCertificate() + throws Exception + { + List certList = new ArrayList(); + + certList.add(_signCert); + + Store certs = new JcaCertStore(certList); + + CMSSignedDataStreamGenerator gen = new CMSSignedDataStreamGenerator(); + + ContentSigner sha1Signer = new JcaContentSignerBuilder("SHA1withRSA").setProvider(BC).build(_origKP.getPrivate()); + + gen.addSignerInfoGenerator(new JcaSignerInfoGeneratorBuilder(new JcaDigestCalculatorProviderBuilder().setProvider(BC).build()).build(sha1Signer, _origCert)); + + gen.addCertificates(certs); + + X509AttributeCertificateHolder attrCert = CMSTestUtil.getAttributeCertificate(); + + Store store = new CollectionStore(Collections.singleton(attrCert)); + + gen.addAttributeCertificates(store); + + ByteArrayOutputStream bOut = new ByteArrayOutputStream(); + + OutputStream sigOut = gen.open(bOut, true); + + sigOut.write(TEST_MESSAGE.getBytes()); + + sigOut.close(); + + CMSSignedDataParser sp = new CMSSignedDataParser(new JcaDigestCalculatorProviderBuilder().setProvider(BC).build(), bOut.toByteArray()); + + sp.getSignedContent().drain(); + + assertEquals(4, sp.getVersion()); + +// store = sp.getAttributeCertificates(); +// +// Collection coll = store.getMatches(null); +// +// assertEquals(1, coll.size()); +// +// assertTrue(coll.contains(new JcaX509AttributeCertificateHolder(attrCert))); + } + + public void testSignerStoreReplacement() + throws Exception + { + List certList = new ArrayList(); + ByteArrayOutputStream bOut = new ByteArrayOutputStream(); + byte[] data = TEST_MESSAGE.getBytes(); + + certList.add(_origCert); + certList.add(_signCert); + + Store certs = new JcaCertStore(certList); + + CMSSignedDataStreamGenerator gen = new CMSSignedDataStreamGenerator(); + + gen.addSignerInfoGenerator(new JcaSimpleSignerInfoGeneratorBuilder().setProvider(BC).build("SHA1withRSA", _origKP.getPrivate(), _origCert)); + + gen.addCertificates(certs); + + OutputStream sigOut = gen.open(bOut, false); + + sigOut.write(data); + + sigOut.close(); + + checkSigParseable(bOut.toByteArray()); + + // + // create new Signer + // + ByteArrayInputStream original = new ByteArrayInputStream(bOut.toByteArray()); + + bOut.reset(); + + gen = new CMSSignedDataStreamGenerator(); + + gen.addSignerInfoGenerator(new JcaSimpleSignerInfoGeneratorBuilder().setProvider(BC).build("SHA224withRSA", _origKP.getPrivate(), _origCert)); + + gen.addCertificates(certs); + + sigOut = gen.open(bOut); + + sigOut.write(data); + + sigOut.close(); + + checkSigParseable(bOut.toByteArray()); + + CMSSignedData sd = new CMSSignedData(bOut.toByteArray()); + + // + // replace signer + // + ByteArrayOutputStream newOut = new ByteArrayOutputStream(); + + CMSSignedDataParser.replaceSigners(original, sd.getSignerInfos(), newOut); + + sd = new CMSSignedData(new CMSProcessableByteArray(data), newOut.toByteArray()); + SignerInformation signer = (SignerInformation)sd.getSignerInfos().getSigners().iterator().next(); + + assertEquals(signer.getDigestAlgOID(), CMSAlgorithm.SHA224.getId()); + + CMSSignedDataParser sp = new CMSSignedDataParser(new JcaDigestCalculatorProviderBuilder().setProvider(BC).build(), new CMSTypedStream(new ByteArrayInputStream(data)), newOut.toByteArray()); + + sp.getSignedContent().drain(); + + verifySignatures(sp); + } + + public void testEncapsulatedSignerStoreReplacement() + throws Exception + { + List certList = new ArrayList(); + ByteArrayOutputStream bOut = new ByteArrayOutputStream(); + + certList.add(_origCert); + certList.add(_signCert); + + Store certs = new JcaCertStore(certList); + + CMSSignedDataStreamGenerator gen = new CMSSignedDataStreamGenerator(); + + gen.addSignerInfoGenerator(new JcaSimpleSignerInfoGeneratorBuilder().setProvider(BC).build("SHA1withRSA", _origKP.getPrivate(), _origCert)); + + gen.addCertificates(certs); + + OutputStream sigOut = gen.open(bOut, true); + + sigOut.write(TEST_MESSAGE.getBytes()); + + sigOut.close(); + + // + // create new Signer + // + ByteArrayInputStream original = new ByteArrayInputStream(bOut.toByteArray()); + + bOut.reset(); + + gen = new CMSSignedDataStreamGenerator(); + + gen.addSignerInfoGenerator(new JcaSimpleSignerInfoGeneratorBuilder().setProvider(BC).build("SHA224withRSA", _origKP.getPrivate(), _origCert)); + + gen.addCertificates(certs); + + sigOut = gen.open(bOut, true); + + sigOut.write(TEST_MESSAGE.getBytes()); + + sigOut.close(); + + CMSSignedData sd = new CMSSignedData(bOut.toByteArray()); + + // + // replace signer + // + ByteArrayOutputStream newOut = new ByteArrayOutputStream(); + + CMSSignedDataParser.replaceSigners(original, sd.getSignerInfos(), newOut); + + sd = new CMSSignedData(newOut.toByteArray()); + SignerInformation signer = (SignerInformation)sd.getSignerInfos().getSigners().iterator().next(); + + assertEquals(signer.getDigestAlgOID(), CMSAlgorithm.SHA224.getId()); + + CMSSignedDataParser sp = new CMSSignedDataParser(new JcaDigestCalculatorProviderBuilder().setProvider(BC).build(), newOut.toByteArray()); + + sp.getSignedContent().drain(); + + verifySignatures(sp); + } + + public void testCertStoreReplacement() + throws Exception + { + List certList = new ArrayList(); + ByteArrayOutputStream bOut = new ByteArrayOutputStream(); + byte[] data = TEST_MESSAGE.getBytes(); + + certList.add(_origDsaCert); + + JcaCertStore certs = new JcaCertStore(certList); + + CMSSignedDataStreamGenerator gen = new CMSSignedDataStreamGenerator(); + + JcaSignerInfoGeneratorBuilder builder = new JcaSignerInfoGeneratorBuilder(new JcaDigestCalculatorProviderBuilder().setProvider(BC).build()); + + gen.addSignerInfoGenerator(builder.build(new JcaContentSignerBuilder("SHA1withRSA").build(_origKP.getPrivate()), _origCert)); + + gen.addCertificates(certs); + + OutputStream sigOut = gen.open(bOut); + + sigOut.write(data); + + sigOut.close(); + + checkSigParseable(bOut.toByteArray()); + + // + // create new certstore with the right certificates + // + certList = new ArrayList(); + certList.add(_origCert); + certList.add(_signCert); + + certs = new JcaCertStore(certList); + + + // + // replace certs + // + ByteArrayInputStream original = new ByteArrayInputStream(bOut.toByteArray()); + ByteArrayOutputStream newOut = new ByteArrayOutputStream(); + + CMSSignedDataParser.replaceCertificatesAndCRLs(original, certs, null, null, newOut); + + CMSSignedDataParser sp = new CMSSignedDataParser(new JcaDigestCalculatorProviderBuilder().setProvider(BC).build(), new CMSTypedStream(new ByteArrayInputStream(data)), newOut.toByteArray()); + + sp.getSignedContent().drain(); + + verifySignatures(sp); + } + + public void testEncapsulatedCertStoreReplacement() + throws Exception + { + List certList = new ArrayList(); + ByteArrayOutputStream bOut = new ByteArrayOutputStream(); + + certList.add(_origDsaCert); + + Store certs = new JcaCertStore(certList); + + CMSSignedDataStreamGenerator gen = new CMSSignedDataStreamGenerator(); + + JcaSignerInfoGeneratorBuilder builder = new JcaSignerInfoGeneratorBuilder(new JcaDigestCalculatorProviderBuilder().setProvider(BC).build()); + + gen.addSignerInfoGenerator(builder.build(new JcaContentSignerBuilder("SHA1withRSA").build(_origKP.getPrivate()), _origCert)); + + gen.addCertificates(certs); + + OutputStream sigOut = gen.open(bOut, true); + + sigOut.write(TEST_MESSAGE.getBytes()); + + sigOut.close(); + + // + // create new certstore with the right certificates + // + certList = new ArrayList(); + certList.add(_origCert); + certList.add(_signCert); + + certs = new JcaCertStore(certList); + + // + // replace certs + // + ByteArrayInputStream original = new ByteArrayInputStream(bOut.toByteArray()); + ByteArrayOutputStream newOut = new ByteArrayOutputStream(); + + CMSSignedDataParser.replaceCertificatesAndCRLs(original, certs, null, null, newOut); + + CMSSignedDataParser sp = new CMSSignedDataParser(new JcaDigestCalculatorProviderBuilder().setProvider(BC).build(), newOut.toByteArray()); + + sp.getSignedContent().drain(); + + verifySignatures(sp); + } + + public void testCertOrdering1() + throws Exception + { + List certList = new ArrayList(); + ByteArrayOutputStream bOut = new ByteArrayOutputStream(); + + certList.add(_origCert); + certList.add(_signCert); + + Store certs = new JcaCertStore(certList); + + CMSSignedDataStreamGenerator gen = new CMSSignedDataStreamGenerator(); + + gen.addSignerInfoGenerator(new JcaSimpleSignerInfoGeneratorBuilder().setProvider(BC).build("SHA1withRSA", _origKP.getPrivate(), _origCert)); + + gen.addCertificates(certs); + + OutputStream sigOut = gen.open(bOut, true); + + sigOut.write(TEST_MESSAGE.getBytes()); + + sigOut.close(); + + CMSSignedDataParser sp = new CMSSignedDataParser(new JcaDigestCalculatorProviderBuilder().setProvider(BC).build(), bOut.toByteArray()); + + sp.getSignedContent().drain(); + certs = sp.getCertificates(); + Iterator it = certs.getMatches(null).iterator(); + + assertEquals(new JcaX509CertificateHolder(_origCert), it.next()); + assertEquals(new JcaX509CertificateHolder(_signCert), it.next()); + } + + public void testCertOrdering2() + throws Exception + { + List certList = new ArrayList(); + ByteArrayOutputStream bOut = new ByteArrayOutputStream(); + + certList.add(_signCert); + certList.add(_origCert); + + Store certs = new JcaCertStore(certList); + + CMSSignedDataStreamGenerator gen = new CMSSignedDataStreamGenerator(); + + gen.addSignerInfoGenerator(new JcaSimpleSignerInfoGeneratorBuilder().setProvider(BC).build("SHA1withRSA", _origKP.getPrivate(), _origCert)); + + gen.addCertificates(certs); + + OutputStream sigOut = gen.open(bOut, true); + + sigOut.write(TEST_MESSAGE.getBytes()); + + sigOut.close(); + + CMSSignedDataParser sp = new CMSSignedDataParser(new JcaDigestCalculatorProviderBuilder().setProvider(BC).build(), bOut.toByteArray()); + + sp.getSignedContent().drain(); + certs = sp.getCertificates(); + Iterator it = certs.getMatches(null).iterator(); + + assertEquals(new JcaX509CertificateHolder(_signCert), it.next()); + assertEquals(new JcaX509CertificateHolder(_origCert), it.next()); + } + + public void testCertsOnly() + throws Exception + { + List certList = new ArrayList(); + certList.add(_origCert); + certList.add(_signCert); + + Store certs = new JcaCertStore(certList); + + ByteArrayOutputStream bOut = new ByteArrayOutputStream(); + + CMSSignedDataStreamGenerator gen = new CMSSignedDataStreamGenerator(); + gen.addCertificates(certs); + + gen.open(bOut).close(); + + checkSigParseable(bOut.toByteArray()); + } + + public static Test suite() + throws Exception + { + init(); + + return new CMSTestSetup(new TestSuite(NewSignedDataStreamTest.class)); + } +} diff --git a/pkix/src/test/java/org/spongycastle/cms/test/NewSignedDataTest.java b/pkix/src/test/java/org/spongycastle/cms/test/NewSignedDataTest.java new file mode 100644 index 00000000..54152ea7 --- /dev/null +++ b/pkix/src/test/java/org/spongycastle/cms/test/NewSignedDataTest.java @@ -0,0 +1,2060 @@ +package org.spongycastle.cms.test; + +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.security.KeyFactory; +import java.security.KeyPair; +import java.security.MessageDigest; +import java.security.Security; +import java.security.cert.X509CRL; +import java.security.cert.X509Certificate; +import java.security.spec.PKCS8EncodedKeySpec; +import java.security.spec.X509EncodedKeySpec; +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +import junit.framework.Test; +import junit.framework.TestCase; +import junit.framework.TestSuite; +import org.spongycastle.asn1.ASN1EncodableVector; +import org.spongycastle.asn1.ASN1InputStream; +import org.spongycastle.asn1.ASN1ObjectIdentifier; +import org.spongycastle.asn1.ASN1OctetString; +import org.spongycastle.asn1.DEROctetString; +import org.spongycastle.asn1.DERSet; +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.cms.ContentInfo; +import org.spongycastle.asn1.ocsp.OCSPResponse; +import org.spongycastle.asn1.pkcs.PKCSObjectIdentifiers; +import org.spongycastle.asn1.x509.AlgorithmIdentifier; +import org.spongycastle.cert.X509AttributeCertificateHolder; +import org.spongycastle.cert.X509CertificateHolder; +import org.spongycastle.cert.jcajce.JcaCRLStore; +import org.spongycastle.cert.jcajce.JcaCertStore; +import org.spongycastle.cert.jcajce.JcaX509CRLHolder; +import org.spongycastle.cert.jcajce.JcaX509CertificateHolder; +import org.spongycastle.cert.ocsp.OCSPResp; +import org.spongycastle.cms.CMSAbsentContent; +import org.spongycastle.cms.CMSAlgorithm; +import org.spongycastle.cms.CMSProcessableByteArray; +import org.spongycastle.cms.CMSSignedData; +import org.spongycastle.cms.CMSSignedDataGenerator; +import org.spongycastle.cms.CMSSignedDataParser; +import org.spongycastle.cms.CMSTypedData; +import org.spongycastle.cms.DefaultCMSSignatureAlgorithmNameGenerator; +import org.spongycastle.cms.DefaultSignedAttributeTableGenerator; +import org.spongycastle.cms.SignerId; +import org.spongycastle.cms.SignerInfoGeneratorBuilder; +import org.spongycastle.cms.SignerInformation; +import org.spongycastle.cms.SignerInformationStore; +import org.spongycastle.cms.SignerInformationVerifier; +import org.spongycastle.cms.SignerInformationVerifierProvider; +import org.spongycastle.cms.bc.BcRSASignerInfoVerifierBuilder; +import org.spongycastle.cms.jcajce.JcaSignerId; +import org.spongycastle.cms.jcajce.JcaSignerInfoGeneratorBuilder; +import org.spongycastle.cms.jcajce.JcaSimpleSignerInfoGeneratorBuilder; +import org.spongycastle.cms.jcajce.JcaSimpleSignerInfoVerifierBuilder; +import org.spongycastle.crypto.params.AsymmetricKeyParameter; +import org.spongycastle.crypto.util.PrivateKeyFactory; +import org.spongycastle.jce.provider.BouncyCastleProvider; +import org.spongycastle.operator.ContentSigner; +import org.spongycastle.operator.DefaultDigestAlgorithmIdentifierFinder; +import org.spongycastle.operator.DefaultSignatureAlgorithmIdentifierFinder; +import org.spongycastle.operator.DigestCalculatorProvider; +import org.spongycastle.operator.OperatorCreationException; +import org.spongycastle.operator.bc.BcContentSignerBuilder; +import org.spongycastle.operator.bc.BcDigestCalculatorProvider; +import org.spongycastle.operator.bc.BcRSAContentSignerBuilder; +import org.spongycastle.operator.jcajce.JcaContentSignerBuilder; +import org.spongycastle.operator.jcajce.JcaDigestCalculatorProviderBuilder; +import org.spongycastle.util.CollectionStore; +import org.spongycastle.util.Store; +import org.spongycastle.util.encoders.Base64; +import org.spongycastle.util.io.Streams; + +public class NewSignedDataTest + extends TestCase +{ + private static final String BC = BouncyCastleProvider.PROVIDER_NAME; + + boolean DEBUG = true; + + private static String _origDN; + private static KeyPair _origKP; + private static X509Certificate _origCert; + + private static String _signDN; + private static KeyPair _signKP; + private static X509Certificate _signCert; + + private static KeyPair _signGostKP; + private static X509Certificate _signGostCert; + + private static KeyPair _signEcDsaKP; + private static X509Certificate _signEcDsaCert; + + private static KeyPair _signEcGostKP; + private static X509Certificate _signEcGostCert; + + private static KeyPair _signDsaKP; + private static X509Certificate _signDsaCert; + + private static String _reciDN; + private static KeyPair _reciKP; + private static X509Certificate _reciCert; + + private static X509CRL _signCrl; + + private static boolean _initialised = false; + + private byte[] disorderedMessage = Base64.decode( + "SU9fc3RkaW5fdXNlZABfX2xpYmNfc3RhcnRfbWFpbgBnZXRob3N0aWQAX19n" + + "bW9uX3M="); + + private byte[] disorderedSet = Base64.decode( + "MIIYXQYJKoZIhvcNAQcCoIIYTjCCGEoCAQExCzAJBgUrDgMCGgUAMAsGCSqG" + + "SIb3DQEHAaCCFqswggJUMIIBwKADAgECAgMMg6wwCgYGKyQDAwECBQAwbzEL" + + "MAkGA1UEBhMCREUxPTA7BgNVBAoUNFJlZ3VsaWVydW5nc2JlaMhvcmRlIGbI" + + "dXIgVGVsZWtvbW11bmlrYXRpb24gdW5kIFBvc3QxITAMBgcCggYBCgcUEwEx" + + "MBEGA1UEAxQKNFItQ0EgMTpQTjAiGA8yMDAwMDMyMjA5NDM1MFoYDzIwMDQw" + + "MTIxMTYwNDUzWjBvMQswCQYDVQQGEwJERTE9MDsGA1UEChQ0UmVndWxpZXJ1" + + "bmdzYmVoyG9yZGUgZsh1ciBUZWxla29tbXVuaWthdGlvbiB1bmQgUG9zdDEh" + + "MAwGBwKCBgEKBxQTATEwEQYDVQQDFAo1Ui1DQSAxOlBOMIGhMA0GCSqGSIb3" + + "DQEBAQUAA4GPADCBiwKBgQCKHkFTJx8GmoqFTxEOxpK9XkC3NZ5dBEKiUv0I" + + "fe3QMqeGMoCUnyJxwW0k2/53duHxtv2yHSZpFKjrjvE/uGwdOMqBMTjMzkFg" + + "19e9JPv061wyADOucOIaNAgha/zFt9XUyrHF21knKCvDNExv2MYIAagkTKaj" + + "LMAw0bu1J0FadQIFAMAAAAEwCgYGKyQDAwECBQADgYEAgFauXpoTLh3Z3pT/" + + "3bhgrxO/2gKGZopWGSWSJPNwq/U3x2EuctOJurj+y2inTcJjespThflpN+7Q" + + "nvsUhXU+jL2MtPlObU0GmLvWbi47cBShJ7KElcZAaxgWMBzdRGqTOdtMv+ev" + + "2t4igGF/q71xf6J2c3pTLWr6P8s6tzLfOCMwggJDMIIBr6ADAgECAgQAuzyu" + + "MAoGBiskAwMBAgUAMG8xCzAJBgNVBAYTAkRFMT0wOwYDVQQKFDRSZWd1bGll" + + "cnVuZ3NiZWjIb3JkZSBmyHVyIFRlbGVrb21tdW5pa2F0aW9uIHVuZCBQb3N0" + + "MSEwDAYHAoIGAQoHFBMBMTARBgNVBAMUCjVSLUNBIDE6UE4wIhgPMjAwMTA4" + + "MjAwODA4MjBaGA8yMDA1MDgyMDA4MDgyMFowSzELMAkGA1UEBhMCREUxEjAQ" + + "BgNVBAoUCVNpZ250cnVzdDEoMAwGBwKCBgEKBxQTATEwGAYDVQQDFBFDQSBT" + + "SUdOVFJVU1QgMTpQTjCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAhV12" + + "N2WhlR6f+3CXP57GrBM9la5Vnsu2b92zv5MZqQOPeEsYbZqDCFkYg1bSwsDE" + + "XsGVQqXdQNAGUaapr/EUVVN+hNZ07GcmC1sPeQECgUkxDYjGi4ihbvzxlahj" + + "L4nX+UTzJVBfJwXoIvJ+lMHOSpnOLIuEL3SRhBItvRECxN0CAwEAAaMSMBAw" + + "DgYDVR0PAQH/BAQDAgEGMAoGBiskAwMBAgUAA4GBACDc9Pc6X8sK1cerphiV" + + "LfFv4kpZb9ev4WPy/C6987Qw1SOTElhZAmxaJQBqmDHWlQ63wj1DEqswk7hG" + + "LrvQk/iX6KXIn8e64uit7kx6DHGRKNvNGofPjr1WelGeGW/T2ZJKgmPDjCkf" + + "sIKt2c3gwa2pDn4mmCz/DStUIqcPDbqLMIICVTCCAcGgAwIBAgIEAJ16STAK" + + "BgYrJAMDAQIFADBvMQswCQYDVQQGEwJERTE9MDsGA1UEChQ0UmVndWxpZXJ1" + + "bmdzYmVoyG9yZGUgZsh1ciBUZWxla29tbXVuaWthdGlvbiB1bmQgUG9zdDEh" + + "MAwGBwKCBgEKBxQTATEwEQYDVQQDFAo1Ui1DQSAxOlBOMCIYDzIwMDEwMjAx" + + "MTM0NDI1WhgPMjAwNTAzMjIwODU1NTFaMG8xCzAJBgNVBAYTAkRFMT0wOwYD" + + "VQQKFDRSZWd1bGllcnVuZ3NiZWjIb3JkZSBmyHVyIFRlbGVrb21tdW5pa2F0" + + "aW9uIHVuZCBQb3N0MSEwDAYHAoIGAQoHFBMBMTARBgNVBAMUCjZSLUNhIDE6" + + "UE4wgaEwDQYJKoZIhvcNAQEBBQADgY8AMIGLAoGBAIOiqxUkzVyqnvthihnl" + + "tsE5m1Xn5TZKeR/2MQPStc5hJ+V4yptEtIx+Fn5rOoqT5VEVWhcE35wdbPvg" + + "JyQFn5msmhPQT/6XSGOlrWRoFummXN9lQzAjCj1sgTcmoLCVQ5s5WpCAOXFw" + + "VWu16qndz3sPItn3jJ0F3Kh3w79NglvPAgUAwAAAATAKBgYrJAMDAQIFAAOB" + + "gQBpSRdnDb6AcNVaXSmGo6+kVPIBhot1LzJOGaPyDNpGXxd7LV4tMBF1U7gr" + + "4k1g9BO6YiMWvw9uiTZmn0CfV8+k4fWEuG/nmafRoGIuay2f+ILuT+C0rnp1" + + "4FgMsEhuVNJJAmb12QV0PZII+UneyhAneZuQQzVUkTcVgYxogxdSOzCCAlUw" + + "ggHBoAMCAQICBACdekowCgYGKyQDAwECBQAwbzELMAkGA1UEBhMCREUxPTA7" + + "BgNVBAoUNFJlZ3VsaWVydW5nc2JlaMhvcmRlIGbIdXIgVGVsZWtvbW11bmlr" + + "YXRpb24gdW5kIFBvc3QxITAMBgcCggYBCgcUEwExMBEGA1UEAxQKNlItQ2Eg" + + "MTpQTjAiGA8yMDAxMDIwMTEzNDcwN1oYDzIwMDUwMzIyMDg1NTUxWjBvMQsw" + + "CQYDVQQGEwJERTE9MDsGA1UEChQ0UmVndWxpZXJ1bmdzYmVoyG9yZGUgZsh1" + + "ciBUZWxla29tbXVuaWthdGlvbiB1bmQgUG9zdDEhMAwGBwKCBgEKBxQTATEw" + + "EQYDVQQDFAo1Ui1DQSAxOlBOMIGhMA0GCSqGSIb3DQEBAQUAA4GPADCBiwKB" + + "gQCKHkFTJx8GmoqFTxEOxpK9XkC3NZ5dBEKiUv0Ife3QMqeGMoCUnyJxwW0k" + + "2/53duHxtv2yHSZpFKjrjvE/uGwdOMqBMTjMzkFg19e9JPv061wyADOucOIa" + + "NAgha/zFt9XUyrHF21knKCvDNExv2MYIAagkTKajLMAw0bu1J0FadQIFAMAA" + + "AAEwCgYGKyQDAwECBQADgYEAV1yTi+2gyB7sUhn4PXmi/tmBxAfe5oBjDW8m" + + "gxtfudxKGZ6l/FUPNcrSc5oqBYxKWtLmf3XX87LcblYsch617jtNTkMzhx9e" + + "qxiD02ufcrxz2EVt0Akdqiz8mdVeqp3oLcNU/IttpSrcA91CAnoUXtDZYwb/" + + "gdQ4FI9l3+qo/0UwggJVMIIBwaADAgECAgQAxIymMAoGBiskAwMBAgUAMG8x" + + "CzAJBgNVBAYTAkRFMT0wOwYDVQQKFDRSZWd1bGllcnVuZ3NiZWjIb3JkZSBm" + + "yHVyIFRlbGVrb21tdW5pa2F0aW9uIHVuZCBQb3N0MSEwDAYHAoIGAQoHFBMB" + + "MTARBgNVBAMUCjZSLUNhIDE6UE4wIhgPMjAwMTEwMTUxMzMxNThaGA8yMDA1" + + "MDYwMTA5NTIxN1owbzELMAkGA1UEBhMCREUxPTA7BgNVBAoUNFJlZ3VsaWVy" + + "dW5nc2JlaMhvcmRlIGbIdXIgVGVsZWtvbW11bmlrYXRpb24gdW5kIFBvc3Qx" + + "ITAMBgcCggYBCgcUEwExMBEGA1UEAxQKN1ItQ0EgMTpQTjCBoTANBgkqhkiG" + + "9w0BAQEFAAOBjwAwgYsCgYEAiokD/j6lEP4FexF356OpU5teUpGGfUKjIrFX" + + "BHc79G0TUzgVxqMoN1PWnWktQvKo8ETaugxLkP9/zfX3aAQzDW4Zki6x6GDq" + + "fy09Agk+RJvhfbbIzRkV4sBBco0n73x7TfG/9NTgVr/96U+I+z/1j30aboM6" + + "9OkLEhjxAr0/GbsCBQDAAAABMAoGBiskAwMBAgUAA4GBAHWRqRixt+EuqHhR" + + "K1kIxKGZL2vZuakYV0R24Gv/0ZR52FE4ECr+I49o8FP1qiGSwnXB0SwjuH2S" + + "iGiSJi+iH/MeY85IHwW1P5e+bOMvEOFhZhQXQixOD7totIoFtdyaj1XGYRef" + + "0f2cPOjNJorXHGV8wuBk+/j++sxbd/Net3FtMIICVTCCAcGgAwIBAgIEAMSM" + + "pzAKBgYrJAMDAQIFADBvMQswCQYDVQQGEwJERTE9MDsGA1UEChQ0UmVndWxp" + + "ZXJ1bmdzYmVoyG9yZGUgZsh1ciBUZWxla29tbXVuaWthdGlvbiB1bmQgUG9z" + + "dDEhMAwGBwKCBgEKBxQTATEwEQYDVQQDFAo3Ui1DQSAxOlBOMCIYDzIwMDEx" + + "MDE1MTMzNDE0WhgPMjAwNTA2MDEwOTUyMTdaMG8xCzAJBgNVBAYTAkRFMT0w" + + "OwYDVQQKFDRSZWd1bGllcnVuZ3NiZWjIb3JkZSBmyHVyIFRlbGVrb21tdW5p" + + "a2F0aW9uIHVuZCBQb3N0MSEwDAYHAoIGAQoHFBMBMTARBgNVBAMUCjZSLUNh" + + "IDE6UE4wgaEwDQYJKoZIhvcNAQEBBQADgY8AMIGLAoGBAIOiqxUkzVyqnvth" + + "ihnltsE5m1Xn5TZKeR/2MQPStc5hJ+V4yptEtIx+Fn5rOoqT5VEVWhcE35wd" + + "bPvgJyQFn5msmhPQT/6XSGOlrWRoFummXN9lQzAjCj1sgTcmoLCVQ5s5WpCA" + + "OXFwVWu16qndz3sPItn3jJ0F3Kh3w79NglvPAgUAwAAAATAKBgYrJAMDAQIF" + + "AAOBgQBi5W96UVDoNIRkCncqr1LLG9vF9SGBIkvFpLDIIbcvp+CXhlvsdCJl" + + "0pt2QEPSDl4cmpOet+CxJTdTuMeBNXxhb7Dvualog69w/+K2JbPhZYxuVFZs" + + "Zh5BkPn2FnbNu3YbJhE60aIkikr72J4XZsI5DxpZCGh6xyV/YPRdKSljFjCC" + + "AlQwggHAoAMCAQICAwyDqzAKBgYrJAMDAQIFADBvMQswCQYDVQQGEwJERTE9" + + "MDsGA1UEChQ0UmVndWxpZXJ1bmdzYmVoyG9yZGUgZsh1ciBUZWxla29tbXVu" + + "aWthdGlvbiB1bmQgUG9zdDEhMAwGBwKCBgEKBxQTATEwEQYDVQQDFAo1Ui1D" + + "QSAxOlBOMCIYDzIwMDAwMzIyMDk0MTI3WhgPMjAwNDAxMjExNjA0NTNaMG8x" + + "CzAJBgNVBAYTAkRFMT0wOwYDVQQKFDRSZWd1bGllcnVuZ3NiZWjIb3JkZSBm" + + "yHVyIFRlbGVrb21tdW5pa2F0aW9uIHVuZCBQb3N0MSEwDAYHAoIGAQoHFBMB" + + "MTARBgNVBAMUCjRSLUNBIDE6UE4wgaEwDQYJKoZIhvcNAQEBBQADgY8AMIGL" + + "AoGBAI8x26tmrFJanlm100B7KGlRemCD1R93PwdnG7svRyf5ZxOsdGrDszNg" + + "xg6ouO8ZHQMT3NC2dH8TvO65Js+8bIyTm51azF6clEg0qeWNMKiiXbBXa+ph" + + "hTkGbXiLYvACZ6/MTJMJ1lcrjpRF7BXtYeYMcEF6znD4pxOqrtbf9z5hAgUA" + + "wAAAATAKBgYrJAMDAQIFAAOBgQB99BjSKlGPbMLQAgXlvA9jUsDNhpnVm3a1" + + "YkfxSqS/dbQlYkbOKvCxkPGA9NBxisBM8l1zFynVjJoy++aysRmcnLY/sHaz" + + "23BF2iU7WERy18H3lMBfYB6sXkfYiZtvQZcWaO48m73ZBySuiV3iXpb2wgs/" + + "Cs20iqroAWxwq/W/9jCCAlMwggG/oAMCAQICBDsFZ9UwCgYGKyQDAwECBQAw" + + "bzELMAkGA1UEBhMCREUxITAMBgcCggYBCgcUEwExMBEGA1UEAxQKNFItQ0Eg" + + "MTpQTjE9MDsGA1UEChQ0UmVndWxpZXJ1bmdzYmVoyG9yZGUgZsh1ciBUZWxl" + + "a29tbXVuaWthdGlvbiB1bmQgUG9zdDAiGA8xOTk5MDEyMTE3MzUzNFoYDzIw" + + "MDQwMTIxMTYwMDAyWjBvMQswCQYDVQQGEwJERTE9MDsGA1UEChQ0UmVndWxp" + + "ZXJ1bmdzYmVoyG9yZGUgZsh1ciBUZWxla29tbXVuaWthdGlvbiB1bmQgUG9z" + + "dDEhMAwGBwKCBgEKBxQTATEwEQYDVQQDFAozUi1DQSAxOlBOMIGfMA0GCSqG" + + "SIb3DQEBAQUAA4GNADCBiQKBgI4B557mbKQg/AqWBXNJhaT/6lwV93HUl4U8" + + "u35udLq2+u9phns1WZkdM3gDfEpL002PeLfHr1ID/96dDYf04lAXQfombils" + + "of1C1k32xOvxjlcrDOuPEMxz9/HDAQZA5MjmmYHAIulGI8Qg4Tc7ERRtg/hd" + + "0QX0/zoOeXoDSEOBAgTAAAABMAoGBiskAwMBAgUAA4GBAIyzwfT3keHI/n2P" + + "LrarRJv96mCohmDZNpUQdZTVjGu5VQjVJwk3hpagU0o/t/FkdzAjOdfEw8Ql" + + "3WXhfIbNLv1YafMm2eWSdeYbLcbB5yJ1od+SYyf9+tm7cwfDAcr22jNRBqx8" + + "wkWKtKDjWKkevaSdy99sAI8jebHtWz7jzydKMIID9TCCA16gAwIBAgICbMcw" + + "DQYJKoZIhvcNAQEFBQAwSzELMAkGA1UEBhMCREUxEjAQBgNVBAoUCVNpZ250" + + "cnVzdDEoMAwGBwKCBgEKBxQTATEwGAYDVQQDFBFDQSBTSUdOVFJVU1QgMTpQ" + + "TjAeFw0wNDA3MzAxMzAyNDZaFw0wNzA3MzAxMzAyNDZaMDwxETAPBgNVBAMM" + + "CFlhY29tOlBOMQ4wDAYDVQRBDAVZYWNvbTELMAkGA1UEBhMCREUxCjAIBgNV" + + "BAUTATEwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAIWzLlYLQApocXIp" + + "pgCCpkkOUVLgcLYKeOd6/bXAnI2dTHQqT2bv7qzfUnYvOqiNgYdF13pOYtKg" + + "XwXMTNFL4ZOI6GoBdNs9TQiZ7KEWnqnr2945HYx7UpgTBclbOK/wGHuCdcwO" + + "x7juZs1ZQPFG0Lv8RoiV9s6HP7POqh1sO0P/AgMBAAGjggH1MIIB8TCBnAYD" + + "VR0jBIGUMIGRgBQcZzNghfnXoXRm8h1+VITC5caNRqFzpHEwbzELMAkGA1UE" + + "BhMCREUxPTA7BgNVBAoUNFJlZ3VsaWVydW5nc2JlaMhvcmRlIGbIdXIgVGVs" + + "ZWtvbW11bmlrYXRpb24gdW5kIFBvc3QxITAMBgcCggYBCgcUEwExMBEGA1UE" + + "AxQKNVItQ0EgMTpQToIEALs8rjAdBgNVHQ4EFgQU2e5KAzkVuKaM9I5heXkz" + + "bcAIuR8wDgYDVR0PAQH/BAQDAgZAMBIGA1UdIAQLMAkwBwYFKyQIAQEwfwYD" + + "VR0fBHgwdjB0oCygKoYobGRhcDovL2Rpci5zaWdudHJ1c3QuZGUvbz1TaWdu" + + "dHJ1c3QsYz1kZaJEpEIwQDEdMBsGA1UEAxMUQ1JMU2lnblNpZ250cnVzdDE6" + + "UE4xEjAQBgNVBAoTCVNpZ250cnVzdDELMAkGA1UEBhMCREUwYgYIKwYBBQUH" + + "AQEEVjBUMFIGCCsGAQUFBzABhkZodHRwOi8vZGlyLnNpZ250cnVzdC5kZS9T" + + "aWdudHJ1c3QvT0NTUC9zZXJ2bGV0L2h0dHBHYXRld2F5LlBvc3RIYW5kbGVy" + + "MBgGCCsGAQUFBwEDBAwwCjAIBgYEAI5GAQEwDgYHAoIGAQoMAAQDAQH/MA0G" + + "CSqGSIb3DQEBBQUAA4GBAHn1m3GcoyD5GBkKUY/OdtD6Sj38LYqYCF+qDbJR" + + "6pqUBjY2wsvXepUppEler+stH8mwpDDSJXrJyuzf7xroDs4dkLl+Rs2x+2tg" + + "BjU+ABkBDMsym2WpwgA8LCdymmXmjdv9tULxY+ec2pjSEzql6nEZNEfrU8nt" + + "ZCSCavgqW4TtMYIBejCCAXYCAQEwUTBLMQswCQYDVQQGEwJERTESMBAGA1UE" + + "ChQJU2lnbnRydXN0MSgwDAYHAoIGAQoHFBMBMTAYBgNVBAMUEUNBIFNJR05U" + + "UlVTVCAxOlBOAgJsxzAJBgUrDgMCGgUAoIGAMBgGCSqGSIb3DQEJAzELBgkq" + + "hkiG9w0BBwEwIwYJKoZIhvcNAQkEMRYEFIYfhPoyfGzkLWWSSLjaHb4HQmaK" + + "MBwGCSqGSIb3DQEJBTEPFw0wNTAzMjQwNzM4MzVaMCEGBSskCAYFMRgWFi92" + + "YXIvZmlsZXMvdG1wXzEvdGVzdDEwDQYJKoZIhvcNAQEFBQAEgYA2IvA8lhVz" + + "VD5e/itUxbFboKxeKnqJ5n/KuO/uBCl1N14+7Z2vtw1sfkIG+bJdp3OY2Cmn" + + "mrQcwsN99Vjal4cXVj8t+DJzFG9tK9dSLvD3q9zT/GQ0kJXfimLVwCa4NaSf" + + "Qsu4xtG0Rav6bCcnzabAkKuNNvKtH8amSRzk870DBg=="); + + public static byte[] xtraCounterSig = Base64.decode( + "MIIR/AYJKoZIhvcNAQcCoIIR7TCCEekCAQExCzAJBgUrDgMCGgUAMBoGCSqG" + + "SIb3DQEHAaANBAtIZWxsbyB3b3JsZKCCDnkwggTPMIIDt6ADAgECAgRDnYD3" + + "MA0GCSqGSIb3DQEBBQUAMFgxCzAJBgNVBAYTAklUMRowGAYDVQQKExFJbi5U" + + "ZS5TLkEuIFMucC5BLjEtMCsGA1UEAxMkSW4uVGUuUy5BLiAtIENlcnRpZmlj" + + "YXRpb24gQXV0aG9yaXR5MB4XDTA4MDkxMjExNDMxMloXDTEwMDkxMjExNDMx" + + "MlowgdgxCzAJBgNVBAYTAklUMSIwIAYDVQQKDBlJbnRlc2EgUy5wLkEuLzA1" + + "MjYyODkwMDE0MSowKAYDVQQLDCFCdXNpbmVzcyBDb2xsYWJvcmF0aW9uICYg" + + "U2VjdXJpdHkxHjAcBgNVBAMMFU1BU1NJTUlMSUFOTyBaSUNDQVJESTERMA8G" + + "A1UEBAwIWklDQ0FSREkxFTATBgNVBCoMDE1BU1NJTUlMSUFOTzEcMBoGA1UE" + + "BRMTSVQ6WkNDTVNNNzZIMTRMMjE5WTERMA8GA1UELhMIMDAwMDI1ODUwgaAw" + + "DQYJKoZIhvcNAQEBBQADgY4AMIGKAoGBALeJTjmyFgx1SIP6c2AuB/kuyHo5" + + "j/prKELTALsFDimre/Hxr3wOSet1TdQfFzU8Lu+EJqgfV9cV+cI1yeH1rZs7" + + "lei7L3tX/VR565IywnguX5xwvteASgWZr537Fkws50bvTEMyYOj1Tf3FZvZU" + + "z4n4OD39KI4mfR9i1eEVIxR3AgQAizpNo4IBoTCCAZ0wHQYDVR0RBBYwFIES" + + "emljY2FyZGlAaW50ZXNhLml0MC8GCCsGAQUFBwEDBCMwITAIBgYEAI5GAQEw" + + "CwYGBACORgEDAgEUMAgGBgQAjkYBBDBZBgNVHSAEUjBQME4GBgQAizABATBE" + + "MEIGCCsGAQUFBwIBFjZodHRwOi8vZS10cnVzdGNvbS5pbnRlc2EuaXQvY2Ff" + + "cHViYmxpY2EvQ1BTX0lOVEVTQS5odG0wDgYDVR0PAQH/BAQDAgZAMIGDBgNV" + + "HSMEfDB6gBQZCQOW0bjFWBt+EORuxPagEgkQqKFcpFowWDELMAkGA1UEBhMC" + + "SVQxGjAYBgNVBAoTEUluLlRlLlMuQS4gUy5wLkEuMS0wKwYDVQQDEyRJbi5U" + + "ZS5TLkEuIC0gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHmCBDzRARMwOwYDVR0f" + + "BDQwMjAwoC6gLIYqaHR0cDovL2UtdHJ1c3Rjb20uaW50ZXNhLml0L0NSTC9J" + + "TlRFU0EuY3JsMB0GA1UdDgQWBBTf5ItL8KmQh541Dxt7YxcWI1254TANBgkq" + + "hkiG9w0BAQUFAAOCAQEAgW+uL1CVWQepbC/wfCmR6PN37Sueb4xiKQj2mTD5" + + "UZ5KQjpivy/Hbuf0NrfKNiDEhAvoHSPC31ebGiKuTMFNyZPHfPEUnyYGSxea" + + "2w837aXJFr6utPNQGBRi89kH90sZDlXtOSrZI+AzJJn5QK3F9gjcayU2NZXQ" + + "MJgRwYmFyn2w4jtox+CwXPQ9E5XgxiMZ4WDL03cWVXDLX00EOJwnDDMUNTRI" + + "m9Zv+4SKTNlfFbi9UTBqWBySkDzAelsfB2U61oqc2h1xKmCtkGMmN9iZT+Qz" + + "ZC/vaaT+hLEBFGAH2gwFrYc4/jTBKyBYeU1vsAxsibIoTs1Apgl6MH75qPDL" + + "BzCCBM8wggO3oAMCAQICBEOdgPcwDQYJKoZIhvcNAQEFBQAwWDELMAkGA1UE" + + "BhMCSVQxGjAYBgNVBAoTEUluLlRlLlMuQS4gUy5wLkEuMS0wKwYDVQQDEyRJ" + + "bi5UZS5TLkEuIC0gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMDgwOTEy" + + "MTE0MzEyWhcNMTAwOTEyMTE0MzEyWjCB2DELMAkGA1UEBhMCSVQxIjAgBgNV" + + "BAoMGUludGVzYSBTLnAuQS4vMDUyNjI4OTAwMTQxKjAoBgNVBAsMIUJ1c2lu" + + "ZXNzIENvbGxhYm9yYXRpb24gJiBTZWN1cml0eTEeMBwGA1UEAwwVTUFTU0lN" + + "SUxJQU5PIFpJQ0NBUkRJMREwDwYDVQQEDAhaSUNDQVJESTEVMBMGA1UEKgwM" + + "TUFTU0lNSUxJQU5PMRwwGgYDVQQFExNJVDpaQ0NNU003NkgxNEwyMTlZMREw" + + "DwYDVQQuEwgwMDAwMjU4NTCBoDANBgkqhkiG9w0BAQEFAAOBjgAwgYoCgYEA" + + "t4lOObIWDHVIg/pzYC4H+S7IejmP+msoQtMAuwUOKat78fGvfA5J63VN1B8X" + + "NTwu74QmqB9X1xX5wjXJ4fWtmzuV6Lsve1f9VHnrkjLCeC5fnHC+14BKBZmv" + + "nfsWTCznRu9MQzJg6PVN/cVm9lTPifg4Pf0ojiZ9H2LV4RUjFHcCBACLOk2j" + + "ggGhMIIBnTAdBgNVHREEFjAUgRJ6aWNjYXJkaUBpbnRlc2EuaXQwLwYIKwYB" + + "BQUHAQMEIzAhMAgGBgQAjkYBATALBgYEAI5GAQMCARQwCAYGBACORgEEMFkG" + + "A1UdIARSMFAwTgYGBACLMAEBMEQwQgYIKwYBBQUHAgEWNmh0dHA6Ly9lLXRy" + + "dXN0Y29tLmludGVzYS5pdC9jYV9wdWJibGljYS9DUFNfSU5URVNBLmh0bTAO" + + "BgNVHQ8BAf8EBAMCBkAwgYMGA1UdIwR8MHqAFBkJA5bRuMVYG34Q5G7E9qAS" + + "CRCooVykWjBYMQswCQYDVQQGEwJJVDEaMBgGA1UEChMRSW4uVGUuUy5BLiBT" + + "LnAuQS4xLTArBgNVBAMTJEluLlRlLlMuQS4gLSBDZXJ0aWZpY2F0aW9uIEF1" + + "dGhvcml0eYIEPNEBEzA7BgNVHR8ENDAyMDCgLqAshipodHRwOi8vZS10cnVz" + + "dGNvbS5pbnRlc2EuaXQvQ1JML0lOVEVTQS5jcmwwHQYDVR0OBBYEFN/ki0vw" + + "qZCHnjUPG3tjFxYjXbnhMA0GCSqGSIb3DQEBBQUAA4IBAQCBb64vUJVZB6ls" + + "L/B8KZHo83ftK55vjGIpCPaZMPlRnkpCOmK/L8du5/Q2t8o2IMSEC+gdI8Lf" + + "V5saIq5MwU3Jk8d88RSfJgZLF5rbDzftpckWvq6081AYFGLz2Qf3SxkOVe05" + + "Ktkj4DMkmflArcX2CNxrJTY1ldAwmBHBiYXKfbDiO2jH4LBc9D0TleDGIxnh" + + "YMvTdxZVcMtfTQQ4nCcMMxQ1NEib1m/7hIpM2V8VuL1RMGpYHJKQPMB6Wx8H" + + "ZTrWipzaHXEqYK2QYyY32JlP5DNkL+9ppP6EsQEUYAfaDAWthzj+NMErIFh5" + + "TW+wDGyJsihOzUCmCXowfvmo8MsHMIIEzzCCA7egAwIBAgIEQ52A9zANBgkq" + + "hkiG9w0BAQUFADBYMQswCQYDVQQGEwJJVDEaMBgGA1UEChMRSW4uVGUuUy5B" + + "LiBTLnAuQS4xLTArBgNVBAMTJEluLlRlLlMuQS4gLSBDZXJ0aWZpY2F0aW9u" + + "IEF1dGhvcml0eTAeFw0wODA5MTIxMTQzMTJaFw0xMDA5MTIxMTQzMTJaMIHY" + + "MQswCQYDVQQGEwJJVDEiMCAGA1UECgwZSW50ZXNhIFMucC5BLi8wNTI2Mjg5" + + "MDAxNDEqMCgGA1UECwwhQnVzaW5lc3MgQ29sbGFib3JhdGlvbiAmIFNlY3Vy" + + "aXR5MR4wHAYDVQQDDBVNQVNTSU1JTElBTk8gWklDQ0FSREkxETAPBgNVBAQM" + + "CFpJQ0NBUkRJMRUwEwYDVQQqDAxNQVNTSU1JTElBTk8xHDAaBgNVBAUTE0lU" + + "OlpDQ01TTTc2SDE0TDIxOVkxETAPBgNVBC4TCDAwMDAyNTg1MIGgMA0GCSqG" + + "SIb3DQEBAQUAA4GOADCBigKBgQC3iU45shYMdUiD+nNgLgf5Lsh6OY/6ayhC" + + "0wC7BQ4pq3vx8a98DknrdU3UHxc1PC7vhCaoH1fXFfnCNcnh9a2bO5Xouy97" + + "V/1UeeuSMsJ4Ll+ccL7XgEoFma+d+xZMLOdG70xDMmDo9U39xWb2VM+J+Dg9" + + "/SiOJn0fYtXhFSMUdwIEAIs6TaOCAaEwggGdMB0GA1UdEQQWMBSBEnppY2Nh" + + "cmRpQGludGVzYS5pdDAvBggrBgEFBQcBAwQjMCEwCAYGBACORgEBMAsGBgQA" + + "jkYBAwIBFDAIBgYEAI5GAQQwWQYDVR0gBFIwUDBOBgYEAIswAQEwRDBCBggr" + + "BgEFBQcCARY2aHR0cDovL2UtdHJ1c3Rjb20uaW50ZXNhLml0L2NhX3B1YmJs" + + "aWNhL0NQU19JTlRFU0EuaHRtMA4GA1UdDwEB/wQEAwIGQDCBgwYDVR0jBHww" + + "eoAUGQkDltG4xVgbfhDkbsT2oBIJEKihXKRaMFgxCzAJBgNVBAYTAklUMRow" + + "GAYDVQQKExFJbi5UZS5TLkEuIFMucC5BLjEtMCsGA1UEAxMkSW4uVGUuUy5B" + + "LiAtIENlcnRpZmljYXRpb24gQXV0aG9yaXR5ggQ80QETMDsGA1UdHwQ0MDIw" + + "MKAuoCyGKmh0dHA6Ly9lLXRydXN0Y29tLmludGVzYS5pdC9DUkwvSU5URVNB" + + "LmNybDAdBgNVHQ4EFgQU3+SLS/CpkIeeNQ8be2MXFiNdueEwDQYJKoZIhvcN" + + "AQEFBQADggEBAIFvri9QlVkHqWwv8Hwpkejzd+0rnm+MYikI9pkw+VGeSkI6" + + "Yr8vx27n9Da3yjYgxIQL6B0jwt9XmxoirkzBTcmTx3zxFJ8mBksXmtsPN+2l" + + "yRa+rrTzUBgUYvPZB/dLGQ5V7Tkq2SPgMySZ+UCtxfYI3GslNjWV0DCYEcGJ" + + "hcp9sOI7aMfgsFz0PROV4MYjGeFgy9N3FlVwy19NBDicJwwzFDU0SJvWb/uE" + + "ikzZXxW4vVEwalgckpA8wHpbHwdlOtaKnNodcSpgrZBjJjfYmU/kM2Qv72mk" + + "/oSxARRgB9oMBa2HOP40wSsgWHlNb7AMbImyKE7NQKYJejB++ajwywcxggM8" + + "MIIDOAIBATBgMFgxCzAJBgNVBAYTAklUMRowGAYDVQQKExFJbi5UZS5TLkEu" + + "IFMucC5BLjEtMCsGA1UEAxMkSW4uVGUuUy5BLiAtIENlcnRpZmljYXRpb24g" + + "QXV0aG9yaXR5AgRDnYD3MAkGBSsOAwIaBQAwDQYJKoZIhvcNAQEBBQAEgYB+" + + "lH2cwLqc91mP8prvgSV+RRzk13dJdZvdoVjgQoFrPhBiZCNIEoHvIhMMA/sM" + + "X6euSRZk7EjD24FasCEGYyd0mJVLEy6TSPmuW+wWz/28w3a6IWXBGrbb/ild" + + "/CJMkPgLPGgOVD1WDwiNKwfasiQSFtySf5DPn3jFevdLeMmEY6GCAjIwggEV" + + "BgkqhkiG9w0BCQYxggEGMIIBAgIBATBgMFgxCzAJBgNVBAYTAklUMRowGAYD" + + "VQQKExFJbi5UZS5TLkEuIFMucC5BLjEtMCsGA1UEAxMkSW4uVGUuUy5BLiAt" + + "IENlcnRpZmljYXRpb24gQXV0aG9yaXR5AgRDnYD3MAkGBSsOAwIaBQAwDQYJ" + + "KoZIhvcNAQEBBQAEgYBHlOULfT5GDigIvxP0qZOy8VbpntmzaPF55VV4buKV" + + "35J+uHp98gXKp0LrHM69V5IRKuyuQzHHFBqsXxsRI9o6KoOfgliD9Xc+BeMg" + + "dKzQhBhBYoFREq8hQM0nSbqDNHYAQyNHMzUA/ZQUO5dlFuH8Dw3iDYAhNtfd" + + "PrlchKJthDCCARUGCSqGSIb3DQEJBjGCAQYwggECAgEBMGAwWDELMAkGA1UE" + + "BhMCSVQxGjAYBgNVBAoTEUluLlRlLlMuQS4gUy5wLkEuMS0wKwYDVQQDEyRJ" + + "bi5UZS5TLkEuIC0gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkCBEOdgPcwCQYF" + + "Kw4DAhoFADANBgkqhkiG9w0BAQEFAASBgEeU5Qt9PkYOKAi/E/Spk7LxVume" + + "2bNo8XnlVXhu4pXfkn64en3yBcqnQusczr1XkhEq7K5DMccUGqxfGxEj2joq" + + "g5+CWIP1dz4F4yB0rNCEGEFigVESryFAzSdJuoM0dgBDI0czNQD9lBQ7l2UW" + + "4fwPDeINgCE2190+uVyEom2E"); + + byte[] noSignedAttrSample2 = Base64.decode( + "MIIIlAYJKoZIhvcNAQcCoIIIhTCCCIECAQExCzAJBgUrDgMCGgUAMAsGCSqG" + + "SIb3DQEHAaCCB3UwggOtMIIDa6ADAgECAgEzMAsGByqGSM44BAMFADCBkDEL" + + "MAkGA1UEBhMCVVMxCzAJBgNVBAgTAkNBMRIwEAYDVQQHEwlQYWxvIEFsdG8x" + + "HTAbBgNVBAoTFFN1biBNaWNyb3N5c3RlbXMgSW5jMSMwIQYDVQQLExpKYXZh" + + "IFNvZnR3YXJlIENvZGUgU2lnbmluZzEcMBoGA1UEAxMTSkNFIENvZGUgU2ln" + + "bmluZyBDQTAeFw0wMTA1MjkxNjQ3MTFaFw0wNjA1MjgxNjQ3MTFaMG4xHTAb" + + "BgNVBAoTFFN1biBNaWNyb3N5c3RlbXMgSW5jMSMwIQYDVQQLExpKYXZhIFNv" + + "ZnR3YXJlIENvZGUgU2lnbmluZzEoMCYGA1UEAxMfVGhlIExlZ2lvbiBvZiB0" + + "aGUgQm91bmN5IENhc3RsZTCCAbcwggEsBgcqhkjOOAQBMIIBHwKBgQD9f1OB" + + "HXUSKVLfSpwu7OTn9hG3UjzvRADDHj+AtlEmaUVdQCJR+1k9jVj6v8X1ujD2" + + "y5tVbNeBO4AdNG/yZmC3a5lQpaSfn+gEexAiwk+7qdf+t8Yb+DtX58aophUP" + + "BPuD9tPFHsMCNVQTWhaRMvZ1864rYdcq7/IiAxmd0UgBxwIVAJdgUI8VIwvM" + + "spK5gqLrhAvwWBz1AoGBAPfhoIXWmz3ey7yrXDa4V7l5lK+7+jrqgvlXTAs9" + + "B4JnUVlXjrrUWU/mcQcQgYC0SRZxI+hMKBYTt88JMozIpuE8FnqLVHyNKOCj" + + "rh4rs6Z1kW6jfwv6ITVi8ftiegEkO8yk8b6oUZCJqIPf4VrlnwaSi2ZegHtV" + + "JWQBTDv+z0kqA4GEAAKBgBWry/FCAZ6miyy39+ftsa+h9lxoL+JtV0MJcUyQ" + + "E4VAhpAwWb8vyjba9AwOylYQTktHX5sAkFvjBiU0LOYDbFSTVZSHMRJgfjxB" + + "SHtICjOEvr1BJrrOrdzqdxcOUge5n7El124BCrv91x5Ol8UTwtiO9LrRXF/d" + + "SyK+RT5n1klRo3YwdDARBglghkgBhvhCAQEEBAMCAIcwDgYDVR0PAQH/BAQD" + + "AgHGMB0GA1UdDgQWBBQwMY4NRcco1AO3w1YsokfDLVseEjAPBgNVHRMBAf8E" + + "BTADAQH/MB8GA1UdIwQYMBaAFGXi9IbJ007wkU5Yomr12HhamsGmMAsGByqG" + + "SM44BAMFAAMvADAsAhRmigTu6QV0sTfEkVljgij/hhdVfAIUQZvMxAnIHc30" + + "y/u0C1T5UEG9glUwggPAMIIDfqADAgECAgEQMAsGByqGSM44BAMFADCBkDEL" + + "MAkGA1UEBhMCVVMxCzAJBgNVBAgTAkNBMRIwEAYDVQQHEwlQYWxvIEFsdG8x" + + "HTAbBgNVBAoTFFN1biBNaWNyb3N5c3RlbXMgSW5jMSMwIQYDVQQLExpKYXZh" + + "IFNvZnR3YXJlIENvZGUgU2lnbmluZzEcMBoGA1UEAxMTSkNFIENvZGUgU2ln" + + "bmluZyBDQTAeFw0wMTA0MjUwNzAwMDBaFw0yMDA0MjUwNzAwMDBaMIGQMQsw" + + "CQYDVQQGEwJVUzELMAkGA1UECBMCQ0ExEjAQBgNVBAcTCVBhbG8gQWx0bzEd" + + "MBsGA1UEChMUU3VuIE1pY3Jvc3lzdGVtcyBJbmMxIzAhBgNVBAsTGkphdmEg" + + "U29mdHdhcmUgQ29kZSBTaWduaW5nMRwwGgYDVQQDExNKQ0UgQ29kZSBTaWdu" + + "aW5nIENBMIIBtzCCASwGByqGSM44BAEwggEfAoGBAOuvNwQeylEeaV2w8o/2" + + "tUkfxqSZBdcpv3S3avUZ2B7kG/gKAZqY/3Cr4kpWhmxTs/zhyIGMMfDE87CL" + + "5nAG7PdpaNuDTHIpiSk2F1w7SgegIAIqRpdRHXDICBgLzgxum3b3BePn+9Nh" + + "eeFgmiSNBpWDPFEg4TDPOFeCphpyDc7TAhUAhCVF4bq5qWKreehbMLiJaxv/" + + "e3UCgYEAq8l0e3Tv7kK1alNNO92QBnJokQ8LpCl2LlU71a5NZVx+KjoEpmem" + + "0HGqpde34sFyDaTRqh6SVEwgAAmisAlBGTMAssNcrkL4sYvKfJbYEH83RFuq" + + "zHjI13J2N2tAmahVZvqoAx6LShECactMuCUGHKB30sms0j3pChD6dnC3+9wD" + + "gYQAAoGALQmYXKy4nMeZfu4gGSo0kPnXq6uu3WtylQ1m+O8nj0Sy7ShEx/6v" + + "sKYnbwBnRYJbB6hWVjvSKVFhXmk51y50dxLPGUr1LcjLcmHETm/6R0M/FLv6" + + "vBhmKMLZZot6LS/CYJJLFP5YPiF/aGK+bEhJ+aBLXoWdGRD5FUVRG3HU9wuj" + + "ZjBkMBEGCWCGSAGG+EIBAQQEAwIABzAPBgNVHRMBAf8EBTADAQH/MB8GA1Ud" + + "IwQYMBaAFGXi9IbJ007wkU5Yomr12HhamsGmMB0GA1UdDgQWBBRl4vSGydNO" + + "8JFOWKJq9dh4WprBpjALBgcqhkjOOAQDBQADLwAwLAIUKvfPPJdd+Xi2CNdB" + + "tNkNRUzktJwCFEXNdWkOIfod1rMpsun3Mx0z/fxJMYHoMIHlAgEBMIGWMIGQ" + + "MQswCQYDVQQGEwJVUzELMAkGA1UECBMCQ0ExEjAQBgNVBAcTCVBhbG8gQWx0" + + "bzEdMBsGA1UEChMUU3VuIE1pY3Jvc3lzdGVtcyBJbmMxIzAhBgNVBAsTGkph" + + "dmEgU29mdHdhcmUgQ29kZSBTaWduaW5nMRwwGgYDVQQDExNKQ0UgQ29kZSBT" + + "aWduaW5nIENBAgEzMAkGBSsOAwIaBQAwCwYHKoZIzjgEAQUABC8wLQIVAIGV" + + "khm+kbV4a/+EP45PHcq0hIViAhR4M9os6IrJnoEDS3Y3l7O6zrSosA=="); + + private static final byte[] rawGost = Base64.decode( + "MIIEBwYJKoZIhvcNAQcCoIID+DCCA/QCAQExDDAKBgYqhQMCAgkFADAfBgkq" + + "hkiG9w0BBwGgEgQQU29tZSBEYXRhIEhFUkUhIaCCAuYwggLiMIICkaADAgEC" + + "AgopoLG9AAIAArWeMAgGBiqFAwICAzBlMSAwHgYJKoZIhvcNAQkBFhFpbmZv" + + "QGNyeXB0b3Byby5ydTELMAkGA1UEBhMCUlUxEzARBgNVBAoTCkNSWVBUTy1Q" + + "Uk8xHzAdBgNVBAMTFlRlc3QgQ2VudGVyIENSWVBUTy1QUk8wHhcNMTIxMDE1" + + "MTEwNDIzWhcNMTQxMDA0MDcwOTQxWjAhMRIwEAYDVQQDDAl0ZXN0IGdvc3Qx" + + "CzAJBgNVBAYTAlJVMGMwHAYGKoUDAgITMBIGByqFAwICJAAGByqFAwICHgED" + + "QwAEQPz/F99AG8wyMQz5uK3vJ3MdHk7ZyFzM4Ofnq8nAmDgI5/Nuzcu791/0" + + "hRd+1i+fArRsiPMdQXOF0E7bEMHwWfWjggFjMIIBXzAOBgNVHQ8BAf8EBAMC" + + "BPAwEwYDVR0lBAwwCgYIKwYBBQUHAwIwHQYDVR0OBBYEFO353ZD7sLCx6rVR" + + "2o/IsSxuE1gAMB8GA1UdIwQYMBaAFG2PXgXZX6yRF5QelZoFMDg3ehAqMFUG" + + "A1UdHwROMEwwSqBIoEaGRGh0dHA6Ly93d3cuY3J5cHRvcHJvLnJ1L0NlcnRF" + + "bnJvbGwvVGVzdCUyMENlbnRlciUyMENSWVBUTy1QUk8oMikuY3JsMIGgBggr" + + "BgEFBQcBAQSBkzCBkDAzBggrBgEFBQcwAYYnaHR0cDovL3d3dy5jcnlwdG9w" + + "cm8ucnUvb2NzcG5jL29jc3Auc3JmMFkGCCsGAQUFBzAChk1odHRwOi8vd3d3" + + "LmNyeXB0b3Byby5ydS9DZXJ0RW5yb2xsL3BraS1zaXRlX1Rlc3QlMjBDZW50" + + "ZXIlMjBDUllQVE8tUFJPKDIpLmNydDAIBgYqhQMCAgMDQQBAR4mr69a62d3l" + + "yK/UZ4Yz/Yi3jqURtbnJR2gugdzkG5pYHRwC41BbDaa1ItP+1gDp4s78+EiK" + + "AJc17CHGZTz3MYHVMIHSAgEBMHMwZTEgMB4GCSqGSIb3DQEJARYRaW5mb0Bj" + + "cnlwdG9wcm8ucnUxCzAJBgNVBAYTAlJVMRMwEQYDVQQKEwpDUllQVE8tUFJP" + + "MR8wHQYDVQQDExZUZXN0IENlbnRlciBDUllQVE8tUFJPAgopoLG9AAIAArWe" + + "MAoGBiqFAwICCQUAMAoGBiqFAwICEwUABED0Gs9zP9lSz/2/e3BUSpzCI3dx" + + "39gfl/pFVkx4p5N/GW5o4gHIST9OhDSmdxwpMSK+39YSRD4R0Ue0faOqWEsj" + + "AAAAAAAAAAAAAAAAAAAAAA=="); + + private static final byte[] noAttrEncData = Base64.decode( + "MIIFjwYJKoZIhvcNAQcCoIIFgDCCBXwCAQExDTALBglghkgBZQMEAgEwgdAG" + + "CSqGSIb3DQEHAaCBwgSBv01JTUUtVmVyc2lvbjogMS4wCkNvbnRlbnQtVHlw" + + "ZTogYXBwbGljYXRpb24vb2N0ZXQtc3RyZWFtCkNvbnRlbnQtVHJhbnNmZXIt" + + "RW5jb2Rpbmc6IGJpbmFyeQpDb250ZW50LURpc3Bvc2l0aW9uOiBhdHRhY2ht" + + "ZW50OyBmaWxlbmFtZT1kb2MuYmluCgpUaGlzIGlzIGEgdmVyeSBodWdlIHNl" + + "Y3JldCwgbWFkZSB3aXRoIG9wZW5zc2wKCgoKoIIDNDCCAzAwggKZoAMCAQIC" + + "AQEwDQYJKoZIhvcNAQEFBQAwgawxCzAJBgNVBAYTAkFUMRAwDgYDVQQIEwdB" + + "dXN0cmlhMQ8wDQYDVQQHEwZWaWVubmExFTATBgNVBAoTDFRpYW5pIFNwaXJp" + + "dDEUMBIGA1UECxMLSlVuaXQgdGVzdHMxGjAYBgNVBAMTEU1hc3NpbWlsaWFu" + + "byBNYXNpMTEwLwYJKoZIhvcNAQkBFiJtYXNzaW1pbGlhbm8ubWFzaUB0aWFu" + + "aS1zcGlyaXQuY29tMCAXDTEyMDEwMjA5MDAzNVoYDzIxOTEwNjA4MDkwMDM1" + + "WjCBjzELMAkGA1UEBhMCQVQxEDAOBgNVBAgTB0F1c3RyaWExFTATBgNVBAoT" + + "DFRpYW5pIFNwaXJpdDEUMBIGA1UECxMLSlVuaXQgVGVzdHMxDjAMBgNVBAMT" + + "BWNlcnQxMTEwLwYJKoZIhvcNAQkBFiJtYXNzaW1pbGlhbm8ubWFzaUB0aWFu" + + "aS1zcGlyaXQuY29tMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDYHz8n" + + "soeWpILn+5tK8XgJc3k5n0h0MOlRXLbZZVB7yuxKMBIZwl8kqqnehfqxX+hr" + + "b2MXSCgKEstnVunJVPUGuNxnQ8Z0R9p1o/9gR0KTXmoJ+Epx5wdEofk4Phsi" + + "MxjC8FVvt3sSnzal1/m0/9KntrPWksefumGm5XD3W43e5wIDAQABo3sweTAJ" + + "BgNVHRMEAjAAMCwGCWCGSAGG+EIBDQQfFh1PcGVuU1NMIEdlbmVyYXRlZCBD" + + "ZXJ0aWZpY2F0ZTAdBgNVHQ4EFgQU8mTZGl0EFv6aHo3bup144d6wYW8wHwYD" + + "VR0jBBgwFoAUdHG2RdrchT0PFcUBiIiYcy5hAA4wDQYJKoZIhvcNAQEFBQAD" + + "gYEATcc52eo73zEA4wmbyPv0lRrmyAxrHvZGIHiKpM8bP38WUB39lgmS8J0S" + + "1ioj21bosiakGj/gXnxlk8M8O+mm4zzpYjy8gqGXiUt20+j3bm7MJYM8ePcq" + + "dG/kReNuLUbRgIA6b0T4o+0WCELhrd9IlTk5IBKjHIjsP/GR1h0t//kxggFb" + + "MIIBVwIBATCBsjCBrDELMAkGA1UEBhMCQVQxEDAOBgNVBAgTB0F1c3RyaWEx" + + "DzANBgNVBAcTBlZpZW5uYTEVMBMGA1UEChMMVGlhbmkgU3Bpcml0MRQwEgYD" + + "VQQLEwtKVW5pdCB0ZXN0czEaMBgGA1UEAxMRTWFzc2ltaWxpYW5vIE1hc2kx" + + "MTAvBgkqhkiG9w0BCQEWIm1hc3NpbWlsaWFuby5tYXNpQHRpYW5pLXNwaXJp" + + "dC5jb20CAQEwCwYJYIZIAWUDBAIBMA0GCSqGSIb3DQEBAQUABIGAEthqA7FK" + + "V1i+MzzS4zz4DxT4lwUYkWfHaDtZADUyTD5lnP3Pf+t/ScpBEGkEtI7hDqOO" + + "zE0WfkBshTx5B/uxDibc/jqjQpSYSz5cvBTgpocIalbqsErOkDYF1QP6UgaV" + + "ZoVGwvGYIuIrFgWqgk08NsPHVVjYseTEhUDwkI1KSxU="); + + byte[] successResp = Base64.decode( + "MIIFnAoBAKCCBZUwggWRBgkrBgEFBQcwAQEEggWCMIIFfjCCARehgZ8wgZwx" + + "CzAJBgNVBAYTAklOMRcwFQYDVQQIEw5BbmRocmEgcHJhZGVzaDESMBAGA1UE" + + "BxMJSHlkZXJhYmFkMQwwCgYDVQQKEwNUQ1MxDDAKBgNVBAsTA0FUQzEeMBwG" + + "A1UEAxMVVENTLUNBIE9DU1AgUmVzcG9uZGVyMSQwIgYJKoZIhvcNAQkBFhVv" + + "Y3NwQHRjcy1jYS50Y3MuY28uaW4YDzIwMDMwNDAyMTIzNDU4WjBiMGAwOjAJ" + + "BgUrDgMCGgUABBRs07IuoCWNmcEl1oHwIak1BPnX8QQUtGyl/iL9WJ1VxjxF" + + "j0hAwJ/s1AcCAQKhERgPMjAwMjA4MjkwNzA5MjZaGA8yMDAzMDQwMjEyMzQ1" + + "OFowDQYJKoZIhvcNAQEFBQADgYEAfbN0TCRFKdhsmvOdUoiJ+qvygGBzDxD/" + + "VWhXYA+16AphHLIWNABR3CgHB3zWtdy2j7DJmQ/R7qKj7dUhWLSqclAiPgFt" + + "QQ1YvSJAYfEIdyHkxv4NP0LSogxrumANcDyC9yt/W9yHjD2ICPBIqCsZLuLk" + + "OHYi5DlwWe9Zm9VFwCGgggPMMIIDyDCCA8QwggKsoAMCAQICAQYwDQYJKoZI" + + "hvcNAQEFBQAwgZQxFDASBgNVBAMTC1RDUy1DQSBPQ1NQMSYwJAYJKoZIhvcN" + + "AQkBFhd0Y3MtY2FAdGNzLWNhLnRjcy5jby5pbjEMMAoGA1UEChMDVENTMQww" + + "CgYDVQQLEwNBVEMxEjAQBgNVBAcTCUh5ZGVyYWJhZDEXMBUGA1UECBMOQW5k" + + "aHJhIHByYWRlc2gxCzAJBgNVBAYTAklOMB4XDTAyMDgyOTA3MTE0M1oXDTAz" + + "MDgyOTA3MTE0M1owgZwxCzAJBgNVBAYTAklOMRcwFQYDVQQIEw5BbmRocmEg" + + "cHJhZGVzaDESMBAGA1UEBxMJSHlkZXJhYmFkMQwwCgYDVQQKEwNUQ1MxDDAK" + + "BgNVBAsTA0FUQzEeMBwGA1UEAxMVVENTLUNBIE9DU1AgUmVzcG9uZGVyMSQw" + + "IgYJKoZIhvcNAQkBFhVvY3NwQHRjcy1jYS50Y3MuY28uaW4wgZ8wDQYJKoZI" + + "hvcNAQEBBQADgY0AMIGJAoGBAM+XWW4caMRv46D7L6Bv8iwtKgmQu0SAybmF" + + "RJiz12qXzdvTLt8C75OdgmUomxp0+gW/4XlTPUqOMQWv463aZRv9Ust4f8MH" + + "EJh4ekP/NS9+d8vEO3P40ntQkmSMcFmtA9E1koUtQ3MSJlcs441JjbgUaVnm" + + "jDmmniQnZY4bU3tVAgMBAAGjgZowgZcwDAYDVR0TAQH/BAIwADALBgNVHQ8E" + + "BAMCB4AwEwYDVR0lBAwwCgYIKwYBBQUHAwkwNgYIKwYBBQUHAQEEKjAoMCYG" + + "CCsGAQUFBzABhhpodHRwOi8vMTcyLjE5LjQwLjExMDo3NzAwLzAtBgNVHR8E" + + "JjAkMCKgIKAehhxodHRwOi8vMTcyLjE5LjQwLjExMC9jcmwuY3JsMA0GCSqG" + + "SIb3DQEBBQUAA4IBAQB6FovM3B4VDDZ15o12gnADZsIk9fTAczLlcrmXLNN4" + + "PgmqgnwF0Ymj3bD5SavDOXxbA65AZJ7rBNAguLUo+xVkgxmoBH7R2sBxjTCc" + + "r07NEadxM3HQkt0aX5XYEl8eRoifwqYAI9h0ziZfTNes8elNfb3DoPPjqq6V" + + "mMg0f0iMS4W8LjNPorjRB+kIosa1deAGPhq0eJ8yr0/s2QR2/WFD5P4aXc8I" + + "KWleklnIImS3zqiPrq6tl2Bm8DZj7vXlTOwmraSQxUwzCKwYob1yGvNOUQTq" + + "pG6jxn7jgDawHU1+WjWQe4Q34/pWeGLysxTraMa+Ug9kPe+jy/qRX2xwvKBZ"); + + public NewSignedDataTest(String name) + { + super(name); + } + + public static void main(String args[]) + { + + junit.textui.TestRunner.run(NewSignedDataTest.class); + } + + public static Test suite() + throws Exception + { + init(); + + return new CMSTestSetup(new TestSuite(NewSignedDataTest.class)); + } + + private static void init() + throws Exception + { + if (!_initialised) + { + _initialised = true; + + if (Security.getProvider(BC) == null) + { + Security.addProvider(new org.spongycastle.jce.provider.BouncyCastleProvider()); + } + + _origDN = "O=Bouncy Castle, C=AU"; + _origKP = CMSTestUtil.makeKeyPair(); + _origCert = CMSTestUtil.makeCertificate(_origKP, _origDN, _origKP, _origDN); + + _signDN = "CN=Bob, OU=Sales, O=Bouncy Castle, C=AU"; + _signKP = CMSTestUtil.makeKeyPair(); + _signCert = CMSTestUtil.makeCertificate(_signKP, _signDN, _origKP, _origDN); + + _signGostKP = CMSTestUtil.makeGostKeyPair(); + _signGostCert = CMSTestUtil.makeCertificate(_signGostKP, _signDN, _origKP, _origDN); + + _signDsaKP = CMSTestUtil.makeDsaKeyPair(); + _signDsaCert = CMSTestUtil.makeCertificate(_signDsaKP, _signDN, _origKP, _origDN); + + _signEcDsaKP = CMSTestUtil.makeEcDsaKeyPair(); + _signEcDsaCert = CMSTestUtil.makeCertificate(_signEcDsaKP, _signDN, _origKP, _origDN); + + _signEcGostKP = CMSTestUtil.makeEcGostKeyPair(); + _signEcGostCert = CMSTestUtil.makeCertificate(_signEcGostKP, _signDN, _origKP, _origDN); + + _reciDN = "CN=Doug, OU=Sales, O=Bouncy Castle, C=AU"; + _reciKP = CMSTestUtil.makeKeyPair(); + _reciCert = CMSTestUtil.makeCertificate(_reciKP, _reciDN, _signKP, _signDN); + + _signCrl = CMSTestUtil.makeCrl(_signKP); + } + } + + private void verifyRSASignatures(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(); + + assertEquals(true, signer.verify(new BcRSASignerInfoVerifierBuilder(new DefaultCMSSignatureAlgorithmNameGenerator(), new DefaultSignatureAlgorithmIdentifierFinder(), new DefaultDigestAlgorithmIdentifierFinder(), new BcDigestCalculatorProvider()).build(cert))); + + if (contentDigest != null) + { + assertTrue(MessageDigest.isEqual(contentDigest, signer.getContentDigest())); + } + } + } + + private void verifySignatures(CMSSignedData s, byte[] contentDigest) + throws Exception + { + Store certStore = s.getCertificates(); + Store crlStore = s.getCRLs(); + 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(); + + assertEquals(true, signer.verify(new JcaSimpleSignerInfoVerifierBuilder().setProvider(BC).build(cert))); + + if (contentDigest != null) + { + assertTrue(MessageDigest.isEqual(contentDigest, signer.getContentDigest())); + } + } + + Collection certColl = certStore.getMatches(null); + Collection crlColl = crlStore.getMatches(null); + + assertEquals(certColl.size(), s.getCertificates().getMatches(null).size()); + assertEquals(crlColl.size(), s.getCRLs().getMatches(null).size()); + } + + private void verifySignatures(CMSSignedData s) + throws Exception + { + verifySignatures(s, null); + } + + public void testDetachedVerification() + throws Exception + { + byte[] data = "Hello World!".getBytes(); + List certList = new ArrayList(); + CMSTypedData msg = new CMSProcessableByteArray(data); + + certList.add(_origCert); + certList.add(_signCert); + + Store certs = new JcaCertStore(certList); + + CMSSignedDataGenerator gen = new CMSSignedDataGenerator(); + + DigestCalculatorProvider digProvider = new JcaDigestCalculatorProviderBuilder().setProvider(BC).build(); + JcaSignerInfoGeneratorBuilder signerInfoGeneratorBuilder = new JcaSignerInfoGeneratorBuilder(digProvider); + ContentSigner sha1Signer = new JcaContentSignerBuilder("SHA1withRSA").setProvider(BC).build(_origKP.getPrivate()); + ContentSigner md5Signer = new JcaContentSignerBuilder("MD5withRSA").setProvider(BC).build(_origKP.getPrivate()); + + gen.addSignerInfoGenerator(signerInfoGeneratorBuilder.build(sha1Signer, _origCert)); + gen.addSignerInfoGenerator(signerInfoGeneratorBuilder.build(md5Signer, _origCert)); + + gen.addCertificates(certs); + + CMSSignedData s = gen.generate(msg); + + MessageDigest sha1 = MessageDigest.getInstance("SHA1", BC); + MessageDigest md5 = MessageDigest.getInstance("MD5", BC); + Map hashes = new HashMap(); + byte[] sha1Hash = sha1.digest(data); + byte[] md5Hash = md5.digest(data); + + hashes.put(CMSAlgorithm.SHA1, sha1Hash); + hashes.put(CMSAlgorithm.MD5, md5Hash); + + s = new CMSSignedData(hashes, s.getEncoded()); + + verifySignatures(s, null); + } + + public void testSHA1AndMD5WithRSAEncapsulatedRepeated() + throws Exception + { + List certList = new ArrayList(); + CMSTypedData msg = new CMSProcessableByteArray("Hello World!".getBytes()); + + certList.add(_origCert); + certList.add(_signCert); + + Store certs = new JcaCertStore(certList); + + CMSSignedDataGenerator gen = new CMSSignedDataGenerator(); + + DigestCalculatorProvider digCalcProv = new JcaDigestCalculatorProviderBuilder().setProvider(BC).build(); + + gen.addSignerInfoGenerator(new JcaSignerInfoGeneratorBuilder(digCalcProv).build(new JcaContentSignerBuilder("SHA1withRSA").setProvider(BC).build(_origKP.getPrivate()), _origCert)); + + gen.addSignerInfoGenerator(new JcaSignerInfoGeneratorBuilder(digCalcProv).build(new JcaContentSignerBuilder("MD5withRSA").setProvider(BC).build(_origKP.getPrivate()), _origCert)); + + gen.addCertificates(certs); + + CMSSignedData s = gen.generate(msg, true); + + ByteArrayInputStream bIn = new ByteArrayInputStream(s.getEncoded()); + ASN1InputStream aIn = new ASN1InputStream(bIn); + + s = new CMSSignedData(ContentInfo.getInstance(aIn.readObject())); + + certs = s.getCertificates(); + + SignerInformationStore signers = s.getSignerInfos(); + + assertEquals(2, signers.size()); + + Collection c = signers.getSigners(); + Iterator it = c.iterator(); + SignerId sid = null; + + while (it.hasNext()) + { + SignerInformation signer = (SignerInformation)it.next(); + Collection certCollection = certs.getMatches(signer.getSID()); + + Iterator certIt = certCollection.iterator(); + X509CertificateHolder cert = (X509CertificateHolder)certIt.next(); + + sid = signer.getSID(); + + assertEquals(true, signer.verify(new JcaSimpleSignerInfoVerifierBuilder().setProvider(BC).build(cert))); + + // + // check content digest + // + + byte[] contentDigest = (byte[])gen.getGeneratedDigests().get(signer.getDigestAlgOID()); + + AttributeTable table = signer.getSignedAttributes(); + Attribute hash = table.get(CMSAttributes.messageDigest); + + assertTrue(MessageDigest.isEqual(contentDigest, ((ASN1OctetString)hash.getAttrValues().getObjectAt(0)).getOctets())); + } + + c = signers.getSigners(sid); + + assertEquals(2, c.size()); + + + // + // try using existing signer + // + + gen = new CMSSignedDataGenerator(); + + gen.addSigners(s.getSignerInfos()); + + gen.addCertificates(s.getCertificates()); + + s = gen.generate(msg, true); + + bIn = new ByteArrayInputStream(s.getEncoded()); + aIn = new ASN1InputStream(bIn); + + s = new CMSSignedData(ContentInfo.getInstance(aIn.readObject())); + + certs = s.getCertificates(); + + signers = s.getSignerInfos(); + c = signers.getSigners(); + it = c.iterator(); + + assertEquals(2, c.size()); + + while (it.hasNext()) + { + SignerInformation signer = (SignerInformation)it.next(); + Collection certCollection = certs.getMatches(signer.getSID()); + + Iterator certIt = certCollection.iterator(); + X509CertificateHolder cert = (X509CertificateHolder)certIt.next(); + + assertEquals(true, signer.verify(new JcaSimpleSignerInfoVerifierBuilder().setProvider(BC).build(cert))); + } + + checkSignerStoreReplacement(s, signers); + } + + public void testSHA1WithRSANoAttributes() + throws Exception + { + List certList = new ArrayList(); + CMSTypedData msg = new CMSProcessableByteArray("Hello world!".getBytes()); + + certList.add(_origCert); + certList.add(_signCert); + + Store certs = new JcaCertStore(certList); + + CMSSignedDataGenerator gen = new CMSSignedDataGenerator(); + ContentSigner sha1Signer = new JcaContentSignerBuilder("SHA1withRSA").setProvider(BC).build(_origKP.getPrivate()); + + JcaSignerInfoGeneratorBuilder builder = new JcaSignerInfoGeneratorBuilder(new JcaDigestCalculatorProviderBuilder().setProvider(BC).build()); + + builder.setDirectSignature(true); + + gen.addSignerInfoGenerator(builder.build(sha1Signer, _origCert)); + + gen.addCertificates(certs); + + CMSSignedData s = gen.generate(msg, false); + + // + // compute expected content digest + // + MessageDigest md = MessageDigest.getInstance("SHA1", BC); + + verifySignatures(s, md.digest("Hello world!".getBytes())); + } + + public void testSHA1WithRSANoAttributesSimple() + throws Exception + { + List certList = new ArrayList(); + CMSTypedData msg = new CMSProcessableByteArray("Hello world!".getBytes()); + + certList.add(_origCert); + certList.add(_signCert); + + Store certs = new JcaCertStore(certList); + + CMSSignedDataGenerator gen = new CMSSignedDataGenerator(); + + JcaSimpleSignerInfoGeneratorBuilder builder = new JcaSimpleSignerInfoGeneratorBuilder().setProvider(BC).setDirectSignature(true); + + gen.addSignerInfoGenerator(builder.build("SHA1withRSA", _origKP.getPrivate(), _origCert)); + + gen.addCertificates(certs); + + CMSSignedData s = gen.generate(msg, false); + + // + // compute expected content digest + // + MessageDigest md = MessageDigest.getInstance("SHA1", BC); + + verifySignatures(s, md.digest("Hello world!".getBytes())); + } + + public void testSHA1WithRSAAndOtherRevocation() + throws Exception + { + List certList = new ArrayList(); + CMSTypedData msg = new CMSProcessableByteArray("Hello world!".getBytes()); + + certList.add(_origCert); + certList.add(_signCert); + + Store certs = new JcaCertStore(certList); + + CMSSignedDataGenerator gen = new CMSSignedDataGenerator(); + + ContentSigner sha1Signer = new JcaContentSignerBuilder("SHA1withRSA").setProvider(BC).build(_origKP.getPrivate()); + + gen.addSignerInfoGenerator(new JcaSignerInfoGeneratorBuilder(new JcaDigestCalculatorProviderBuilder().setProvider(BC).build()).build(sha1Signer, _origCert)); + + gen.addCertificates(certs); + + List otherInfo = new ArrayList(); + OCSPResp response = new OCSPResp(successResp); + + otherInfo.add(response.toASN1Structure()); + + gen.addOtherRevocationInfo(CMSObjectIdentifiers.id_ri_ocsp_response, new CollectionStore(otherInfo)); + + CMSSignedData s; + + s = gen.generate(msg, false); + + // + // check version + // + assertEquals(5, s.getVersion()); + + // + // compute expected content digest + // + MessageDigest md = MessageDigest.getInstance("SHA1", BC); + + verifySignatures(s, md.digest("Hello world!".getBytes())); + + Store dataOtherInfo = s.getOtherRevocationInfo(CMSObjectIdentifiers.id_ri_ocsp_response); + + assertEquals(1, dataOtherInfo.getMatches(null).size()); + + OCSPResp dataResponse = new OCSPResp(OCSPResponse.getInstance(dataOtherInfo.getMatches(null).iterator().next())); + + assertEquals(response, dataResponse); + } + + public void testSHA1WithRSAAndAttributeTableSimple() + throws Exception + { + MessageDigest md = MessageDigest.getInstance("SHA1", BC); + List certList = new ArrayList(); + CMSTypedData msg = new CMSProcessableByteArray("Hello world!".getBytes()); + + certList.add(_origCert); + certList.add(_signCert); + + Store certs = new JcaCertStore(certList); + + CMSSignedDataGenerator gen = new CMSSignedDataGenerator(); + + Attribute attr = new Attribute(CMSAttributes.messageDigest, + new DERSet( + new DEROctetString( + md.digest("Hello world!".getBytes())))); + + ASN1EncodableVector v = new ASN1EncodableVector(); + + v.add(attr); + + JcaSimpleSignerInfoGeneratorBuilder builder = new JcaSimpleSignerInfoGeneratorBuilder().setProvider(BC).setSignedAttributeGenerator(new DefaultSignedAttributeTableGenerator(new AttributeTable(v))); + + gen.addSignerInfoGenerator(builder.build("SHA1withRSA", _origKP.getPrivate(), _origCert)); + + gen.addCertificates(certs); + + CMSSignedData s = gen.generate(new CMSAbsentContent(), false); + + // + // the signature is detached, so need to add msg before passing on + // + s = new CMSSignedData(msg, s.getEncoded()); + // + // compute expected content digest + // + + verifySignatures(s, md.digest("Hello world!".getBytes())); + verifyRSASignatures(s, md.digest("Hello world!".getBytes())); + } + + public void testSHA1WithRSAAndAttributeTable() + throws Exception + { + MessageDigest md = MessageDigest.getInstance("SHA1", BC); + List certList = new ArrayList(); + CMSTypedData msg = new CMSProcessableByteArray("Hello world!".getBytes()); + + certList.add(_origCert); + certList.add(_signCert); + + Store certs = new JcaCertStore(certList); + + CMSSignedDataGenerator gen = new CMSSignedDataGenerator(); + + Attribute attr = new Attribute(CMSAttributes.messageDigest, + new DERSet( + new DEROctetString( + md.digest("Hello world!".getBytes())))); + + ASN1EncodableVector v = new ASN1EncodableVector(); + + v.add(attr); + + JcaSignerInfoGeneratorBuilder builder = new JcaSignerInfoGeneratorBuilder(new JcaDigestCalculatorProviderBuilder().setProvider(BC).build()); + + builder.setSignedAttributeGenerator(new DefaultSignedAttributeTableGenerator(new AttributeTable(v))); + + ContentSigner sha1Signer = new JcaContentSignerBuilder("SHA1withRSA").setProvider(BC).build(_origKP.getPrivate()); + + gen.addSignerInfoGenerator(builder.build(sha1Signer, _origCert)); + + gen.addCertificates(certs); + + CMSSignedData s = gen.generate(new CMSAbsentContent(), false); + + // + // the signature is detached, so need to add msg before passing on + // + s = new CMSSignedData(msg, s.getEncoded()); + // + // compute expected content digest + // + + verifySignatures(s, md.digest("Hello world!".getBytes())); + verifyRSASignatures(s, md.digest("Hello world!".getBytes())); + } + + public void testLwSHA1WithRSAAndAttributeTable() + throws Exception + { + MessageDigest md = MessageDigest.getInstance("SHA1", BC); + List certList = new ArrayList(); + CMSTypedData msg = new CMSProcessableByteArray("Hello world!".getBytes()); + + certList.add(_origCert); + certList.add(_signCert); + + Store certs = new JcaCertStore(certList); + + CMSSignedDataGenerator gen = new CMSSignedDataGenerator(); + + Attribute attr = new Attribute(CMSAttributes.messageDigest, + new DERSet( + new DEROctetString( + md.digest("Hello world!".getBytes())))); + + ASN1EncodableVector v = new ASN1EncodableVector(); + + v.add(attr); + + AsymmetricKeyParameter privKey = PrivateKeyFactory.createKey(_origKP.getPrivate().getEncoded()); + + AlgorithmIdentifier sigAlgId = new DefaultSignatureAlgorithmIdentifierFinder().find("SHA1withRSA"); + AlgorithmIdentifier digAlgId = new DefaultDigestAlgorithmIdentifierFinder().find(sigAlgId); + + BcContentSignerBuilder contentSignerBuilder = new BcRSAContentSignerBuilder(sigAlgId, digAlgId); + + gen.addSignerInfoGenerator( + new SignerInfoGeneratorBuilder(new BcDigestCalculatorProvider()) + .setSignedAttributeGenerator(new DefaultSignedAttributeTableGenerator(new AttributeTable(v))) + .build(contentSignerBuilder.build(privKey), new JcaX509CertificateHolder(_origCert))); + + gen.addCertificates(certs); + + CMSSignedData s = gen.generate(new CMSAbsentContent(), false); + + // + // the signature is detached, so need to add msg before passing on + // + s = new CMSSignedData(msg, s.getEncoded()); + // + // compute expected content digest + // + + verifySignatures(s, md.digest("Hello world!".getBytes())); + verifyRSASignatures(s, md.digest("Hello world!".getBytes())); + } + + public void testSHA1WithRSAEncapsulated() + throws Exception + { + encapsulatedTest(_signKP, _signCert, "SHA1withRSA"); + } + + public void testSHA1WithRSAEncapsulatedSubjectKeyID() + throws Exception + { + subjectKeyIDTest(_signKP, _signCert, "SHA1withRSA"); + } + + public void testSHA1WithRSAPSS() + throws Exception + { + rsaPSSTest("SHA1withRSAandMGF1"); + } + + public void testSHA224WithRSAPSS() + throws Exception + { + rsaPSSTest("SHA224withRSAandMGF1"); + } + + public void testSHA256WithRSAPSS() + throws Exception + { + rsaPSSTest("SHA256withRSAandMGF1"); + } + + public void testSHA384WithRSAPSS() + throws Exception + { + rsaPSSTest("SHA384withRSAandMGF1"); + } + + public void testSHA224WithRSAEncapsulated() + throws Exception + { + encapsulatedTest(_signKP, _signCert, "SHA224withRSA"); + } + + public void testSHA256WithRSAEncapsulated() + throws Exception + { + encapsulatedTest(_signKP, _signCert, "SHA256withRSA"); + } + + public void testRIPEMD128WithRSAEncapsulated() + throws Exception + { + encapsulatedTest(_signKP, _signCert, "RIPEMD128withRSA"); + } + + public void testRIPEMD160WithRSAEncapsulated() + throws Exception + { + encapsulatedTest(_signKP, _signCert, "RIPEMD160withRSA"); + } + + public void testRIPEMD256WithRSAEncapsulated() + throws Exception + { + encapsulatedTest(_signKP, _signCert, "RIPEMD256withRSA"); + } + + public void testECDSAEncapsulated() + throws Exception + { + encapsulatedTest(_signEcDsaKP, _signEcDsaCert, "SHA1withECDSA"); + } + + public void testECDSAEncapsulatedSubjectKeyID() + throws Exception + { + subjectKeyIDTest(_signEcDsaKP, _signEcDsaCert, "SHA1withECDSA"); + } + + public void testECDSASHA224Encapsulated() + throws Exception + { + encapsulatedTest(_signEcDsaKP, _signEcDsaCert, "SHA224withECDSA"); + } + + public void testECDSASHA256Encapsulated() + throws Exception + { + encapsulatedTest(_signEcDsaKP, _signEcDsaCert, "SHA256withECDSA"); + } + + public void testECDSASHA384Encapsulated() + throws Exception + { + encapsulatedTest(_signEcDsaKP, _signEcDsaCert, "SHA384withECDSA"); + } + + public void testECDSASHA512Encapsulated() + throws Exception + { + encapsulatedTest(_signEcDsaKP, _signEcDsaCert, "SHA512withECDSA"); + } + + public void testECDSASHA512EncapsulatedWithKeyFactoryAsEC() + throws Exception + { + X509EncodedKeySpec pubSpec = new X509EncodedKeySpec(_signEcDsaKP.getPublic().getEncoded()); + PKCS8EncodedKeySpec privSpec = new PKCS8EncodedKeySpec(_signEcDsaKP.getPrivate().getEncoded()); + KeyFactory keyFact = KeyFactory.getInstance("EC", BC); + KeyPair kp = new KeyPair(keyFact.generatePublic(pubSpec), keyFact.generatePrivate(privSpec)); + + encapsulatedTest(kp, _signEcDsaCert, "SHA512withECDSA"); + } + + public void testDSAEncapsulated() + throws Exception + { + encapsulatedTest(_signDsaKP, _signDsaCert, "SHA1withDSA"); + } + + public void testDSAEncapsulatedSubjectKeyID() + throws Exception + { + subjectKeyIDTest(_signDsaKP, _signDsaCert, "SHA1withDSA"); + } + + public void testGOST3411WithGOST3410Encapsulated() + throws Exception + { + encapsulatedTest(_signGostKP, _signGostCert, "GOST3411withGOST3410"); + } + + public void testGOST3411WithECGOST3410Encapsulated() + throws Exception + { + encapsulatedTest(_signEcGostKP, _signEcGostCert, "GOST3411withECGOST3410"); + } + + public void testGostNoAttributesEncapsulated() + throws Exception + { + CMSSignedData data = new CMSSignedData(rawGost); + + Store certStore = data.getCertificates(); + SignerInformationStore signers = data.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(); + + assertEquals(true, signer.verify(new JcaSimpleSignerInfoVerifierBuilder().setProvider("SC").build(cert))); + } + } + + public void testSHA1WithRSACounterSignature() + throws Exception + { + List certList = new ArrayList(); + List crlList = new ArrayList(); + CMSTypedData msg = new CMSProcessableByteArray("Hello World!".getBytes()); + + certList.add(_signCert); + certList.add(_origCert); + + crlList.add(_signCrl); + + Store certStore = new JcaCertStore(certList); + Store crlStore = new JcaCRLStore(crlList); + + CMSSignedDataGenerator gen = new CMSSignedDataGenerator(); + + ContentSigner sha1Signer = new JcaContentSignerBuilder("SHA1withRSA").setProvider(BC).build(_signKP.getPrivate()); + + gen.addSignerInfoGenerator(new JcaSignerInfoGeneratorBuilder(new JcaDigestCalculatorProviderBuilder().setProvider(BC).build()).build(sha1Signer, _signCert)); + + gen.addCertificates(certStore); + gen.addCRLs(crlStore); + + CMSSignedData s = gen.generate(msg, true); + SignerInformation origSigner = (SignerInformation)s.getSignerInfos().getSigners().toArray()[0]; + SignerInformationStore counterSigners1 = gen.generateCounterSigners(origSigner); + SignerInformationStore counterSigners2 = gen.generateCounterSigners(origSigner); + + SignerInformation signer1 = SignerInformation.addCounterSigners(origSigner, counterSigners1); + SignerInformation signer2 = SignerInformation.addCounterSigners(signer1, counterSigners2); + + SignerInformationStore cs = signer2.getCounterSignatures(); + Collection csSigners = cs.getSigners(); + assertEquals(2, csSigners.size()); + + Iterator it = csSigners.iterator(); + while (it.hasNext()) + { + SignerInformation cSigner = (SignerInformation)it.next(); + Collection certCollection = certStore.getMatches(cSigner.getSID()); + + Iterator certIt = certCollection.iterator(); + X509CertificateHolder cert = (X509CertificateHolder)certIt.next(); + + assertTrue(cSigner.isCounterSignature()); + assertNull(cSigner.getSignedAttributes().get(PKCSObjectIdentifiers.pkcs_9_at_contentType)); + assertEquals(true, cSigner.verify(new JcaSimpleSignerInfoVerifierBuilder().setProvider(BC).build(cert))); + } + } + + public void testSHA1WithRSACounterSignatureAndVerifierProvider() + throws Exception + { + List certList = new ArrayList(); + List crlList = new ArrayList(); + CMSTypedData msg = new CMSProcessableByteArray("Hello World!".getBytes()); + + certList.add(_signCert); + certList.add(_origCert); + + crlList.add(_signCrl); + + Store certStore = new JcaCertStore(certList); + Store crlStore = new JcaCRLStore(crlList); + + CMSSignedDataGenerator gen = new CMSSignedDataGenerator(); + + ContentSigner sha1Signer = new JcaContentSignerBuilder("SHA1withRSA").setProvider(BC).build(_signKP.getPrivate()); + + gen.addSignerInfoGenerator(new JcaSignerInfoGeneratorBuilder(new JcaDigestCalculatorProviderBuilder().setProvider(BC).build()).build(sha1Signer, _signCert)); + + gen.addCertificates(certStore); + gen.addCRLs(crlStore); + + CMSSignedData s = gen.generate(msg, true); + + SignerInformationVerifierProvider vProv = new SignerInformationVerifierProvider() + { + public SignerInformationVerifier get(SignerId signerId) + throws OperatorCreationException + { + return new JcaSimpleSignerInfoVerifierBuilder().setProvider(BC).build(_signCert); + } + }; + + assertTrue(s.verifySignatures(vProv)); + + SignerInformation origSigner = (SignerInformation)s.getSignerInfos().getSigners().toArray()[0]; + + gen = new CMSSignedDataGenerator(); + + sha1Signer = new JcaContentSignerBuilder("SHA1withRSA").setProvider(BC).build(_origKP.getPrivate()); + + gen.addSignerInfoGenerator(new JcaSignerInfoGeneratorBuilder(new JcaDigestCalculatorProviderBuilder().setProvider(BC).build()).build(sha1Signer, _origCert)); + + SignerInformationStore counterSigners = gen.generateCounterSigners(origSigner); + + SignerInformation signer1 = SignerInformation.addCounterSigners(origSigner, counterSigners); + + List signers = new ArrayList(); + + signers.add(signer1); + + s = CMSSignedData.replaceSigners(s, new SignerInformationStore(signers)); + + assertTrue(s.verifySignatures(vProv, true)); + + // provider can't handle counter sig + assertFalse(s.verifySignatures(vProv, false)); + + vProv = new SignerInformationVerifierProvider() + { + public SignerInformationVerifier get(SignerId signerId) + throws OperatorCreationException + { + if (_signCert.getSerialNumber().equals(signerId.getSerialNumber())) + { + return new JcaSimpleSignerInfoVerifierBuilder().setProvider(BC).build(_signCert); + } + else + { + return new JcaSimpleSignerInfoVerifierBuilder().setProvider(BC).build(_origCert); + } + } + }; + + // verify sig and counter sig. + assertFalse(s.verifySignatures(vProv, false)); + } + + private void rsaPSSTest(String signatureAlgorithmName) + throws Exception + { + List certList = new ArrayList(); + CMSTypedData msg = new CMSProcessableByteArray("Hello world!".getBytes()); + + certList.add(_origCert); + certList.add(_signCert); + + Store certs = new JcaCertStore(certList); + + CMSSignedDataGenerator gen = new CMSSignedDataGenerator(); + + ContentSigner contentSigner = new JcaContentSignerBuilder(signatureAlgorithmName).setProvider(BC).build(_origKP.getPrivate()); + + JcaSignerInfoGeneratorBuilder siBuilder = new JcaSignerInfoGeneratorBuilder(new JcaDigestCalculatorProviderBuilder().setProvider(BC).build()); + + siBuilder.setDirectSignature(true); + + gen.addSignerInfoGenerator(siBuilder.build(contentSigner, _origCert)); + + gen.addCertificates(certs); + + CMSSignedData s = gen.generate(msg, false); + + // + // compute expected content digest + // + String digestName = signatureAlgorithmName.substring(0, signatureAlgorithmName.indexOf('w')); + MessageDigest md = MessageDigest.getInstance(digestName, BC); + + verifySignatures(s, md.digest("Hello world!".getBytes())); + } + + private void subjectKeyIDTest( + KeyPair signaturePair, + X509Certificate signatureCert, + String signatureAlgorithm) + throws Exception + { + List certList = new ArrayList(); + List crlList = new ArrayList(); + CMSTypedData msg = new CMSProcessableByteArray("Hello World!".getBytes()); + + certList.add(signatureCert); + certList.add(_origCert); + + crlList.add(_signCrl); + + Store certStore = new JcaCertStore(certList); + Store crlStore = new JcaCRLStore(crlList); + + CMSSignedDataGenerator gen = new CMSSignedDataGenerator(); + + ContentSigner contentSigner = new JcaContentSignerBuilder(signatureAlgorithm).setProvider(BC).build(signaturePair.getPrivate()); + + gen.addSignerInfoGenerator(new JcaSignerInfoGeneratorBuilder(new JcaDigestCalculatorProviderBuilder().setProvider(BC).build()).build(contentSigner, CMSTestUtil.createSubjectKeyId(signatureCert.getPublicKey()).getKeyIdentifier())); + + gen.addCertificates(certStore); + gen.addCRLs(crlStore); + + CMSSignedData s = gen.generate(msg, true); + + assertEquals(3, s.getVersion()); + + ByteArrayInputStream bIn = new ByteArrayInputStream(s.getEncoded()); + ASN1InputStream aIn = new ASN1InputStream(bIn); + + s = new CMSSignedData(ContentInfo.getInstance(aIn.readObject())); + + 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(); + + assertEquals(true, signer.verify(new JcaSimpleSignerInfoVerifierBuilder().setProvider(BC).build(cert))); + } + + // + // check for CRLs + // + Collection crls = crlStore.getMatches(null); + + assertEquals(1, crls.size()); + + assertTrue(crls.contains(new JcaX509CRLHolder(_signCrl))); + + // + // try using existing signer + // + + gen = new CMSSignedDataGenerator(); + + gen.addSigners(s.getSignerInfos()); + + gen.addCertificates(s.getCertificates()); + + s = gen.generate(msg, true); + + bIn = new ByteArrayInputStream(s.getEncoded()); + aIn = new ASN1InputStream(bIn); + + s = new CMSSignedData(ContentInfo.getInstance(aIn.readObject())); + + certStore = s.getCertificates(); + + signers = s.getSignerInfos(); + c = signers.getSigners(); + 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(); + + assertEquals(true, signer.verify(new JcaSimpleSignerInfoVerifierBuilder().setProvider(BC).build(cert))); + } + + checkSignerStoreReplacement(s, signers); + } + + private void encapsulatedTest( + KeyPair signaturePair, + X509Certificate signatureCert, + String signatureAlgorithm) + throws Exception + { + List certList = new ArrayList(); + List crlList = new ArrayList(); + CMSTypedData msg = new CMSProcessableByteArray("Hello World!".getBytes()); + + certList.add(signatureCert); + certList.add(_origCert); + + crlList.add(_signCrl); + + Store certs = new JcaCertStore(certList); + Store crlStore = new JcaCRLStore(crlList); + + CMSSignedDataGenerator gen = new CMSSignedDataGenerator(); + + ContentSigner contentSigner = new JcaContentSignerBuilder(signatureAlgorithm).setProvider(BC).build(signaturePair.getPrivate()); + + gen.addSignerInfoGenerator(new JcaSignerInfoGeneratorBuilder(new JcaDigestCalculatorProviderBuilder().setProvider(BC).build()).build(contentSigner, signatureCert)); + + gen.addCertificates(certs); + + CMSSignedData s = gen.generate(msg, true); + + ByteArrayInputStream bIn = new ByteArrayInputStream(s.getEncoded()); + ASN1InputStream aIn = new ASN1InputStream(bIn); + + s = new CMSSignedData(ContentInfo.getInstance(aIn.readObject())); + + certs = s.getCertificates(); + + SignerInformationStore signers = s.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(); + + assertEquals(true, signer.verify(new JcaSimpleSignerInfoVerifierBuilder().setProvider(BC).build(cert))); + } + + // + // check signer information lookup + // + + SignerId sid = new JcaSignerId(signatureCert); + + Collection collection = signers.getSigners(sid); + + assertEquals(1, collection.size()); + assertTrue(collection.iterator().next() instanceof SignerInformation); + + // + // check for CRLs + // + Collection crls = crlStore.getMatches(null); + + assertEquals(1, crls.size()); + + assertTrue(crls.contains(new JcaX509CRLHolder(_signCrl))); + + // + // try using existing signer + // + + gen = new CMSSignedDataGenerator(); + + gen.addSigners(s.getSignerInfos()); + + gen.addCertificates(s.getCertificates()); + + s = gen.generate(msg, true); + + bIn = new ByteArrayInputStream(s.getEncoded()); + aIn = new ASN1InputStream(bIn); + + s = new CMSSignedData(ContentInfo.getInstance(aIn.readObject())); + + certs = s.getCertificates(); + + signers = s.getSignerInfos(); + c = signers.getSigners(); + 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(); + + assertEquals(true, signer.verify(new JcaSimpleSignerInfoVerifierBuilder().setProvider(BC).build(cert))); + } + + checkSignerStoreReplacement(s, signers); + } + + // + // signerInformation store replacement test. + // + private void checkSignerStoreReplacement( + CMSSignedData orig, + SignerInformationStore signers) + throws Exception + { + CMSSignedData s = CMSSignedData.replaceSigners(orig, signers); + + Store certs = s.getCertificates(); + + signers = s.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(); + + assertEquals(true, signer.verify(new JcaSimpleSignerInfoVerifierBuilder().setProvider(BC).build(cert))); + } + } + + public void testUnsortedAttributes() + throws Exception + { + CMSSignedData s = new CMSSignedData(new CMSProcessableByteArray(disorderedMessage), disorderedSet); + + Store certs = s.getCertificates(); + + SignerInformationStore signers = s.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(); + + assertEquals(true, signer.verify(new JcaSimpleSignerInfoVerifierBuilder().setProvider(BC).build(cert))); + } + } + + public void testNullContentWithSigner() + throws Exception + { + List certList = new ArrayList(); + + certList.add(_origCert); + certList.add(_signCert); + + Store certs = new JcaCertStore(certList); + + CMSSignedDataGenerator gen = new CMSSignedDataGenerator(); + + ContentSigner sha1Signer = new JcaContentSignerBuilder("SHA1withRSA").setProvider(BC).build(_origKP.getPrivate()); + + gen.addSignerInfoGenerator(new JcaSignerInfoGeneratorBuilder(new JcaDigestCalculatorProviderBuilder().setProvider(BC).build()).build(sha1Signer, _origCert)); + + gen.addCertificates(certs); + + CMSSignedData s = gen.generate(new CMSAbsentContent(), false); + + ByteArrayInputStream bIn = new ByteArrayInputStream(s.getEncoded()); + ASN1InputStream aIn = new ASN1InputStream(bIn); + + s = new CMSSignedData(ContentInfo.getInstance(aIn.readObject())); + + verifySignatures(s); + } + + public void testWithAttributeCertificate() + throws Exception + { + List certList = new ArrayList(); + CMSTypedData msg = new CMSProcessableByteArray("Hello World!".getBytes()); + + + certList.add(_signDsaCert); + + Store certs = new JcaCertStore(certList); + + CMSSignedDataGenerator gen = new CMSSignedDataGenerator(); + + JcaSignerInfoGeneratorBuilder builder = new JcaSignerInfoGeneratorBuilder(new JcaDigestCalculatorProviderBuilder().setProvider(BC).build()); + ContentSigner sha1Signer = new JcaContentSignerBuilder("SHA1withRSA").setProvider(BC).build(_origKP.getPrivate()); + + gen.addSignerInfoGenerator(builder.build(sha1Signer, _origCert)); + + gen.addCertificates(certs); + + X509AttributeCertificateHolder attrCert = CMSTestUtil.getAttributeCertificate(); + List attrList = new ArrayList(); + + attrList.add(new X509AttributeCertificateHolder(attrCert.getEncoded())); + + Store store = new CollectionStore(attrList); + + gen.addAttributeCertificates(store); + + CMSSignedData sd = gen.generate(msg); + + assertEquals(4, sd.getVersion()); + + store = sd.getAttributeCertificates(); + + Collection coll = store.getMatches(null); + + assertEquals(1, coll.size()); + + assertTrue(coll.contains(new X509AttributeCertificateHolder(attrCert.getEncoded()))); + + // + // create new certstore + // + certList = new ArrayList(); + certList.add(_origCert); + certList.add(_signCert); + + certs = new JcaCertStore(certList); + + + // + // replace certs + // + sd = CMSSignedData.replaceCertificatesAndCRLs(sd, certs, null, null); + + verifySignatures(sd); + } + + public void testCertStoreReplacement() + throws Exception + { + List certList = new ArrayList(); + CMSTypedData msg = new CMSProcessableByteArray("Hello World!".getBytes()); + + + certList.add(_signDsaCert); + + Store certs = new JcaCertStore(certList); + + CMSSignedDataGenerator gen = new CMSSignedDataGenerator(); + + ContentSigner sha1Signer = new JcaContentSignerBuilder("SHA1withRSA").setProvider(BC).build(_origKP.getPrivate()); + + gen.addSignerInfoGenerator(new JcaSignerInfoGeneratorBuilder(new JcaDigestCalculatorProviderBuilder().setProvider(BC).build()).build(sha1Signer, _origCert)); + + gen.addCertificates(certs); + + CMSSignedData sd = gen.generate(msg); + + // + // create new certstore + // + certList = new ArrayList(); + certList.add(_origCert); + certList.add(_signCert); + + certs = new JcaCertStore(certList); + + // + // replace certs + // + sd = CMSSignedData.replaceCertificatesAndCRLs(sd, certs, null, null); + + verifySignatures(sd); + } + + public void testEncapsulatedCertStoreReplacement() + throws Exception + { + List certList = new ArrayList(); + CMSTypedData msg = new CMSProcessableByteArray("Hello World!".getBytes()); + + + certList.add(_signDsaCert); + + Store certs = new JcaCertStore(certList); + + CMSSignedDataGenerator gen = new CMSSignedDataGenerator(); + ContentSigner sha1Signer = new JcaContentSignerBuilder("SHA1withRSA").setProvider(BC).build(_origKP.getPrivate()); + + gen.addSignerInfoGenerator(new JcaSignerInfoGeneratorBuilder(new JcaDigestCalculatorProviderBuilder().setProvider(BC).build()).build(sha1Signer, _origCert)); + + gen.addCertificates(certs); + + CMSSignedData sd = gen.generate(msg, true); + + // + // create new certstore + // + certList = new ArrayList(); + certList.add(_origCert); + certList.add(_signCert); + + certs = new JcaCertStore(certList); + + + // + // replace certs + // + sd = CMSSignedData.replaceCertificatesAndCRLs(sd, certs, null, null); + + verifySignatures(sd); + } + + public void testCertOrdering1() + throws Exception + { + List certList = new ArrayList(); + CMSTypedData msg = new CMSProcessableByteArray("Hello World!".getBytes()); + + certList.add(_origCert); + certList.add(_signCert); + certList.add(_signDsaCert); + + Store certs = new JcaCertStore(certList); + + CMSSignedDataGenerator gen = new CMSSignedDataGenerator(); + + ContentSigner sha1Signer = new JcaContentSignerBuilder("SHA1withRSA").setProvider(BC).build(_origKP.getPrivate()); + + gen.addSignerInfoGenerator(new JcaSignerInfoGeneratorBuilder(new JcaDigestCalculatorProviderBuilder().setProvider(BC).build()).build(sha1Signer, _origCert)); + + gen.addCertificates(certs); + + CMSSignedData sd = gen.generate(msg, true); + + certs = sd.getCertificates(); + Iterator it = certs.getMatches(null).iterator(); + + assertEquals(new JcaX509CertificateHolder(_origCert), it.next()); + assertEquals(new JcaX509CertificateHolder(_signCert), it.next()); + assertEquals(new JcaX509CertificateHolder(_signDsaCert), it.next()); + } + + public void testCertOrdering2() + throws Exception + { + List certList = new ArrayList(); + CMSTypedData msg = new CMSProcessableByteArray("Hello World!".getBytes()); + + certList.add(_signCert); + certList.add(_signDsaCert); + certList.add(_origCert); + + Store certs = new JcaCertStore(certList); + + CMSSignedDataGenerator gen = new CMSSignedDataGenerator(); + + ContentSigner sha1Signer = new JcaContentSignerBuilder("SHA1withRSA").setProvider(BC).build(_origKP.getPrivate()); + + gen.addSignerInfoGenerator(new JcaSignerInfoGeneratorBuilder(new JcaDigestCalculatorProviderBuilder().setProvider(BC).build()).build(sha1Signer, _origCert)); + + gen.addCertificates(certs); + + CMSSignedData sd = gen.generate(msg, true); + + certs = sd.getCertificates(); + Iterator it = certs.getMatches(null).iterator(); + + assertEquals(new JcaX509CertificateHolder(_signCert), it.next()); + assertEquals(new JcaX509CertificateHolder(_signDsaCert), it.next()); + assertEquals(new JcaX509CertificateHolder(_origCert), it.next()); + } + + public void testSignerStoreReplacement() + throws Exception + { + List certList = new ArrayList(); + CMSTypedData msg = new CMSProcessableByteArray("Hello World!".getBytes()); + + certList.add(_origCert); + certList.add(_signCert); + + Store certs = new JcaCertStore(certList); + + CMSSignedDataGenerator gen = new CMSSignedDataGenerator(); + + ContentSigner sha1Signer = new JcaContentSignerBuilder("SHA1withRSA").setProvider(BC).build(_origKP.getPrivate()); + + gen.addSignerInfoGenerator(new JcaSignerInfoGeneratorBuilder(new JcaDigestCalculatorProviderBuilder().setProvider(BC).build()).build(sha1Signer, _origCert)); + + gen.addCertificates(certs); + + CMSSignedData original = gen.generate(msg, true); + + // + // create new Signer + // + gen = new CMSSignedDataGenerator(); + + ContentSigner sha224Signer = new JcaContentSignerBuilder("SHA224withRSA").setProvider(BC).build(_origKP.getPrivate()); + + gen.addSignerInfoGenerator(new JcaSignerInfoGeneratorBuilder(new JcaDigestCalculatorProviderBuilder().setProvider(BC).build()).build(sha224Signer, _origCert)); + + gen.addCertificates(certs); + + CMSSignedData newSD = gen.generate(msg, true); + + // + // replace signer + // + CMSSignedData sd = CMSSignedData.replaceSigners(original, newSD.getSignerInfos()); + + SignerInformation signer = (SignerInformation)sd.getSignerInfos().getSigners().iterator().next(); + + assertEquals(CMSAlgorithm.SHA224.getId(), signer.getDigestAlgOID()); + + // we use a parser here as it requires the digests to be correct in the digest set, if it + // isn't we'll get a NullPointerException + CMSSignedDataParser sp = new CMSSignedDataParser(new JcaDigestCalculatorProviderBuilder().setProvider(BC).build(), sd.getEncoded()); + + sp.getSignedContent().drain(); + + verifySignatures(sp); + } + + public void testEncapsulatedSamples() + throws Exception + { + testSample("PSSSignDataSHA1Enc.sig"); + testSample("PSSSignDataSHA256Enc.sig"); + testSample("PSSSignDataSHA512Enc.sig"); + } + + public void testSamples() + throws Exception + { + testSample("PSSSignData.data", "PSSSignDataSHA1.sig"); + testSample("PSSSignData.data", "PSSSignDataSHA256.sig"); + testSample("PSSSignData.data", "PSSSignDataSHA512.sig"); + } + + public void testNoAttrEncapsulatedSample() + throws Exception + { + CMSSignedData s = new CMSSignedData(noAttrEncData); + + Store certStore = s.getCertificates(); + + assertNotNull(certStore); + + SignerInformationStore signers = s.getSignerInfos(); + + assertNotNull(signers); + + 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(); + + if (!signer.verify(new JcaSimpleSignerInfoVerifierBuilder().setProvider(BC).build(cert))) + { + fail("Verification FAILED! "); + } + } + } + + public void testCounterSig() + throws Exception + { + CMSSignedData sig = new CMSSignedData(getInput("counterSig.p7m")); + + SignerInformationStore ss = sig.getSignerInfos(); + Collection signers = ss.getSigners(); + + SignerInformationStore cs = ((SignerInformation)signers.iterator().next()).getCounterSignatures(); + Collection csSigners = cs.getSigners(); + assertEquals(1, csSigners.size()); + + Iterator it = csSigners.iterator(); + while (it.hasNext()) + { + SignerInformation cSigner = (SignerInformation)it.next(); + Collection certCollection = sig.getCertificates().getMatches(cSigner.getSID()); + + Iterator certIt = certCollection.iterator(); + X509CertificateHolder cert = (X509CertificateHolder)certIt.next(); + + assertTrue(cSigner.isCounterSignature()); + assertNull(cSigner.getSignedAttributes().get(PKCSObjectIdentifiers.pkcs_9_at_contentType)); + assertEquals(true, cSigner.verify(new JcaSimpleSignerInfoVerifierBuilder().setProvider(BC).build(cert))); + } + + verifySignatures(sig); + } + + public void testCertificateManagement() + throws Exception + { + CMSSignedDataGenerator sGen = new CMSSignedDataGenerator(); + + List certList = new ArrayList(); + + certList.add(_origCert); + certList.add(_signCert); + + Store certs = new JcaCertStore(certList); + + sGen.addCertificates(certs); + + CMSSignedData sData = sGen.generate(new CMSAbsentContent(), true); + + CMSSignedData rsData = new CMSSignedData(sData.getEncoded()); + + assertEquals(2, rsData.getCertificates().getMatches(null).size()); + } + + private void testSample(String sigName) + throws Exception + { + CMSSignedData sig = new CMSSignedData(getInput(sigName)); + + verifySignatures(sig); + } + + private void testSample(String messageName, String sigName) + throws Exception + { + CMSSignedData sig = new CMSSignedData(new CMSProcessableByteArray(getInput(messageName)), getInput(sigName)); + + verifySignatures(sig); + } + + private byte[] getInput(String name) + throws IOException + { + return Streams.readAll(getClass().getResourceAsStream(name)); + } + + public void testForMultipleCounterSignatures() + throws Exception + { + CMSSignedData sd = new CMSSignedData(xtraCounterSig); + + for (Iterator sI = sd.getSignerInfos().getSigners().iterator(); sI.hasNext();) + { + SignerInformation sigI = (SignerInformation)sI.next(); + + SignerInformationStore counter = sigI.getCounterSignatures(); + List sigs = new ArrayList(counter.getSigners()); + + assertEquals(2, sigs.size()); + } + } + + private void verifySignatures(CMSSignedDataParser sp) + throws Exception + { + 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(); + + assertEquals(true, signer.verify(new JcaSimpleSignerInfoVerifierBuilder().setProvider(BC).build(cert))); + } + } + + private class TestCMSSignatureAlgorithmNameGenerator + extends DefaultCMSSignatureAlgorithmNameGenerator + { + void setDigestAlgorithmMapping(ASN1ObjectIdentifier oid, String algName) + { + super.setSigningDigestAlgorithmMapping(oid, algName); + } + + void setEncryptionAlgorithmMapping(ASN1ObjectIdentifier oid, String algName) + { + super.setSigningEncryptionAlgorithmMapping(oid, algName); + } + } +} diff --git a/pkix/src/test/java/org/spongycastle/cms/test/NullProviderTest.java b/pkix/src/test/java/org/spongycastle/cms/test/NullProviderTest.java new file mode 100644 index 00000000..640f3f59 --- /dev/null +++ b/pkix/src/test/java/org/spongycastle/cms/test/NullProviderTest.java @@ -0,0 +1,281 @@ +package org.spongycastle.cms.test; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.OutputStream; +import java.math.BigInteger; +import java.security.GeneralSecurityException; +import java.security.KeyPair; +import java.security.KeyPairGenerator; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import java.security.NoSuchProviderException; +import java.security.PrivateKey; +import java.security.PublicKey; +import java.security.SecureRandom; +import java.security.cert.X509Certificate; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.Date; +import java.util.Iterator; +import java.util.List; + +import junit.framework.Test; +import junit.framework.TestCase; +import junit.framework.TestSuite; +import org.spongycastle.asn1.ASN1InputStream; +import org.spongycastle.asn1.ASN1ObjectIdentifier; +import org.spongycastle.asn1.cms.ContentInfo; +import org.spongycastle.asn1.pkcs.PKCSObjectIdentifiers; +import org.spongycastle.asn1.x509.X509Name; +import org.spongycastle.cert.X509CertificateHolder; +import org.spongycastle.cms.CMSEnvelopedData; +import org.spongycastle.cms.CMSEnvelopedDataGenerator; +import org.spongycastle.cms.CMSProcessableByteArray; +import org.spongycastle.cms.CMSSignedData; +import org.spongycastle.cms.CMSSignedDataGenerator; +import org.spongycastle.cms.CMSSignedDataParser; +import org.spongycastle.cms.CMSSignedDataStreamGenerator; +import org.spongycastle.cms.CMSTypedData; +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.JcaSignerInfoGeneratorBuilder; +import org.spongycastle.cms.jcajce.JcaSimpleSignerInfoVerifierBuilder; +import org.spongycastle.cms.jcajce.JcaX509CertSelectorConverter; +import org.spongycastle.cms.jcajce.JceCMSContentEncryptorBuilder; +import org.spongycastle.cms.jcajce.JceKeyTransEnvelopedRecipient; +import org.spongycastle.cms.jcajce.JceKeyTransRecipientInfoGenerator; +import org.spongycastle.operator.DigestCalculatorProvider; +import org.spongycastle.operator.jcajce.JcaContentSignerBuilder; +import org.spongycastle.operator.jcajce.JcaDigestCalculatorProviderBuilder; +import org.spongycastle.util.CollectionStore; +import org.spongycastle.util.Store; +import org.spongycastle.x509.X509V3CertificateGenerator; + +public class NullProviderTest + extends TestCase +{ + static KeyPair keyPair; + static X509Certificate keyCert; + private static final String TEST_MESSAGE = "Hello World!"; + + private JcaX509CertSelectorConverter selectorConverter = new JcaX509CertSelectorConverter(); + + static + { + try + { + keyPair = generateKeyPair(); + String origDN = "O=Bouncy Castle, C=AU"; + keyCert = makeCertificate(keyPair, origDN, keyPair, origDN); + } + catch (Exception e) + { + throw new RuntimeException(e); + } + } + + public void testSHA1WithRSAEncapsulated() + throws Exception + { + List certList = new ArrayList(); + CMSTypedData msg = new CMSProcessableByteArray(TEST_MESSAGE.getBytes()); + + certList.add(new X509CertificateHolder(keyCert.getEncoded())); + + DigestCalculatorProvider digCalcProv = new JcaDigestCalculatorProviderBuilder().build(); + + CMSSignedDataGenerator gen = new CMSSignedDataGenerator(); + + gen.addSignerInfoGenerator(new JcaSignerInfoGeneratorBuilder(digCalcProv).build(new JcaContentSignerBuilder("SHA1withRSA").build(keyPair.getPrivate()), keyCert)); + + gen.addCertificates(new CollectionStore(certList)); + + CMSSignedData s = gen.generate(msg, true); + + ByteArrayInputStream bIn = new ByteArrayInputStream(s.getEncoded()); + ASN1InputStream aIn = new ASN1InputStream(bIn); + + s = new CMSSignedData(ContentInfo.getInstance(aIn.readObject())); + + Store certsAndCrls = s.getCertificates(); + + SignerInformationStore signers = s.getSignerInfos(); + Collection c = signers.getSigners(); + Iterator it = c.iterator(); + + while (it.hasNext()) + { + SignerInformation signer = (SignerInformation)it.next(); + Collection certCollection = certsAndCrls.getMatches(signer.getSID()); + Iterator certIt = certCollection.iterator(); + X509CertificateHolder cert = (X509CertificateHolder)certIt.next(); + + assertEquals(true, signer.verify(new JcaSimpleSignerInfoVerifierBuilder().build(cert))); + } + } + + public void testSHA1WithRSAStream() + throws Exception + { + List certList = new ArrayList(); + ByteArrayOutputStream bOut = new ByteArrayOutputStream(); + + certList.add(new X509CertificateHolder(keyCert.getEncoded())); + + DigestCalculatorProvider digCalcProv = new JcaDigestCalculatorProviderBuilder().build(); + + CMSSignedDataStreamGenerator gen = new CMSSignedDataStreamGenerator(); + + gen.addSignerInfoGenerator(new JcaSignerInfoGeneratorBuilder(digCalcProv).build(new JcaContentSignerBuilder("SHA1withRSA").build(keyPair.getPrivate()), keyCert)); + + gen.addCertificates(new CollectionStore(certList)); + + OutputStream sigOut = gen.open(bOut); + + sigOut.write(TEST_MESSAGE.getBytes()); + + sigOut.close(); + + CMSSignedDataParser sp = new CMSSignedDataParser(digCalcProv, + new CMSTypedStream(new ByteArrayInputStream(TEST_MESSAGE.getBytes())), bOut.toByteArray()); + + sp.getSignedContent().drain(); + + // + // compute expected content digest + // + MessageDigest md = MessageDigest.getInstance("SHA1"); + + byte[] contentDigest = md.digest(TEST_MESSAGE.getBytes()); + Store certStore = sp.getCertificates(); + SignerInformationStore signers = sp.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(); + + assertEquals(true, signer.verify(new JcaSimpleSignerInfoVerifierBuilder().build(cert))); + + if (contentDigest != null) + { + assertTrue(MessageDigest.isEqual(contentDigest, signer.getContentDigest())); + } + } + } + + public void testKeyTransDES() + throws Exception + { + testKeyTrans(CMSEnvelopedDataGenerator.DES_EDE3_CBC); + } + + public void testKeyTransAES128() + throws Exception + { + testKeyTrans(CMSEnvelopedDataGenerator.AES128_CBC); + } + + public void testKeyTransAES192() + throws Exception + { + testKeyTrans(CMSEnvelopedDataGenerator.AES192_CBC); + } + + public void testKeyTransAES256() + throws Exception + { + testKeyTrans(CMSEnvelopedDataGenerator.AES256_CBC); + } + + private void testKeyTrans(String algorithm) + throws Exception + { + byte[] data = "WallaWallaWashington".getBytes(); + + CMSEnvelopedDataGenerator edGen = new CMSEnvelopedDataGenerator(); + + edGen.addRecipientInfoGenerator(new JceKeyTransRecipientInfoGenerator(keyCert)); + + CMSEnvelopedData ed = edGen.generate( + new CMSProcessableByteArray(data), + new JceCMSContentEncryptorBuilder(new ASN1ObjectIdentifier(algorithm)).build()); + + RecipientInformationStore recipients = ed.getRecipientInfos(); + + assertEquals(ed.getEncryptionAlgOID(), algorithm); + + Collection c = recipients.getRecipients(); + + assertEquals(1, c.size()); + + Iterator it = c.iterator(); + + while (it.hasNext()) + { + RecipientInformation recipient = (RecipientInformation)it.next(); + + assertEquals(recipient.getKeyEncryptionAlgOID(), PKCSObjectIdentifiers.rsaEncryption.getId()); + + byte[] recData = recipient.getContent(new JceKeyTransEnvelopedRecipient(keyPair.getPrivate())); + + assertEquals(true, Arrays.equals(data, recData)); + } + } + + private static KeyPair generateKeyPair() + throws NoSuchProviderException, NoSuchAlgorithmException + { + KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA", "SunRsaSign"); + + kpg.initialize(512, new SecureRandom()); + + return kpg.generateKeyPair(); + } + + private static X509Certificate makeCertificate(KeyPair subKP, String _subDN, KeyPair issKP, String _issDN) + throws GeneralSecurityException, IOException + { + + PublicKey subPub = subKP.getPublic(); + PrivateKey issPriv = issKP.getPrivate(); + PublicKey issPub = issKP.getPublic(); + + X509V3CertificateGenerator v3CertGen = new X509V3CertificateGenerator(); + + v3CertGen.reset(); + v3CertGen.setSerialNumber(BigInteger.valueOf(1)); + v3CertGen.setIssuerDN(new X509Name(_issDN)); + v3CertGen.setNotBefore(new Date(System.currentTimeMillis())); + v3CertGen.setNotAfter(new Date(System.currentTimeMillis() + (1000L * 60 * 60 * 24 * 100))); + v3CertGen.setSubjectDN(new X509Name(_subDN)); + v3CertGen.setPublicKey(subPub); + + v3CertGen.setSignatureAlgorithm("SHA1WithRSA"); + + X509Certificate _cert = v3CertGen.generate(issPriv, "SunRsaSign"); + + _cert.checkValidity(new Date()); + _cert.verify(issPub); + + return _cert; + } + + public static Test suite() + throws Exception + { + return new TestSuite(NullProviderTest.class); + } +} 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()); + } + } +} diff --git a/pkix/src/test/java/org/spongycastle/cms/test/SHA1DigestCalculator.java b/pkix/src/test/java/org/spongycastle/cms/test/SHA1DigestCalculator.java new file mode 100644 index 00000000..f3d5fd72 --- /dev/null +++ b/pkix/src/test/java/org/spongycastle/cms/test/SHA1DigestCalculator.java @@ -0,0 +1,44 @@ +package org.spongycastle.cms.test; + +import java.io.ByteArrayOutputStream; +import java.io.OutputStream; + +import org.spongycastle.asn1.oiw.OIWObjectIdentifiers; +import org.spongycastle.asn1.x509.AlgorithmIdentifier; +import org.spongycastle.crypto.Digest; +import org.spongycastle.crypto.digests.SHA1Digest; +import org.spongycastle.operator.DigestCalculator; + + +class SHA1DigestCalculator + implements DigestCalculator +{ + private ByteArrayOutputStream bOut = new ByteArrayOutputStream(); + + public AlgorithmIdentifier getAlgorithmIdentifier() + { + return new AlgorithmIdentifier(OIWObjectIdentifiers.idSHA1); + } + + public OutputStream getOutputStream() + { + return bOut; + } + + public byte[] getDigest() + { + byte[] bytes = bOut.toByteArray(); + + bOut.reset(); + + Digest sha1 = new SHA1Digest(); + + sha1.update(bytes, 0, bytes.length); + + byte[] digest = new byte[sha1.getDigestSize()]; + + sha1.doFinal(digest, 0); + + return digest; + } +} diff --git a/pkix/src/test/java/org/spongycastle/cms/test/SunProviderTest.java b/pkix/src/test/java/org/spongycastle/cms/test/SunProviderTest.java new file mode 100644 index 00000000..a92417c2 --- /dev/null +++ b/pkix/src/test/java/org/spongycastle/cms/test/SunProviderTest.java @@ -0,0 +1,284 @@ +package org.spongycastle.cms.test; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.OutputStream; +import java.math.BigInteger; +import java.security.GeneralSecurityException; +import java.security.KeyPair; +import java.security.KeyPairGenerator; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import java.security.NoSuchProviderException; +import java.security.PrivateKey; +import java.security.PublicKey; +import java.security.SecureRandom; +import java.security.cert.X509Certificate; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.Date; +import java.util.Iterator; +import java.util.List; + +import junit.framework.Test; +import junit.framework.TestCase; +import junit.framework.TestSuite; +import org.spongycastle.asn1.ASN1InputStream; +import org.spongycastle.asn1.ASN1ObjectIdentifier; +import org.spongycastle.asn1.cms.ContentInfo; +import org.spongycastle.asn1.pkcs.PKCSObjectIdentifiers; +import org.spongycastle.asn1.x509.X509Name; +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.CMSProcessableByteArray; +import org.spongycastle.cms.CMSSignedData; +import org.spongycastle.cms.CMSSignedDataGenerator; +import org.spongycastle.cms.CMSSignedDataParser; +import org.spongycastle.cms.CMSSignedDataStreamGenerator; +import org.spongycastle.cms.CMSTypedData; +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.JcaSignerInfoGeneratorBuilder; +import org.spongycastle.cms.jcajce.JcaSignerInfoVerifierBuilder; +import org.spongycastle.cms.jcajce.JcaSimpleSignerInfoVerifierBuilder; +import org.spongycastle.cms.jcajce.JcaX509CertSelectorConverter; +import org.spongycastle.cms.jcajce.JceCMSContentEncryptorBuilder; +import org.spongycastle.cms.jcajce.JceKeyTransEnvelopedRecipient; +import org.spongycastle.cms.jcajce.JceKeyTransRecipientInfoGenerator; +import org.spongycastle.operator.DigestCalculatorProvider; +import org.spongycastle.operator.jcajce.JcaContentSignerBuilder; +import org.spongycastle.operator.jcajce.JcaDigestCalculatorProviderBuilder; +import org.spongycastle.util.CollectionStore; +import org.spongycastle.util.Store; +import org.spongycastle.x509.X509V3CertificateGenerator; + +public class SunProviderTest + extends TestCase +{ + static KeyPair keyPair; + static X509Certificate keyCert; + private static final String TEST_MESSAGE = "Hello World!"; + private static final JcaX509CertSelectorConverter selectorConverter = new JcaX509CertSelectorConverter(); + + static + { + try + { + keyPair = generateKeyPair(); + String origDN = "O=Bouncy Castle, C=AU"; + keyCert = makeCertificate(keyPair, origDN, keyPair, origDN); + } + catch (Exception e) + { + throw new RuntimeException(e); + } + } + + public void testSHA1WithRSAEncapsulated() + throws Exception + { + List certList = new ArrayList(); + CMSTypedData msg = new CMSProcessableByteArray(TEST_MESSAGE.getBytes()); + + certList.add(new X509CertificateHolder(keyCert.getEncoded())); + + DigestCalculatorProvider digCalcProv = new JcaDigestCalculatorProviderBuilder().build(); + + CMSSignedDataGenerator gen = new CMSSignedDataGenerator(); + + gen.addSignerInfoGenerator(new JcaSignerInfoGeneratorBuilder(digCalcProv).build(new JcaContentSignerBuilder("SHA1withRSA").setProvider("SunRsaSign").build(keyPair.getPrivate()), keyCert)); + + gen.addCertificates(new CollectionStore(certList)); + + CMSSignedData s = gen.generate(msg, true); + + ByteArrayInputStream bIn = new ByteArrayInputStream(s.getEncoded()); + ASN1InputStream aIn = new ASN1InputStream(bIn); + + s = new CMSSignedData(ContentInfo.getInstance(aIn.readObject())); + + Store certsAndCrls = s.getCertificates(); + + SignerInformationStore signers = s.getSignerInfos(); + Collection c = signers.getSigners(); + Iterator it = c.iterator(); + + while (it.hasNext()) + { + SignerInformation signer = (SignerInformation)it.next(); + Collection certCollection = certsAndCrls.getMatches(signer.getSID()); + + Iterator certIt = certCollection.iterator(); + X509Certificate cert = new JcaX509CertificateConverter().getCertificate((X509CertificateHolder)certIt.next()); + + assertEquals(true, signer.verify(new JcaSignerInfoVerifierBuilder(new JcaDigestCalculatorProviderBuilder().build()).setProvider("SunRsaSign").build(cert))); + } + } + + public void testSHA1WithRSAStream() + throws Exception + { + List certList = new ArrayList(); + ByteArrayOutputStream bOut = new ByteArrayOutputStream(); + + certList.add(new X509CertificateHolder(keyCert.getEncoded())); + + DigestCalculatorProvider digCalcProv = new JcaDigestCalculatorProviderBuilder().build(); + + CMSSignedDataStreamGenerator gen = new CMSSignedDataStreamGenerator(); + + gen.addSignerInfoGenerator(new JcaSignerInfoGeneratorBuilder(digCalcProv).build(new JcaContentSignerBuilder("SHA1withRSA").setProvider("SunRsaSign").build(keyPair.getPrivate()), keyCert)); + + gen.addCertificates(new CollectionStore(certList)); + + OutputStream sigOut = gen.open(bOut); + + sigOut.write(TEST_MESSAGE.getBytes()); + + sigOut.close(); + + CMSSignedDataParser sp = new CMSSignedDataParser(digCalcProv, + new CMSTypedStream(new ByteArrayInputStream(TEST_MESSAGE.getBytes())), bOut.toByteArray()); + + sp.getSignedContent().drain(); + + // + // compute expected content digest + // + MessageDigest md = MessageDigest.getInstance("SHA1", "SUN"); + + byte[] contentDigest = md.digest(TEST_MESSAGE.getBytes()); + Store certStore = sp.getCertificates(); + SignerInformationStore signers = sp.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(); + + assertEquals(true, signer.verify(new JcaSimpleSignerInfoVerifierBuilder().setProvider("SunRsaSign").build(new JcaX509CertificateConverter().getCertificate(cert)))); + + if (contentDigest != null) + { + assertTrue(MessageDigest.isEqual(contentDigest, signer.getContentDigest())); + } + } + } + + public void testKeyTransDES() + throws Exception + { + testKeyTrans(CMSEnvelopedDataGenerator.DES_EDE3_CBC); + } + + public void testKeyTransAES128() + throws Exception + { + testKeyTrans(CMSEnvelopedDataGenerator.AES128_CBC); + } + + public void testKeyTransAES192() + throws Exception + { + testKeyTrans(CMSEnvelopedDataGenerator.AES192_CBC); + } + + public void testKeyTransAES256() + throws Exception + { + testKeyTrans(CMSEnvelopedDataGenerator.AES256_CBC); + } + + private void testKeyTrans(String algorithm) + throws Exception + { + byte[] data = "WallaWallaWashington".getBytes(); + + CMSEnvelopedDataGenerator edGen = new CMSEnvelopedDataGenerator(); + + edGen.addRecipientInfoGenerator(new JceKeyTransRecipientInfoGenerator(keyCert).setProvider("SunJCE")); + + CMSEnvelopedData ed = edGen.generate( + new CMSProcessableByteArray(data), + new JceCMSContentEncryptorBuilder(new ASN1ObjectIdentifier(algorithm)).setProvider("SunJCE").build()); + + RecipientInformationStore recipients = ed.getRecipientInfos(); + + + assertEquals(ed.getEncryptionAlgOID(), algorithm); + + Collection c = recipients.getRecipients(); + + assertEquals(1, c.size()); + + Iterator it = c.iterator(); + + while (it.hasNext()) + { + RecipientInformation recipient = (RecipientInformation)it.next(); + + assertEquals(recipient.getKeyEncryptionAlgOID(), PKCSObjectIdentifiers.rsaEncryption.getId()); + + byte[] recData = recipient.getContent(new JceKeyTransEnvelopedRecipient(keyPair.getPrivate()).setProvider("SunJCE")); + + assertEquals(true, Arrays.equals(data, recData)); + } + } + + private static KeyPair generateKeyPair() + throws NoSuchProviderException, NoSuchAlgorithmException + { + KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA", "SunRsaSign"); + + kpg.initialize(512, new SecureRandom()); + + return kpg.generateKeyPair(); + } + + private static X509Certificate makeCertificate(KeyPair subKP, String _subDN, KeyPair issKP, String _issDN) + throws GeneralSecurityException, IOException + { + + PublicKey subPub = subKP.getPublic(); + PrivateKey issPriv = issKP.getPrivate(); + PublicKey issPub = issKP.getPublic(); + + X509V3CertificateGenerator v3CertGen = new X509V3CertificateGenerator(); + + v3CertGen.reset(); + v3CertGen.setSerialNumber(BigInteger.valueOf(1)); + v3CertGen.setIssuerDN(new X509Name(_issDN)); + v3CertGen.setNotBefore(new Date(System.currentTimeMillis())); + v3CertGen.setNotAfter(new Date(System.currentTimeMillis() + (1000L * 60 * 60 * 24 * 100))); + v3CertGen.setSubjectDN(new X509Name(_subDN)); + v3CertGen.setPublicKey(subPub); + + v3CertGen.setSignatureAlgorithm("SHA1WithRSA"); + + X509Certificate _cert = v3CertGen.generate(issPriv, "SunRsaSign"); + + _cert.checkValidity(new Date()); + _cert.verify(issPub); + + return _cert; + } + + public static Test suite() + throws Exception + { + return new TestSuite(SunProviderTest.class); + } +} |