diff options
author | Sergio Giro <sgiro@google.com> | 2016-02-02 15:16:50 +0000 |
---|---|---|
committer | Sergio Giro <sgiro@google.com> | 2016-02-02 15:16:50 +0000 |
commit | bdb7b3d37025690a0434040b4e0d0623d9fa74af (patch) | |
tree | 999e02ffd121091903c893bfa01244d9c8d27456 /bcpkix/src | |
parent | 6d876f3f0ae553704a1dcf7e89003fcf14717037 (diff) | |
download | bouncycastle-bdb7b3d37025690a0434040b4e0d0623d9fa74af.tar.gz |
bouncycastle: Android tree with upstream code for version 1.54
Change-Id: I3958e32dd005cfb37985a6f13e2464a872290658
Diffstat (limited to 'bcpkix/src')
120 files changed, 3924 insertions, 1775 deletions
diff --git a/bcpkix/src/main/java/org/bouncycastle/cert/X509AttributeCertificateHolder.java b/bcpkix/src/main/java/org/bouncycastle/cert/X509AttributeCertificateHolder.java index c465c834..e6b0d7ec 100644 --- a/bcpkix/src/main/java/org/bouncycastle/cert/X509AttributeCertificateHolder.java +++ b/bcpkix/src/main/java/org/bouncycastle/cert/X509AttributeCertificateHolder.java @@ -279,7 +279,7 @@ public class X509AttributeCertificateHolder */ public byte[] getSignature() { - return attrCert.getSignatureValue().getBytes(); + return attrCert.getSignatureValue().getOctets(); } /** @@ -340,7 +340,7 @@ public class X509AttributeCertificateHolder throw new CertException("unable to process signature: " + e.getMessage(), e); } - return verifier.verify(attrCert.getSignatureValue().getBytes()); + return verifier.verify(this.getSignature()); } public boolean equals( diff --git a/bcpkix/src/main/java/org/bouncycastle/cert/X509CRLHolder.java b/bcpkix/src/main/java/org/bouncycastle/cert/X509CRLHolder.java index 29c48fa6..4b773e2e 100644 --- a/bcpkix/src/main/java/org/bouncycastle/cert/X509CRLHolder.java +++ b/bcpkix/src/main/java/org/bouncycastle/cert/X509CRLHolder.java @@ -291,7 +291,7 @@ public class X509CRLHolder throw new CertException("unable to process signature: " + e.getMessage(), e); } - return verifier.verify(x509CRL.getSignature().getBytes()); + return verifier.verify(x509CRL.getSignature().getOctets()); } public boolean equals( diff --git a/bcpkix/src/main/java/org/bouncycastle/cert/X509CertificateHolder.java b/bcpkix/src/main/java/org/bouncycastle/cert/X509CertificateHolder.java index dc61c78f..b5ad578d 100644 --- a/bcpkix/src/main/java/org/bouncycastle/cert/X509CertificateHolder.java +++ b/bcpkix/src/main/java/org/bouncycastle/cert/X509CertificateHolder.java @@ -240,7 +240,7 @@ public class X509CertificateHolder */ public byte[] getSignature() { - return x509Certificate.getSignature().getBytes(); + return x509Certificate.getSignature().getOctets(); } /** @@ -289,7 +289,7 @@ public class X509CertificateHolder throw new CertException("unable to process signature: " + e.getMessage(), e); } - return verifier.verify(x509Certificate.getSignature().getBytes()); + return verifier.verify(this.getSignature()); } public boolean equals( diff --git a/bcpkix/src/main/java/org/bouncycastle/cert/X509ExtensionUtils.java b/bcpkix/src/main/java/org/bouncycastle/cert/X509ExtensionUtils.java index aa371381..fa8cb1ed 100644 --- a/bcpkix/src/main/java/org/bouncycastle/cert/X509ExtensionUtils.java +++ b/bcpkix/src/main/java/org/bouncycastle/cert/X509ExtensionUtils.java @@ -23,56 +23,57 @@ public class X509ExtensionUtils { private DigestCalculator calculator; + /** + * Base constructor - for conformance to RFC 5280 use a calculator based on SHA-1. + * + * @param calculator a calculator for calculating subject key ids. + */ public X509ExtensionUtils(DigestCalculator calculator) { this.calculator = calculator; } + /** + * Create an AuthorityKeyIdentifier from the passed in arguments. + * + * @param certHolder the issuer certificate that the AuthorityKeyIdentifier should refer to. + * @return an AuthorityKeyIdentifier. + */ public AuthorityKeyIdentifier createAuthorityKeyIdentifier( X509CertificateHolder certHolder) { - if (certHolder.getVersionNumber() != 3) - { - GeneralName genName = new GeneralName(certHolder.getIssuer()); - SubjectPublicKeyInfo info = certHolder.getSubjectPublicKeyInfo(); - - return new AuthorityKeyIdentifier( - calculateIdentifier(info), new GeneralNames(genName), certHolder.getSerialNumber()); - } - else - { - GeneralName genName = new GeneralName(certHolder.getIssuer()); - Extension ext = certHolder.getExtension(Extension.subjectKeyIdentifier); + GeneralName genName = new GeneralName(certHolder.getIssuer()); - if (ext != null) - { - ASN1OctetString str = ASN1OctetString.getInstance(ext.getParsedValue()); - - return new AuthorityKeyIdentifier( - str.getOctets(), new GeneralNames(genName), certHolder.getSerialNumber()); - } - else - { - SubjectPublicKeyInfo info = certHolder.getSubjectPublicKeyInfo(); - - return new AuthorityKeyIdentifier( - calculateIdentifier(info), new GeneralNames(genName), certHolder.getSerialNumber()); - } - } + return new AuthorityKeyIdentifier( + getSubjectKeyIdentifier(certHolder), new GeneralNames(genName), certHolder.getSerialNumber()); } + /** + * Create an AuthorityKeyIdentifier from the passed in SubjectPublicKeyInfo. + * + * @param publicKeyInfo the SubjectPublicKeyInfo to base the key identifier on. + * @return an AuthorityKeyIdentifier. + */ public AuthorityKeyIdentifier createAuthorityKeyIdentifier(SubjectPublicKeyInfo publicKeyInfo) { return new AuthorityKeyIdentifier(calculateIdentifier(publicKeyInfo)); } + /** + * Create an AuthorityKeyIdentifier from the passed in arguments. + * + * @param publicKeyInfo the SubjectPublicKeyInfo to base the key identifier on. + * @param generalNames the general names to associate with the issuer cert's issuer. + * @param serial the serial number of the issuer cert. + * @return an AuthorityKeyIdentifier. + */ public AuthorityKeyIdentifier createAuthorityKeyIdentifier(SubjectPublicKeyInfo publicKeyInfo, GeneralNames generalNames, BigInteger serial) { return new AuthorityKeyIdentifier(calculateIdentifier(publicKeyInfo), generalNames, serial); } /** - * Return a RFC 3280 type 1 key identifier. As in: + * Return a RFC 5280 type 1 key identifier. As in: * <pre> * (1) The keyIdentifier is composed of the 160-bit SHA-1 hash of the * value of the BIT STRING subjectPublicKey (excluding the tag, @@ -88,7 +89,7 @@ public class X509ExtensionUtils } /** - * Return a RFC 3280 type 2 key identifier. As in: + * Return a RFC 5280 type 2 key identifier. As in: * <pre> * (2) The keyIdentifier is composed of a four bit type field with * the value 0100 followed by the least significant 60 bits of the @@ -110,6 +111,27 @@ public class X509ExtensionUtils return new SubjectKeyIdentifier(id); } + private byte[] getSubjectKeyIdentifier(X509CertificateHolder certHolder) + { + if (certHolder.getVersionNumber() != 3) + { + return calculateIdentifier(certHolder.getSubjectPublicKeyInfo()); + } + else + { + Extension ext = certHolder.getExtension(Extension.subjectKeyIdentifier); + + if (ext != null) + { + return ASN1OctetString.getInstance(ext.getParsedValue()).getOctets(); + } + else + { + return calculateIdentifier(certHolder.getSubjectPublicKeyInfo()); + } + } + } + private byte[] calculateIdentifier(SubjectPublicKeyInfo publicKeyInfo) { byte[] bytes = publicKeyInfo.getPublicKeyData().getBytes(); diff --git a/bcpkix/src/main/java/org/bouncycastle/cert/X509v2AttributeCertificateBuilder.java b/bcpkix/src/main/java/org/bouncycastle/cert/X509v2AttributeCertificateBuilder.java index 4cd10a3f..b5c3f591 100644 --- a/bcpkix/src/main/java/org/bouncycastle/cert/X509v2AttributeCertificateBuilder.java +++ b/bcpkix/src/main/java/org/bouncycastle/cert/X509v2AttributeCertificateBuilder.java @@ -11,6 +11,7 @@ import org.bouncycastle.asn1.ASN1ObjectIdentifier; import org.bouncycastle.asn1.DERSet; import org.bouncycastle.asn1.x509.AttCertIssuer; import org.bouncycastle.asn1.x509.Attribute; +import org.bouncycastle.asn1.x509.Extension; import org.bouncycastle.asn1.x509.ExtensionsGenerator; import org.bouncycastle.asn1.x509.V2AttributeCertificateInfoGenerator; import org.bouncycastle.operator.ContentSigner; @@ -102,7 +103,7 @@ public class X509v2AttributeCertificateBuilder } /** - * Add a given extension field for the standard extensions tag + * Add a given extension field for the standard extensions tag made up of the passed in parameters. * * @param oid the OID defining the extension type. * @param isCritical true if the extension is critical, false otherwise. @@ -121,7 +122,7 @@ public class X509v2AttributeCertificateBuilder } /** - * Add a given extension field for the standard extensions tag (tag 3) using a byte encoding of the + * Add a given extension field for the standard extensions using a byte encoding of the * extension value. * * @param oid the OID defining the extension type. @@ -140,6 +141,21 @@ public class X509v2AttributeCertificateBuilder return this; } + /** + * Add a given extension field for the standard extensions. + * + * @param extension the full extension value. + * @return this builder object. + */ + public X509v2AttributeCertificateBuilder addExtension( + Extension extension) + throws CertIOException + { + extGenerator.addExtension(extension); + + return this; + } + /** * Generate an X509 certificate, based on the current issuer and subject * using the passed in signer. diff --git a/bcpkix/src/main/java/org/bouncycastle/cert/X509v2CRLBuilder.java b/bcpkix/src/main/java/org/bouncycastle/cert/X509v2CRLBuilder.java index 896f55be..95a3d911 100644 --- a/bcpkix/src/main/java/org/bouncycastle/cert/X509v2CRLBuilder.java +++ b/bcpkix/src/main/java/org/bouncycastle/cert/X509v2CRLBuilder.java @@ -11,12 +11,12 @@ import org.bouncycastle.asn1.ASN1Integer; import org.bouncycastle.asn1.ASN1ObjectIdentifier; import org.bouncycastle.asn1.ASN1Sequence; import org.bouncycastle.asn1.x500.X500Name; +import org.bouncycastle.asn1.x509.Extension; import org.bouncycastle.asn1.x509.Extensions; import org.bouncycastle.asn1.x509.ExtensionsGenerator; import org.bouncycastle.asn1.x509.TBSCertList; import org.bouncycastle.asn1.x509.Time; import org.bouncycastle.asn1.x509.V2TBSCertListGenerator; -import org.bouncycastle.asn1.x509.X509Extensions; import org.bouncycastle.operator.ContentSigner; /** @@ -152,22 +152,6 @@ public class X509v2CRLBuilder return this; } - - /** - * Add a CRL entry with extensions. - * - * @param userCertificateSerial serial number of revoked certificate. - * @param revocationDate date of certificate revocation. - * @param extensions extension set to be associated with this CRLEntry. - * @return the current builder. - * @deprecated use method taking Extensions - */ - public X509v2CRLBuilder addCRLEntry(BigInteger userCertificateSerial, Date revocationDate, X509Extensions extensions) - { - tbsGen.addCRLEntry(new ASN1Integer(userCertificateSerial), new Time(revocationDate), Extensions.getInstance(extensions)); - - return this; - } /** * Add a CRL entry with extensions. @@ -245,6 +229,21 @@ public class X509v2CRLBuilder } /** + * Add a given extension field for the standard extensions tag (tag 3). + * + * @param extension the full extension value. + * @return this builder object. + */ + public X509v2CRLBuilder addExtension( + Extension extension) + throws CertIOException + { + extGenerator.addExtension(extension); + + return this; + } + + /** * Generate an X.509 CRL, based on the current issuer and subject * using the passed in signer. * diff --git a/bcpkix/src/main/java/org/bouncycastle/cert/X509v3CertificateBuilder.java b/bcpkix/src/main/java/org/bouncycastle/cert/X509v3CertificateBuilder.java index 22905b97..5cb131bc 100644 --- a/bcpkix/src/main/java/org/bouncycastle/cert/X509v3CertificateBuilder.java +++ b/bcpkix/src/main/java/org/bouncycastle/cert/X509v3CertificateBuilder.java @@ -126,6 +126,21 @@ public class X509v3CertificateBuilder } /** + * Add a given extension field for the standard extensions tag (tag 3). + * + * @param extension the full extension value. + * @return this builder object. + */ + public X509v3CertificateBuilder addExtension( + Extension extension) + throws CertIOException + { + extGenerator.addExtension(extension); + + return this; + } + + /** * Add a given extension field for the standard extensions tag (tag 3) using a byte encoding of the * extension value. * diff --git a/bcpkix/src/main/java/org/bouncycastle/cert/crmf/CertificateRequestMessage.java b/bcpkix/src/main/java/org/bouncycastle/cert/crmf/CertificateRequestMessage.java index b07b1d60..2fd3dad8 100644 --- a/bcpkix/src/main/java/org/bouncycastle/cert/crmf/CertificateRequestMessage.java +++ b/bcpkix/src/main/java/org/bouncycastle/cert/crmf/CertificateRequestMessage.java @@ -294,7 +294,7 @@ public class CertificateRequestMessage CRMFUtil.derEncodeToStream(certReqMsg.getCertReq(), verifier.getOutputStream()); } - return verifier.verify(popoSign.getSignature().getBytes()); + return verifier.verify(popoSign.getSignature().getOctets()); } /** diff --git a/bcpkix/src/main/java/org/bouncycastle/cert/crmf/jcajce/CRMFHelper.java b/bcpkix/src/main/java/org/bouncycastle/cert/crmf/jcajce/CRMFHelper.java index 4878615b..c482b862 100644 --- a/bcpkix/src/main/java/org/bouncycastle/cert/crmf/jcajce/CRMFHelper.java +++ b/bcpkix/src/main/java/org/bouncycastle/cert/crmf/jcajce/CRMFHelper.java @@ -41,8 +41,8 @@ import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo; import org.bouncycastle.asn1.x9.X9ObjectIdentifiers; import org.bouncycastle.cert.crmf.CRMFException; import org.bouncycastle.cms.CMSAlgorithm; +import org.bouncycastle.jcajce.util.AlgorithmParametersUtils; import org.bouncycastle.jcajce.util.JcaJceHelper; -import org.bouncycastle.jcajce.util.JcaJceUtils; class CRMFHelper { @@ -183,7 +183,7 @@ class CRMFHelper try { - JcaJceUtils.loadParameters(params, sParams); + AlgorithmParametersUtils.loadParameters(params, sParams); } catch (IOException e) { @@ -392,7 +392,7 @@ class CRMFHelper { try { - asn1Params = JcaJceUtils.extractParameters(params); + asn1Params = AlgorithmParametersUtils.extractParameters(params); } catch (IOException e) { diff --git a/bcpkix/src/main/java/org/bouncycastle/cert/crmf/jcajce/JceCRMFEncryptorBuilder.java b/bcpkix/src/main/java/org/bouncycastle/cert/crmf/jcajce/JceCRMFEncryptorBuilder.java index 701d36ea..009ddfe8 100644 --- a/bcpkix/src/main/java/org/bouncycastle/cert/crmf/jcajce/JceCRMFEncryptorBuilder.java +++ b/bcpkix/src/main/java/org/bouncycastle/cert/crmf/jcajce/JceCRMFEncryptorBuilder.java @@ -17,12 +17,16 @@ import org.bouncycastle.cert.crmf.CRMFException; import org.bouncycastle.jcajce.util.DefaultJcaJceHelper; import org.bouncycastle.jcajce.util.NamedJcaJceHelper; import org.bouncycastle.jcajce.util.ProviderJcaJceHelper; +import org.bouncycastle.operator.DefaultSecretKeySizeProvider; import org.bouncycastle.operator.GenericKey; import org.bouncycastle.operator.OutputEncryptor; +import org.bouncycastle.operator.SecretKeySizeProvider; import org.bouncycastle.operator.jcajce.JceGenericKey; public class JceCRMFEncryptorBuilder { + private static final SecretKeySizeProvider KEY_SIZE_PROVIDER = DefaultSecretKeySizeProvider.INSTANCE; + private final ASN1ObjectIdentifier encryptionOID; private final int keySize; @@ -86,6 +90,11 @@ public class JceCRMFEncryptorBuilder if (keySize < 0) { + keySize = KEY_SIZE_PROVIDER.getKeySize(encryptionOID); + } + + if (keySize < 0) + { keyGen.init(random); } else diff --git a/bcpkix/src/main/java/org/bouncycastle/cert/crmf/test/AllTests.java b/bcpkix/src/main/java/org/bouncycastle/cert/crmf/test/AllTests.java index 712210e4..837ddd03 100644 --- a/bcpkix/src/main/java/org/bouncycastle/cert/crmf/test/AllTests.java +++ b/bcpkix/src/main/java/org/bouncycastle/cert/crmf/test/AllTests.java @@ -15,6 +15,7 @@ import java.util.Date; import javax.security.auth.x500.X500Principal; +import junit.framework.Assert; import junit.framework.Test; import junit.framework.TestCase; import junit.framework.TestSuite; @@ -22,10 +23,14 @@ import org.bouncycastle.asn1.ASN1ObjectIdentifier; import org.bouncycastle.asn1.crmf.CRMFObjectIdentifiers; import org.bouncycastle.asn1.crmf.EncKeyWithID; import org.bouncycastle.asn1.crmf.EncryptedValue; +import org.bouncycastle.asn1.nist.NISTObjectIdentifiers; +import org.bouncycastle.asn1.ntt.NTTObjectIdentifiers; +import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers; import org.bouncycastle.asn1.x500.X500Name; import org.bouncycastle.asn1.x509.GeneralName; import org.bouncycastle.cert.X509CertificateHolder; import org.bouncycastle.cert.X509v1CertificateBuilder; +import org.bouncycastle.cert.crmf.CRMFException; import org.bouncycastle.cert.crmf.EncryptedValueBuilder; import org.bouncycastle.cert.crmf.EncryptedValuePadder; import org.bouncycastle.cert.crmf.EncryptedValueParser; @@ -44,6 +49,7 @@ import org.bouncycastle.cert.jcajce.JcaX509CertificateConverter; import org.bouncycastle.cert.jcajce.JcaX509v1CertificateBuilder; import org.bouncycastle.cms.CMSAlgorithm; import org.bouncycastle.cms.CMSEnvelopedDataGenerator; +import org.bouncycastle.cms.CMSException; import org.bouncycastle.cms.RecipientId; import org.bouncycastle.cms.RecipientInformation; import org.bouncycastle.cms.RecipientInformationStore; @@ -53,6 +59,7 @@ import org.bouncycastle.cms.jcajce.JceKeyTransRecipientId; import org.bouncycastle.cms.jcajce.JceKeyTransRecipientInfoGenerator; import org.bouncycastle.jce.provider.BouncyCastleProvider; import org.bouncycastle.operator.OperatorCreationException; +import org.bouncycastle.operator.OutputEncryptor; import org.bouncycastle.operator.jcajce.JcaContentSignerBuilder; import org.bouncycastle.operator.jcajce.JcaContentVerifierProviderBuilder; import org.bouncycastle.operator.jcajce.JceAsymmetricKeyWrapper; @@ -112,19 +119,26 @@ public class AllTests .setPublicKey(kp.getPublic()); certReqBuild.addControl(new JcaPKIArchiveControlBuilder(kp.getPrivate(), new X500Principal("CN=Test")) - .addRecipientGenerator(new JceKeyTransRecipientInfoGenerator(cert).setProvider(BC)) - .build(new JceCMSContentEncryptorBuilder(new ASN1ObjectIdentifier(CMSEnvelopedDataGenerator.AES128_CBC)).setProvider(BC).build())); + .addRecipientGenerator(new JceKeyTransRecipientInfoGenerator(cert).setProvider(BC)) + .build(new JceCMSContentEncryptorBuilder(new ASN1ObjectIdentifier(CMSEnvelopedDataGenerator.AES128_CBC)).setProvider(BC).build())); - JcaCertificateRequestMessage certReqMsg = new JcaCertificateRequestMessage(certReqBuild.build()); + JcaCertificateRequestMessage certReqMsg = new JcaCertificateRequestMessage(certReqBuild.build()).setProvider(BC); - assertEquals(new X500Principal("CN=Test"), certReqMsg.getSubjectX500Principal()); - assertEquals(kp.getPublic(), certReqMsg.getPublicKey()); + TestCase.assertEquals(new X500Principal("CN=Test"), certReqMsg.getSubjectX500Principal()); + TestCase.assertEquals(kp.getPublic(), certReqMsg.getPublicKey()); + + checkCertReqMsgWithArchiveControl(kp, cert, certReqMsg); + checkCertReqMsgWithArchiveControl(kp, cert, new JcaCertificateRequestMessage(certReqMsg.getEncoded())); + } + private void checkCertReqMsgWithArchiveControl(KeyPair kp, X509Certificate cert, JcaCertificateRequestMessage certReqMsg) + throws CRMFException, CMSException, IOException + { PKIArchiveControl archiveControl = (PKIArchiveControl)certReqMsg.getControl(CRMFObjectIdentifiers.id_regCtrl_pkiArchiveOptions); - assertEquals(PKIArchiveControl.encryptedPrivKey, archiveControl.getArchiveType()); + TestCase.assertEquals(PKIArchiveControl.encryptedPrivKey, archiveControl.getArchiveType()); - assertTrue(archiveControl.isEnvelopedData()); + TestCase.assertTrue(archiveControl.isEnvelopedData()); RecipientInformationStore recips = archiveControl.getEnvelopedData().getRecipientInfos(); @@ -132,15 +146,15 @@ public class AllTests RecipientInformation recipientInformation = recips.get(recipientId); - assertNotNull(recipientInformation); + TestCase.assertNotNull(recipientInformation); EncKeyWithID encKeyWithID = EncKeyWithID.getInstance(recipientInformation.getContent(new JceKeyTransEnvelopedRecipient(kp.getPrivate()).setProvider(BC))); - assertTrue(encKeyWithID.hasIdentifier()); - assertFalse(encKeyWithID.isIdentifierUTF8String()); + TestCase.assertTrue(encKeyWithID.hasIdentifier()); + TestCase.assertFalse(encKeyWithID.isIdentifierUTF8String()); - assertEquals(new GeneralName(X500Name.getInstance(new X500Principal("CN=Test").getEncoded())), encKeyWithID.getIdentifier()); - assertTrue(Arrays.areEqual(kp.getPrivate().getEncoded(), encKeyWithID.getPrivateKey().getEncoded())); + TestCase.assertEquals(new GeneralName(X500Name.getInstance(new X500Principal("CN=Test").getEncoded())), encKeyWithID.getIdentifier()); + TestCase.assertTrue(Arrays.areEqual(kp.getPrivate().getEncoded(), encKeyWithID.getPrivateKey().getEncoded())); } public void testProofOfPossessionWithoutSender() @@ -160,25 +174,42 @@ public class AllTests .setProofOfPossessionSigningKeySigner(new JcaContentSignerBuilder("SHA1withRSA").setProvider(BC).build(kp.getPrivate())); certReqBuild.addControl(new JcaPKIArchiveControlBuilder(kp.getPrivate(), new X500Principal("CN=test")) - .addRecipientGenerator(new JceKeyTransRecipientInfoGenerator(cert).setProvider(BC)) - .build(new JceCMSContentEncryptorBuilder(new ASN1ObjectIdentifier(CMSEnvelopedDataGenerator.AES128_CBC)).setProvider(BC).build())); + .addRecipientGenerator(new JceKeyTransRecipientInfoGenerator(cert).setProvider(BC)) + .build(new JceCMSContentEncryptorBuilder(new ASN1ObjectIdentifier(CMSEnvelopedDataGenerator.AES128_CBC)).setProvider(BC).build())); - JcaCertificateRequestMessage certReqMsg = new JcaCertificateRequestMessage(certReqBuild.build().getEncoded()); + JcaCertificateRequestMessage certReqMsg = new JcaCertificateRequestMessage(certReqBuild.build().getEncoded()).setProvider(BC); // check that internal check on popo signing is working okay try { certReqMsg.isValidSigningKeyPOP(new JcaContentVerifierProviderBuilder().setProvider(BC).build(kp.getPublic())); - fail("IllegalStateException not thrown"); + TestCase.fail("IllegalStateException not thrown"); } catch (IllegalStateException e) { // ignore } - assertTrue(certReqMsg.isValidSigningKeyPOP(new JcaContentVerifierProviderBuilder().setProvider(BC).build(kp.getPublic()), new PKMACBuilder(new JcePKMACValuesCalculator().setProvider(BC)), "fred".toCharArray())); + TestCase.assertTrue(certReqMsg.isValidSigningKeyPOP(new JcaContentVerifierProviderBuilder().setProvider(BC).build(kp.getPublic()), new PKMACBuilder(new JcePKMACValuesCalculator().setProvider(BC)), "fred".toCharArray())); - assertEquals(kp.getPublic(), certReqMsg.getPublicKey()); + TestCase.assertEquals(kp.getPublic(), certReqMsg.getPublicKey()); + + certReqMsg = new JcaCertificateRequestMessage(certReqBuild.build()).setProvider(BC); + + // check that internal check on popo signing is working okay + try + { + certReqMsg.isValidSigningKeyPOP(new JcaContentVerifierProviderBuilder().setProvider(BC).build(kp.getPublic())); + TestCase.fail("IllegalStateException not thrown"); + } + catch (IllegalStateException e) + { + // ignore + } + + TestCase.assertTrue(certReqMsg.isValidSigningKeyPOP(new JcaContentVerifierProviderBuilder().setProvider(BC).build(kp.getPublic()), new PKMACBuilder(new JcePKMACValuesCalculator().setProvider(BC)), "fred".toCharArray())); + + TestCase.assertEquals(kp.getPublic(), certReqMsg.getPublicKey()); } public void testProofOfPossessionWithSender() @@ -249,6 +280,30 @@ public class AllTests assertEquals(kp.getPublic(), certReqMsg.getPublicKey()); } + public void testKeySizes() + throws Exception + { + verifyKeySize(NISTObjectIdentifiers.id_aes128_CBC, 128); + verifyKeySize(NISTObjectIdentifiers.id_aes192_CBC, 192); + verifyKeySize(NISTObjectIdentifiers.id_aes256_CBC, 256); + + verifyKeySize(NTTObjectIdentifiers.id_camellia128_cbc, 128); + verifyKeySize(NTTObjectIdentifiers.id_camellia192_cbc, 192); + verifyKeySize(NTTObjectIdentifiers.id_camellia256_cbc, 256); + + verifyKeySize(PKCSObjectIdentifiers.des_EDE3_CBC, 192); + } + + private void verifyKeySize(ASN1ObjectIdentifier oid, int keySize) + throws Exception + { + JceCRMFEncryptorBuilder encryptorBuilder = new JceCRMFEncryptorBuilder(oid).setProvider(BC); + + OutputEncryptor outputEncryptor = encryptorBuilder.build(); + + Assert.assertEquals(keySize / 8, ((byte[])(outputEncryptor.getKey().getRepresentation())).length); + } + public void testEncryptedValue() throws Exception { diff --git a/bcpkix/src/main/java/org/bouncycastle/cert/jcajce/JcaAttrCertStore.java b/bcpkix/src/main/java/org/bouncycastle/cert/jcajce/JcaAttrCertStore.java deleted file mode 100644 index b857d966..00000000 --- a/bcpkix/src/main/java/org/bouncycastle/cert/jcajce/JcaAttrCertStore.java +++ /dev/null @@ -1,62 +0,0 @@ -package org.bouncycastle.cert.jcajce; - -import java.io.IOException; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.Iterator; -import java.util.List; - -import org.bouncycastle.util.CollectionStore; -import org.bouncycastle.x509.X509AttributeCertificate; - -/** - * Class for storing Attribute Certificates for later lookup. - * <p> - * The class will convert X509AttributeCertificate objects into X509AttributeCertificateHolder objects. - * </p> - */ -public class JcaAttrCertStore - extends CollectionStore -{ - /** - * Basic constructor. - * - * @param collection - initial contents for the store, this is copied. - */ - public JcaAttrCertStore(Collection collection) - throws IOException - { - super(convertCerts(collection)); - } - - public JcaAttrCertStore(X509AttributeCertificate attrCert) - throws IOException - { - this(Collections.singletonList(attrCert)); - } - - private static Collection convertCerts(Collection collection) - throws IOException - { - List list = new ArrayList(collection.size()); - - for (Iterator it = collection.iterator(); it.hasNext();) - { - Object o = it.next(); - - if (o instanceof X509AttributeCertificate) - { - X509AttributeCertificate cert = (X509AttributeCertificate)o; - - list.add(new JcaX509AttributeCertificateHolder(cert)); - } - else - { - list.add(o); - } - } - - return list; - } -} diff --git a/bcpkix/src/main/java/org/bouncycastle/cert/jcajce/JcaX509AttributeCertificateHolder.java b/bcpkix/src/main/java/org/bouncycastle/cert/jcajce/JcaX509AttributeCertificateHolder.java deleted file mode 100644 index 1ceafce0..00000000 --- a/bcpkix/src/main/java/org/bouncycastle/cert/jcajce/JcaX509AttributeCertificateHolder.java +++ /dev/null @@ -1,26 +0,0 @@ -package org.bouncycastle.cert.jcajce; - -import java.io.IOException; - -import org.bouncycastle.asn1.x509.AttributeCertificate; -import org.bouncycastle.cert.X509AttributeCertificateHolder; -import org.bouncycastle.x509.X509AttributeCertificate; - -/** - * JCA helper class for converting an old style X509AttributeCertificate into a X509AttributeCertificateHolder object. - */ -public class JcaX509AttributeCertificateHolder - extends X509AttributeCertificateHolder -{ - /** - * Base constructor. - * - * @param cert AttributeCertificate to be used a the source for the holder creation. - * @throws IOException if there is a problem extracting the attribute certificate information. - */ - public JcaX509AttributeCertificateHolder(X509AttributeCertificate cert) - throws IOException - { - super(AttributeCertificate.getInstance(cert.getEncoded())); - } -} diff --git a/bcpkix/src/main/java/org/bouncycastle/cert/jcajce/JcaX509ExtensionUtils.java b/bcpkix/src/main/java/org/bouncycastle/cert/jcajce/JcaX509ExtensionUtils.java index 162c94f1..0838f089 100644 --- a/bcpkix/src/main/java/org/bouncycastle/cert/jcajce/JcaX509ExtensionUtils.java +++ b/bcpkix/src/main/java/org/bouncycastle/cert/jcajce/JcaX509ExtensionUtils.java @@ -96,7 +96,7 @@ public class JcaX509ExtensionUtils */ public SubjectKeyIdentifier createTruncatedSubjectKeyIdentifier(PublicKey publicKey) { - return super.createSubjectKeyIdentifier(SubjectPublicKeyInfo.getInstance(publicKey.getEncoded())); + return super.createTruncatedSubjectKeyIdentifier(SubjectPublicKeyInfo.getInstance(publicKey.getEncoded())); } /** diff --git a/bcpkix/src/main/java/org/bouncycastle/cert/ocsp/BasicOCSPResp.java b/bcpkix/src/main/java/org/bouncycastle/cert/ocsp/BasicOCSPResp.java index 7a038707..d74bef00 100644 --- a/bcpkix/src/main/java/org/bouncycastle/cert/ocsp/BasicOCSPResp.java +++ b/bcpkix/src/main/java/org/bouncycastle/cert/ocsp/BasicOCSPResp.java @@ -137,7 +137,7 @@ public class BasicOCSPResp public byte[] getSignature() { - return resp.getSignature().getBytes(); + return resp.getSignature().getOctets(); } public X509CertificateHolder[] getCerts() diff --git a/bcpkix/src/main/java/org/bouncycastle/cert/ocsp/BasicOCSPRespBuilder.java b/bcpkix/src/main/java/org/bouncycastle/cert/ocsp/BasicOCSPRespBuilder.java index d06dcfca..56959071 100644 --- a/bcpkix/src/main/java/org/bouncycastle/cert/ocsp/BasicOCSPRespBuilder.java +++ b/bcpkix/src/main/java/org/bouncycastle/cert/ocsp/BasicOCSPRespBuilder.java @@ -93,7 +93,7 @@ public class BasicOCSPRespBuilder public SingleResponse toResponse() throws Exception { - return new SingleResponse(certId.toASN1Object(), certStatus, thisUpdate, nextUpdate, extensions); + return new SingleResponse(certId.toASN1Primitive(), certStatus, thisUpdate, nextUpdate, extensions); } } @@ -130,7 +130,7 @@ public class BasicOCSPRespBuilder CertificateID certID, CertificateStatus certStatus) { - list.add(new ResponseObject(certID, certStatus, new Date(), null, null)); + this.addResponse(certID, certStatus, new Date(), null, null); return this; } @@ -145,9 +145,9 @@ public class BasicOCSPRespBuilder public BasicOCSPRespBuilder addResponse( CertificateID certID, CertificateStatus certStatus, - Extensions singleExtensions) + Extensions singleExtensions) { - list.add(new ResponseObject(certID, certStatus, new Date(), null, singleExtensions)); + this.addResponse(certID, certStatus, new Date(), null, singleExtensions); return this; } @@ -164,13 +164,32 @@ public class BasicOCSPRespBuilder CertificateID certID, CertificateStatus certStatus, Date nextUpdate, - Extensions singleExtensions) + Extensions singleExtensions) { - list.add(new ResponseObject(certID, certStatus, new Date(), nextUpdate, singleExtensions)); + this.addResponse(certID, certStatus, new Date(), nextUpdate, singleExtensions); return this; } - + + /** + * Add a response for a particular Certificate ID. + * + * @param certID certificate ID details + * @param thisUpdate date this response was valid on + * @param nextUpdate date when next update should be requested + * @param certStatus status of the certificate - null if okay + */ + public BasicOCSPRespBuilder addResponse( + CertificateID certID, + CertificateStatus certStatus, + Date thisUpdate, + Date nextUpdate) + { + this.addResponse(certID, certStatus, thisUpdate, nextUpdate, null); + + return this; + } + /** * Add a response for a particular Certificate ID. * @@ -185,7 +204,7 @@ public class BasicOCSPRespBuilder CertificateStatus certStatus, Date thisUpdate, Date nextUpdate, - Extensions singleExtensions) + Extensions singleExtensions) { list.add(new ResponseObject(certID, certStatus, thisUpdate, nextUpdate, singleExtensions)); @@ -227,7 +246,7 @@ public class BasicOCSPRespBuilder } } - ResponseData tbsResp = new ResponseData(responderID.toASN1Object(), new ASN1GeneralizedTime(producedAt), new DERSequence(responses), responseExtensions); + ResponseData tbsResp = new ResponseData(responderID.toASN1Primitive(), new ASN1GeneralizedTime(producedAt), new DERSequence(responses), responseExtensions); DERBitString bitSig; try diff --git a/bcpkix/src/main/java/org/bouncycastle/cert/ocsp/CertificateID.java b/bcpkix/src/main/java/org/bouncycastle/cert/ocsp/CertificateID.java index c6b09ad8..aa97f196 100644 --- a/bcpkix/src/main/java/org/bouncycastle/cert/ocsp/CertificateID.java +++ b/bcpkix/src/main/java/org/bouncycastle/cert/ocsp/CertificateID.java @@ -88,7 +88,7 @@ public class CertificateID } } - public CertID toASN1Object() + public CertID toASN1Primitive() { return id; } diff --git a/bcpkix/src/main/java/org/bouncycastle/cert/ocsp/OCSPReq.java b/bcpkix/src/main/java/org/bouncycastle/cert/ocsp/OCSPReq.java index 2706c401..437d37be 100644 --- a/bcpkix/src/main/java/org/bouncycastle/cert/ocsp/OCSPReq.java +++ b/bcpkix/src/main/java/org/bouncycastle/cert/ocsp/OCSPReq.java @@ -174,7 +174,7 @@ public class OCSPReq return null; } - return req.getOptionalSignature().getSignature().getBytes(); + return req.getOptionalSignature().getSignature().getOctets(); } public X509CertificateHolder[] getCerts() diff --git a/bcpkix/src/main/java/org/bouncycastle/cert/ocsp/OCSPReqBuilder.java b/bcpkix/src/main/java/org/bouncycastle/cert/ocsp/OCSPReqBuilder.java index e7e8e0f5..b0cfb9ef 100644 --- a/bcpkix/src/main/java/org/bouncycastle/cert/ocsp/OCSPReqBuilder.java +++ b/bcpkix/src/main/java/org/bouncycastle/cert/ocsp/OCSPReqBuilder.java @@ -42,7 +42,7 @@ public class OCSPReqBuilder public Request toRequest() throws Exception { - return new Request(certId.toASN1Object(), extensions); + return new Request(certId.toASN1Primitive(), extensions); } } diff --git a/bcpkix/src/main/java/org/bouncycastle/cert/ocsp/RespID.java b/bcpkix/src/main/java/org/bouncycastle/cert/ocsp/RespID.java index 4322ab5b..a0fd765a 100644 --- a/bcpkix/src/main/java/org/bouncycastle/cert/ocsp/RespID.java +++ b/bcpkix/src/main/java/org/bouncycastle/cert/ocsp/RespID.java @@ -64,7 +64,7 @@ public class RespID } } - public ResponderID toASN1Object() + public ResponderID toASN1Primitive() { return id; } diff --git a/bcpkix/src/main/java/org/bouncycastle/cert/ocsp/test/OCSPTest.java b/bcpkix/src/main/java/org/bouncycastle/cert/ocsp/test/OCSPTest.java index 5c57c7f6..6e7de684 100644 --- a/bcpkix/src/main/java/org/bouncycastle/cert/ocsp/test/OCSPTest.java +++ b/bcpkix/src/main/java/org/bouncycastle/cert/ocsp/test/OCSPTest.java @@ -14,10 +14,10 @@ import org.bouncycastle.asn1.ASN1Exception; import org.bouncycastle.asn1.ASN1OctetString; import org.bouncycastle.asn1.DEROctetString; import org.bouncycastle.asn1.ocsp.OCSPObjectIdentifiers; +import org.bouncycastle.asn1.x500.X500Name; import org.bouncycastle.asn1.x509.Extension; import org.bouncycastle.asn1.x509.ExtensionsGenerator; import org.bouncycastle.asn1.x509.GeneralName; -import org.bouncycastle.asn1.x509.X509Name; import org.bouncycastle.cert.CertIOException; import org.bouncycastle.cert.X509CertificateHolder; import org.bouncycastle.cert.jcajce.JcaX509CertificateHolder; @@ -33,7 +33,6 @@ import org.bouncycastle.cert.ocsp.Req; import org.bouncycastle.cert.ocsp.RespID; import org.bouncycastle.cert.ocsp.SingleResp; import org.bouncycastle.cert.ocsp.jcajce.JcaBasicOCSPRespBuilder; -import org.bouncycastle.jce.X509Principal; import org.bouncycastle.jce.provider.BouncyCastleProvider; import org.bouncycastle.operator.DigestCalculatorProvider; import org.bouncycastle.operator.jcajce.JcaContentSignerBuilder; @@ -282,7 +281,7 @@ public class OCSPTest DigestCalculatorProvider digCalcProv = new JcaDigestCalculatorProviderBuilder().setProvider(BC).build(); String origDN = "CN=Eric H. Echidna, E=eric@bouncycastle.org, O=Bouncy Castle, C=AU"; - GeneralName origName = new GeneralName(new X509Name(origDN)); + GeneralName origName = new GeneralName(new X500Name(origDN)); // // general id value for our test issuer cert and a serial number. @@ -323,7 +322,7 @@ public class OCSPTest gen = new OCSPReqBuilder(); - gen.setRequestorName(new GeneralName(GeneralName.directoryName, new X509Principal("CN=fred"))); + gen.setRequestorName(new GeneralName(GeneralName.directoryName, new X500Name("CN=fred"))); gen.addRequest( new CertificateID(digCalcProv.get(CertificateID.HASH_SHA1), testCert, BigInteger.valueOf(1))); @@ -387,7 +386,7 @@ public class OCSPTest rand.nextBytes(sampleNonce); - gen.setRequestorName(new GeneralName(GeneralName.directoryName, new X509Principal("CN=fred"))); + gen.setRequestorName(new GeneralName(GeneralName.directoryName, new X500Name("CN=fred"))); ExtensionsGenerator extGen = new ExtensionsGenerator(); @@ -472,7 +471,7 @@ public class OCSPTest DigestCalculatorProvider digCalcProv = new JcaDigestCalculatorProviderBuilder().setProvider(BC).build(); String origDN = "CN=Eric H. Echidna, E=eric@bouncycastle.org, O=Bouncy Castle, C=AU"; - GeneralName origName = new GeneralName(new X509Name(origDN)); + GeneralName origName = new GeneralName(new X500Name(origDN)); // // general id value for our test issuer cert and a serial number. @@ -515,7 +514,7 @@ public class OCSPTest gen = new OCSPReqBuilder(); - gen.setRequestorName(new GeneralName(GeneralName.directoryName, new X509Principal("CN=fred"))); + gen.setRequestorName(new GeneralName(GeneralName.directoryName, new X500Name("CN=fred"))); gen.addRequest( new CertificateID(digCalcProv.get(CertificateID.HASH_SHA1), testCert, BigInteger.valueOf(1))); @@ -577,7 +576,7 @@ public class OCSPTest rand.nextBytes(sampleNonce); - gen.setRequestorName(new GeneralName(GeneralName.directoryName, new X509Principal("CN=fred"))); + gen.setRequestorName(new GeneralName(GeneralName.directoryName, new X500Name("CN=fred"))); ExtensionsGenerator extGen = new ExtensionsGenerator(); @@ -702,7 +701,7 @@ public class OCSPTest X509CertificateHolder testCert = new JcaX509CertificateHolder(OCSPTestUtil.makeCertificate(signKP, signDN, signKP, signDN)); String origDN = "CN=Eric H. Echidna, E=eric@bouncycastle.org, O=Bouncy Castle, C=AU"; - GeneralName origName = new GeneralName(new X509Name(origDN)); + GeneralName origName = new GeneralName(new X500Name(origDN)); DigestCalculatorProvider digCalcProv = new JcaDigestCalculatorProviderBuilder().setProvider(BC).build(); // @@ -746,7 +745,7 @@ public class OCSPTest gen = new OCSPReqBuilder(); - gen.setRequestorName(new GeneralName(GeneralName.directoryName, new X509Principal("CN=fred"))); + gen.setRequestorName(new GeneralName(GeneralName.directoryName, new X500Name("CN=fred"))); gen.addRequest( new CertificateID(digCalcProv.get(CertificateID.HASH_SHA1), testCert, BigInteger.valueOf(1))); @@ -810,7 +809,7 @@ public class OCSPTest rand.nextBytes(sampleNonce); - gen.setRequestorName(new GeneralName(GeneralName.directoryName, new X509Principal("CN=fred"))); + gen.setRequestorName(new GeneralName(GeneralName.directoryName, new X500Name("CN=fred"))); ExtensionsGenerator extGen = new ExtensionsGenerator(); diff --git a/bcpkix/src/main/java/org/bouncycastle/cert/ocsp/test/OCSPTestUtil.java b/bcpkix/src/main/java/org/bouncycastle/cert/ocsp/test/OCSPTestUtil.java index cab31e76..f6dd98c5 100644 --- a/bcpkix/src/main/java/org/bouncycastle/cert/ocsp/test/OCSPTestUtil.java +++ b/bcpkix/src/main/java/org/bouncycastle/cert/ocsp/test/OCSPTestUtil.java @@ -1,6 +1,5 @@ package org.bouncycastle.cert.ocsp.test; -import java.io.ByteArrayInputStream; import java.io.IOException; import java.math.BigInteger; import java.security.KeyPair; @@ -13,8 +12,6 @@ import java.util.Date; import javax.crypto.KeyGenerator; -import org.bouncycastle.asn1.ASN1InputStream; -import org.bouncycastle.asn1.ASN1Sequence; import org.bouncycastle.asn1.x509.AuthorityKeyIdentifier; import org.bouncycastle.asn1.x509.BasicConstraints; import org.bouncycastle.asn1.x509.SubjectKeyIdentifier; @@ -153,11 +150,7 @@ public class OCSPTestUtil private static AuthorityKeyIdentifier createAuthorityKeyId(PublicKey _pubKey) throws IOException { - - ByteArrayInputStream _bais = new ByteArrayInputStream(_pubKey - .getEncoded()); - SubjectPublicKeyInfo _info = new SubjectPublicKeyInfo( - (ASN1Sequence)new ASN1InputStream(_bais).readObject()); + SubjectPublicKeyInfo _info = SubjectPublicKeyInfo.getInstance(_pubKey.getEncoded()); return new AuthorityKeyIdentifier(_info); } diff --git a/bcpkix/src/main/java/org/bouncycastle/cert/path/test/CertPathTest.java b/bcpkix/src/main/java/org/bouncycastle/cert/path/test/CertPathTest.java index 3b8e23e0..b1e55da7 100644 --- a/bcpkix/src/main/java/org/bouncycastle/cert/path/test/CertPathTest.java +++ b/bcpkix/src/main/java/org/bouncycastle/cert/path/test/CertPathTest.java @@ -151,7 +151,7 @@ public class CertPathTest // ignore okay } - CertificateFactory cf = CertificateFactory.getInstance("X.509"); + CertificateFactory cf = CertificateFactory.getInstance("X.509", "BC"); List certCol = new ArrayList(); certCol.add(cf.generateCertificate(new ByteArrayInputStream(certA))); @@ -239,7 +239,7 @@ public class CertPathTest // list = new ArrayList(); - CertPath certPath = CertificateFactory.getInstance("X.509","BC").generateCertPath(list); + CertPath certPath = CertificateFactory.getInstance("X.509", "BC").generateCertPath(list); if (certPath.getCertificates().size() != 0) { fail("list wrong size."); diff --git a/bcpkix/src/main/java/org/bouncycastle/cert/test/AllTests.java b/bcpkix/src/main/java/org/bouncycastle/cert/test/AllTests.java index a5806862..6b85e8e7 100644 --- a/bcpkix/src/main/java/org/bouncycastle/cert/test/AllTests.java +++ b/bcpkix/src/main/java/org/bouncycastle/cert/test/AllTests.java @@ -2,6 +2,7 @@ package org.bouncycastle.cert.test; import java.security.Security; +import junit.extensions.TestSetup; import junit.framework.Test; import junit.framework.TestCase; import junit.framework.TestSuite; @@ -52,6 +53,26 @@ public class AllTests suite.addTestSuite(BcPKCS10Test.class); suite.addTest(ConverterTest.suite()); - return suite; + return new BCTestSetup(suite); } + + static class BCTestSetup + extends TestSetup + { + public BCTestSetup(Test test) + { + super(test); + } + + protected void setUp() + { + Security.addProvider(new BouncyCastleProvider()); + } + + protected void tearDown() + { + Security.removeProvider("BC"); + } + } + }
\ No newline at end of file diff --git a/bcpkix/src/main/java/org/bouncycastle/cert/test/BcAttrCertTest.java b/bcpkix/src/main/java/org/bouncycastle/cert/test/BcAttrCertTest.java index 520920ad..e4ca2153 100644 --- a/bcpkix/src/main/java/org/bouncycastle/cert/test/BcAttrCertTest.java +++ b/bcpkix/src/main/java/org/bouncycastle/cert/test/BcAttrCertTest.java @@ -584,7 +584,7 @@ public class BcAttrCertTest principals = holder.getEntityNames(); - X500Name principal0 = new X500Name(RFC4519Style.INSTANCE, principals[0]); + X500Name principal0 = X500Name.getInstance(RFC4519Style.INSTANCE, principals[0]); if (!principal0.toString().equals("c=US,o=vt,ou=Class 2,ou=Virginia Tech User,cn=Markus Lorch (mlorch),1.2.840.113549.1.9.1=mlorch@vt.edu")) { System.err.println(principal0.toString()); diff --git a/bcpkix/src/main/java/org/bouncycastle/cert/test/BcCertTest.java b/bcpkix/src/main/java/org/bouncycastle/cert/test/BcCertTest.java index fd551381..e47fed79 100644 --- a/bcpkix/src/main/java/org/bouncycastle/cert/test/BcCertTest.java +++ b/bcpkix/src/main/java/org/bouncycastle/cert/test/BcCertTest.java @@ -23,6 +23,7 @@ import org.bouncycastle.asn1.ASN1Object; import org.bouncycastle.asn1.ASN1ObjectIdentifier; import org.bouncycastle.asn1.DERBitString; import org.bouncycastle.asn1.DERSequence; +import org.bouncycastle.asn1.oiw.OIWObjectIdentifiers; import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers; import org.bouncycastle.asn1.x500.X500Name; import org.bouncycastle.asn1.x500.X500NameBuilder; @@ -39,6 +40,7 @@ import org.bouncycastle.asn1.x509.GeneralNames; import org.bouncycastle.asn1.x509.KeyPurposeId; import org.bouncycastle.asn1.x509.KeyUsage; import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo; +import org.bouncycastle.asn1.x9.X9ObjectIdentifiers; import org.bouncycastle.cert.CertException; import org.bouncycastle.cert.X509CRLEntryHolder; import org.bouncycastle.cert.X509CRLHolder; @@ -58,10 +60,15 @@ import org.bouncycastle.crypto.generators.RSAKeyPairGenerator; import org.bouncycastle.crypto.params.AsymmetricKeyParameter; import org.bouncycastle.crypto.params.DSAKeyGenerationParameters; import org.bouncycastle.crypto.params.DSAParameters; +import org.bouncycastle.crypto.params.ECDomainParameters; +import org.bouncycastle.crypto.params.ECPrivateKeyParameters; +import org.bouncycastle.crypto.params.ECPublicKeyParameters; import org.bouncycastle.crypto.params.RSAKeyGenerationParameters; import org.bouncycastle.crypto.params.RSAKeyParameters; import org.bouncycastle.crypto.params.RSAPrivateCrtKeyParameters; +import org.bouncycastle.crypto.util.PublicKeyFactory; import org.bouncycastle.crypto.util.SubjectPublicKeyInfoFactory; +import org.bouncycastle.math.ec.ECCurve; import org.bouncycastle.operator.ContentSigner; import org.bouncycastle.operator.ContentVerifierProvider; import org.bouncycastle.operator.DefaultDigestAlgorithmIdentifierFinder; @@ -69,9 +76,13 @@ import org.bouncycastle.operator.DefaultSignatureAlgorithmIdentifierFinder; import org.bouncycastle.operator.OperatorCreationException; import org.bouncycastle.operator.bc.BcDSAContentSignerBuilder; import org.bouncycastle.operator.bc.BcDSAContentVerifierProviderBuilder; +import org.bouncycastle.operator.bc.BcECContentSignerBuilder; +import org.bouncycastle.operator.bc.BcECContentVerifierProviderBuilder; import org.bouncycastle.operator.bc.BcRSAContentSignerBuilder; import org.bouncycastle.operator.bc.BcRSAContentVerifierProviderBuilder; +import org.bouncycastle.util.Strings; import org.bouncycastle.util.encoders.Base64; +import org.bouncycastle.util.encoders.Hex; public class BcCertTest extends TestCase @@ -471,7 +482,7 @@ public class BcCertTest } catch (Exception e) { - fail(dump + System.getProperty("line.separator") + getName() + ": "+ id + " failed - exception " + e.toString(), e); + fail(dump + Strings.lineSeparator() + getName() + ": "+ id + " failed - exception " + e.toString(), e); } } @@ -779,6 +790,10 @@ public class BcCertTest assertTrue(cert.isSignatureValid(new BcDSAContentVerifierProviderBuilder(digAlgFinder).build(pubKey))); + AsymmetricKeyParameter certPubKey = PublicKeyFactory.createKey(cert.getSubjectPublicKeyInfo()); + + assertTrue(cert.isSignatureValid(new BcDSAContentVerifierProviderBuilder(digAlgFinder).build(certPubKey))); + ByteArrayInputStream bIn = new ByteArrayInputStream(cert.getEncoded()); CertificateFactory fact = CertificateFactory.getInstance("X.509"); @@ -787,6 +802,74 @@ public class BcCertTest //System.out.println(cert); } + /** + * we generate a self signed certificate for the sake of testing - ECDSA + */ + public void checkCreation3() + { + ECCurve curve = new ECCurve.Fp( + new BigInteger("883423532389192164791648750360308885314476597252960362792450860609699839"), // q + new BigInteger("7fffffffffffffffffffffff7fffffffffff8000000000007ffffffffffc", 16), // a + new BigInteger("6b016c3bdcf18941d0d654921475ca71a9db2fb27d1d37796185c2942c0a", 16)); // b + + ECDomainParameters params = new ECDomainParameters( + curve, + curve.decodePoint(Hex.decode("020ffa963cdca8816ccc33b8642bedf905c3d358573d3f27fbbd3b3cb9aaaf")), // G + new BigInteger("883423532389192164791648750360308884807550341691627752275345424702807307")); // n + + + ECPrivateKeyParameters privKey = new ECPrivateKeyParameters( + new BigInteger("876300101507107567501066130761671078357010671067781776716671676178726717"), // d + params); + + ECPublicKeyParameters pubKey = new ECPublicKeyParameters( + curve.decodePoint(Hex.decode("025b6dc53bc61a2548ffb0f671472de6c9521a9d2d2534e65abfcbd5fe0c70")), // Q + params); + + // + // distinguished name table. + // + X500NameBuilder builder = createStdBuilder(); + + // + // toString test + // + X500Name p = builder.build(); + String s = p.toString(); + + if (!s.equals("1.2.840.113549.1.9.1=feedback-crypto@bouncycastle.org,st=Victoria,l=Melbourne,o=The Legion of the Bouncy Castle,c=AU")) + { + fail("ordered X509Principal test failed - s = " + s + "."); + } + + // + // create the certificate - version 3 + // + try + { + ContentSigner sigGen = new BcECContentSignerBuilder( + new AlgorithmIdentifier(X9ObjectIdentifiers.ecdsa_with_SHA1), + new AlgorithmIdentifier(OIWObjectIdentifiers.idSHA1)).build(privKey); + BcX509v3CertificateBuilder certGen = new BcX509v3CertificateBuilder(builder.build(), BigInteger.valueOf(1), new Date(System.currentTimeMillis() - 50000), new Date(System.currentTimeMillis() + 50000), builder.build(), pubKey); + + X509CertificateHolder cert = certGen.build(sigGen); + + if (!cert.isValidOn(new Date())) + { + fail("not valid on date"); + } + + if (!cert.isSignatureValid(new BcECContentVerifierProviderBuilder(new DefaultDigestAlgorithmIdentifierFinder()).build(pubKey))) + { + fail("signature invalid"); + } + } + catch (Exception e) + { + fail("error setting generating cert - " + e.toString()); + } + } + private X500NameBuilder createStdBuilder() { X500NameBuilder builder = new X500NameBuilder(RFC4519Style.INSTANCE); @@ -813,7 +896,7 @@ public class BcCertTest } catch (Exception e) { - fail(dump + System.getProperty("line.separator") + getName() + ": "+ id + " failed - exception " + e.toString()); + fail(dump + Strings.lineSeparator() + getName() + ": "+ id + " failed - exception " + e.toString()); } } @@ -1416,6 +1499,7 @@ public class BcCertTest checkCreation1(); checkCreation2(); + checkCreation3(); checkCreation5(); createPSSCert("SHA1withRSAandMGF1"); diff --git a/bcpkix/src/main/java/org/bouncycastle/cert/test/CertPathLoopTest.java b/bcpkix/src/main/java/org/bouncycastle/cert/test/CertPathLoopTest.java index 09e921c1..b7d1fd26 100644 --- a/bcpkix/src/main/java/org/bouncycastle/cert/test/CertPathLoopTest.java +++ b/bcpkix/src/main/java/org/bouncycastle/cert/test/CertPathLoopTest.java @@ -1,6 +1,5 @@ package org.bouncycastle.cert.test;
-import java.io.ByteArrayInputStream;
import java.math.BigInteger;
import java.security.InvalidAlgorithmParameterException;
import java.security.KeyPair;
@@ -28,8 +27,6 @@ import java.util.HashSet; import java.util.List;
import java.util.Set;
-import org.bouncycastle.asn1.ASN1InputStream;
-import org.bouncycastle.asn1.ASN1Sequence;
import org.bouncycastle.asn1.x500.X500Name;
import org.bouncycastle.asn1.x509.BasicConstraints;
import org.bouncycastle.asn1.x509.Extension;
@@ -296,8 +293,7 @@ public class CertPathLoopTest static SubjectPublicKeyInfo getPublicKeyInfo(PublicKey k)
throws Exception
{
- return new SubjectPublicKeyInfo((ASN1Sequence)new ASN1InputStream(
- new ByteArrayInputStream(k.getEncoded())).readObject());
+ return SubjectPublicKeyInfo.getInstance(k.getEncoded());
}
}
diff --git a/bcpkix/src/main/java/org/bouncycastle/cert/test/CertTest.java b/bcpkix/src/main/java/org/bouncycastle/cert/test/CertTest.java index 30dec302..71807406 100644 --- a/bcpkix/src/main/java/org/bouncycastle/cert/test/CertTest.java +++ b/bcpkix/src/main/java/org/bouncycastle/cert/test/CertTest.java @@ -38,6 +38,7 @@ import org.bouncycastle.asn1.ASN1Encodable; import org.bouncycastle.asn1.ASN1EncodableVector; import org.bouncycastle.asn1.ASN1Enumerated; import org.bouncycastle.asn1.ASN1ObjectIdentifier; +import org.bouncycastle.asn1.ASN1OctetString; import org.bouncycastle.asn1.ASN1Primitive; import org.bouncycastle.asn1.DERNull; import org.bouncycastle.asn1.DEROctetString; @@ -51,15 +52,13 @@ import org.bouncycastle.asn1.x509.AlgorithmIdentifier; import org.bouncycastle.asn1.x509.AuthorityKeyIdentifier; import org.bouncycastle.asn1.x509.CRLReason; import org.bouncycastle.asn1.x509.Extension; +import org.bouncycastle.asn1.x509.Extensions; import org.bouncycastle.asn1.x509.ExtensionsGenerator; import org.bouncycastle.asn1.x509.GeneralName; import org.bouncycastle.asn1.x509.GeneralNames; import org.bouncycastle.asn1.x509.IssuingDistributionPoint; import org.bouncycastle.asn1.x509.KeyPurposeId; import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo; -import org.bouncycastle.asn1.x509.X509CertificateStructure; -import org.bouncycastle.asn1.x509.X509Extension; -import org.bouncycastle.asn1.x509.X509Extensions; import org.bouncycastle.asn1.x9.X9ObjectIdentifiers; import org.bouncycastle.cert.X509CRLEntryHolder; import org.bouncycastle.cert.X509CRLHolder; @@ -71,6 +70,7 @@ import org.bouncycastle.cert.jcajce.JcaX509CRLConverter; import org.bouncycastle.cert.jcajce.JcaX509CRLHolder; import org.bouncycastle.cert.jcajce.JcaX509CertificateConverter; import org.bouncycastle.cert.jcajce.JcaX509CertificateHolder; +import org.bouncycastle.cert.jcajce.JcaX509ExtensionUtils; import org.bouncycastle.cert.jcajce.JcaX509v1CertificateBuilder; import org.bouncycastle.cert.jcajce.JcaX509v2CRLBuilder; import org.bouncycastle.cert.jcajce.JcaX509v3CertificateBuilder; @@ -93,11 +93,10 @@ import org.bouncycastle.operator.bc.BcRSAContentSignerBuilder; import org.bouncycastle.operator.bc.BcRSAContentVerifierProviderBuilder; import org.bouncycastle.operator.jcajce.JcaContentSignerBuilder; import org.bouncycastle.operator.jcajce.JcaContentVerifierProviderBuilder; +import org.bouncycastle.util.Strings; import org.bouncycastle.util.encoders.Base64; import org.bouncycastle.util.encoders.Hex; import org.bouncycastle.util.test.SimpleTest; -import org.bouncycastle.x509.extension.AuthorityKeyIdentifierStructure; -import org.bouncycastle.x509.extension.X509ExtensionUtil; public class CertTest extends SimpleTest @@ -107,414 +106,414 @@ public class CertTest // test CA byte[] testCAp12 = Base64.decode( "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" - + "HLhcYQcQ1R+RucctAgIEAAAA"); + + "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" + + "HLhcYQcQ1R+RucctAgIEAAAA"); // // server.crt // - byte[] cert1 = Base64.decode( - "MIIDXjCCAsegAwIBAgIBBzANBgkqhkiG9w0BAQQFADCBtzELMAkGA1UEBhMCQVUx" - + "ETAPBgNVBAgTCFZpY3RvcmlhMRgwFgYDVQQHEw9Tb3V0aCBNZWxib3VybmUxGjAY" - + "BgNVBAoTEUNvbm5lY3QgNCBQdHkgTHRkMR4wHAYDVQQLExVDZXJ0aWZpY2F0ZSBB" - + "dXRob3JpdHkxFTATBgNVBAMTDENvbm5lY3QgNCBDQTEoMCYGCSqGSIb3DQEJARYZ" - + "d2VibWFzdGVyQGNvbm5lY3Q0LmNvbS5hdTAeFw0wMDA2MDIwNzU2MjFaFw0wMTA2" - + "MDIwNzU2MjFaMIG4MQswCQYDVQQGEwJBVTERMA8GA1UECBMIVmljdG9yaWExGDAW" - + "BgNVBAcTD1NvdXRoIE1lbGJvdXJuZTEaMBgGA1UEChMRQ29ubmVjdCA0IFB0eSBM" - + "dGQxFzAVBgNVBAsTDldlYnNlcnZlciBUZWFtMR0wGwYDVQQDExR3d3cyLmNvbm5l" - + "Y3Q0LmNvbS5hdTEoMCYGCSqGSIb3DQEJARYZd2VibWFzdGVyQGNvbm5lY3Q0LmNv" - + "bS5hdTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEArvDxclKAhyv7Q/Wmr2re" - + "Gw4XL9Cnh9e+6VgWy2AWNy/MVeXdlxzd7QAuc1eOWQkGQEiLPy5XQtTY+sBUJ3AO" - + "Rvd2fEVJIcjf29ey7bYua9J/vz5MG2KYo9/WCHIwqD9mmG9g0xLcfwq/s8ZJBswE" - + "7sb85VU+h94PTvsWOsWuKaECAwEAAaN3MHUwJAYDVR0RBB0wG4EZd2VibWFzdGVy" - + "QGNvbm5lY3Q0LmNvbS5hdTA6BglghkgBhvhCAQ0ELRYrbW9kX3NzbCBnZW5lcmF0" - + "ZWQgY3VzdG9tIHNlcnZlciBjZXJ0aWZpY2F0ZTARBglghkgBhvhCAQEEBAMCBkAw" - + "DQYJKoZIhvcNAQEEBQADgYEAotccfKpwSsIxM1Hae8DR7M/Rw8dg/RqOWx45HNVL" - + "iBS4/3N/TO195yeQKbfmzbAA2jbPVvIvGgTxPgO1MP4ZgvgRhasaa0qCJCkWvpM4" - + "yQf33vOiYQbpv4rTwzU8AmRlBG45WdjyNIigGV+oRc61aKCTnLq7zB8N3z1TF/bF" - + "5/8="); + byte[] cert1 = Base64.decode( + "MIIDXjCCAsegAwIBAgIBBzANBgkqhkiG9w0BAQQFADCBtzELMAkGA1UEBhMCQVUx" + + "ETAPBgNVBAgTCFZpY3RvcmlhMRgwFgYDVQQHEw9Tb3V0aCBNZWxib3VybmUxGjAY" + + "BgNVBAoTEUNvbm5lY3QgNCBQdHkgTHRkMR4wHAYDVQQLExVDZXJ0aWZpY2F0ZSBB" + + "dXRob3JpdHkxFTATBgNVBAMTDENvbm5lY3QgNCBDQTEoMCYGCSqGSIb3DQEJARYZ" + + "d2VibWFzdGVyQGNvbm5lY3Q0LmNvbS5hdTAeFw0wMDA2MDIwNzU2MjFaFw0wMTA2" + + "MDIwNzU2MjFaMIG4MQswCQYDVQQGEwJBVTERMA8GA1UECBMIVmljdG9yaWExGDAW" + + "BgNVBAcTD1NvdXRoIE1lbGJvdXJuZTEaMBgGA1UEChMRQ29ubmVjdCA0IFB0eSBM" + + "dGQxFzAVBgNVBAsTDldlYnNlcnZlciBUZWFtMR0wGwYDVQQDExR3d3cyLmNvbm5l" + + "Y3Q0LmNvbS5hdTEoMCYGCSqGSIb3DQEJARYZd2VibWFzdGVyQGNvbm5lY3Q0LmNv" + + "bS5hdTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEArvDxclKAhyv7Q/Wmr2re" + + "Gw4XL9Cnh9e+6VgWy2AWNy/MVeXdlxzd7QAuc1eOWQkGQEiLPy5XQtTY+sBUJ3AO" + + "Rvd2fEVJIcjf29ey7bYua9J/vz5MG2KYo9/WCHIwqD9mmG9g0xLcfwq/s8ZJBswE" + + "7sb85VU+h94PTvsWOsWuKaECAwEAAaN3MHUwJAYDVR0RBB0wG4EZd2VibWFzdGVy" + + "QGNvbm5lY3Q0LmNvbS5hdTA6BglghkgBhvhCAQ0ELRYrbW9kX3NzbCBnZW5lcmF0" + + "ZWQgY3VzdG9tIHNlcnZlciBjZXJ0aWZpY2F0ZTARBglghkgBhvhCAQEEBAMCBkAw" + + "DQYJKoZIhvcNAQEEBQADgYEAotccfKpwSsIxM1Hae8DR7M/Rw8dg/RqOWx45HNVL" + + "iBS4/3N/TO195yeQKbfmzbAA2jbPVvIvGgTxPgO1MP4ZgvgRhasaa0qCJCkWvpM4" + + "yQf33vOiYQbpv4rTwzU8AmRlBG45WdjyNIigGV+oRc61aKCTnLq7zB8N3z1TF/bF" + + "5/8="); // // ca.crt // - byte[] cert2 = Base64.decode( - "MIIDbDCCAtWgAwIBAgIBADANBgkqhkiG9w0BAQQFADCBtzELMAkGA1UEBhMCQVUx" - + "ETAPBgNVBAgTCFZpY3RvcmlhMRgwFgYDVQQHEw9Tb3V0aCBNZWxib3VybmUxGjAY" - + "BgNVBAoTEUNvbm5lY3QgNCBQdHkgTHRkMR4wHAYDVQQLExVDZXJ0aWZpY2F0ZSBB" - + "dXRob3JpdHkxFTATBgNVBAMTDENvbm5lY3QgNCBDQTEoMCYGCSqGSIb3DQEJARYZ" - + "d2VibWFzdGVyQGNvbm5lY3Q0LmNvbS5hdTAeFw0wMDA2MDIwNzU1MzNaFw0wMTA2" - + "MDIwNzU1MzNaMIG3MQswCQYDVQQGEwJBVTERMA8GA1UECBMIVmljdG9yaWExGDAW" - + "BgNVBAcTD1NvdXRoIE1lbGJvdXJuZTEaMBgGA1UEChMRQ29ubmVjdCA0IFB0eSBM" - + "dGQxHjAcBgNVBAsTFUNlcnRpZmljYXRlIEF1dGhvcml0eTEVMBMGA1UEAxMMQ29u" - + "bmVjdCA0IENBMSgwJgYJKoZIhvcNAQkBFhl3ZWJtYXN0ZXJAY29ubmVjdDQuY29t" - + "LmF1MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDgs5ptNG6Qv1ZpCDuUNGmv" - + "rhjqMDPd3ri8JzZNRiiFlBA4e6/ReaO1U8ASewDeQMH6i9R6degFdQRLngbuJP0s" - + "xcEE+SksEWNvygfzLwV9J/q+TQDyJYK52utb++lS0b48A1KPLwEsyL6kOAgelbur" - + "ukwxowprKUIV7Knf1ajetQIDAQABo4GFMIGCMCQGA1UdEQQdMBuBGXdlYm1hc3Rl" - + "ckBjb25uZWN0NC5jb20uYXUwDwYDVR0TBAgwBgEB/wIBADA2BglghkgBhvhCAQ0E" - + "KRYnbW9kX3NzbCBnZW5lcmF0ZWQgY3VzdG9tIENBIGNlcnRpZmljYXRlMBEGCWCG" - + "SAGG+EIBAQQEAwICBDANBgkqhkiG9w0BAQQFAAOBgQCsGvfdghH8pPhlwm1r3pQk" - + "msnLAVIBb01EhbXm2861iXZfWqGQjrGAaA0ZpXNk9oo110yxoqEoSJSzniZa7Xtz" - + "soTwNUpE0SLHvWf/SlKdFWlzXA+vOZbzEv4UmjeelekTm7lc01EEa5QRVzOxHFtQ" - + "DhkaJ8VqOMajkQFma2r9iA=="); + byte[] cert2 = Base64.decode( + "MIIDbDCCAtWgAwIBAgIBADANBgkqhkiG9w0BAQQFADCBtzELMAkGA1UEBhMCQVUx" + + "ETAPBgNVBAgTCFZpY3RvcmlhMRgwFgYDVQQHEw9Tb3V0aCBNZWxib3VybmUxGjAY" + + "BgNVBAoTEUNvbm5lY3QgNCBQdHkgTHRkMR4wHAYDVQQLExVDZXJ0aWZpY2F0ZSBB" + + "dXRob3JpdHkxFTATBgNVBAMTDENvbm5lY3QgNCBDQTEoMCYGCSqGSIb3DQEJARYZ" + + "d2VibWFzdGVyQGNvbm5lY3Q0LmNvbS5hdTAeFw0wMDA2MDIwNzU1MzNaFw0wMTA2" + + "MDIwNzU1MzNaMIG3MQswCQYDVQQGEwJBVTERMA8GA1UECBMIVmljdG9yaWExGDAW" + + "BgNVBAcTD1NvdXRoIE1lbGJvdXJuZTEaMBgGA1UEChMRQ29ubmVjdCA0IFB0eSBM" + + "dGQxHjAcBgNVBAsTFUNlcnRpZmljYXRlIEF1dGhvcml0eTEVMBMGA1UEAxMMQ29u" + + "bmVjdCA0IENBMSgwJgYJKoZIhvcNAQkBFhl3ZWJtYXN0ZXJAY29ubmVjdDQuY29t" + + "LmF1MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDgs5ptNG6Qv1ZpCDuUNGmv" + + "rhjqMDPd3ri8JzZNRiiFlBA4e6/ReaO1U8ASewDeQMH6i9R6degFdQRLngbuJP0s" + + "xcEE+SksEWNvygfzLwV9J/q+TQDyJYK52utb++lS0b48A1KPLwEsyL6kOAgelbur" + + "ukwxowprKUIV7Knf1ajetQIDAQABo4GFMIGCMCQGA1UdEQQdMBuBGXdlYm1hc3Rl" + + "ckBjb25uZWN0NC5jb20uYXUwDwYDVR0TBAgwBgEB/wIBADA2BglghkgBhvhCAQ0E" + + "KRYnbW9kX3NzbCBnZW5lcmF0ZWQgY3VzdG9tIENBIGNlcnRpZmljYXRlMBEGCWCG" + + "SAGG+EIBAQQEAwICBDANBgkqhkiG9w0BAQQFAAOBgQCsGvfdghH8pPhlwm1r3pQk" + + "msnLAVIBb01EhbXm2861iXZfWqGQjrGAaA0ZpXNk9oo110yxoqEoSJSzniZa7Xtz" + + "soTwNUpE0SLHvWf/SlKdFWlzXA+vOZbzEv4UmjeelekTm7lc01EEa5QRVzOxHFtQ" + + "DhkaJ8VqOMajkQFma2r9iA=="); // // testx509.pem // - byte[] cert3 = Base64.decode( - "MIIBWzCCAQYCARgwDQYJKoZIhvcNAQEEBQAwODELMAkGA1UEBhMCQVUxDDAKBgNV" - + "BAgTA1FMRDEbMBkGA1UEAxMSU1NMZWF5L3JzYSB0ZXN0IENBMB4XDTk1MDYxOTIz" - + "MzMxMloXDTk1MDcxNzIzMzMxMlowOjELMAkGA1UEBhMCQVUxDDAKBgNVBAgTA1FM" - + "RDEdMBsGA1UEAxMUU1NMZWF5L3JzYSB0ZXN0IGNlcnQwXDANBgkqhkiG9w0BAQEF" - + "AANLADBIAkEAqtt6qS5GTxVxGZYWa0/4u+IwHf7p2LNZbcPBp9/OfIcYAXBQn8hO" - + "/Re1uwLKXdCjIoaGs4DLdG88rkzfyK5dPQIDAQABMAwGCCqGSIb3DQIFBQADQQAE" - + "Wc7EcF8po2/ZO6kNCwK/ICH6DobgLekA5lSLr5EvuioZniZp5lFzAw4+YzPQ7XKJ" - + "zl9HYIMxATFyqSiD9jsx"); + byte[] cert3 = Base64.decode( + "MIIBWzCCAQYCARgwDQYJKoZIhvcNAQEEBQAwODELMAkGA1UEBhMCQVUxDDAKBgNV" + + "BAgTA1FMRDEbMBkGA1UEAxMSU1NMZWF5L3JzYSB0ZXN0IENBMB4XDTk1MDYxOTIz" + + "MzMxMloXDTk1MDcxNzIzMzMxMlowOjELMAkGA1UEBhMCQVUxDDAKBgNVBAgTA1FM" + + "RDEdMBsGA1UEAxMUU1NMZWF5L3JzYSB0ZXN0IGNlcnQwXDANBgkqhkiG9w0BAQEF" + + "AANLADBIAkEAqtt6qS5GTxVxGZYWa0/4u+IwHf7p2LNZbcPBp9/OfIcYAXBQn8hO" + + "/Re1uwLKXdCjIoaGs4DLdG88rkzfyK5dPQIDAQABMAwGCCqGSIb3DQIFBQADQQAE" + + "Wc7EcF8po2/ZO6kNCwK/ICH6DobgLekA5lSLr5EvuioZniZp5lFzAw4+YzPQ7XKJ" + + "zl9HYIMxATFyqSiD9jsx"); // // v3-cert1.pem // - byte[] cert4 = Base64.decode( - "MIICjTCCAfigAwIBAgIEMaYgRzALBgkqhkiG9w0BAQQwRTELMAkGA1UEBhMCVVMx" - + "NjA0BgNVBAoTLU5hdGlvbmFsIEFlcm9uYXV0aWNzIGFuZCBTcGFjZSBBZG1pbmlz" - + "dHJhdGlvbjAmFxE5NjA1MjgxMzQ5MDUrMDgwMBcROTgwNTI4MTM0OTA1KzA4MDAw" - + "ZzELMAkGA1UEBhMCVVMxNjA0BgNVBAoTLU5hdGlvbmFsIEFlcm9uYXV0aWNzIGFu" - + "ZCBTcGFjZSBBZG1pbmlzdHJhdGlvbjEgMAkGA1UEBRMCMTYwEwYDVQQDEwxTdGV2" - + "ZSBTY2hvY2gwWDALBgkqhkiG9w0BAQEDSQAwRgJBALrAwyYdgxmzNP/ts0Uyf6Bp" - + "miJYktU/w4NG67ULaN4B5CnEz7k57s9o3YY3LecETgQ5iQHmkwlYDTL2fTgVfw0C" - + "AQOjgaswgagwZAYDVR0ZAQH/BFowWDBWMFQxCzAJBgNVBAYTAlVTMTYwNAYDVQQK" - + "Ey1OYXRpb25hbCBBZXJvbmF1dGljcyBhbmQgU3BhY2UgQWRtaW5pc3RyYXRpb24x" - + "DTALBgNVBAMTBENSTDEwFwYDVR0BAQH/BA0wC4AJODMyOTcwODEwMBgGA1UdAgQR" - + "MA8ECTgzMjk3MDgyM4ACBSAwDQYDVR0KBAYwBAMCBkAwCwYJKoZIhvcNAQEEA4GB" - + "AH2y1VCEw/A4zaXzSYZJTTUi3uawbbFiS2yxHvgf28+8Js0OHXk1H1w2d6qOHH21" - + "X82tZXd/0JtG0g1T9usFFBDvYK8O0ebgz/P5ELJnBL2+atObEuJy1ZZ0pBDWINR3" - + "WkDNLCGiTkCKp0F5EWIrVDwh54NNevkCQRZita+z4IBO"); + byte[] cert4 = Base64.decode( + "MIICjTCCAfigAwIBAgIEMaYgRzALBgkqhkiG9w0BAQQwRTELMAkGA1UEBhMCVVMx" + + "NjA0BgNVBAoTLU5hdGlvbmFsIEFlcm9uYXV0aWNzIGFuZCBTcGFjZSBBZG1pbmlz" + + "dHJhdGlvbjAmFxE5NjA1MjgxMzQ5MDUrMDgwMBcROTgwNTI4MTM0OTA1KzA4MDAw" + + "ZzELMAkGA1UEBhMCVVMxNjA0BgNVBAoTLU5hdGlvbmFsIEFlcm9uYXV0aWNzIGFu" + + "ZCBTcGFjZSBBZG1pbmlzdHJhdGlvbjEgMAkGA1UEBRMCMTYwEwYDVQQDEwxTdGV2" + + "ZSBTY2hvY2gwWDALBgkqhkiG9w0BAQEDSQAwRgJBALrAwyYdgxmzNP/ts0Uyf6Bp" + + "miJYktU/w4NG67ULaN4B5CnEz7k57s9o3YY3LecETgQ5iQHmkwlYDTL2fTgVfw0C" + + "AQOjgaswgagwZAYDVR0ZAQH/BFowWDBWMFQxCzAJBgNVBAYTAlVTMTYwNAYDVQQK" + + "Ey1OYXRpb25hbCBBZXJvbmF1dGljcyBhbmQgU3BhY2UgQWRtaW5pc3RyYXRpb24x" + + "DTALBgNVBAMTBENSTDEwFwYDVR0BAQH/BA0wC4AJODMyOTcwODEwMBgGA1UdAgQR" + + "MA8ECTgzMjk3MDgyM4ACBSAwDQYDVR0KBAYwBAMCBkAwCwYJKoZIhvcNAQEEA4GB" + + "AH2y1VCEw/A4zaXzSYZJTTUi3uawbbFiS2yxHvgf28+8Js0OHXk1H1w2d6qOHH21" + + "X82tZXd/0JtG0g1T9usFFBDvYK8O0ebgz/P5ELJnBL2+atObEuJy1ZZ0pBDWINR3" + + "WkDNLCGiTkCKp0F5EWIrVDwh54NNevkCQRZita+z4IBO"); // // v3-cert2.pem // - byte[] cert5 = Base64.decode( - "MIICiTCCAfKgAwIBAgIEMeZfHzANBgkqhkiG9w0BAQQFADB9MQswCQYDVQQGEwJD" - + "YTEPMA0GA1UEBxMGTmVwZWFuMR4wHAYDVQQLExVObyBMaWFiaWxpdHkgQWNjZXB0" - + "ZWQxHzAdBgNVBAoTFkZvciBEZW1vIFB1cnBvc2VzIE9ubHkxHDAaBgNVBAMTE0Vu" - + "dHJ1c3QgRGVtbyBXZWIgQ0EwHhcNOTYwNzEyMTQyMDE1WhcNOTYxMDEyMTQyMDE1" - + "WjB0MSQwIgYJKoZIhvcNAQkBExVjb29rZUBpc3NsLmF0bC5ocC5jb20xCzAJBgNV" - + "BAYTAlVTMScwJQYDVQQLEx5IZXdsZXR0IFBhY2thcmQgQ29tcGFueSAoSVNTTCkx" - + "FjAUBgNVBAMTDVBhdWwgQS4gQ29va2UwXDANBgkqhkiG9w0BAQEFAANLADBIAkEA" - + "6ceSq9a9AU6g+zBwaL/yVmW1/9EE8s5you1mgjHnj0wAILuoB3L6rm6jmFRy7QZT" - + "G43IhVZdDua4e+5/n1ZslwIDAQABo2MwYTARBglghkgBhvhCAQEEBAMCB4AwTAYJ" - + "YIZIAYb4QgENBD8WPVRoaXMgY2VydGlmaWNhdGUgaXMgb25seSBpbnRlbmRlZCBm" - + "b3IgZGVtb25zdHJhdGlvbiBwdXJwb3Nlcy4wDQYJKoZIhvcNAQEEBQADgYEAi8qc" - + "F3zfFqy1sV8NhjwLVwOKuSfhR/Z8mbIEUeSTlnH3QbYt3HWZQ+vXI8mvtZoBc2Fz" - + "lexKeIkAZXCesqGbs6z6nCt16P6tmdfbZF3I3AWzLquPcOXjPf4HgstkyvVBn0Ap" - + "jAFN418KF/Cx4qyHB4cjdvLrRjjQLnb2+ibo7QU="); + byte[] cert5 = Base64.decode( + "MIICiTCCAfKgAwIBAgIEMeZfHzANBgkqhkiG9w0BAQQFADB9MQswCQYDVQQGEwJD" + + "YTEPMA0GA1UEBxMGTmVwZWFuMR4wHAYDVQQLExVObyBMaWFiaWxpdHkgQWNjZXB0" + + "ZWQxHzAdBgNVBAoTFkZvciBEZW1vIFB1cnBvc2VzIE9ubHkxHDAaBgNVBAMTE0Vu" + + "dHJ1c3QgRGVtbyBXZWIgQ0EwHhcNOTYwNzEyMTQyMDE1WhcNOTYxMDEyMTQyMDE1" + + "WjB0MSQwIgYJKoZIhvcNAQkBExVjb29rZUBpc3NsLmF0bC5ocC5jb20xCzAJBgNV" + + "BAYTAlVTMScwJQYDVQQLEx5IZXdsZXR0IFBhY2thcmQgQ29tcGFueSAoSVNTTCkx" + + "FjAUBgNVBAMTDVBhdWwgQS4gQ29va2UwXDANBgkqhkiG9w0BAQEFAANLADBIAkEA" + + "6ceSq9a9AU6g+zBwaL/yVmW1/9EE8s5you1mgjHnj0wAILuoB3L6rm6jmFRy7QZT" + + "G43IhVZdDua4e+5/n1ZslwIDAQABo2MwYTARBglghkgBhvhCAQEEBAMCB4AwTAYJ" + + "YIZIAYb4QgENBD8WPVRoaXMgY2VydGlmaWNhdGUgaXMgb25seSBpbnRlbmRlZCBm" + + "b3IgZGVtb25zdHJhdGlvbiBwdXJwb3Nlcy4wDQYJKoZIhvcNAQEEBQADgYEAi8qc" + + "F3zfFqy1sV8NhjwLVwOKuSfhR/Z8mbIEUeSTlnH3QbYt3HWZQ+vXI8mvtZoBc2Fz" + + "lexKeIkAZXCesqGbs6z6nCt16P6tmdfbZF3I3AWzLquPcOXjPf4HgstkyvVBn0Ap" + + "jAFN418KF/Cx4qyHB4cjdvLrRjjQLnb2+ibo7QU="); // // pem encoded pkcs7 // - byte[] cert6 = Base64.decode( - "MIAGCSqGSIb3DQEHAqCAMIACAQExCzAJBgUrDgMCGgUAMIAGCSqGSIb3DQEHAQAAoIIJbzCCAj0w" - + "ggGmAhEAzbp/VvDf5LxU/iKss3KqVTANBgkqhkiG9w0BAQIFADBfMQswCQYDVQQGEwJVUzEXMBUG" - + "A1UEChMOVmVyaVNpZ24sIEluYy4xNzA1BgNVBAsTLkNsYXNzIDEgUHVibGljIFByaW1hcnkgQ2Vy" - + "dGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNOTYwMTI5MDAwMDAwWhcNMjgwODAxMjM1OTU5WjBfMQsw" - + "CQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xNzA1BgNVBAsTLkNsYXNzIDEgUHVi" - + "bGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwgZ8wDQYJKoZIhvcNAQEBBQADgY0A" - + "MIGJAoGBAOUZv22jVmEtmUhx9mfeuY3rt56GgAqRDvo4Ja9GiILlc6igmyRdDR/MZW4MsNBWhBiH" - + "mgabEKFz37RYOWtuwfYV1aioP6oSBo0xrH+wNNePNGeICc0UEeJORVZpH3gCgNrcR5EpuzbJY1zF" - + "4Ncth3uhtzKwezC6Ki8xqu6jZ9rbAgMBAAEwDQYJKoZIhvcNAQECBQADgYEATD+4i8Zo3+5DMw5d" - + "6abLB4RNejP/khv0Nq3YlSI2aBFsfELM85wuxAc/FLAPT/+Qknb54rxK6Y/NoIAK98Up8YIiXbix" - + "3YEjo3slFUYweRb46gVLlH8dwhzI47f0EEA8E8NfH1PoSOSGtHuhNbB7Jbq4046rPzidADQAmPPR" - + "cZQwggMuMIICl6ADAgECAhEA0nYujRQMPX2yqCVdr+4NdTANBgkqhkiG9w0BAQIFADBfMQswCQYD" - + "VQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xNzA1BgNVBAsTLkNsYXNzIDEgUHVibGlj" - + "IFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNOTgwNTEyMDAwMDAwWhcNMDgwNTEy" - + "MjM1OTU5WjCBzDEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRy" - + "dXN0IE5ldHdvcmsxRjBEBgNVBAsTPXd3dy52ZXJpc2lnbi5jb20vcmVwb3NpdG9yeS9SUEEgSW5j" - + "b3JwLiBCeSBSZWYuLExJQUIuTFREKGMpOTgxSDBGBgNVBAMTP1ZlcmlTaWduIENsYXNzIDEgQ0Eg" - + "SW5kaXZpZHVhbCBTdWJzY3JpYmVyLVBlcnNvbmEgTm90IFZhbGlkYXRlZDCBnzANBgkqhkiG9w0B" - + "AQEFAAOBjQAwgYkCgYEAu1pEigQWu1X9A3qKLZRPFXg2uA1Ksm+cVL+86HcqnbnwaLuV2TFBcHqB" - + "S7lIE1YtxwjhhEKrwKKSq0RcqkLwgg4C6S/7wju7vsknCl22sDZCM7VuVIhPh0q/Gdr5FegPh7Yc" - + "48zGmo5/aiSS4/zgZbqnsX7vyds3ashKyAkG5JkCAwEAAaN8MHowEQYJYIZIAYb4QgEBBAQDAgEG" - + "MEcGA1UdIARAMD4wPAYLYIZIAYb4RQEHAQEwLTArBggrBgEFBQcCARYfd3d3LnZlcmlzaWduLmNv" - + "bS9yZXBvc2l0b3J5L1JQQTAPBgNVHRMECDAGAQH/AgEAMAsGA1UdDwQEAwIBBjANBgkqhkiG9w0B" - + "AQIFAAOBgQCIuDc73dqUNwCtqp/hgQFxHpJqbS/28Z3TymQ43BuYDAeGW4UVag+5SYWklfEXfWe0" - + "fy0s3ZpCnsM+tI6q5QsG3vJWKvozx74Z11NMw73I4xe1pElCY+zCphcPXVgaSTyQXFWjZSAA/Rgg" - + "5V+CprGoksVYasGNAzzrw80FopCubjCCA/gwggNhoAMCAQICEBbbn/1G1zppD6KsP01bwywwDQYJ" - + "KoZIhvcNAQEEBQAwgcwxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQLExZWZXJpU2ln" - + "biBUcnVzdCBOZXR3b3JrMUYwRAYDVQQLEz13d3cudmVyaXNpZ24uY29tL3JlcG9zaXRvcnkvUlBB" - + "IEluY29ycC4gQnkgUmVmLixMSUFCLkxURChjKTk4MUgwRgYDVQQDEz9WZXJpU2lnbiBDbGFzcyAx" - + "IENBIEluZGl2aWR1YWwgU3Vic2NyaWJlci1QZXJzb25hIE5vdCBWYWxpZGF0ZWQwHhcNMDAxMDAy" - + "MDAwMDAwWhcNMDAxMjAxMjM1OTU5WjCCAQcxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYD" - + "VQQLExZWZXJpU2lnbiBUcnVzdCBOZXR3b3JrMUYwRAYDVQQLEz13d3cudmVyaXNpZ24uY29tL3Jl" - + "cG9zaXRvcnkvUlBBIEluY29ycC4gYnkgUmVmLixMSUFCLkxURChjKTk4MR4wHAYDVQQLExVQZXJz" - + "b25hIE5vdCBWYWxpZGF0ZWQxJzAlBgNVBAsTHkRpZ2l0YWwgSUQgQ2xhc3MgMSAtIE1pY3Jvc29m" - + "dDETMBEGA1UEAxQKRGF2aWQgUnlhbjElMCMGCSqGSIb3DQEJARYWZGF2aWRAbGl2ZW1lZGlhLmNv" - + "bS5hdTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAqxBsdeNmSvFqhMNwhQgNzM8mdjX9eSXb" - + "DawpHtQHjmh0AKJSa3IwUY0VIsyZHuXWktO/CgaMBVPt6OVf/n0R2sQigMP6Y+PhEiS0vCJBL9aK" - + "0+pOo2qXrjVBmq+XuCyPTnc+BOSrU26tJsX0P9BYorwySiEGxGanBNATdVL4NdUCAwEAAaOBnDCB" - + "mTAJBgNVHRMEAjAAMEQGA1UdIAQ9MDswOQYLYIZIAYb4RQEHAQgwKjAoBggrBgEFBQcCARYcaHR0" - + "cHM6Ly93d3cudmVyaXNpZ24uY29tL3JwYTARBglghkgBhvhCAQEEBAMCB4AwMwYDVR0fBCwwKjAo" - + "oCagJIYiaHR0cDovL2NybC52ZXJpc2lnbi5jb20vY2xhc3MxLmNybDANBgkqhkiG9w0BAQQFAAOB" - + "gQBC8yIIdVGpFTf8/YiL14cMzcmL0nIRm4kGR3U59z7UtcXlfNXXJ8MyaeI/BnXwG/gD5OKYqW6R" - + "yca9vZOxf1uoTBl82gInk865ED3Tej6msCqFzZffnSUQvOIeqLxxDlqYRQ6PmW2nAnZeyjcnbI5Y" - + "syQSM2fmo7n6qJFP+GbFezGCAkUwggJBAgEBMIHhMIHMMRcwFQYDVQQKEw5WZXJpU2lnbiwgSW5j" - + "LjEfMB0GA1UECxMWVmVyaVNpZ24gVHJ1c3QgTmV0d29yazFGMEQGA1UECxM9d3d3LnZlcmlzaWdu" - + "LmNvbS9yZXBvc2l0b3J5L1JQQSBJbmNvcnAuIEJ5IFJlZi4sTElBQi5MVEQoYyk5ODFIMEYGA1UE" - + "AxM/VmVyaVNpZ24gQ2xhc3MgMSBDQSBJbmRpdmlkdWFsIFN1YnNjcmliZXItUGVyc29uYSBOb3Qg" - + "VmFsaWRhdGVkAhAW25/9Rtc6aQ+irD9NW8MsMAkGBSsOAwIaBQCggbowGAYJKoZIhvcNAQkDMQsG" - + "CSqGSIb3DQEHATAcBgkqhkiG9w0BCQUxDxcNMDAxMDAyMTczNTE4WjAjBgkqhkiG9w0BCQQxFgQU" - + "gZjSaBEY2oxGvlQUIMnxSXhivK8wWwYJKoZIhvcNAQkPMU4wTDAKBggqhkiG9w0DBzAOBggqhkiG" - + "9w0DAgICAIAwDQYIKoZIhvcNAwICAUAwBwYFKw4DAgcwDQYIKoZIhvcNAwICASgwBwYFKw4DAh0w" - + "DQYJKoZIhvcNAQEBBQAEgYAzk+PU91/ZFfoiuKOECjxEh9fDYE2jfDCheBIgh5gdcCo+sS1WQs8O" - + "HreQ9Nop/JdJv1DQMBK6weNBBDoP0EEkRm1XCC144XhXZC82jBZohYmi2WvDbbC//YN58kRMYMyy" - + "srrfn4Z9I+6kTriGXkrpGk9Q0LSGjmG2BIsqiF0dvwAAAAAAAA=="); + byte[] cert6 = Base64.decode( + "MIAGCSqGSIb3DQEHAqCAMIACAQExCzAJBgUrDgMCGgUAMIAGCSqGSIb3DQEHAQAAoIIJbzCCAj0w" + + "ggGmAhEAzbp/VvDf5LxU/iKss3KqVTANBgkqhkiG9w0BAQIFADBfMQswCQYDVQQGEwJVUzEXMBUG" + + "A1UEChMOVmVyaVNpZ24sIEluYy4xNzA1BgNVBAsTLkNsYXNzIDEgUHVibGljIFByaW1hcnkgQ2Vy" + + "dGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNOTYwMTI5MDAwMDAwWhcNMjgwODAxMjM1OTU5WjBfMQsw" + + "CQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xNzA1BgNVBAsTLkNsYXNzIDEgUHVi" + + "bGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwgZ8wDQYJKoZIhvcNAQEBBQADgY0A" + + "MIGJAoGBAOUZv22jVmEtmUhx9mfeuY3rt56GgAqRDvo4Ja9GiILlc6igmyRdDR/MZW4MsNBWhBiH" + + "mgabEKFz37RYOWtuwfYV1aioP6oSBo0xrH+wNNePNGeICc0UEeJORVZpH3gCgNrcR5EpuzbJY1zF" + + "4Ncth3uhtzKwezC6Ki8xqu6jZ9rbAgMBAAEwDQYJKoZIhvcNAQECBQADgYEATD+4i8Zo3+5DMw5d" + + "6abLB4RNejP/khv0Nq3YlSI2aBFsfELM85wuxAc/FLAPT/+Qknb54rxK6Y/NoIAK98Up8YIiXbix" + + "3YEjo3slFUYweRb46gVLlH8dwhzI47f0EEA8E8NfH1PoSOSGtHuhNbB7Jbq4046rPzidADQAmPPR" + + "cZQwggMuMIICl6ADAgECAhEA0nYujRQMPX2yqCVdr+4NdTANBgkqhkiG9w0BAQIFADBfMQswCQYD" + + "VQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xNzA1BgNVBAsTLkNsYXNzIDEgUHVibGlj" + + "IFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNOTgwNTEyMDAwMDAwWhcNMDgwNTEy" + + "MjM1OTU5WjCBzDEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRy" + + "dXN0IE5ldHdvcmsxRjBEBgNVBAsTPXd3dy52ZXJpc2lnbi5jb20vcmVwb3NpdG9yeS9SUEEgSW5j" + + "b3JwLiBCeSBSZWYuLExJQUIuTFREKGMpOTgxSDBGBgNVBAMTP1ZlcmlTaWduIENsYXNzIDEgQ0Eg" + + "SW5kaXZpZHVhbCBTdWJzY3JpYmVyLVBlcnNvbmEgTm90IFZhbGlkYXRlZDCBnzANBgkqhkiG9w0B" + + "AQEFAAOBjQAwgYkCgYEAu1pEigQWu1X9A3qKLZRPFXg2uA1Ksm+cVL+86HcqnbnwaLuV2TFBcHqB" + + "S7lIE1YtxwjhhEKrwKKSq0RcqkLwgg4C6S/7wju7vsknCl22sDZCM7VuVIhPh0q/Gdr5FegPh7Yc" + + "48zGmo5/aiSS4/zgZbqnsX7vyds3ashKyAkG5JkCAwEAAaN8MHowEQYJYIZIAYb4QgEBBAQDAgEG" + + "MEcGA1UdIARAMD4wPAYLYIZIAYb4RQEHAQEwLTArBggrBgEFBQcCARYfd3d3LnZlcmlzaWduLmNv" + + "bS9yZXBvc2l0b3J5L1JQQTAPBgNVHRMECDAGAQH/AgEAMAsGA1UdDwQEAwIBBjANBgkqhkiG9w0B" + + "AQIFAAOBgQCIuDc73dqUNwCtqp/hgQFxHpJqbS/28Z3TymQ43BuYDAeGW4UVag+5SYWklfEXfWe0" + + "fy0s3ZpCnsM+tI6q5QsG3vJWKvozx74Z11NMw73I4xe1pElCY+zCphcPXVgaSTyQXFWjZSAA/Rgg" + + "5V+CprGoksVYasGNAzzrw80FopCubjCCA/gwggNhoAMCAQICEBbbn/1G1zppD6KsP01bwywwDQYJ" + + "KoZIhvcNAQEEBQAwgcwxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQLExZWZXJpU2ln" + + "biBUcnVzdCBOZXR3b3JrMUYwRAYDVQQLEz13d3cudmVyaXNpZ24uY29tL3JlcG9zaXRvcnkvUlBB" + + "IEluY29ycC4gQnkgUmVmLixMSUFCLkxURChjKTk4MUgwRgYDVQQDEz9WZXJpU2lnbiBDbGFzcyAx" + + "IENBIEluZGl2aWR1YWwgU3Vic2NyaWJlci1QZXJzb25hIE5vdCBWYWxpZGF0ZWQwHhcNMDAxMDAy" + + "MDAwMDAwWhcNMDAxMjAxMjM1OTU5WjCCAQcxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYD" + + "VQQLExZWZXJpU2lnbiBUcnVzdCBOZXR3b3JrMUYwRAYDVQQLEz13d3cudmVyaXNpZ24uY29tL3Jl" + + "cG9zaXRvcnkvUlBBIEluY29ycC4gYnkgUmVmLixMSUFCLkxURChjKTk4MR4wHAYDVQQLExVQZXJz" + + "b25hIE5vdCBWYWxpZGF0ZWQxJzAlBgNVBAsTHkRpZ2l0YWwgSUQgQ2xhc3MgMSAtIE1pY3Jvc29m" + + "dDETMBEGA1UEAxQKRGF2aWQgUnlhbjElMCMGCSqGSIb3DQEJARYWZGF2aWRAbGl2ZW1lZGlhLmNv" + + "bS5hdTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAqxBsdeNmSvFqhMNwhQgNzM8mdjX9eSXb" + + "DawpHtQHjmh0AKJSa3IwUY0VIsyZHuXWktO/CgaMBVPt6OVf/n0R2sQigMP6Y+PhEiS0vCJBL9aK" + + "0+pOo2qXrjVBmq+XuCyPTnc+BOSrU26tJsX0P9BYorwySiEGxGanBNATdVL4NdUCAwEAAaOBnDCB" + + "mTAJBgNVHRMEAjAAMEQGA1UdIAQ9MDswOQYLYIZIAYb4RQEHAQgwKjAoBggrBgEFBQcCARYcaHR0" + + "cHM6Ly93d3cudmVyaXNpZ24uY29tL3JwYTARBglghkgBhvhCAQEEBAMCB4AwMwYDVR0fBCwwKjAo" + + "oCagJIYiaHR0cDovL2NybC52ZXJpc2lnbi5jb20vY2xhc3MxLmNybDANBgkqhkiG9w0BAQQFAAOB" + + "gQBC8yIIdVGpFTf8/YiL14cMzcmL0nIRm4kGR3U59z7UtcXlfNXXJ8MyaeI/BnXwG/gD5OKYqW6R" + + "yca9vZOxf1uoTBl82gInk865ED3Tej6msCqFzZffnSUQvOIeqLxxDlqYRQ6PmW2nAnZeyjcnbI5Y" + + "syQSM2fmo7n6qJFP+GbFezGCAkUwggJBAgEBMIHhMIHMMRcwFQYDVQQKEw5WZXJpU2lnbiwgSW5j" + + "LjEfMB0GA1UECxMWVmVyaVNpZ24gVHJ1c3QgTmV0d29yazFGMEQGA1UECxM9d3d3LnZlcmlzaWdu" + + "LmNvbS9yZXBvc2l0b3J5L1JQQSBJbmNvcnAuIEJ5IFJlZi4sTElBQi5MVEQoYyk5ODFIMEYGA1UE" + + "AxM/VmVyaVNpZ24gQ2xhc3MgMSBDQSBJbmRpdmlkdWFsIFN1YnNjcmliZXItUGVyc29uYSBOb3Qg" + + "VmFsaWRhdGVkAhAW25/9Rtc6aQ+irD9NW8MsMAkGBSsOAwIaBQCggbowGAYJKoZIhvcNAQkDMQsG" + + "CSqGSIb3DQEHATAcBgkqhkiG9w0BCQUxDxcNMDAxMDAyMTczNTE4WjAjBgkqhkiG9w0BCQQxFgQU" + + "gZjSaBEY2oxGvlQUIMnxSXhivK8wWwYJKoZIhvcNAQkPMU4wTDAKBggqhkiG9w0DBzAOBggqhkiG" + + "9w0DAgICAIAwDQYIKoZIhvcNAwICAUAwBwYFKw4DAgcwDQYIKoZIhvcNAwICASgwBwYFKw4DAh0w" + + "DQYJKoZIhvcNAQEBBQAEgYAzk+PU91/ZFfoiuKOECjxEh9fDYE2jfDCheBIgh5gdcCo+sS1WQs8O" + + "HreQ9Nop/JdJv1DQMBK6weNBBDoP0EEkRm1XCC144XhXZC82jBZohYmi2WvDbbC//YN58kRMYMyy" + + "srrfn4Z9I+6kTriGXkrpGk9Q0LSGjmG2BIsqiF0dvwAAAAAAAA=="); // // dsaWithSHA1 cert // - byte[] cert7 = Base64.decode( - "MIIEXAYJKoZIhvcNAQcCoIIETTCCBEkCAQExCzAJBgUrDgMCGgUAMAsGCSqG" - + "SIb3DQEHAaCCAsMwggK/MIIB4AIBADCBpwYFKw4DAhswgZ0CQQEkJRHP+mN7" - + "d8miwTMN55CUSmo3TO8WGCxgY61TX5k+7NU4XPf1TULjw3GobwaJX13kquPh" - + "fVXk+gVy46n4Iw3hAhUBSe/QF4BUj+pJOF9ROBM4u+FEWA8CQQD4mSJbrABj" - + "TUWrlnAte8pS22Tq4/FPO7jHSqjijUHfXKTrHL1OEqV3SVWcFy5j/cqBgX/z" - + "m8Q12PFp/PjOhh+nMA4xDDAKBgNVBAMTA0lEMzAeFw05NzEwMDEwMDAwMDBa" - + "Fw0zODAxMDEwMDAwMDBaMA4xDDAKBgNVBAMTA0lEMzCB8DCBpwYFKw4DAhsw" - + "gZ0CQQEkJRHP+mN7d8miwTMN55CUSmo3TO8WGCxgY61TX5k+7NU4XPf1TULj" - + "w3GobwaJX13kquPhfVXk+gVy46n4Iw3hAhUBSe/QF4BUj+pJOF9ROBM4u+FE" - + "WA8CQQD4mSJbrABjTUWrlnAte8pS22Tq4/FPO7jHSqjijUHfXKTrHL1OEqV3" - + "SVWcFy5j/cqBgX/zm8Q12PFp/PjOhh+nA0QAAkEAkYkXLYMtGVGWj9OnzjPn" - + "sB9sefSRPrVegZJCZbpW+Iv0/1RP1u04pHG9vtRpIQLjzUiWvLMU9EKQTThc" - + "eNMmWDCBpwYFKw4DAhswgZ0CQQEkJRHP+mN7d8miwTMN55CUSmo3TO8WGCxg" - + "Y61TX5k+7NU4XPf1TULjw3GobwaJX13kquPhfVXk+gVy46n4Iw3hAhUBSe/Q" - + "F4BUj+pJOF9ROBM4u+FEWA8CQQD4mSJbrABjTUWrlnAte8pS22Tq4/FPO7jH" - + "SqjijUHfXKTrHL1OEqV3SVWcFy5j/cqBgX/zm8Q12PFp/PjOhh+nAy8AMCwC" - + "FBY3dBSdeprGcqpr6wr3xbG+6WW+AhRMm/facKJNxkT3iKgJbp7R8Xd3QTGC" - + "AWEwggFdAgEBMBMwDjEMMAoGA1UEAxMDSUQzAgEAMAkGBSsOAwIaBQCgXTAY" - + "BgkqhkiG9w0BCQMxCwYJKoZIhvcNAQcBMBwGCSqGSIb3DQEJBTEPFw0wMjA1" - + "MjQyMzEzMDdaMCMGCSqGSIb3DQEJBDEWBBS4WMsoJhf7CVbZYCFcjoTRzPkJ" - + "xjCBpwYFKw4DAhswgZ0CQQEkJRHP+mN7d8miwTMN55CUSmo3TO8WGCxgY61T" - + "X5k+7NU4XPf1TULjw3GobwaJX13kquPhfVXk+gVy46n4Iw3hAhUBSe/QF4BU" - + "j+pJOF9ROBM4u+FEWA8CQQD4mSJbrABjTUWrlnAte8pS22Tq4/FPO7jHSqji" - + "jUHfXKTrHL1OEqV3SVWcFy5j/cqBgX/zm8Q12PFp/PjOhh+nBC8wLQIVALID" - + "dt+MHwawrDrwsO1Z6sXBaaJsAhRaKssrpevmLkbygKPV07XiAKBG02Zvb2Jh" - + "cg=="); + byte[] cert7 = Base64.decode( + "MIIEXAYJKoZIhvcNAQcCoIIETTCCBEkCAQExCzAJBgUrDgMCGgUAMAsGCSqG" + + "SIb3DQEHAaCCAsMwggK/MIIB4AIBADCBpwYFKw4DAhswgZ0CQQEkJRHP+mN7" + + "d8miwTMN55CUSmo3TO8WGCxgY61TX5k+7NU4XPf1TULjw3GobwaJX13kquPh" + + "fVXk+gVy46n4Iw3hAhUBSe/QF4BUj+pJOF9ROBM4u+FEWA8CQQD4mSJbrABj" + + "TUWrlnAte8pS22Tq4/FPO7jHSqjijUHfXKTrHL1OEqV3SVWcFy5j/cqBgX/z" + + "m8Q12PFp/PjOhh+nMA4xDDAKBgNVBAMTA0lEMzAeFw05NzEwMDEwMDAwMDBa" + + "Fw0zODAxMDEwMDAwMDBaMA4xDDAKBgNVBAMTA0lEMzCB8DCBpwYFKw4DAhsw" + + "gZ0CQQEkJRHP+mN7d8miwTMN55CUSmo3TO8WGCxgY61TX5k+7NU4XPf1TULj" + + "w3GobwaJX13kquPhfVXk+gVy46n4Iw3hAhUBSe/QF4BUj+pJOF9ROBM4u+FE" + + "WA8CQQD4mSJbrABjTUWrlnAte8pS22Tq4/FPO7jHSqjijUHfXKTrHL1OEqV3" + + "SVWcFy5j/cqBgX/zm8Q12PFp/PjOhh+nA0QAAkEAkYkXLYMtGVGWj9OnzjPn" + + "sB9sefSRPrVegZJCZbpW+Iv0/1RP1u04pHG9vtRpIQLjzUiWvLMU9EKQTThc" + + "eNMmWDCBpwYFKw4DAhswgZ0CQQEkJRHP+mN7d8miwTMN55CUSmo3TO8WGCxg" + + "Y61TX5k+7NU4XPf1TULjw3GobwaJX13kquPhfVXk+gVy46n4Iw3hAhUBSe/Q" + + "F4BUj+pJOF9ROBM4u+FEWA8CQQD4mSJbrABjTUWrlnAte8pS22Tq4/FPO7jH" + + "SqjijUHfXKTrHL1OEqV3SVWcFy5j/cqBgX/zm8Q12PFp/PjOhh+nAy8AMCwC" + + "FBY3dBSdeprGcqpr6wr3xbG+6WW+AhRMm/facKJNxkT3iKgJbp7R8Xd3QTGC" + + "AWEwggFdAgEBMBMwDjEMMAoGA1UEAxMDSUQzAgEAMAkGBSsOAwIaBQCgXTAY" + + "BgkqhkiG9w0BCQMxCwYJKoZIhvcNAQcBMBwGCSqGSIb3DQEJBTEPFw0wMjA1" + + "MjQyMzEzMDdaMCMGCSqGSIb3DQEJBDEWBBS4WMsoJhf7CVbZYCFcjoTRzPkJ" + + "xjCBpwYFKw4DAhswgZ0CQQEkJRHP+mN7d8miwTMN55CUSmo3TO8WGCxgY61T" + + "X5k+7NU4XPf1TULjw3GobwaJX13kquPhfVXk+gVy46n4Iw3hAhUBSe/QF4BU" + + "j+pJOF9ROBM4u+FEWA8CQQD4mSJbrABjTUWrlnAte8pS22Tq4/FPO7jHSqji" + + "jUHfXKTrHL1OEqV3SVWcFy5j/cqBgX/zm8Q12PFp/PjOhh+nBC8wLQIVALID" + + "dt+MHwawrDrwsO1Z6sXBaaJsAhRaKssrpevmLkbygKPV07XiAKBG02Zvb2Jh" + + "cg=="); // // testcrl.pem // - byte[] crl1 = Base64.decode( + byte[] crl1 = Base64.decode( "MIICjTCCAfowDQYJKoZIhvcNAQECBQAwXzELMAkGA1UEBhMCVVMxIDAeBgNVBAoT" - + "F1JTQSBEYXRhIFNlY3VyaXR5LCBJbmMuMS4wLAYDVQQLEyVTZWN1cmUgU2VydmVy" - + "IENlcnRpZmljYXRpb24gQXV0aG9yaXR5Fw05NTA1MDIwMjEyMjZaFw05NTA2MDEw" - + "MDAxNDlaMIIBaDAWAgUCQQAABBcNOTUwMjAxMTcyNDI2WjAWAgUCQQAACRcNOTUw" - + "MjEwMDIxNjM5WjAWAgUCQQAADxcNOTUwMjI0MDAxMjQ5WjAWAgUCQQAADBcNOTUw" - + "MjI1MDA0NjQ0WjAWAgUCQQAAGxcNOTUwMzEzMTg0MDQ5WjAWAgUCQQAAFhcNOTUw" - + "MzE1MTkxNjU0WjAWAgUCQQAAGhcNOTUwMzE1MTk0MDQxWjAWAgUCQQAAHxcNOTUw" - + "MzI0MTk0NDMzWjAWAgUCcgAABRcNOTUwMzI5MjAwNzExWjAWAgUCcgAAERcNOTUw" - + "MzMwMDIzNDI2WjAWAgUCQQAAIBcNOTUwNDA3MDExMzIxWjAWAgUCcgAAHhcNOTUw" - + "NDA4MDAwMjU5WjAWAgUCcgAAQRcNOTUwNDI4MTcxNzI0WjAWAgUCcgAAOBcNOTUw" - + "NDI4MTcyNzIxWjAWAgUCcgAATBcNOTUwNTAyMDIxMjI2WjANBgkqhkiG9w0BAQIF" - + "AAN+AHqOEJXSDejYy0UwxxrH/9+N2z5xu/if0J6qQmK92W0hW158wpJg+ovV3+wQ" - + "wvIEPRL2rocL0tKfAsVq1IawSJzSNgxG0lrcla3MrJBnZ4GaZDu4FutZh72MR3Gt" - + "JaAL3iTJHJD55kK2D/VoyY1djlsPuNh6AEgdVwFAyp0v"); + + "F1JTQSBEYXRhIFNlY3VyaXR5LCBJbmMuMS4wLAYDVQQLEyVTZWN1cmUgU2VydmVy" + + "IENlcnRpZmljYXRpb24gQXV0aG9yaXR5Fw05NTA1MDIwMjEyMjZaFw05NTA2MDEw" + + "MDAxNDlaMIIBaDAWAgUCQQAABBcNOTUwMjAxMTcyNDI2WjAWAgUCQQAACRcNOTUw" + + "MjEwMDIxNjM5WjAWAgUCQQAADxcNOTUwMjI0MDAxMjQ5WjAWAgUCQQAADBcNOTUw" + + "MjI1MDA0NjQ0WjAWAgUCQQAAGxcNOTUwMzEzMTg0MDQ5WjAWAgUCQQAAFhcNOTUw" + + "MzE1MTkxNjU0WjAWAgUCQQAAGhcNOTUwMzE1MTk0MDQxWjAWAgUCQQAAHxcNOTUw" + + "MzI0MTk0NDMzWjAWAgUCcgAABRcNOTUwMzI5MjAwNzExWjAWAgUCcgAAERcNOTUw" + + "MzMwMDIzNDI2WjAWAgUCQQAAIBcNOTUwNDA3MDExMzIxWjAWAgUCcgAAHhcNOTUw" + + "NDA4MDAwMjU5WjAWAgUCcgAAQRcNOTUwNDI4MTcxNzI0WjAWAgUCcgAAOBcNOTUw" + + "NDI4MTcyNzIxWjAWAgUCcgAATBcNOTUwNTAyMDIxMjI2WjANBgkqhkiG9w0BAQIF" + + "AAN+AHqOEJXSDejYy0UwxxrH/9+N2z5xu/if0J6qQmK92W0hW158wpJg+ovV3+wQ" + + "wvIEPRL2rocL0tKfAsVq1IawSJzSNgxG0lrcla3MrJBnZ4GaZDu4FutZh72MR3Gt" + + "JaAL3iTJHJD55kK2D/VoyY1djlsPuNh6AEgdVwFAyp0v"); // // ecdsa cert with extra octet string. // - byte[] oldEcdsa = Base64.decode( - "MIICljCCAkCgAwIBAgIBATALBgcqhkjOPQQBBQAwgY8xCzAJBgNVBAYTAkFVMSgwJ" - + "gYDVQQKEx9UaGUgTGVnaW9uIG9mIHRoZSBCb3VuY3kgQ2FzdGxlMRIwEAYDVQQHEw" - + "lNZWxib3VybmUxETAPBgNVBAgTCFZpY3RvcmlhMS8wLQYJKoZIhvcNAQkBFiBmZWV" - + "kYmFjay1jcnlwdG9AYm91bmN5Y2FzdGxlLm9yZzAeFw0wMTEyMDcwMTAwMDRaFw0w" - + "MTEyMDcwMTAxNDRaMIGPMQswCQYDVQQGEwJBVTEoMCYGA1UEChMfVGhlIExlZ2lvb" - + "iBvZiB0aGUgQm91bmN5IENhc3RsZTESMBAGA1UEBxMJTWVsYm91cm5lMREwDwYDVQ" - + "QIEwhWaWN0b3JpYTEvMC0GCSqGSIb3DQEJARYgZmVlZGJhY2stY3J5cHRvQGJvdW5" - + "jeWNhc3RsZS5vcmcwgeQwgb0GByqGSM49AgEwgbECAQEwKQYHKoZIzj0BAQIef///" - + "////////////f///////gAAAAAAAf///////MEAEHn///////////////3///////" - + "4AAAAAAAH///////AQeawFsO9zxiUHQ1lSSFHXKcanbL7J9HTd5YYXClCwKBB8CD/" - + "qWPNyogWzMM7hkK+35BcPTWFc9Pyf7vTs8uaqvAh5///////////////9///+eXpq" - + "fXZBx+9FSJoiQnQsDIgAEHwJbbcU7xholSP+w9nFHLebJUhqdLSU05lq/y9X+DHAw" - + "CwYHKoZIzj0EAQUAA0MAMEACHnz6t4UNoVROp74ma4XNDjjGcjaqiIWPZLK8Bdw3G" - + "QIeLZ4j3a6ividZl344UH+UPUE7xJxlYGuy7ejTsqRR"); - - byte[] uncompressedPtEC = Base64.decode( - "MIIDKzCCAsGgAwIBAgICA+kwCwYHKoZIzj0EAQUAMGYxCzAJBgNVBAYTAkpQ" - + "MRUwEwYDVQQKEwxuaXRlY2guYWMuanAxDjAMBgNVBAsTBWFpbGFiMQ8wDQYD" - + "VQQDEwZ0ZXN0Y2ExHzAdBgkqhkiG9w0BCQEWEHRlc3RjYUBsb2NhbGhvc3Qw" - + "HhcNMDExMDEzMTE1MzE3WhcNMjAxMjEyMTE1MzE3WjBmMQswCQYDVQQGEwJK" - + "UDEVMBMGA1UEChMMbml0ZWNoLmFjLmpwMQ4wDAYDVQQLEwVhaWxhYjEPMA0G" - + "A1UEAxMGdGVzdGNhMR8wHQYJKoZIhvcNAQkBFhB0ZXN0Y2FAbG9jYWxob3N0" - + "MIIBczCCARsGByqGSM49AgEwggEOAgEBMDMGByqGSM49AQECKEdYWnajFmnZ" - + "tzrukK2XWdle2v+GsD9l1ZiR6g7ozQDbhFH/bBiMDQcwVAQoJ5EQKrI54/CT" - + "xOQ2pMsd/fsXD+EX8YREd8bKHWiLz8lIVdD5cBNeVwQoMKSc6HfI7vKZp8Q2" - + "zWgIFOarx1GQoWJbMcSt188xsl30ncJuJT2OoARRBAqJ4fD+q6hbqgNSjTQ7" - + "htle1KO3eiaZgcJ8rrnyN8P+5A8+5K+H9aQ/NbBR4Gs7yto5PXIUZEUgodHA" - + "TZMSAcSq5ZYt4KbnSYaLY0TtH9CqAigEwZ+hglbT21B7ZTzYX2xj0x+qooJD" - + "hVTLtIPaYJK2HrMPxTw6/zfrAgEPA1IABAnvfFcFDgD/JicwBGn6vR3N8MIn" - + "mptZf/mnJ1y649uCF60zOgdwIyI7pVSxBFsJ7ohqXEHW0x7LrGVkdSEiipiH" - + "LYslqh3xrqbAgPbl93GUo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB" - + "/wQEAwIBxjAdBgNVHQ4EFgQUAEo62Xm9H6DcsE0zUDTza4BRG90wCwYHKoZI" - + "zj0EAQUAA1cAMFQCKAQsCHHSNOqfJXLgt3bg5+k49hIBGVr/bfG0B9JU3rNt" - + "Ycl9Y2zfRPUCKAK2ccOQXByAWfsasDu8zKHxkZv7LVDTFjAIffz3HaCQeVhD" - + "z+fauEg="); - - byte[] keyUsage = Base64.decode( - "MIIE7TCCBFagAwIBAgIEOAOR7jANBgkqhkiG9w0BAQQFADCByTELMAkGA1UE" - + "BhMCVVMxFDASBgNVBAoTC0VudHJ1c3QubmV0MUgwRgYDVQQLFD93d3cuZW50" - + "cnVzdC5uZXQvQ2xpZW50X0NBX0luZm8vQ1BTIGluY29ycC4gYnkgcmVmLiBs" - + "aW1pdHMgbGlhYi4xJTAjBgNVBAsTHChjKSAxOTk5IEVudHJ1c3QubmV0IExp" - + "bWl0ZWQxMzAxBgNVBAMTKkVudHJ1c3QubmV0IENsaWVudCBDZXJ0aWZpY2F0" - + "aW9uIEF1dGhvcml0eTAeFw05OTEwMTIxOTI0MzBaFw0xOTEwMTIxOTU0MzBa" - + "MIHJMQswCQYDVQQGEwJVUzEUMBIGA1UEChMLRW50cnVzdC5uZXQxSDBGBgNV" - + "BAsUP3d3dy5lbnRydXN0Lm5ldC9DbGllbnRfQ0FfSW5mby9DUFMgaW5jb3Jw" - + "LiBieSByZWYuIGxpbWl0cyBsaWFiLjElMCMGA1UECxMcKGMpIDE5OTkgRW50" - + "cnVzdC5uZXQgTGltaXRlZDEzMDEGA1UEAxMqRW50cnVzdC5uZXQgQ2xpZW50" - + "IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIGdMA0GCSqGSIb3DQEBAQUAA4GL" - + "ADCBhwKBgQDIOpleMRffrCdvkHvkGf9FozTC28GoT/Bo6oT9n3V5z8GKUZSv" - + "x1cDR2SerYIbWtp/N3hHuzeYEpbOxhN979IMMFGpOZ5V+Pux5zDeg7K6PvHV" - + "iTs7hbqqdCz+PzFur5GVbgbUB01LLFZHGARS2g4Qk79jkJvh34zmAqTmT173" - + "iwIBA6OCAeAwggHcMBEGCWCGSAGG+EIBAQQEAwIABzCCASIGA1UdHwSCARkw" - + "ggEVMIHkoIHhoIHepIHbMIHYMQswCQYDVQQGEwJVUzEUMBIGA1UEChMLRW50" - + "cnVzdC5uZXQxSDBGBgNVBAsUP3d3dy5lbnRydXN0Lm5ldC9DbGllbnRfQ0Ff" - + "SW5mby9DUFMgaW5jb3JwLiBieSByZWYuIGxpbWl0cyBsaWFiLjElMCMGA1UE" - + "CxMcKGMpIDE5OTkgRW50cnVzdC5uZXQgTGltaXRlZDEzMDEGA1UEAxMqRW50" - + "cnVzdC5uZXQgQ2xpZW50IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MQ0wCwYD" - + "VQQDEwRDUkwxMCygKqAohiZodHRwOi8vd3d3LmVudHJ1c3QubmV0L0NSTC9D" - + "bGllbnQxLmNybDArBgNVHRAEJDAigA8xOTk5MTAxMjE5MjQzMFqBDzIwMTkx" - + "MDEyMTkyNDMwWjALBgNVHQ8EBAMCAQYwHwYDVR0jBBgwFoAUxPucKXuXzUyW" - + "/O5bs8qZdIuV6kwwHQYDVR0OBBYEFMT7nCl7l81MlvzuW7PKmXSLlepMMAwG" - + "A1UdEwQFMAMBAf8wGQYJKoZIhvZ9B0EABAwwChsEVjQuMAMCBJAwDQYJKoZI" - + "hvcNAQEEBQADgYEAP66K8ddmAwWePvrqHEa7pFuPeJoSSJn59DXeDDYHAmsQ" - + "OokUgZwxpnyyQbJq5wcBoUv5nyU7lsqZwz6hURzzwy5E97BnRqqS5TvaHBkU" - + "ODDV4qIxJS7x7EU47fgGWANzYrAQMY9Av2TgXD7FTx/aEkP/TOYGJqibGapE" - + "PHayXOw="); + byte[] oldEcdsa = Base64.decode( + "MIICljCCAkCgAwIBAgIBATALBgcqhkjOPQQBBQAwgY8xCzAJBgNVBAYTAkFVMSgwJ" + + "gYDVQQKEx9UaGUgTGVnaW9uIG9mIHRoZSBCb3VuY3kgQ2FzdGxlMRIwEAYDVQQHEw" + + "lNZWxib3VybmUxETAPBgNVBAgTCFZpY3RvcmlhMS8wLQYJKoZIhvcNAQkBFiBmZWV" + + "kYmFjay1jcnlwdG9AYm91bmN5Y2FzdGxlLm9yZzAeFw0wMTEyMDcwMTAwMDRaFw0w" + + "MTEyMDcwMTAxNDRaMIGPMQswCQYDVQQGEwJBVTEoMCYGA1UEChMfVGhlIExlZ2lvb" + + "iBvZiB0aGUgQm91bmN5IENhc3RsZTESMBAGA1UEBxMJTWVsYm91cm5lMREwDwYDVQ" + + "QIEwhWaWN0b3JpYTEvMC0GCSqGSIb3DQEJARYgZmVlZGJhY2stY3J5cHRvQGJvdW5" + + "jeWNhc3RsZS5vcmcwgeQwgb0GByqGSM49AgEwgbECAQEwKQYHKoZIzj0BAQIef///" + + "////////////f///////gAAAAAAAf///////MEAEHn///////////////3///////" + + "4AAAAAAAH///////AQeawFsO9zxiUHQ1lSSFHXKcanbL7J9HTd5YYXClCwKBB8CD/" + + "qWPNyogWzMM7hkK+35BcPTWFc9Pyf7vTs8uaqvAh5///////////////9///+eXpq" + + "fXZBx+9FSJoiQnQsDIgAEHwJbbcU7xholSP+w9nFHLebJUhqdLSU05lq/y9X+DHAw" + + "CwYHKoZIzj0EAQUAA0MAMEACHnz6t4UNoVROp74ma4XNDjjGcjaqiIWPZLK8Bdw3G" + + "QIeLZ4j3a6ividZl344UH+UPUE7xJxlYGuy7ejTsqRR"); + + byte[] uncompressedPtEC = Base64.decode( + "MIIDKzCCAsGgAwIBAgICA+kwCwYHKoZIzj0EAQUAMGYxCzAJBgNVBAYTAkpQ" + + "MRUwEwYDVQQKEwxuaXRlY2guYWMuanAxDjAMBgNVBAsTBWFpbGFiMQ8wDQYD" + + "VQQDEwZ0ZXN0Y2ExHzAdBgkqhkiG9w0BCQEWEHRlc3RjYUBsb2NhbGhvc3Qw" + + "HhcNMDExMDEzMTE1MzE3WhcNMjAxMjEyMTE1MzE3WjBmMQswCQYDVQQGEwJK" + + "UDEVMBMGA1UEChMMbml0ZWNoLmFjLmpwMQ4wDAYDVQQLEwVhaWxhYjEPMA0G" + + "A1UEAxMGdGVzdGNhMR8wHQYJKoZIhvcNAQkBFhB0ZXN0Y2FAbG9jYWxob3N0" + + "MIIBczCCARsGByqGSM49AgEwggEOAgEBMDMGByqGSM49AQECKEdYWnajFmnZ" + + "tzrukK2XWdle2v+GsD9l1ZiR6g7ozQDbhFH/bBiMDQcwVAQoJ5EQKrI54/CT" + + "xOQ2pMsd/fsXD+EX8YREd8bKHWiLz8lIVdD5cBNeVwQoMKSc6HfI7vKZp8Q2" + + "zWgIFOarx1GQoWJbMcSt188xsl30ncJuJT2OoARRBAqJ4fD+q6hbqgNSjTQ7" + + "htle1KO3eiaZgcJ8rrnyN8P+5A8+5K+H9aQ/NbBR4Gs7yto5PXIUZEUgodHA" + + "TZMSAcSq5ZYt4KbnSYaLY0TtH9CqAigEwZ+hglbT21B7ZTzYX2xj0x+qooJD" + + "hVTLtIPaYJK2HrMPxTw6/zfrAgEPA1IABAnvfFcFDgD/JicwBGn6vR3N8MIn" + + "mptZf/mnJ1y649uCF60zOgdwIyI7pVSxBFsJ7ohqXEHW0x7LrGVkdSEiipiH" + + "LYslqh3xrqbAgPbl93GUo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB" + + "/wQEAwIBxjAdBgNVHQ4EFgQUAEo62Xm9H6DcsE0zUDTza4BRG90wCwYHKoZI" + + "zj0EAQUAA1cAMFQCKAQsCHHSNOqfJXLgt3bg5+k49hIBGVr/bfG0B9JU3rNt" + + "Ycl9Y2zfRPUCKAK2ccOQXByAWfsasDu8zKHxkZv7LVDTFjAIffz3HaCQeVhD" + + "z+fauEg="); + + byte[] keyUsage = Base64.decode( + "MIIE7TCCBFagAwIBAgIEOAOR7jANBgkqhkiG9w0BAQQFADCByTELMAkGA1UE" + + "BhMCVVMxFDASBgNVBAoTC0VudHJ1c3QubmV0MUgwRgYDVQQLFD93d3cuZW50" + + "cnVzdC5uZXQvQ2xpZW50X0NBX0luZm8vQ1BTIGluY29ycC4gYnkgcmVmLiBs" + + "aW1pdHMgbGlhYi4xJTAjBgNVBAsTHChjKSAxOTk5IEVudHJ1c3QubmV0IExp" + + "bWl0ZWQxMzAxBgNVBAMTKkVudHJ1c3QubmV0IENsaWVudCBDZXJ0aWZpY2F0" + + "aW9uIEF1dGhvcml0eTAeFw05OTEwMTIxOTI0MzBaFw0xOTEwMTIxOTU0MzBa" + + "MIHJMQswCQYDVQQGEwJVUzEUMBIGA1UEChMLRW50cnVzdC5uZXQxSDBGBgNV" + + "BAsUP3d3dy5lbnRydXN0Lm5ldC9DbGllbnRfQ0FfSW5mby9DUFMgaW5jb3Jw" + + "LiBieSByZWYuIGxpbWl0cyBsaWFiLjElMCMGA1UECxMcKGMpIDE5OTkgRW50" + + "cnVzdC5uZXQgTGltaXRlZDEzMDEGA1UEAxMqRW50cnVzdC5uZXQgQ2xpZW50" + + "IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIGdMA0GCSqGSIb3DQEBAQUAA4GL" + + "ADCBhwKBgQDIOpleMRffrCdvkHvkGf9FozTC28GoT/Bo6oT9n3V5z8GKUZSv" + + "x1cDR2SerYIbWtp/N3hHuzeYEpbOxhN979IMMFGpOZ5V+Pux5zDeg7K6PvHV" + + "iTs7hbqqdCz+PzFur5GVbgbUB01LLFZHGARS2g4Qk79jkJvh34zmAqTmT173" + + "iwIBA6OCAeAwggHcMBEGCWCGSAGG+EIBAQQEAwIABzCCASIGA1UdHwSCARkw" + + "ggEVMIHkoIHhoIHepIHbMIHYMQswCQYDVQQGEwJVUzEUMBIGA1UEChMLRW50" + + "cnVzdC5uZXQxSDBGBgNVBAsUP3d3dy5lbnRydXN0Lm5ldC9DbGllbnRfQ0Ff" + + "SW5mby9DUFMgaW5jb3JwLiBieSByZWYuIGxpbWl0cyBsaWFiLjElMCMGA1UE" + + "CxMcKGMpIDE5OTkgRW50cnVzdC5uZXQgTGltaXRlZDEzMDEGA1UEAxMqRW50" + + "cnVzdC5uZXQgQ2xpZW50IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MQ0wCwYD" + + "VQQDEwRDUkwxMCygKqAohiZodHRwOi8vd3d3LmVudHJ1c3QubmV0L0NSTC9D" + + "bGllbnQxLmNybDArBgNVHRAEJDAigA8xOTk5MTAxMjE5MjQzMFqBDzIwMTkx" + + "MDEyMTkyNDMwWjALBgNVHQ8EBAMCAQYwHwYDVR0jBBgwFoAUxPucKXuXzUyW" + + "/O5bs8qZdIuV6kwwHQYDVR0OBBYEFMT7nCl7l81MlvzuW7PKmXSLlepMMAwG" + + "A1UdEwQFMAMBAf8wGQYJKoZIhvZ9B0EABAwwChsEVjQuMAMCBJAwDQYJKoZI" + + "hvcNAQEEBQADgYEAP66K8ddmAwWePvrqHEa7pFuPeJoSSJn59DXeDDYHAmsQ" + + "OokUgZwxpnyyQbJq5wcBoUv5nyU7lsqZwz6hURzzwy5E97BnRqqS5TvaHBkU" + + "ODDV4qIxJS7x7EU47fgGWANzYrAQMY9Av2TgXD7FTx/aEkP/TOYGJqibGapE" + + "PHayXOw="); byte[] nameCert = Base64.decode( - "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"); byte[] probSelfSignedCert = Base64.decode( - "MIICxTCCAi6gAwIBAgIQAQAAAAAAAAAAAAAAAAAAATANBgkqhkiG9w0BAQUFADBF" + "MIICxTCCAi6gAwIBAgIQAQAAAAAAAAAAAAAAAAAAATANBgkqhkiG9w0BAQUFADBF" + "MScwJQYDVQQKEx4gRElSRUNUSU9OIEdFTkVSQUxFIERFUyBJTVBPVFMxGjAYBgNV" + "BAMTESBBQyBNSU5FRkkgQiBURVNUMB4XDTA0MDUwNzEyMDAwMFoXDTE0MDUwNzEy" + "MDAwMFowRTEnMCUGA1UEChMeIERJUkVDVElPTiBHRU5FUkFMRSBERVMgSU1QT1RT" @@ -532,7 +531,7 @@ public class CertTest byte[] gost34102001base = Base64.decode( - "MIIB1DCCAYECEEjpVKXP6Wn1yVz3VeeDQa8wCgYGKoUDAgIDBQAwbTEfMB0G" + "MIIB1DCCAYECEEjpVKXP6Wn1yVz3VeeDQa8wCgYGKoUDAgIDBQAwbTEfMB0G" + "A1UEAwwWR29zdFIzNDEwLTIwMDEgZXhhbXBsZTESMBAGA1UECgwJQ3J5cHRv" + "UHJvMQswCQYDVQQGEwJSVTEpMCcGCSqGSIb3DQEJARYaR29zdFIzNDEwLTIw" + "MDFAZXhhbXBsZS5jb20wHhcNMDUwMjAzMTUxNjQ2WhcNMTUwMjAzMTUxNjQ2" @@ -545,7 +544,7 @@ public class CertTest + "HOLjUaqzefrlGb11WpHYrvWFg+FcLA=="); byte[] gost341094base = Base64.decode( - "MIICDzCCAbwCEBcxKsIb0ghYvAQeUjfQdFAwCgYGKoUDAgIEBQAwaTEdMBsG" + "MIICDzCCAbwCEBcxKsIb0ghYvAQeUjfQdFAwCgYGKoUDAgIEBQAwaTEdMBsG" + "A1UEAwwUR29zdFIzNDEwLTk0IGV4YW1wbGUxEjAQBgNVBAoMCUNyeXB0b1By" + "bzELMAkGA1UEBhMCUlUxJzAlBgkqhkiG9w0BCQEWGEdvc3RSMzQxMC05NEBl" + "eGFtcGxlLmNvbTAeFw0wNTAyMDMxNTE2NTFaFw0xNTAyMDMxNTE2NTFaMGkx" @@ -559,7 +558,7 @@ public class CertTest + "v7CZ0pTM8IzMzkUBW3GHsUjCFpanFZDfg2zuN+3kT+694n9B"); byte[] gost341094A = Base64.decode( - "MIICSDCCAfWgAwIBAgIBATAKBgYqhQMCAgQFADCBgTEXMBUGA1UEAxMOZGVmYXVsdDM0MTAtOTQx" + "MIICSDCCAfWgAwIBAgIBATAKBgYqhQMCAgQFADCBgTEXMBUGA1UEAxMOZGVmYXVsdDM0MTAtOTQx" + "DTALBgNVBAoTBERpZ3QxDzANBgNVBAsTBkNyeXB0bzEOMAwGA1UEBxMFWS1vbGExDDAKBgNVBAgT" + "A01FTDELMAkGA1UEBhMCcnUxGzAZBgkqhkiG9w0BCQEWDHRlc3RAdGVzdC5ydTAeFw0wNTAzMjkx" + "MzExNTdaFw0wNjAzMjkxMzExNTdaMIGBMRcwFQYDVQQDEw5kZWZhdWx0MzQxMC05NDENMAsGA1UE" @@ -572,20 +571,20 @@ public class CertTest + "wWTPiZenvNoJ4R1uzeX+vREm"); byte[] gost341094B = Base64.decode( - "MIICSDCCAfWgAwIBAgIBATAKBgYqhQMCAgQFADCBgTEXMBUGA1UEAxMOcGFyYW0xLTM0MTAtOTQx" - + "DTALBgNVBAoTBERpZ3QxDzANBgNVBAsTBkNyeXB0bzEOMAwGA1UEBxMFWS1PbGExDDAKBgNVBAgT" - + "A01lbDELMAkGA1UEBhMCcnUxGzAZBgkqhkiG9w0BCQEWDHRlc3RAdGVzdC5ydTAeFw0wNTAzMjkx" - + "MzEzNTZaFw0wNjAzMjkxMzEzNTZaMIGBMRcwFQYDVQQDEw5wYXJhbTEtMzQxMC05NDENMAsGA1UE" - + "ChMERGlndDEPMA0GA1UECxMGQ3J5cHRvMQ4wDAYDVQQHEwVZLU9sYTEMMAoGA1UECBMDTWVsMQsw" - + "CQYDVQQGEwJydTEbMBkGCSqGSIb3DQEJARYMdGVzdEB0ZXN0LnJ1MIGlMBwGBiqFAwICFDASBgcq" - + "hQMCAiADBgcqhQMCAh4BA4GEAASBgEa+AAcZmijWs1M9x5Pn9efE8D9ztG1NMoIt0/hNZNqln3+j" - + "lMZjyqPt+kTLIjtmvz9BRDmIDk6FZz+4LhG2OTL7yGpWfrMxMRr56nxomTN9aLWRqbyWmn3brz9Y" - + "AUD3ifnwjjIuW7UM84JNlDTOdxx0XRUfLQIPMCXe9cO02Xskow8wDTALBgNVHQ8EBAMCB4AwCgYG" - + "KoUDAgIEBQADQQBzFcnuYc/639OTW+L5Ecjw9KxGr+dwex7lsS9S1BUgKa3m1d5c+cqI0B2XUFi5" - + "4iaHHJG0dCyjtQYLJr0OZjRw"); + "MIICSDCCAfWgAwIBAgIBATAKBgYqhQMCAgQFADCBgTEXMBUGA1UEAxMOcGFyYW0xLTM0MTAtOTQx" + + "DTALBgNVBAoTBERpZ3QxDzANBgNVBAsTBkNyeXB0bzEOMAwGA1UEBxMFWS1PbGExDDAKBgNVBAgT" + + "A01lbDELMAkGA1UEBhMCcnUxGzAZBgkqhkiG9w0BCQEWDHRlc3RAdGVzdC5ydTAeFw0wNTAzMjkx" + + "MzEzNTZaFw0wNjAzMjkxMzEzNTZaMIGBMRcwFQYDVQQDEw5wYXJhbTEtMzQxMC05NDENMAsGA1UE" + + "ChMERGlndDEPMA0GA1UECxMGQ3J5cHRvMQ4wDAYDVQQHEwVZLU9sYTEMMAoGA1UECBMDTWVsMQsw" + + "CQYDVQQGEwJydTEbMBkGCSqGSIb3DQEJARYMdGVzdEB0ZXN0LnJ1MIGlMBwGBiqFAwICFDASBgcq" + + "hQMCAiADBgcqhQMCAh4BA4GEAASBgEa+AAcZmijWs1M9x5Pn9efE8D9ztG1NMoIt0/hNZNqln3+j" + + "lMZjyqPt+kTLIjtmvz9BRDmIDk6FZz+4LhG2OTL7yGpWfrMxMRr56nxomTN9aLWRqbyWmn3brz9Y" + + "AUD3ifnwjjIuW7UM84JNlDTOdxx0XRUfLQIPMCXe9cO02Xskow8wDTALBgNVHQ8EBAMCB4AwCgYG" + + "KoUDAgIEBQADQQBzFcnuYc/639OTW+L5Ecjw9KxGr+dwex7lsS9S1BUgKa3m1d5c+cqI0B2XUFi5" + + "4iaHHJG0dCyjtQYLJr0OZjRw"); byte[] gost34102001A = Base64.decode( - "MIICCzCCAbigAwIBAgIBATAKBgYqhQMCAgMFADCBhDEaMBgGA1UEAxMRZGVmYXVsdC0zNDEwLTIw" + "MIICCzCCAbigAwIBAgIBATAKBgYqhQMCAgMFADCBhDEaMBgGA1UEAxMRZGVmYXVsdC0zNDEwLTIw" + "MDExDTALBgNVBAoTBERpZ3QxDzANBgNVBAsTBkNyeXB0bzEOMAwGA1UEBxMFWS1PbGExDDAKBgNV" + "BAgTA01lbDELMAkGA1UEBhMCcnUxGzAZBgkqhkiG9w0BCQEWDHRlc3RAdGVzdC5ydTAeFw0wNTAz" + "MjkxMzE4MzFaFw0wNjAzMjkxMzE4MzFaMIGEMRowGAYDVQQDExFkZWZhdWx0LTM0MTAtMjAwMTEN" @@ -597,7 +596,7 @@ public class CertTest + "ZftGNsbbyp1NFg7zda0="); byte[] gostCA1 = Base64.decode( - "MIIDNDCCAuGgAwIBAgIQZLcKDcWcQopF+jp4p9jylDAKBgYqhQMCAgQFADBm" + "MIIDNDCCAuGgAwIBAgIQZLcKDcWcQopF+jp4p9jylDAKBgYqhQMCAgQFADBm" + "MQswCQYDVQQGEwJSVTEPMA0GA1UEBxMGTW9zY293MRcwFQYDVQQKEw5PT08g" + "Q3J5cHRvLVBybzEUMBIGA1UECxMLRGV2ZWxvcG1lbnQxFzAVBgNVBAMTDkNQ" + "IENTUCBUZXN0IENBMB4XDTAyMDYwOTE1NTIyM1oXDTA5MDYwOTE1NTkyOVow" @@ -618,7 +617,7 @@ public class CertTest + "G2IN96RB7KrowEHeW+k="); byte[] gostCA2 = Base64.decode( - "MIIC2DCCAoWgAwIBAgIQe9ZCugm42pRKNcHD8466zTAKBgYqhQMCAgMFADB+" + "MIIC2DCCAoWgAwIBAgIQe9ZCugm42pRKNcHD8466zTAKBgYqhQMCAgMFADB+" + "MRowGAYJKoZIhvcNAQkBFgtzYmFAZGlndC5ydTELMAkGA1UEBhMCUlUxDDAK" + "BgNVBAgTA01FTDEUMBIGA1UEBxMLWW9zaGthci1PbGExDTALBgNVBAoTBERp" + "Z3QxDzANBgNVBAsTBkNyeXB0bzEPMA0GA1UEAxMGc2JhLUNBMB4XDTA0MDgw" @@ -637,203 +636,203 @@ public class CertTest + "mcTovpq088927shE"); byte[] inDirectCrl = Base64.decode( - "MIIdXjCCHMcCAQEwDQYJKoZIhvcNAQEFBQAwdDELMAkGA1UEBhMCREUxHDAaBgNV" - +"BAoUE0RldXRzY2hlIFRlbGVrb20gQUcxFzAVBgNVBAsUDlQtVGVsZVNlYyBUZXN0" - +"MS4wDAYHAoIGAQoHFBMBMTAeBgNVBAMUF1QtVGVsZVNlYyBUZXN0IERJUiA4OlBO" - +"Fw0wNjA4MDQwODQ1MTRaFw0wNjA4MDQxNDQ1MTRaMIIbfzB+AgQvrj/pFw0wMzA3" - +"MjIwNTQxMjhaMGcwZQYDVR0dAQH/BFswWaRXMFUxCzAJBgNVBAYTAkRFMRwwGgYD" - +"VQQKFBNEZXV0c2NoZSBUZWxla29tIEFHMSgwDAYHAoIGAQoHFBMBMTAYBgNVBAMU" - +"EVNpZ0cgVGVzdCBDQSA0OlBOMH4CBC+uP+oXDTAzMDcyMjA1NDEyOFowZzBlBgNV" - +"HR0BAf8EWzBZpFcwVTELMAkGA1UEBhMCREUxHDAaBgNVBAoUE0RldXRzY2hlIFRl" - +"bGVrb20gQUcxKDAMBgcCggYBCgcUEwExMBgGA1UEAxQRU2lnRyBUZXN0IENBIDQ6" - +"UE4wfgIEL64/5xcNMDQwNDA1MTMxODE3WjBnMGUGA1UdHQEB/wRbMFmkVzBVMQsw" - +"CQYDVQQGEwJERTEcMBoGA1UEChQTRGV1dHNjaGUgVGVsZWtvbSBBRzEoMAwGBwKC" - +"BgEKBxQTATEwGAYDVQQDFBFTaWdHIFRlc3QgQ0EgNDpQTjB+AgQvrj/oFw0wNDA0" - +"MDUxMzE4MTdaMGcwZQYDVR0dAQH/BFswWaRXMFUxCzAJBgNVBAYTAkRFMRwwGgYD" - +"VQQKFBNEZXV0c2NoZSBUZWxla29tIEFHMSgwDAYHAoIGAQoHFBMBMTAYBgNVBAMU" - +"EVNpZ0cgVGVzdCBDQSA0OlBOMH4CBC+uP+UXDTAzMDExMzExMTgxMVowZzBlBgNV" - +"HR0BAf8EWzBZpFcwVTELMAkGA1UEBhMCREUxHDAaBgNVBAoUE0RldXRzY2hlIFRl" - +"bGVrb20gQUcxKDAMBgcCggYBCgcUEwExMBgGA1UEAxQRU2lnRyBUZXN0IENBIDQ6" - +"UE4wfgIEL64/5hcNMDMwMTEzMTExODExWjBnMGUGA1UdHQEB/wRbMFmkVzBVMQsw" - +"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"); + "MIIdXjCCHMcCAQEwDQYJKoZIhvcNAQEFBQAwdDELMAkGA1UEBhMCREUxHDAaBgNV" + + "BAoUE0RldXRzY2hlIFRlbGVrb20gQUcxFzAVBgNVBAsUDlQtVGVsZVNlYyBUZXN0" + + "MS4wDAYHAoIGAQoHFBMBMTAeBgNVBAMUF1QtVGVsZVNlYyBUZXN0IERJUiA4OlBO" + + "Fw0wNjA4MDQwODQ1MTRaFw0wNjA4MDQxNDQ1MTRaMIIbfzB+AgQvrj/pFw0wMzA3" + + "MjIwNTQxMjhaMGcwZQYDVR0dAQH/BFswWaRXMFUxCzAJBgNVBAYTAkRFMRwwGgYD" + + "VQQKFBNEZXV0c2NoZSBUZWxla29tIEFHMSgwDAYHAoIGAQoHFBMBMTAYBgNVBAMU" + + "EVNpZ0cgVGVzdCBDQSA0OlBOMH4CBC+uP+oXDTAzMDcyMjA1NDEyOFowZzBlBgNV" + + "HR0BAf8EWzBZpFcwVTELMAkGA1UEBhMCREUxHDAaBgNVBAoUE0RldXRzY2hlIFRl" + + "bGVrb20gQUcxKDAMBgcCggYBCgcUEwExMBgGA1UEAxQRU2lnRyBUZXN0IENBIDQ6" + + "UE4wfgIEL64/5xcNMDQwNDA1MTMxODE3WjBnMGUGA1UdHQEB/wRbMFmkVzBVMQsw" + + "CQYDVQQGEwJERTEcMBoGA1UEChQTRGV1dHNjaGUgVGVsZWtvbSBBRzEoMAwGBwKC" + + "BgEKBxQTATEwGAYDVQQDFBFTaWdHIFRlc3QgQ0EgNDpQTjB+AgQvrj/oFw0wNDA0" + + "MDUxMzE4MTdaMGcwZQYDVR0dAQH/BFswWaRXMFUxCzAJBgNVBAYTAkRFMRwwGgYD" + + "VQQKFBNEZXV0c2NoZSBUZWxla29tIEFHMSgwDAYHAoIGAQoHFBMBMTAYBgNVBAMU" + + "EVNpZ0cgVGVzdCBDQSA0OlBOMH4CBC+uP+UXDTAzMDExMzExMTgxMVowZzBlBgNV" + + "HR0BAf8EWzBZpFcwVTELMAkGA1UEBhMCREUxHDAaBgNVBAoUE0RldXRzY2hlIFRl" + + "bGVrb20gQUcxKDAMBgcCggYBCgcUEwExMBgGA1UEAxQRU2lnRyBUZXN0IENBIDQ6" + + "UE4wfgIEL64/5hcNMDMwMTEzMTExODExWjBnMGUGA1UdHQEB/wRbMFmkVzBVMQsw" + + "CQYDVQQGEwJERTEcMBoGA1UEChQTRGV1dHNjaGUgVGVsZWtvbSBBRzEoMAwGBwKC" + + "BgEKBxQTATEwGAYDVQQDFBFTaWdHIFRlc3QgQ0EgNDpQTjB+AgQvrj/jFw0wMzAx" + + "MTMxMTI2NTZaMGcwZQYDVR0dAQH/BFswWaRXMFUxCzAJBgNVBAYTAkRFMRwwGgYD" + + "VQQKFBNEZXV0c2NoZSBUZWxla29tIEFHMSgwDAYHAoIGAQoHFBMBMTAYBgNVBAMU" + + "EVNpZ0cgVGVzdCBDQSA0OlBOMH4CBC+uP+QXDTAzMDExMzExMjY1NlowZzBlBgNV" + + "HR0BAf8EWzBZpFcwVTELMAkGA1UEBhMCREUxHDAaBgNVBAoUE0RldXRzY2hlIFRl" + + "bGVrb20gQUcxKDAMBgcCggYBCgcUEwExMBgGA1UEAxQRU2lnRyBUZXN0IENBIDQ6" + + "UE4wfgIEL64/4hcNMDQwNzEzMDc1ODM4WjBnMGUGA1UdHQEB/wRbMFmkVzBVMQsw" + + "CQYDVQQGEwJERTEcMBoGA1UEChQTRGV1dHNjaGUgVGVsZWtvbSBBRzEoMAwGBwKC" + + "BgEKBxQTATEwGAYDVQQDFBFTaWdHIFRlc3QgQ0EgNDpQTjB+AgQvrj/eFw0wMzAy" + + "MTcwNjMzMjVaMGcwZQYDVR0dAQH/BFswWaRXMFUxCzAJBgNVBAYTAkRFMRwwGgYD" + + "VQQKFBNEZXV0c2NoZSBUZWxla29tIEFHMSgwDAYHAoIGAQoHFBMBMTAYBgNVBAMU" + + "EVNpZ0cgVGVzdCBDQSA0OlBOMH4CBC+uP98XDTAzMDIxNzA2MzMyNVowZzBlBgNV" + + "HR0BAf8EWzBZpFcwVTELMAkGA1UEBhMCREUxHDAaBgNVBAoUE0RldXRzY2hlIFRl" + + "bGVrb20gQUcxKDAMBgcCggYBCgcUEwExMBgGA1UEAxQRU2lnRyBUZXN0IENBIDQ6" + + "UE4wfgIEL64/0xcNMDMwMjE3MDYzMzI1WjBnMGUGA1UdHQEB/wRbMFmkVzBVMQsw" + + "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"); byte[] directCRL = Base64.decode( - "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" - +"MQ=="); + "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" + + "MQ=="); private final byte[] pkcs7CrlProblem = Base64.decode( - "MIIwSAYJKoZIhvcNAQcCoIIwOTCCMDUCAQExCzAJBgUrDgMCGgUAMAsGCSqG" + "MIIwSAYJKoZIhvcNAQcCoIIwOTCCMDUCAQExCzAJBgUrDgMCGgUAMAsGCSqG" + "SIb3DQEHAaCCEsAwggP4MIIC4KADAgECAgF1MA0GCSqGSIb3DQEBBQUAMEUx" + "CzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1HZW9UcnVzdCBJbmMuMR4wHAYDVQQD" + "ExVHZW9UcnVzdCBDQSBmb3IgQWRvYmUwHhcNMDQxMjAyMjEyNTM5WhcNMDYx" @@ -1119,7 +1118,7 @@ public class CertTest + "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=="); private final byte[] emptyDNCert = Base64.decode( - "MIICfTCCAeagAwIBAgIBajANBgkqhkiG9w0BAQQFADB8MQswCQYDVQQGEwJVUzEMMAoGA1UEChMD" + "MIICfTCCAeagAwIBAgIBajANBgkqhkiG9w0BAQQFADB8MQswCQYDVQQGEwJVUzEMMAoGA1UEChMD" + "Q0RXMQkwBwYDVQQLEwAxCTAHBgNVBAcTADEJMAcGA1UECBMAMRowGAYDVQQDExFUZW1wbGFyIFRl" + "c3QgMTAyNDEiMCAGCSqGSIb3DQEJARYTdGVtcGxhcnRlc3RAY2R3LmNvbTAeFw0wNjA1MjIwNTAw" + "MDBaFw0xMDA1MjIwNTAwMDBaMHwxCzAJBgNVBAYTAlVTMQwwCgYDVQQKEwNDRFcxCTAHBgNVBAsT" @@ -1146,7 +1145,7 @@ public class CertTest "g1DjB8zy5DEjiULIc+HeIveF81W9lOxGkZxnrFjXBSqnjLeFKgF1hffXOAP7zUM="); private final byte[] gostRFC4491_2001 = Base64.decode( - "MIIB0DCCAX8CECv1xh7CEb0Xx9zUYma0LiEwCAYGKoUDAgIDMG0xHzAdBgNVBAMM" + + "MIIB0DCCAX8CECv1xh7CEb0Xx9zUYma0LiEwCAYGKoUDAgIDMG0xHzAdBgNVBAMM" + "Fkdvc3RSMzQxMC0yMDAxIGV4YW1wbGUxEjAQBgNVBAoMCUNyeXB0b1BybzELMAkG" + "A1UEBhMCUlUxKTAnBgkqhkiG9w0BCQEWGkdvc3RSMzQxMC0yMDAxQGV4YW1wbGUu" + "Y29tMB4XDTA1MDgxNjE0MTgyMFoXDTE1MDgxNjE0MTgyMFowbTEfMB0GA1UEAwwW" + @@ -1182,46 +1181,46 @@ public class CertTest } public void checkCertificate( - int id, - byte[] bytes) + int id, + byte[] bytes) { - ByteArrayInputStream bIn; - String dump = ""; + ByteArrayInputStream bIn; + String dump = ""; try { bIn = new ByteArrayInputStream(bytes); - CertificateFactory fact = CertificateFactory.getInstance("X.509", "BC"); + CertificateFactory fact = CertificateFactory.getInstance("X.509", "BC"); Certificate cert = fact.generateCertificate(bIn); - PublicKey k = cert.getPublicKey(); + PublicKey k = cert.getPublicKey(); // System.out.println(cert); } catch (Exception e) { - fail(dump + System.getProperty("line.separator") + getName() + ": "+ id + " failed - exception " + e.toString(), e); + fail(dump + Strings.lineSeparator() + getName() + ": " + id + " failed - exception " + e.toString(), e); } } public void checkNameCertificate( - int id, - byte[] bytes) + int id, + byte[] bytes) { - ByteArrayInputStream bIn; - String dump = ""; + ByteArrayInputStream bIn; + String dump = ""; try { bIn = new ByteArrayInputStream(bytes); - CertificateFactory fact = CertificateFactory.getInstance("X.509", "BC"); + CertificateFactory fact = CertificateFactory.getInstance("X.509", "BC"); X509Certificate cert = (X509Certificate)fact.generateCertificate(bIn); - PublicKey k = cert.getPublicKey(); + PublicKey k = cert.getPublicKey(); if (!cert.getIssuerDN().toString().equals("C=DE,O=DATEV eG,0.2.262.1.10.7.20=1+CN=CA DATEV D03 1:PN")) { fail(id + " failed - name test."); @@ -1230,27 +1229,27 @@ public class CertTest } catch (Exception e) { - fail(dump + System.getProperty("line.separator") + getName() + ": "+ id + " failed - exception " + e.toString(), e); + fail(dump + Strings.lineSeparator() + getName() + ": " + id + " failed - exception " + e.toString(), e); } } public void checkKeyUsage( - int id, - byte[] bytes) + int id, + byte[] bytes) { - ByteArrayInputStream bIn; - String dump = ""; + ByteArrayInputStream bIn; + String dump = ""; try { bIn = new ByteArrayInputStream(bytes); - CertificateFactory fact = CertificateFactory.getInstance("X.509", "BC"); + CertificateFactory fact = CertificateFactory.getInstance("X.509", "BC"); X509Certificate cert = (X509Certificate)fact.generateCertificate(bIn); - PublicKey k = cert.getPublicKey(); + PublicKey k = cert.getPublicKey(); if (cert.getKeyUsage()[7]) { @@ -1261,35 +1260,35 @@ public class CertTest } catch (Exception e) { - fail(dump + System.getProperty("line.separator") + getName() + ": "+ id + " failed - exception " + e.toString(), e); + fail(dump + Strings.lineSeparator() + getName() + ": " + id + " failed - exception " + e.toString(), e); } } public void checkSelfSignedCertificate( - int id, - byte[] bytes) + int id, + byte[] bytes) { - ByteArrayInputStream bIn; - String dump = ""; + ByteArrayInputStream bIn; + String dump = ""; try { bIn = new ByteArrayInputStream(bytes); - CertificateFactory fact = CertificateFactory.getInstance("X.509", "BC"); + CertificateFactory fact = CertificateFactory.getInstance("X.509", "BC"); Certificate cert = fact.generateCertificate(bIn); - PublicKey k = cert.getPublicKey(); + PublicKey k = cert.getPublicKey(); cert.verify(k); // System.out.println(cert); } catch (Exception e) { - fail(dump + System.getProperty("line.separator") + getName() + ": "+ id + " failed - exception " + e.toString(), e); + fail(dump + Strings.lineSeparator() + getName() + ": " + id + " failed - exception " + e.toString(), e); } } @@ -1332,10 +1331,10 @@ public class CertTest // // set up the keys // - PrivateKey privKey; - PublicKey pubKey; + PrivateKey privKey; + PublicKey pubKey; - KeyFactory fact = KeyFactory.getInstance("RSA", "BC"); + KeyFactory fact = KeyFactory.getInstance("RSA", "BC"); privKey = fact.generatePrivate(privKeySpec); pubKey = fact.generatePublic(pubKeySpec); @@ -1359,7 +1358,7 @@ public class CertTest // create the certificate - version 3 - without extensions // ContentSigner sigGen = new JcaContentSignerBuilder("SHA256WithRSAEncryption").setProvider(BC).build(privKey); - X509v3CertificateBuilder certGen = new JcaX509v3CertificateBuilder(builder.build(), BigInteger.valueOf(1), new Date(System.currentTimeMillis() - 50000), new Date(System.currentTimeMillis() + 50000),builder.build(), pubKey); + X509v3CertificateBuilder certGen = new JcaX509v3CertificateBuilder(builder.build(), BigInteger.valueOf(1), new Date(System.currentTimeMillis() - 50000), new Date(System.currentTimeMillis() + 50000), builder.build(), pubKey); X509Certificate cert = new JcaX509CertificateConverter().setProvider(BC).getCertificate(certGen.build(sigGen)); @@ -1415,8 +1414,8 @@ public class CertTest fail("signature test failed"); } - ByteArrayInputStream bIn = new ByteArrayInputStream(cert.getEncoded()); - CertificateFactory certFact = CertificateFactory.getInstance("X.509", "BC"); + ByteArrayInputStream bIn = new ByteArrayInputStream(cert.getEncoded()); + CertificateFactory certFact = CertificateFactory.getInstance("X.509", "BC"); cert = (X509Certificate)certFact.generateCertificate(bIn); @@ -1432,10 +1431,10 @@ public class CertTest } Collection c = cert.getSubjectAlternativeNames(); - Iterator it = c.iterator(); + Iterator it = c.iterator(); while (it.hasNext()) { - List gn = (List)it.next(); + List gn = (List)it.next(); if (!gn.get(1).equals("test@test.test") && !gn.get(1).equals("dom.test.test")) { fail("failed subject alternative names test"); @@ -1451,7 +1450,7 @@ public class CertTest // create the certificate - version 1 // sigGen = new JcaContentSignerBuilder("MD5WithRSAEncryption").setProvider(BC).build(privKey); - X509v1CertificateBuilder certGen1 = new JcaX509v1CertificateBuilder(builder.build(), BigInteger.valueOf(1), new Date(System.currentTimeMillis() - 50000),new Date(System.currentTimeMillis() + 50000),builder.build(),pubKey); + X509v1CertificateBuilder certGen1 = new JcaX509v1CertificateBuilder(builder.build(), BigInteger.valueOf(1), new Date(System.currentTimeMillis() - 50000), new Date(System.currentTimeMillis() + 50000), builder.build(), pubKey); cert = new JcaX509CertificateConverter().setProvider(BC).getCertificate(certGen1.build(sigGen)); @@ -1495,7 +1494,7 @@ public class CertTest // distinguished name table. // builder = new X500NameBuilder(BCStyle.INSTANCE); - + builder.addRDN(BCStyle.C, "AU"); builder.addRDN(BCStyle.O, "The Legion of the Bouncy Castle"); builder.addRDN(BCStyle.L, "Melbourne"); @@ -1541,12 +1540,12 @@ public class CertTest // // set up the keys // - PrivateKey privKey; - PublicKey pubKey; + PrivateKey privKey; + PublicKey pubKey; try { - KeyPairGenerator g = KeyPairGenerator.getInstance("DSA", "SUN"); + KeyPairGenerator g = KeyPairGenerator.getInstance("DSA", "SUN"); g.initialize(512, new SecureRandom()); @@ -1575,48 +1574,48 @@ public class CertTest // ContentSigner sigGen = new JcaContentSignerBuilder("SHA1withDSA").setProvider(BC).build(privKey); - JcaX509v3CertificateBuilder certGen = new JcaX509v3CertificateBuilder(builder.build(),BigInteger.valueOf(1),new Date(System.currentTimeMillis() - 50000),new Date(System.currentTimeMillis() + 50000),builder.build(),pubKey); + JcaX509v3CertificateBuilder certGen = new JcaX509v3CertificateBuilder(builder.build(), BigInteger.valueOf(1), new Date(System.currentTimeMillis() - 50000), new Date(System.currentTimeMillis() + 50000), builder.build(), pubKey); - X509Certificate cert = new JcaX509CertificateConverter().setProvider(BC).getCertificate(certGen.build(sigGen)); + X509Certificate cert = new JcaX509CertificateConverter().setProvider(BC).getCertificate(certGen.build(sigGen)); - cert.checkValidity(new Date()); + cert.checkValidity(new Date()); - cert.verify(pubKey); + cert.verify(pubKey); - ByteArrayInputStream bIn = new ByteArrayInputStream(cert.getEncoded()); - CertificateFactory fact = CertificateFactory.getInstance("X.509", BC); + ByteArrayInputStream bIn = new ByteArrayInputStream(cert.getEncoded()); + CertificateFactory fact = CertificateFactory.getInstance("X.509", BC); - cert = (X509Certificate)fact.generateCertificate(bIn); + cert = (X509Certificate)fact.generateCertificate(bIn); - // System.out.println(cert); + // System.out.println(cert); // // create the certificate - version 1 // sigGen = new JcaContentSignerBuilder("SHA1withDSA").setProvider(BC).build(privKey); - JcaX509v1CertificateBuilder certGen1 = new JcaX509v1CertificateBuilder(builder.build(),BigInteger.valueOf(1),new Date(System.currentTimeMillis() - 50000),new Date(System.currentTimeMillis() + 50000),builder.build(),pubKey); - - cert = new JcaX509CertificateConverter().setProvider(BC).getCertificate(certGen1.build(sigGen)); + JcaX509v1CertificateBuilder certGen1 = new JcaX509v1CertificateBuilder(builder.build(), BigInteger.valueOf(1), new Date(System.currentTimeMillis() - 50000), new Date(System.currentTimeMillis() + 50000), builder.build(), pubKey); - cert.checkValidity(new Date()); + cert = new JcaX509CertificateConverter().setProvider(BC).getCertificate(certGen1.build(sigGen)); - cert.verify(pubKey); + cert.checkValidity(new Date()); - bIn = new ByteArrayInputStream(cert.getEncoded()); - fact = CertificateFactory.getInstance("X.509", BC); + cert.verify(pubKey); - cert = (X509Certificate)fact.generateCertificate(bIn); + bIn = new ByteArrayInputStream(cert.getEncoded()); + fact = CertificateFactory.getInstance("X.509", BC); + + cert = (X509Certificate)fact.generateCertificate(bIn); - //System.out.println(cert); + //System.out.println(cert); // // exception test // try { - certGen1 = new JcaX509v1CertificateBuilder(builder.build(),BigInteger.valueOf(1),new Date(System.currentTimeMillis() - 50000),new Date(System.currentTimeMillis() + 50000),builder.build(),dudPublicKey); + certGen1 = new JcaX509v1CertificateBuilder(builder.build(), BigInteger.valueOf(1), new Date(System.currentTimeMillis() - 50000), new Date(System.currentTimeMillis() + 50000), builder.build(), dudPublicKey); fail("key without encoding not detected in v1"); @@ -1627,16 +1626,36 @@ public class CertTest } } + private void checkComparison(byte[] encCert) + throws NoSuchProviderException, CertificateException + { + CertificateFactory bcFact = CertificateFactory.getInstance("X.509", "BC"); + CertificateFactory sunFact = CertificateFactory.getInstance("X.509", "SUN"); + + X509Certificate bcCert = (X509Certificate)bcFact.generateCertificate(new ByteArrayInputStream(encCert)); + X509Certificate sunCert = (X509Certificate)sunFact.generateCertificate(new ByteArrayInputStream(encCert)); + + if (!bcCert.equals(sunCert) || !sunCert.equals(bcCert)) + { + fail("BC/Sun equals test failed"); + } + + if (bcCert.hashCode() != sunCert.hashCode()) + { + fail("BC/Sun hashCode test failed"); + } + } + private X500NameBuilder createStdBuilder() { X500NameBuilder builder = new X500NameBuilder(BCStyle.INSTANCE); - + builder.addRDN(BCStyle.C, "AU"); builder.addRDN(BCStyle.O, "The Legion of the Bouncy Castle"); builder.addRDN(BCStyle.L, "Melbourne"); builder.addRDN(BCStyle.ST, "Victoria"); builder.addRDN(BCStyle.E, "feedback-crypto@bouncycastle.org"); - + return builder; } @@ -1667,12 +1686,12 @@ public class CertTest // // set up the keys // - PrivateKey privKey; - PublicKey pubKey; + PrivateKey privKey; + PublicKey pubKey; try { - KeyFactory fact = KeyFactory.getInstance("ECDSA", BC); + KeyFactory fact = KeyFactory.getInstance("ECDSA", BC); privKey = fact.generatePrivate(privKeySpec); pubKey = fact.generatePublic(pubKeySpec); @@ -1693,7 +1712,7 @@ public class CertTest // toString test // X500Name p = builder.build(); - String s = p.toString(); + String s = p.toString(); if (!s.equals("C=AU,O=The Legion of the Bouncy Castle,L=Melbourne,ST=Victoria,E=feedback-crypto@bouncycastle.org")) { @@ -1714,10 +1733,10 @@ public class CertTest // // create the certificate - version 3 // - try + try { - ContentSigner sigGen = new JcaContentSignerBuilder("SHA1withECDSA").setProvider(BC).build(privKey); - JcaX509v3CertificateBuilder certGen = new JcaX509v3CertificateBuilder(builder.build(),BigInteger.valueOf(1),new Date(System.currentTimeMillis() - 50000),new Date(System.currentTimeMillis() + 50000),builder.build(),pubKey); + ContentSigner sigGen = new JcaContentSignerBuilder("SHA1withECDSA").setProvider(BC).build(privKey); + JcaX509v3CertificateBuilder certGen = new JcaX509v3CertificateBuilder(builder.build(), BigInteger.valueOf(1), new Date(System.currentTimeMillis() - 50000), new Date(System.currentTimeMillis() + 50000), builder.build(), pubKey); X509Certificate cert = new JcaX509CertificateConverter().setProvider(BC).getCertificate(certGen.build(sigGen)); @@ -1725,8 +1744,8 @@ public class CertTest cert.verify(pubKey); - ByteArrayInputStream bIn = new ByteArrayInputStream(cert.getEncoded()); - CertificateFactory fact = CertificateFactory.getInstance("X.509", BC); + ByteArrayInputStream bIn = new ByteArrayInputStream(cert.getEncoded()); + CertificateFactory fact = CertificateFactory.getInstance("X.509", BC); cert = (X509Certificate)fact.generateCertificate(bIn); @@ -1735,7 +1754,7 @@ public class CertTest // ((ECPointEncoder)pubKey).setPointFormat("UNCOMPRESSED"); - certGen = new JcaX509v3CertificateBuilder(builder.build(),BigInteger.valueOf(1),new Date(System.currentTimeMillis() - 50000),new Date(System.currentTimeMillis() + 50000),builder.build(),pubKey); + certGen = new JcaX509v3CertificateBuilder(builder.build(), BigInteger.valueOf(1), new Date(System.currentTimeMillis() - 50000), new Date(System.currentTimeMillis() + 50000), builder.build(), pubKey); cert = new JcaX509CertificateConverter().setProvider(BC).getCertificate(certGen.build(sigGen)); @@ -1797,10 +1816,10 @@ public class CertTest // // set up the keys // - PrivateKey privKey; - PublicKey pubKey; + PrivateKey privKey; + PublicKey pubKey; - KeyFactory fact = KeyFactory.getInstance("ECDSA", BC); + KeyFactory fact = KeyFactory.getInstance("ECDSA", BC); privKey = fact.generatePrivate(privKeySpec); pubKey = fact.generatePublic(pubKeySpec); @@ -1815,7 +1834,7 @@ public class CertTest // create the certificate - version 3 // ContentSigner sigGen = new JcaContentSignerBuilder(algorithm).setProvider(BC).build(privKey); - X509v3CertificateBuilder certGen = new JcaX509v3CertificateBuilder(builder.build(),BigInteger.valueOf(1),new Date(System.currentTimeMillis() - 50000),new Date(System.currentTimeMillis() + 50000),builder.build(),pubKey); + X509v3CertificateBuilder certGen = new JcaX509v3CertificateBuilder(builder.build(), BigInteger.valueOf(1), new Date(System.currentTimeMillis() - 50000), new Date(System.currentTimeMillis() + 50000), builder.build(), pubKey); X509Certificate cert = new JcaX509CertificateConverter().setProvider(BC).getCertificate(certGen.build(sigGen)); @@ -1823,8 +1842,8 @@ public class CertTest cert.verify(pubKey); - ByteArrayInputStream bIn = new ByteArrayInputStream(cert.getEncoded()); - CertificateFactory certFact = CertificateFactory.getInstance("X.509", BC); + ByteArrayInputStream bIn = new ByteArrayInputStream(cert.getEncoded()); + CertificateFactory certFact = CertificateFactory.getInstance("X.509", BC); cert = (X509Certificate)certFact.generateCertificate(bIn); @@ -1833,7 +1852,7 @@ public class CertTest // ((ECPointEncoder)pubKey).setPointFormat("UNCOMPRESSED"); - certGen = new JcaX509v3CertificateBuilder(builder.build(),BigInteger.valueOf(1),new Date(System.currentTimeMillis() - 50000),new Date(System.currentTimeMillis() + 50000),builder.build(),pubKey); + certGen = new JcaX509v3CertificateBuilder(builder.build(), BigInteger.valueOf(1), new Date(System.currentTimeMillis() - 50000), new Date(System.currentTimeMillis() + 50000), builder.build(), pubKey); cert = new JcaX509CertificateConverter().setProvider(BC).getCertificate(certGen.build(sigGen)); @@ -1850,7 +1869,7 @@ public class CertTest { fail("ECDSA oid incorrect."); } - + if (cert.getSigAlgParams() != null) { fail("sig parameters present"); @@ -1870,17 +1889,17 @@ public class CertTest } private void checkCRL( - int id, - byte[] bytes) + int id, + byte[] bytes) { - ByteArrayInputStream bIn; - String dump = ""; + ByteArrayInputStream bIn; + String dump = ""; try { bIn = new ByteArrayInputStream(bytes); - CertificateFactory fact = CertificateFactory.getInstance("X.509", BC); + CertificateFactory fact = CertificateFactory.getInstance("X.509", BC); CRL cert = fact.generateCRL(bIn); @@ -1888,7 +1907,7 @@ public class CertTest } catch (Exception e) { - fail(dump + System.getProperty("line.separator") + getName() + ": "+ id + " failed - exception " + e.toString(), e); + fail(dump + Strings.lineSeparator() + getName() + ": " + id + " failed - exception " + e.toString(), e); } } @@ -1896,16 +1915,18 @@ public class CertTest public void checkCRLCreation1() throws Exception { - KeyPairGenerator kpGen = KeyPairGenerator.getInstance("RSA", BC); - Date now = new Date(); - KeyPair pair = kpGen.generateKeyPair(); - X509v2CRLBuilder crlGen = new X509v2CRLBuilder(new X500Name("CN=Test CA"), now); + KeyPairGenerator kpGen = KeyPairGenerator.getInstance("RSA", BC); + Date now = new Date(); + KeyPair pair = kpGen.generateKeyPair(); + X509v2CRLBuilder crlGen = new X509v2CRLBuilder(new X500Name("CN=Test CA"), now); crlGen.setNextUpdate(new Date(now.getTime() + 100000)); crlGen.addCRLEntry(BigInteger.ONE, now, CRLReason.privilegeWithdrawn); - crlGen.addExtension(X509Extensions.AuthorityKeyIdentifier, false, new AuthorityKeyIdentifierStructure(pair.getPublic())); + JcaX509ExtensionUtils extUtils = new JcaX509ExtensionUtils(); + + crlGen.addExtension(Extension.authorityKeyIdentifier, false, extUtils.createAuthorityKeyIdentifier(pair.getPublic())); X509CRLHolder crl = crlGen.build(new JcaContentSignerBuilder("SHA256withRSAEncryption").setProvider(BC).build(pair.getPrivate())); @@ -1921,7 +1942,7 @@ public class CertTest fail("failed to find CRL extension"); } - AuthorityKeyIdentifier authId = new AuthorityKeyIdentifierStructure(authExt); + AuthorityKeyIdentifier authId = AuthorityKeyIdentifier.getInstance(authExt.getParsedValue()); X509CRLEntryHolder entry = crl.getRevokedCertificate(BigInteger.ONE); @@ -1940,11 +1961,11 @@ public class CertTest fail("CRL entry extension not found"); } - Extension ext = entry.getExtension(X509Extension.reasonCode); + Extension ext = entry.getExtension(Extension.reasonCode); if (ext != null) { - ASN1Enumerated reasonCode = (ASN1Enumerated)ASN1Enumerated.getInstance(ext.getParsedValue()); + ASN1Enumerated reasonCode = ASN1Enumerated.getInstance(ext.getParsedValue()); if (reasonCode.getValue().intValue() != CRLReason.privilegeWithdrawn) { @@ -1960,14 +1981,14 @@ public class CertTest public void checkCRLCreation2() throws Exception { - KeyPairGenerator kpGen = KeyPairGenerator.getInstance("RSA", BC); + KeyPairGenerator kpGen = KeyPairGenerator.getInstance("RSA", BC); - Date now = new Date(); - KeyPair pair = kpGen.generateKeyPair(); - X509v2CRLBuilder crlGen = new JcaX509v2CRLBuilder(new X500Principal("CN=Test CA"), now); + Date now = new Date(); + KeyPair pair = kpGen.generateKeyPair(); + X509v2CRLBuilder crlGen = new JcaX509v2CRLBuilder(new X500Principal("CN=Test CA"), now); crlGen.setNextUpdate(new Date(now.getTime() + 100000)); - + Vector extOids = new Vector(); Vector extValues = new Vector(); @@ -1975,19 +1996,21 @@ public class CertTest try { - extOids.addElement(X509Extensions.ReasonCode); - extValues.addElement(new X509Extension(false, new DEROctetString(crlReason.getEncoded()))); + extOids.addElement(Extension.reasonCode); + extValues.addElement(new Extension(Extension.reasonCode, false, new DEROctetString(crlReason.getEncoded()))); } catch (IOException e) { throw new IllegalArgumentException("error encoding reason: " + e); } - X509Extensions entryExtensions = new X509Extensions(extOids, extValues); + Extensions entryExtensions = generateExtensions(extOids, extValues); crlGen.addCRLEntry(BigInteger.ONE, now, entryExtensions); - crlGen.addExtension(X509Extensions.AuthorityKeyIdentifier, false, new AuthorityKeyIdentifierStructure(pair.getPublic())); + JcaX509ExtensionUtils extUtils = new JcaX509ExtensionUtils(); + + crlGen.addExtension(Extension.authorityKeyIdentifier, false, extUtils.createAuthorityKeyIdentifier(pair.getPublic())); X509CRLHolder crlHolder = crlGen.build(new JcaContentSignerBuilder("SHA256withRSAEncryption").setProvider(BC).build(pair.getPrivate())); @@ -1998,14 +2021,14 @@ public class CertTest fail("failed CRL issuer test"); } - byte[] authExt = crl.getExtensionValue(X509Extensions.AuthorityKeyIdentifier.getId()); + byte[] authExt = crl.getExtensionValue(Extension.authorityKeyIdentifier.getId()); if (authExt == null) { fail("failed to find CRL extension"); } - AuthorityKeyIdentifier authId = new AuthorityKeyIdentifierStructure(authExt); + AuthorityKeyIdentifier authId = AuthorityKeyIdentifier.getInstance(ASN1OctetString.getInstance(authExt).getOctets()); X509CRLEntry entry = crl.getRevokedCertificate(BigInteger.ONE); @@ -2024,11 +2047,11 @@ public class CertTest fail("CRL entry extension not found"); } - byte[] ext = entry.getExtensionValue(X509Extensions.ReasonCode.getId()); + byte[] ext = entry.getExtensionValue(Extension.reasonCode.getId()); if (ext != null) { - ASN1Enumerated reasonCode = (ASN1Enumerated)X509ExtensionUtil.fromExtensionValue(ext); + ASN1Enumerated reasonCode = (ASN1Enumerated)fromExtensionValue(ext); if (reasonCode.getValue().intValue() != CRLReason.privilegeWithdrawn) { @@ -2044,10 +2067,10 @@ public class CertTest public void checkCRLCreation3() throws Exception { - KeyPairGenerator kpGen = KeyPairGenerator.getInstance("RSA", BC); - Date now = new Date(); - KeyPair pair = kpGen.generateKeyPair(); - X509v2CRLBuilder crlGen = new JcaX509v2CRLBuilder(new X500Principal("CN=Test CA"), now); + KeyPairGenerator kpGen = KeyPairGenerator.getInstance("RSA", BC); + Date now = new Date(); + KeyPair pair = kpGen.generateKeyPair(); + X509v2CRLBuilder crlGen = new JcaX509v2CRLBuilder(new X500Principal("CN=Test CA"), now); crlGen.setNextUpdate(new Date(now.getTime() + 100000)); @@ -2058,19 +2081,21 @@ public class CertTest try { - extOids.addElement(X509Extensions.ReasonCode); - extValues.addElement(new X509Extension(false, new DEROctetString(crlReason.getEncoded()))); + extOids.addElement(Extension.reasonCode); + extValues.addElement(new Extension(Extension.reasonCode, false, new DEROctetString(crlReason.getEncoded()))); } catch (IOException e) { throw new IllegalArgumentException("error encoding reason: " + e); } - X509Extensions entryExtensions = new X509Extensions(extOids, extValues); + Extensions entryExtensions = generateExtensions(extOids, extValues); crlGen.addCRLEntry(BigInteger.ONE, now, entryExtensions); - crlGen.addExtension(X509Extensions.AuthorityKeyIdentifier, false, new AuthorityKeyIdentifierStructure(pair.getPublic())); + JcaX509ExtensionUtils extUtils = new JcaX509ExtensionUtils(); + + crlGen.addExtension(Extension.authorityKeyIdentifier, false, extUtils.createAuthorityKeyIdentifier(pair.getPublic())); X509CRLHolder crlHolder = crlGen.build(new JcaContentSignerBuilder("SHA256withRSAEncryption").setProvider(BC).build(pair.getPrivate())); @@ -2081,14 +2106,14 @@ public class CertTest fail("failed CRL issuer test"); } - byte[] authExt = crl.getExtensionValue(X509Extensions.AuthorityKeyIdentifier.getId()); + byte[] authExt = crl.getExtensionValue(Extension.authorityKeyIdentifier.getId()); if (authExt == null) { fail("failed to find CRL extension"); } - AuthorityKeyIdentifier authId = new AuthorityKeyIdentifierStructure(authExt); + AuthorityKeyIdentifier authId = AuthorityKeyIdentifier.getInstance(ASN1OctetString.getInstance(authExt).getOctets()); X509CRLEntry entry = crl.getRevokedCertificate(BigInteger.ONE); @@ -2107,11 +2132,11 @@ public class CertTest fail("CRL entry extension not found"); } - byte[] ext = entry.getExtensionValue(X509Extensions.ReasonCode.getId()); + byte[] ext = entry.getExtensionValue(Extension.reasonCode.getId()); if (ext != null) { - ASN1Enumerated reasonCode = (ASN1Enumerated)X509ExtensionUtil.fromExtensionValue(ext); + ASN1Enumerated reasonCode = (ASN1Enumerated)fromExtensionValue(ext); if (reasonCode.getValue().intValue() != CRLReason.privilegeWithdrawn) { @@ -2135,11 +2160,11 @@ public class CertTest crlGen.addCRLEntry(BigInteger.valueOf(2), now, entryExtensions); - crlGen.addExtension(X509Extension.authorityKeyIdentifier, false, new AuthorityKeyIdentifierStructure(pair.getPublic())); + crlGen.addExtension(Extension.authorityKeyIdentifier, false, extUtils.createAuthorityKeyIdentifier(pair.getPublic())); crlHolder = crlGen.build(new JcaContentSignerBuilder("SHA256withRSAEncryption").setProvider(BC).build(pair.getPrivate())); - int count = 0; + int count = 0; boolean oneFound = false; boolean twoFound = false; @@ -2151,7 +2176,7 @@ public class CertTest if (crlEnt.getSerialNumber().intValue() == 1) { oneFound = true; - Extension extn = crlEnt.getExtension(X509Extension.reasonCode); + Extension extn = crlEnt.getExtension(Extension.reasonCode); if (extn != null) { @@ -2214,10 +2239,10 @@ public class CertTest // // set up the keys // - PrivateKey privKey; - PublicKey pubKey; + PrivateKey privKey; + PublicKey pubKey; - KeyPairGenerator g = KeyPairGenerator.getInstance("GOST3410", BC); + KeyPairGenerator g = KeyPairGenerator.getInstance("GOST3410", BC); GOST3410ParameterSpec gost3410P = new GOST3410ParameterSpec("GostR3410-94-CryptoPro-A"); g.initialize(gost3410P, new SecureRandom()); @@ -2240,7 +2265,7 @@ public class CertTest // create the certificate - version 3 // ContentSigner sigGen = new JcaContentSignerBuilder("GOST3411withGOST3410").setProvider(BC).build(privKey); - X509v3CertificateBuilder certGen = new JcaX509v3CertificateBuilder(builder.build(),BigInteger.valueOf(1),new Date(System.currentTimeMillis() - 50000),new Date(System.currentTimeMillis() + 50000),builder.build(),pubKey); + X509v3CertificateBuilder certGen = new JcaX509v3CertificateBuilder(builder.build(), BigInteger.valueOf(1), new Date(System.currentTimeMillis() - 50000), new Date(System.currentTimeMillis() + 50000), builder.build(), pubKey); X509Certificate cert = new JcaX509CertificateConverter().setProvider(BC).getCertificate(certGen.build(sigGen)); @@ -2256,15 +2281,15 @@ public class CertTest // cert.verify(cert.getPublicKey()); - ByteArrayInputStream bIn = new ByteArrayInputStream(cert.getEncoded()); - CertificateFactory fact = CertificateFactory.getInstance("X.509", BC); + ByteArrayInputStream bIn = new ByteArrayInputStream(cert.getEncoded()); + CertificateFactory fact = CertificateFactory.getInstance("X.509", BC); cert = (X509Certificate)fact.generateCertificate(bIn); //System.out.println(cert); //check getEncoded() - byte[] bytes = cert.getEncoded(); + byte[] bytes = cert.getEncoded(); } public void checkCreation5() @@ -2290,11 +2315,11 @@ public class CertTest // // set up the keys // - SecureRandom rand = new SecureRandom(); - PrivateKey privKey; - PublicKey pubKey; + SecureRandom rand = new SecureRandom(); + PrivateKey privKey; + PublicKey pubKey; - KeyFactory fact = KeyFactory.getInstance("RSA", BC); + KeyFactory fact = KeyFactory.getInstance("RSA", BC); privKey = fact.generatePrivate(privKeySpec); pubKey = fact.generatePublic(pubKeySpec); @@ -2302,8 +2327,8 @@ public class CertTest // // distinguished name table. // - Vector ord = new Vector(); - Vector values = new Vector(); + Vector ord = new Vector(); + Vector values = new Vector(); X500NameBuilder builder = createStdBuilder(); @@ -2311,13 +2336,13 @@ public class CertTest // create base certificate - version 3 // ContentSigner sigGen = new JcaContentSignerBuilder("MD5WithRSAEncryption").setProvider(BC).build(privKey); - X509v3CertificateBuilder certGen = new JcaX509v3CertificateBuilder(builder.build(),BigInteger.valueOf(1),new Date(System.currentTimeMillis() - 50000),new Date(System.currentTimeMillis() + 50000),builder.build(),pubKey) + X509v3CertificateBuilder certGen = new JcaX509v3CertificateBuilder(builder.build(), BigInteger.valueOf(1), new Date(System.currentTimeMillis() - 50000), new Date(System.currentTimeMillis() + 50000), builder.build(), pubKey) .addExtension(new ASN1ObjectIdentifier("2.5.29.15"), true, - new X509KeyUsage(X509KeyUsage.encipherOnly)) + new X509KeyUsage(X509KeyUsage.encipherOnly)) .addExtension(new ASN1ObjectIdentifier("2.5.29.37"), true, - new DERSequence(KeyPurposeId.anyExtendedKeyUsage)) + new DERSequence(KeyPurposeId.anyExtendedKeyUsage)) .addExtension(new ASN1ObjectIdentifier("2.5.29.17"), true, - new GeneralNames(new GeneralName(GeneralName.rfc822Name, "test@test.test"))); + new GeneralNames(new GeneralName(GeneralName.rfc822Name, "test@test.test"))); X509Certificate baseCert = new JcaX509CertificateConverter().setProvider(BC).getCertificate(certGen.build(sigGen)); @@ -2325,7 +2350,7 @@ public class CertTest // copy certificate // - certGen = new JcaX509v3CertificateBuilder(builder.build(),BigInteger.valueOf(1),new Date(System.currentTimeMillis() - 50000),new Date(System.currentTimeMillis() + 50000),builder.build(),pubKey) + certGen = new JcaX509v3CertificateBuilder(builder.build(), BigInteger.valueOf(1), new Date(System.currentTimeMillis() - 50000), new Date(System.currentTimeMillis() + 50000), builder.build(), pubKey) .copyAndAddExtension(new ASN1ObjectIdentifier("2.5.29.15"), true, baseCert) .copyAndAddExtension(new ASN1ObjectIdentifier("2.5.29.37"), false, baseCert); @@ -2379,15 +2404,15 @@ public class CertTest throws Exception { String cert = "MIIBsDCCAVoCAQYwDQYJKoZIhvcNAQEFBQAwYzELMAkGA1UEBhMCQVUxEzARBgNV" - + "BAgTClF1ZWVuc2xhbmQxGjAYBgNVBAoTEUNyeXB0U29mdCBQdHkgTHRkMSMwIQYD" - + "VQQDExpTZXJ2ZXIgdGVzdCBjZXJ0ICg1MTIgYml0KTAeFw0wNjA5MTEyMzU4NTVa" - + "Fw0wNjEwMTEyMzU4NTVaMGMxCzAJBgNVBAYTAkFVMRMwEQYDVQQIEwpRdWVlbnNs" - + "YW5kMRowGAYDVQQKExFDcnlwdFNvZnQgUHR5IEx0ZDEjMCEGA1UEAxMaU2VydmVy" - + "IHRlc3QgY2VydCAoNTEyIGJpdCkwXDANBgkqhkiG9w0BAQEFAANLADBIAkEAn7PD" - + "hCeV/xIxUg8V70YRxK2A5jZbD92A12GN4PxyRQk0/lVmRUNMaJdq/qigpd9feP/u" - + "12S4PwTLb/8q/v657QIDAQABMA0GCSqGSIb3DQEBBQUAA0EAbynCRIlUQgaqyNgU" - + "DF6P14yRKUtX8akOP2TwStaSiVf/akYqfLFm3UGka5XbPj4rifrZ0/sOoZEEBvHQ" - + "e20sRA=="; + + "BAgTClF1ZWVuc2xhbmQxGjAYBgNVBAoTEUNyeXB0U29mdCBQdHkgTHRkMSMwIQYD" + + "VQQDExpTZXJ2ZXIgdGVzdCBjZXJ0ICg1MTIgYml0KTAeFw0wNjA5MTEyMzU4NTVa" + + "Fw0wNjEwMTEyMzU4NTVaMGMxCzAJBgNVBAYTAkFVMRMwEQYDVQQIEwpRdWVlbnNs" + + "YW5kMRowGAYDVQQKExFDcnlwdFNvZnQgUHR5IEx0ZDEjMCEGA1UEAxMaU2VydmVy" + + "IHRlc3QgY2VydCAoNTEyIGJpdCkwXDANBgkqhkiG9w0BAQEFAANLADBIAkEAn7PD" + + "hCeV/xIxUg8V70YRxK2A5jZbD92A12GN4PxyRQk0/lVmRUNMaJdq/qigpd9feP/u" + + "12S4PwTLb/8q/v657QIDAQABMA0GCSqGSIb3DQEBBQUAA0EAbynCRIlUQgaqyNgU" + + "DF6P14yRKUtX8akOP2TwStaSiVf/akYqfLFm3UGka5XbPj4rifrZ0/sOoZEEBvHQ" + + "e20sRA=="; CertificateFactory certFact = CertificateFactory.getInstance("X.509", BC); @@ -2546,15 +2571,15 @@ public class CertTest // // distinguished name table. // - + X500NameBuilder builder = createStdBuilder(); // // create base certificate - version 3 // ContentSigner sigGen = new JcaContentSignerBuilder(algorithm).setProvider(BC).build(privKey); - JcaX509v3CertificateBuilder certGen = new JcaX509v3CertificateBuilder(builder.build(),BigInteger.valueOf(1), - new Date(System.currentTimeMillis() - 50000),new Date(System.currentTimeMillis() + 50000),builder.build(),pubKey); + JcaX509v3CertificateBuilder certGen = new JcaX509v3CertificateBuilder(builder.build(), BigInteger.valueOf(1), + new Date(System.currentTimeMillis() - 50000), new Date(System.currentTimeMillis() + 50000), builder.build(), pubKey); certGen.addExtension(new ASN1ObjectIdentifier("2.5.29.15"), true, new X509KeyUsage(X509KeyUsage.encipherOnly)); @@ -2572,18 +2597,18 @@ public class CertTest throws NoSuchAlgorithmException, NoSuchProviderException, InvalidKeySpecException { RSAPublicKeySpec pubKeySpec = new RSAPublicKeySpec( - new BigInteger("a56e4a0e701017589a5187dc7ea841d156f2ec0e36ad52a44dfeb1e61f7ad991d8c51056ffedb162b4c0f283a12a88a394dff526ab7291cbb307ceabfce0b1dfd5cd9508096d5b2b8b6df5d671ef6377c0921cb23c270a70e2598e6ff89d19f105acc2d3f0cb35f29280e1386b6f64c4ef22e1e1f20d0ce8cffb2249bd9a2137",16), - new BigInteger("010001",16)); + new BigInteger("a56e4a0e701017589a5187dc7ea841d156f2ec0e36ad52a44dfeb1e61f7ad991d8c51056ffedb162b4c0f283a12a88a394dff526ab7291cbb307ceabfce0b1dfd5cd9508096d5b2b8b6df5d671ef6377c0921cb23c270a70e2598e6ff89d19f105acc2d3f0cb35f29280e1386b6f64c4ef22e1e1f20d0ce8cffb2249bd9a2137", 16), + new BigInteger("010001", 16)); RSAPrivateCrtKeySpec privKeySpec = new RSAPrivateCrtKeySpec( - new BigInteger("a56e4a0e701017589a5187dc7ea841d156f2ec0e36ad52a44dfeb1e61f7ad991d8c51056ffedb162b4c0f283a12a88a394dff526ab7291cbb307ceabfce0b1dfd5cd9508096d5b2b8b6df5d671ef6377c0921cb23c270a70e2598e6ff89d19f105acc2d3f0cb35f29280e1386b6f64c4ef22e1e1f20d0ce8cffb2249bd9a2137",16), - new BigInteger("010001",16), - new BigInteger("33a5042a90b27d4f5451ca9bbbd0b44771a101af884340aef9885f2a4bbe92e894a724ac3c568c8f97853ad07c0266c8c6a3ca0929f1e8f11231884429fc4d9ae55fee896a10ce707c3ed7e734e44727a39574501a532683109c2abacaba283c31b4bd2f53c3ee37e352cee34f9e503bd80c0622ad79c6dcee883547c6a3b325",16), - new BigInteger("e7e8942720a877517273a356053ea2a1bc0c94aa72d55c6e86296b2dfc967948c0a72cbccca7eacb35706e09a1df55a1535bd9b3cc34160b3b6dcd3eda8e6443",16), - new BigInteger("b69dca1cf7d4d7ec81e75b90fcca874abcde123fd2700180aa90479b6e48de8d67ed24f9f19d85ba275874f542cd20dc723e6963364a1f9425452b269a6799fd",16), - new BigInteger("28fa13938655be1f8a159cbaca5a72ea190c30089e19cd274a556f36c4f6e19f554b34c077790427bbdd8dd3ede2448328f385d81b30e8e43b2fffa027861979",16), - new BigInteger("1a8b38f398fa712049898d7fb79ee0a77668791299cdfa09efc0e507acb21ed74301ef5bfd48be455eaeb6e1678255827580a8e4e8e14151d1510a82a3f2e729",16), - new BigInteger("27156aba4126d24a81f3a528cbfb27f56886f840a9f6e86e17a44b94fe9319584b8e22fdde1e5a2e3bd8aa5ba8d8584194eb2190acf832b847f13a3d24a79f4d",16)); + new BigInteger("a56e4a0e701017589a5187dc7ea841d156f2ec0e36ad52a44dfeb1e61f7ad991d8c51056ffedb162b4c0f283a12a88a394dff526ab7291cbb307ceabfce0b1dfd5cd9508096d5b2b8b6df5d671ef6377c0921cb23c270a70e2598e6ff89d19f105acc2d3f0cb35f29280e1386b6f64c4ef22e1e1f20d0ce8cffb2249bd9a2137", 16), + new BigInteger("010001", 16), + new BigInteger("33a5042a90b27d4f5451ca9bbbd0b44771a101af884340aef9885f2a4bbe92e894a724ac3c568c8f97853ad07c0266c8c6a3ca0929f1e8f11231884429fc4d9ae55fee896a10ce707c3ed7e734e44727a39574501a532683109c2abacaba283c31b4bd2f53c3ee37e352cee34f9e503bd80c0622ad79c6dcee883547c6a3b325", 16), + new BigInteger("e7e8942720a877517273a356053ea2a1bc0c94aa72d55c6e86296b2dfc967948c0a72cbccca7eacb35706e09a1df55a1535bd9b3cc34160b3b6dcd3eda8e6443", 16), + new BigInteger("b69dca1cf7d4d7ec81e75b90fcca874abcde123fd2700180aa90479b6e48de8d67ed24f9f19d85ba275874f542cd20dc723e6963364a1f9425452b269a6799fd", 16), + new BigInteger("28fa13938655be1f8a159cbaca5a72ea190c30089e19cd274a556f36c4f6e19f554b34c077790427bbdd8dd3ede2448328f385d81b30e8e43b2fffa027861979", 16), + new BigInteger("1a8b38f398fa712049898d7fb79ee0a77668791299cdfa09efc0e507acb21ed74301ef5bfd48be455eaeb6e1678255827580a8e4e8e14151d1510a82a3f2e729", 16), + new BigInteger("27156aba4126d24a81f3a528cbfb27f56886f840a9f6e86e17a44b94fe9319584b8e22fdde1e5a2e3bd8aa5ba8d8584194eb2190acf832b847f13a3d24a79f4d", 16)); KeyFactory fact = KeyFactory.getInstance("RSA", BC); @@ -2591,7 +2616,7 @@ public class CertTest } private void rfc4491Test() - throws Exception + throws Exception { CertificateFactory certFact = CertificateFactory.getInstance("X.509", BC); @@ -2612,10 +2637,10 @@ public class CertTest PrivateKey privKey = pair.getPrivate(); ContentSigner sigGen = new JcaContentSignerBuilder("MD5WithRSAEncryption").setProvider(BC).build(privKey); - JcaX509v3CertificateBuilder certGen = new JcaX509v3CertificateBuilder(new X500Name("CN=Test"),BigInteger.valueOf(1),new Date(System.currentTimeMillis() - 50000),new Date(System.currentTimeMillis() + 50000),new X500Name("CN=Test"),pubKey); + JcaX509v3CertificateBuilder certGen = new JcaX509v3CertificateBuilder(new X500Name("CN=Test"), BigInteger.valueOf(1), new Date(System.currentTimeMillis() - 50000), new Date(System.currentTimeMillis() + 50000), new X500Name("CN=Test"), pubKey); X509Certificate cert = new JcaX509CertificateConverter().setProvider(BC).getCertificate(certGen.build(sigGen)); - X509CertificateStructure struct = X509CertificateStructure.getInstance(ASN1Primitive.fromByteArray(cert.getEncoded())); + org.bouncycastle.asn1.x509.Certificate struct = org.bouncycastle.asn1.x509.Certificate.getInstance(ASN1Primitive.fromByteArray(cert.getEncoded())); ASN1Encodable tbsCertificate = struct.getTBSCertificate(); AlgorithmIdentifier sig = struct.getSignatureAlgorithm(); @@ -2627,14 +2652,14 @@ public class CertTest v.add(struct.getSignature()); // verify - ByteArrayInputStream bIn; - String dump = ""; + ByteArrayInputStream bIn; + String dump = ""; try { bIn = new ByteArrayInputStream(new DERSequence(v).getEncoded()); - CertificateFactory fact = CertificateFactory.getInstance("X.509", BC); + CertificateFactory fact = CertificateFactory.getInstance("X.509", BC); cert = (X509Certificate)fact.generateCertificate(bIn); @@ -2642,7 +2667,7 @@ public class CertTest } catch (Exception e) { - fail(dump + System.getProperty("line.separator") + getName() + ": testNullDerNull failed - exception " + e.toString(), e); + fail(dump + Strings.lineSeparator() + getName() + ": testNullDerNull failed - exception " + e.toString(), e); } } @@ -2655,8 +2680,8 @@ public class CertTest keyStore.load(input, "test".toCharArray()); - X509Certificate certificate = (X509Certificate) keyStore.getCertificate("ca"); - PrivateKey privateKey = (PrivateKey) keyStore.getKey("ca", null); + X509Certificate certificate = (X509Certificate)keyStore.getCertificate("ca"); + PrivateKey privateKey = (PrivateKey)keyStore.getKey("ca", null); X500Name issuer = X500Name.getInstance(certificate.getIssuerX500Principal().getEncoded()); @@ -2699,7 +2724,7 @@ public class CertTest CertificateFactory fac = CertificateFactory.getInstance("X.509"); - X509CRL jceCRL = (X509CRL) fac.generateCRL(new ByteArrayInputStream(crl.getEncoded())); + X509CRL jceCRL = (X509CRL)fac.generateCRL(new ByteArrayInputStream(crl.getEncoded())); jceCRL.verify(certificate.getPublicKey()); @@ -2718,8 +2743,8 @@ public class CertTest keyStore.load(input, "test".toCharArray()); - X509Certificate certificate = (X509Certificate) keyStore.getCertificate("ca"); - PrivateKey privateKey = (PrivateKey) keyStore.getKey("ca", null); + X509Certificate certificate = (X509Certificate)keyStore.getCertificate("ca"); + PrivateKey privateKey = (PrivateKey)keyStore.getKey("ca", null); X500Name crlIssuer = X500Name.getInstance(certificate.getSubjectX500Principal().getEncoded()); X500Name caName = X500Name.getInstance(certificate.getIssuerX500Principal().getEncoded()); @@ -2770,7 +2795,7 @@ public class CertTest CertificateFactory fac = CertificateFactory.getInstance("X.509"); - X509CRL jceCRL = (X509CRL) fac.generateCRL(new ByteArrayInputStream(crl.getEncoded())); + X509CRL jceCRL = (X509CRL)fac.generateCRL(new ByteArrayInputStream(crl.getEncoded())); jceCRL.verify(certificate.getPublicKey()); @@ -2789,8 +2814,8 @@ public class CertTest keyStore.load(input, "test".toCharArray()); - X509Certificate certificate = (X509Certificate) keyStore.getCertificate("ca"); - PrivateKey privateKey = (PrivateKey) keyStore.getKey("ca", null); + X509Certificate certificate = (X509Certificate)keyStore.getCertificate("ca"); + PrivateKey privateKey = (PrivateKey)keyStore.getKey("ca", null); X500Name crlIssuer = X500Name.getInstance(certificate.getSubjectX500Principal().getEncoded()); X500Name caName = X500Name.getInstance(certificate.getIssuerX500Principal().getEncoded()); @@ -2859,7 +2884,7 @@ public class CertTest } crlEntry = crl.getRevokedCertificate(BigInteger.valueOf(130)); - if (!crlEntry.getCertificateIssuer().equals(new X500Principal(caName.getEncoded()))) + if (!(new X500Principal(caName.getEncoded())).equals(crlEntry.getCertificateIssuer())) { fail("JCA 2 certificate issuer incorrect"); } @@ -2875,8 +2900,8 @@ public class CertTest keyStore.load(input, "test".toCharArray()); - X509Certificate certificate = (X509Certificate) keyStore.getCertificate("ca"); - PrivateKey privateKey = (PrivateKey) keyStore.getKey("ca", null); + X509Certificate certificate = (X509Certificate)keyStore.getCertificate("ca"); + PrivateKey privateKey = (PrivateKey)keyStore.getKey("ca", null); X500Name crlIssuer = X500Name.getInstance(certificate.getSubjectX500Principal().getEncoded()); X500Name caName = X500Name.getInstance(certificate.getIssuerX500Principal().getEncoded()); @@ -2938,6 +2963,9 @@ public class CertTest checkCertificate(6, oldEcdsa); checkCertificate(7, cert7); + checkComparison(cert1); + checkComparison(cert2); + checkKeyUsage(8, keyUsage); checkSelfSignedCertificate(9, uncompressedPtEC); checkNameCertificate(10, nameCert); @@ -2985,8 +3013,32 @@ public class CertTest checkCertificate(18, emptyDNCert); } + private Extensions generateExtensions(Vector oids, Vector values) + throws IOException + { + ExtensionsGenerator extGen = new ExtensionsGenerator(); + + for (int i = 0; i != oids.size(); i++) + { + Extension ext = (Extension)values.elementAt(i); + + extGen.addExtension((ASN1ObjectIdentifier)oids.elementAt(i), ext.isCritical(), ext.getParsedValue()); + } + + return extGen.generate(); + } + + private static ASN1Primitive fromExtensionValue( + byte[] encodedValue) + throws IOException + { + ASN1OctetString octs = (ASN1OctetString)ASN1Primitive.fromByteArray(encodedValue); + + return ASN1Primitive.fromByteArray(octs.getOctets()); + } + public static void main( - String[] args) + String[] args) { Security.addProvider(new BouncyCastleProvider()); diff --git a/bcpkix/src/main/java/org/bouncycastle/cert/test/X509ExtensionUtilsTest.java b/bcpkix/src/main/java/org/bouncycastle/cert/test/X509ExtensionUtilsTest.java index cd06082e..23338468 100644 --- a/bcpkix/src/main/java/org/bouncycastle/cert/test/X509ExtensionUtilsTest.java +++ b/bcpkix/src/main/java/org/bouncycastle/cert/test/X509ExtensionUtilsTest.java @@ -1,11 +1,27 @@ package org.bouncycastle.cert.test; +import java.io.ByteArrayInputStream; import java.io.IOException; +import java.math.BigInteger; +import java.security.KeyFactory; +import java.security.PublicKey; +import java.security.Security; +import java.security.cert.CertificateFactory; +import java.security.cert.X509Certificate; +import java.security.spec.X509EncodedKeySpec; import org.bouncycastle.asn1.ASN1Primitive; +import org.bouncycastle.asn1.DEROctetString; +import org.bouncycastle.asn1.x500.X500Name; +import org.bouncycastle.asn1.x509.AuthorityKeyIdentifier; +import org.bouncycastle.asn1.x509.GeneralName; +import org.bouncycastle.asn1.x509.GeneralNames; import org.bouncycastle.asn1.x509.SubjectKeyIdentifier; import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo; +import org.bouncycastle.cert.X509CertificateHolder; import org.bouncycastle.cert.X509ExtensionUtils; +import org.bouncycastle.cert.jcajce.JcaX509ExtensionUtils; +import org.bouncycastle.jce.provider.BouncyCastleProvider; import org.bouncycastle.util.Arrays; import org.bouncycastle.util.encoders.Base64; import org.bouncycastle.util.encoders.Hex; @@ -20,7 +36,9 @@ public class X509ExtensionUtilsTest private static byte[] shaID = Hex.decode("d8128a06d6c2feb0865994a2936e7b75b836a021"); private static byte[] shaTruncID = Hex.decode("436e7b75b836a021"); - private X509ExtensionUtils x509ExtensionUtils = new X509ExtensionUtils(new SHA1DigestCalculator()); + + private static byte[] v0Cert = Base64.decode("MIIBuTCCASICAQEwDQYJKoZIhvcNAQEFBQAwJTEWMBQGA1UECgwNQm91bmN5IENhc3RsZTELMAkGA1UEBhMCQVUwHhcNMTUwNzIxMjIwNzI3WhcNMTUxMDI5MjIwNzI3WjAlMRYwFAYDVQQKDA1Cb3VuY3kgQ2FzdGxlMQswCQYDVQQGEwJBVTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA9MhYrfDoC69iS/56gdvuwOvXKMsx9dSBZnK9KOnCFtc3fTeVp+61CeExuKXafqz0ZK/5ps0D+RMCOcIZXtXZsdC3CwgVx3k/CHKgrnp51v8sbgFzRrGr68Mp9Dr01wdgxjDCGgToUiBybU8IhsUc2nmwn3+Y+ZoIOvyQDuh3hXUCAwEAATANBgkqhkiG9w0BAQUFAAOBgQDvpEa3KFe7b+y7/MPNloabj6lfwW4vdKk4bg9+yMHFsb62OB8/RP4sJ+XIB91cGYINgA4d511juc9t6t7kEp6GijqWwAUtQfbyhZIO8DsCl96y3RfUag1L7Q3pn0SfyW0NAI8O9eKG/Hl6WmxRlvx3zmKz1bU+VSlnZoYt+6qZyg=="); + private static byte[] v3Cert = Base64.decode("MIICKzCCAZSgAwIBAgIBAjANBgkqhkiG9w0BAQUFADAlMRYwFAYDVQQKDA1Cb3VuY3kgQ2FzdGxlMQswCQYDVQQGEwJBVTAeFw0xNTA3MjEyMjA3MjdaFw0xNTEwMjkyMjA3MjdaMEMxDDAKBgNVBAMMA0JvYjEOMAwGA1UECwwFU2FsZXMxFjAUBgNVBAoMDUJvdW5jeSBDYXN0bGUxCzAJBgNVBAYTAkFVMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCHpUGlsn0Y+az7XGj3wq+om/kGNbdP+bKE6Du6x92Mq2SC8Fez5RdOkhJJqxk5U8O+Hj9dqoxBkpeqA5NA52agXNz4WlSDBii17U9PPoj7LPXlfXMujf18k/IY71M79/XRjj/xbqNEJQQAH+EHyFMVxFDaOHJ4huL3gq/C7v9tTQIDAQABo00wSzAdBgNVHQ4EFgQUxHM/5+X91RvdmNdbNFZ02Fug92wwHwYDVR0jBBgwFoAU8NRqCpfiTCDshX7mgx4L6KeXxJ0wCQYDVR0TBAIwADANBgkqhkiG9w0BAQUFAAOBgQCvqwjs+9IiWGlLmFc9b+ON7upBb8JCwVh5+Ks7F4waZ5gmLuUXZLEeMDvosSB6bPFgDWSIZsdxn/V4/hUMEJkvfRZJ5J/k1a7Yogi3XyFcE4k1p1W5ZQ+wm+CQwAWmOFdpJUCMsC1h2xJUu9agEPWowdc9P2+LL04ghFq9SnXsYg=="); public String getName() { @@ -28,28 +46,137 @@ public class X509ExtensionUtilsTest } public void performTest() + throws Exception + { + basicTest(); + jcaTest(); + } + + public void basicTest() throws IOException { + X509ExtensionUtils x509ExtensionUtils = new X509ExtensionUtils(new SHA1DigestCalculator()); + SubjectPublicKeyInfo pubInfo = SubjectPublicKeyInfo.getInstance(ASN1Primitive.fromByteArray(pubKeyInfo)); SubjectKeyIdentifier ski = x509ExtensionUtils.createSubjectKeyIdentifier(pubInfo); if (!Arrays.areEqual(shaID, ski.getKeyIdentifier())) { - fail("SHA-1 ID does not match"); + fail("basic SHA-1 ID does not match"); } ski = x509ExtensionUtils.createTruncatedSubjectKeyIdentifier(pubInfo); if (!Arrays.areEqual(shaTruncID, ski.getKeyIdentifier())) { - fail("truncated SHA-1 ID does not match"); + fail("basic truncated SHA-1 ID does not match"); + } + + AuthorityKeyIdentifier authKeyId = x509ExtensionUtils.createAuthorityKeyIdentifier(new X509CertificateHolder(v0Cert)); + if (!authKeyId.getAuthorityCertIssuer().equals(new GeneralNames(new GeneralName(new X500Name("O=Bouncy Castle, C=AU"))))) + { + fail("v0 issuer not matched"); + } + if (!Arrays.areEqual(Hex.decode("f0d46a0a97e24c20ec857ee6831e0be8a797c49d"), authKeyId.getKeyIdentifier())) + { + fail("v0 keyID not matched"); + } + if (!authKeyId.getAuthorityCertSerialNumber().equals(BigInteger.valueOf(1))) + { + fail("v0 serial not matched"); + } + + authKeyId = x509ExtensionUtils.createAuthorityKeyIdentifier(new X509CertificateHolder(v3Cert)); + if (!authKeyId.getAuthorityCertIssuer().equals(new GeneralNames(new GeneralName(new X500Name("O=Bouncy Castle, C=AU"))))) + { + fail("v3 issuer not matched"); + } + if (!Arrays.areEqual(Hex.decode("c4733fe7e5fdd51bdd98d75b345674d85ba0f76c"), authKeyId.getKeyIdentifier())) + { + fail("v3 keyID not matched"); + } + if (!authKeyId.getAuthorityCertSerialNumber().equals(BigInteger.valueOf(2))) + { + fail("v3 serial not matched"); + } + } + + public void jcaTest() + throws Exception + { + JcaX509ExtensionUtils x509ExtensionUtils = new JcaX509ExtensionUtils(); + + PublicKey key = KeyFactory.getInstance("RSA", "BC").generatePublic(new X509EncodedKeySpec(pubKeyInfo)); + + SubjectKeyIdentifier ski = x509ExtensionUtils.createSubjectKeyIdentifier(key); + + if (!Arrays.areEqual(shaID, ski.getKeyIdentifier())) + { + fail("jca SHA-1 ID does not match"); + } + + ski = x509ExtensionUtils.createTruncatedSubjectKeyIdentifier(key); + + if (!Arrays.areEqual(shaTruncID, ski.getKeyIdentifier())) + { + fail("jca truncated SHA-1 ID does not match"); + } + + CertificateFactory cFact = CertificateFactory.getInstance("X.509", "BC"); + + X509Certificate v0certificate = (X509Certificate)cFact.generateCertificate(new ByteArrayInputStream(v0Cert)); + X509Certificate v3certificate = (X509Certificate)cFact.generateCertificate(new ByteArrayInputStream(v3Cert)); + + AuthorityKeyIdentifier authKeyId = x509ExtensionUtils.createAuthorityKeyIdentifier(v0certificate); + if (!authKeyId.getAuthorityCertIssuer().equals(new GeneralNames(new GeneralName(new X500Name("O=Bouncy Castle, C=AU"))))) + { + fail("v0 issuer not matched"); + } + if (!Arrays.areEqual(Hex.decode("f0d46a0a97e24c20ec857ee6831e0be8a797c49d"), authKeyId.getKeyIdentifier())) + { + fail("v0 keyID not matched"); + } + if (!authKeyId.getAuthorityCertSerialNumber().equals(BigInteger.valueOf(1))) + { + fail("v0 serial not matched"); + } + + authKeyId = x509ExtensionUtils.createAuthorityKeyIdentifier(v3certificate); + if (!authKeyId.getAuthorityCertIssuer().equals(new GeneralNames(new GeneralName(new X500Name("O=Bouncy Castle, C=AU"))))) + { + fail("v3 issuer not matched"); + } + if (!Arrays.areEqual(Hex.decode("c4733fe7e5fdd51bdd98d75b345674d85ba0f76c"), authKeyId.getKeyIdentifier())) + { + fail("v3 keyID not matched"); + } + if (!authKeyId.getAuthorityCertSerialNumber().equals(BigInteger.valueOf(2))) + { + fail("v3 serial not matched"); + } + + // simulate the JCA X509Certificate.getExtension() method. + authKeyId = AuthorityKeyIdentifier.getInstance(JcaX509ExtensionUtils.parseExtensionValue(new DEROctetString(authKeyId).getEncoded())); + if (!authKeyId.getAuthorityCertIssuer().equals(new GeneralNames(new GeneralName(new X500Name("O=Bouncy Castle, C=AU"))))) + { + fail("v3 issuer not matched"); + } + if (!Arrays.areEqual(Hex.decode("c4733fe7e5fdd51bdd98d75b345674d85ba0f76c"), authKeyId.getKeyIdentifier())) + { + fail("v3 keyID not matched"); + } + if (!authKeyId.getAuthorityCertSerialNumber().equals(BigInteger.valueOf(2))) + { + fail("v3 serial not matched"); } } public static void main( String[] args) { + Security.addProvider(new BouncyCastleProvider()); + runTest(new X509ExtensionUtilsTest()); } } diff --git a/bcpkix/src/main/java/org/bouncycastle/cms/CMSAlgorithm.java b/bcpkix/src/main/java/org/bouncycastle/cms/CMSAlgorithm.java index a17fa2c4..17731c10 100644 --- a/bcpkix/src/main/java/org/bouncycastle/cms/CMSAlgorithm.java +++ b/bcpkix/src/main/java/org/bouncycastle/cms/CMSAlgorithm.java @@ -7,53 +7,71 @@ import org.bouncycastle.asn1.nist.NISTObjectIdentifiers; import org.bouncycastle.asn1.ntt.NTTObjectIdentifiers; import org.bouncycastle.asn1.oiw.OIWObjectIdentifiers; import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers; +import org.bouncycastle.asn1.sec.SECObjectIdentifiers; import org.bouncycastle.asn1.teletrust.TeleTrusTObjectIdentifiers; import org.bouncycastle.asn1.x9.X9ObjectIdentifiers; public class CMSAlgorithm { - public static final ASN1ObjectIdentifier DES_CBC = OIWObjectIdentifiers.desCBC; - public static final ASN1ObjectIdentifier DES_EDE3_CBC = PKCSObjectIdentifiers.des_EDE3_CBC; - public static final ASN1ObjectIdentifier RC2_CBC = PKCSObjectIdentifiers.RC2_CBC; - public static final ASN1ObjectIdentifier IDEA_CBC = new ASN1ObjectIdentifier("1.3.6.1.4.1.188.7.1.1.2"); - public static final ASN1ObjectIdentifier CAST5_CBC = new ASN1ObjectIdentifier("1.2.840.113533.7.66.10"); - - public static final ASN1ObjectIdentifier AES128_CBC = NISTObjectIdentifiers.id_aes128_CBC; - public static final ASN1ObjectIdentifier AES192_CBC = NISTObjectIdentifiers.id_aes192_CBC; - public static final ASN1ObjectIdentifier AES256_CBC = NISTObjectIdentifiers.id_aes256_CBC; - public static final ASN1ObjectIdentifier AES128_CCM = NISTObjectIdentifiers.id_aes128_CCM; - public static final ASN1ObjectIdentifier AES192_CCM = NISTObjectIdentifiers.id_aes192_CCM; - public static final ASN1ObjectIdentifier AES256_CCM = NISTObjectIdentifiers.id_aes256_CCM; - public static final ASN1ObjectIdentifier AES128_GCM = NISTObjectIdentifiers.id_aes128_GCM; - public static final ASN1ObjectIdentifier AES192_GCM = NISTObjectIdentifiers.id_aes192_GCM; - public static final ASN1ObjectIdentifier AES256_GCM = NISTObjectIdentifiers.id_aes256_GCM; - - public static final ASN1ObjectIdentifier CAMELLIA128_CBC = NTTObjectIdentifiers.id_camellia128_cbc; - public static final ASN1ObjectIdentifier CAMELLIA192_CBC = NTTObjectIdentifiers.id_camellia192_cbc; - public static final ASN1ObjectIdentifier CAMELLIA256_CBC = NTTObjectIdentifiers.id_camellia256_cbc; - public static final ASN1ObjectIdentifier SEED_CBC = KISAObjectIdentifiers.id_seedCBC; - - public static final ASN1ObjectIdentifier DES_EDE3_WRAP = PKCSObjectIdentifiers.id_alg_CMS3DESwrap; - public static final ASN1ObjectIdentifier AES128_WRAP = NISTObjectIdentifiers.id_aes128_wrap; - public static final ASN1ObjectIdentifier AES192_WRAP = NISTObjectIdentifiers.id_aes192_wrap; - public static final ASN1ObjectIdentifier AES256_WRAP = NISTObjectIdentifiers.id_aes256_wrap; - public static final ASN1ObjectIdentifier CAMELLIA128_WRAP = NTTObjectIdentifiers.id_camellia128_wrap; - public static final ASN1ObjectIdentifier CAMELLIA192_WRAP = NTTObjectIdentifiers.id_camellia192_wrap; - public static final ASN1ObjectIdentifier CAMELLIA256_WRAP = NTTObjectIdentifiers.id_camellia256_wrap; - public static final ASN1ObjectIdentifier SEED_WRAP = KISAObjectIdentifiers.id_npki_app_cmsSeed_wrap; - - public static final ASN1ObjectIdentifier ECDH_SHA1KDF = X9ObjectIdentifiers.dhSinglePass_stdDH_sha1kdf_scheme; - public static final ASN1ObjectIdentifier ECMQV_SHA1KDF = X9ObjectIdentifiers.mqvSinglePass_sha1kdf_scheme; - - public static final ASN1ObjectIdentifier SHA1 = OIWObjectIdentifiers.idSHA1; - public static final ASN1ObjectIdentifier SHA224 = NISTObjectIdentifiers.id_sha224; - public static final ASN1ObjectIdentifier SHA256 = NISTObjectIdentifiers.id_sha256; - public static final ASN1ObjectIdentifier SHA384 = NISTObjectIdentifiers.id_sha384; - public static final ASN1ObjectIdentifier SHA512 = NISTObjectIdentifiers.id_sha512; - public static final ASN1ObjectIdentifier MD5 = PKCSObjectIdentifiers.md5; - public static final ASN1ObjectIdentifier GOST3411 = CryptoProObjectIdentifiers.gostR3411; - public static final ASN1ObjectIdentifier RIPEMD128 = TeleTrusTObjectIdentifiers.ripemd128; - public static final ASN1ObjectIdentifier RIPEMD160 = TeleTrusTObjectIdentifiers.ripemd160; - public static final ASN1ObjectIdentifier RIPEMD256 = TeleTrusTObjectIdentifiers.ripemd256; + public static final ASN1ObjectIdentifier DES_CBC = OIWObjectIdentifiers.desCBC.intern(); + public static final ASN1ObjectIdentifier DES_EDE3_CBC = PKCSObjectIdentifiers.des_EDE3_CBC.intern(); + public static final ASN1ObjectIdentifier RC2_CBC = PKCSObjectIdentifiers.RC2_CBC.intern(); + public static final ASN1ObjectIdentifier IDEA_CBC = new ASN1ObjectIdentifier("1.3.6.1.4.1.188.7.1.1.2").intern(); + public static final ASN1ObjectIdentifier CAST5_CBC = new ASN1ObjectIdentifier("1.2.840.113533.7.66.10").intern(); + + public static final ASN1ObjectIdentifier AES128_CBC = NISTObjectIdentifiers.id_aes128_CBC.intern(); + public static final ASN1ObjectIdentifier AES192_CBC = NISTObjectIdentifiers.id_aes192_CBC.intern(); + public static final ASN1ObjectIdentifier AES256_CBC = NISTObjectIdentifiers.id_aes256_CBC.intern(); + public static final ASN1ObjectIdentifier AES128_CCM = NISTObjectIdentifiers.id_aes128_CCM.intern(); + public static final ASN1ObjectIdentifier AES192_CCM = NISTObjectIdentifiers.id_aes192_CCM.intern(); + public static final ASN1ObjectIdentifier AES256_CCM = NISTObjectIdentifiers.id_aes256_CCM.intern(); + public static final ASN1ObjectIdentifier AES128_GCM = NISTObjectIdentifiers.id_aes128_GCM.intern(); + public static final ASN1ObjectIdentifier AES192_GCM = NISTObjectIdentifiers.id_aes192_GCM.intern(); + public static final ASN1ObjectIdentifier AES256_GCM = NISTObjectIdentifiers.id_aes256_GCM.intern(); + + public static final ASN1ObjectIdentifier CAMELLIA128_CBC = NTTObjectIdentifiers.id_camellia128_cbc.intern(); + public static final ASN1ObjectIdentifier CAMELLIA192_CBC = NTTObjectIdentifiers.id_camellia192_cbc.intern(); + public static final ASN1ObjectIdentifier CAMELLIA256_CBC = NTTObjectIdentifiers.id_camellia256_cbc.intern(); + public static final ASN1ObjectIdentifier SEED_CBC = KISAObjectIdentifiers.id_seedCBC.intern(); + + public static final ASN1ObjectIdentifier DES_EDE3_WRAP = PKCSObjectIdentifiers.id_alg_CMS3DESwrap.intern(); + public static final ASN1ObjectIdentifier AES128_WRAP = NISTObjectIdentifiers.id_aes128_wrap.intern(); + public static final ASN1ObjectIdentifier AES192_WRAP = NISTObjectIdentifiers.id_aes192_wrap.intern(); + public static final ASN1ObjectIdentifier AES256_WRAP = NISTObjectIdentifiers.id_aes256_wrap.intern(); + public static final ASN1ObjectIdentifier CAMELLIA128_WRAP = NTTObjectIdentifiers.id_camellia128_wrap.intern(); + public static final ASN1ObjectIdentifier CAMELLIA192_WRAP = NTTObjectIdentifiers.id_camellia192_wrap.intern(); + public static final ASN1ObjectIdentifier CAMELLIA256_WRAP = NTTObjectIdentifiers.id_camellia256_wrap.intern(); + public static final ASN1ObjectIdentifier SEED_WRAP = KISAObjectIdentifiers.id_npki_app_cmsSeed_wrap.intern(); + + public static final ASN1ObjectIdentifier ECDH_SHA1KDF = X9ObjectIdentifiers.dhSinglePass_stdDH_sha1kdf_scheme.intern(); + public static final ASN1ObjectIdentifier ECCDH_SHA1KDF = X9ObjectIdentifiers.dhSinglePass_cofactorDH_sha1kdf_scheme.intern(); + public static final ASN1ObjectIdentifier ECMQV_SHA1KDF = X9ObjectIdentifiers.mqvSinglePass_sha1kdf_scheme.intern(); + + public static final ASN1ObjectIdentifier ECDH_SHA224KDF = SECObjectIdentifiers.dhSinglePass_stdDH_sha224kdf_scheme.intern(); + public static final ASN1ObjectIdentifier ECCDH_SHA224KDF = SECObjectIdentifiers.dhSinglePass_cofactorDH_sha224kdf_scheme.intern(); + public static final ASN1ObjectIdentifier ECMQV_SHA224KDF = SECObjectIdentifiers.mqvSinglePass_sha224kdf_scheme.intern(); + + public static final ASN1ObjectIdentifier ECDH_SHA256KDF = SECObjectIdentifiers.dhSinglePass_stdDH_sha256kdf_scheme.intern(); + public static final ASN1ObjectIdentifier ECCDH_SHA256KDF = SECObjectIdentifiers.dhSinglePass_cofactorDH_sha256kdf_scheme.intern(); + public static final ASN1ObjectIdentifier ECMQV_SHA256KDF = SECObjectIdentifiers.mqvSinglePass_sha256kdf_scheme.intern(); + + public static final ASN1ObjectIdentifier ECDH_SHA384KDF = SECObjectIdentifiers.dhSinglePass_stdDH_sha384kdf_scheme.intern(); + public static final ASN1ObjectIdentifier ECCDH_SHA384KDF = SECObjectIdentifiers.dhSinglePass_cofactorDH_sha384kdf_scheme.intern(); + public static final ASN1ObjectIdentifier ECMQV_SHA384KDF = SECObjectIdentifiers.mqvSinglePass_sha384kdf_scheme.intern(); + + public static final ASN1ObjectIdentifier ECDH_SHA512KDF = SECObjectIdentifiers.dhSinglePass_stdDH_sha512kdf_scheme.intern(); + public static final ASN1ObjectIdentifier ECCDH_SHA512KDF = SECObjectIdentifiers.dhSinglePass_cofactorDH_sha512kdf_scheme.intern(); + public static final ASN1ObjectIdentifier ECMQV_SHA512KDF = SECObjectIdentifiers.mqvSinglePass_sha512kdf_scheme.intern(); + + public static final ASN1ObjectIdentifier SHA1 = OIWObjectIdentifiers.idSHA1.intern(); + public static final ASN1ObjectIdentifier SHA224 = NISTObjectIdentifiers.id_sha224.intern(); + public static final ASN1ObjectIdentifier SHA256 = NISTObjectIdentifiers.id_sha256.intern(); + public static final ASN1ObjectIdentifier SHA384 = NISTObjectIdentifiers.id_sha384.intern(); + public static final ASN1ObjectIdentifier SHA512 = NISTObjectIdentifiers.id_sha512.intern(); + public static final ASN1ObjectIdentifier MD5 = PKCSObjectIdentifiers.md5.intern(); + public static final ASN1ObjectIdentifier GOST3411 = CryptoProObjectIdentifiers.gostR3411.intern(); + public static final ASN1ObjectIdentifier RIPEMD128 = TeleTrusTObjectIdentifiers.ripemd128.intern(); + public static final ASN1ObjectIdentifier RIPEMD160 = TeleTrusTObjectIdentifiers.ripemd160.intern(); + public static final ASN1ObjectIdentifier RIPEMD256 = TeleTrusTObjectIdentifiers.ripemd256.intern(); } diff --git a/bcpkix/src/main/java/org/bouncycastle/cms/CMSAttributeTableGenerator.java b/bcpkix/src/main/java/org/bouncycastle/cms/CMSAttributeTableGenerator.java index 528c738b..a38752c1 100644 --- a/bcpkix/src/main/java/org/bouncycastle/cms/CMSAttributeTableGenerator.java +++ b/bcpkix/src/main/java/org/bouncycastle/cms/CMSAttributeTableGenerator.java @@ -1,18 +1,20 @@ package org.bouncycastle.cms; -import org.bouncycastle.asn1.cms.AttributeTable; - import java.util.Map; +import org.bouncycastle.asn1.cms.AttributeTable; + /** * Note: The SIGNATURE parameter is only available when generating unsigned attributes. */ public interface CMSAttributeTableGenerator { - static final String CONTENT_TYPE = "contentType"; - static final String DIGEST = "digest"; - static final String SIGNATURE = "encryptedDigest"; - static final String DIGEST_ALGORITHM_IDENTIFIER = "digestAlgID"; + String CONTENT_TYPE = "contentType"; + String DIGEST = "digest"; + String SIGNATURE = "encryptedDigest"; + String DIGEST_ALGORITHM_IDENTIFIER = "digestAlgID"; + String MAC_ALGORITHM_IDENTIFIER = "macAlgID"; + String SIGNATURE_ALGORITHM_IDENTIFIER = "signatureAlgID"; AttributeTable getAttributes(Map parameters) throws CMSAttributeTableGenerationException; diff --git a/bcpkix/src/main/java/org/bouncycastle/cms/CMSAuthenticatedData.java b/bcpkix/src/main/java/org/bouncycastle/cms/CMSAuthenticatedData.java index f8c08740..24760501 100644 --- a/bcpkix/src/main/java/org/bouncycastle/cms/CMSAuthenticatedData.java +++ b/bcpkix/src/main/java/org/bouncycastle/cms/CMSAuthenticatedData.java @@ -4,10 +4,13 @@ import java.io.IOException; import java.io.InputStream; import org.bouncycastle.asn1.ASN1Encodable; +import org.bouncycastle.asn1.ASN1EncodableVector; import org.bouncycastle.asn1.ASN1OctetString; import org.bouncycastle.asn1.ASN1Set; +import org.bouncycastle.asn1.cms.Attribute; import org.bouncycastle.asn1.cms.AttributeTable; import org.bouncycastle.asn1.cms.AuthenticatedData; +import org.bouncycastle.asn1.cms.CMSAlgorithmProtection; import org.bouncycastle.asn1.cms.CMSAttributes; import org.bouncycastle.asn1.cms.ContentInfo; import org.bouncycastle.asn1.x509.AlgorithmIdentifier; @@ -89,7 +92,6 @@ public class CMSAuthenticatedData this.macAlg = authData.getMacAlgorithm(); - this.authAttrs = authData.getAuthAttrs(); this.mac = authData.getMac().getOctets(); this.unauthAttrs = authData.getUnauthAttrs(); @@ -111,6 +113,34 @@ public class CMSAuthenticatedData throw new CMSException("a digest calculator provider is required if authenticated attributes are present"); } + AttributeTable table = new AttributeTable(authAttrs); + + ASN1EncodableVector protectionAttributes = table.getAll(CMSAttributes.cmsAlgorithmProtect); + if (protectionAttributes.size() > 1) + { + throw new CMSException("Only one instance of a cmsAlgorithmProtect attribute can be present"); + } + + if (protectionAttributes.size() > 0) + { + Attribute attr = Attribute.getInstance(protectionAttributes.get(0)); + if (attr.getAttrValues().size() != 1) + { + throw new CMSException("A cmsAlgorithmProtect attribute MUST contain exactly one value"); + } + + CMSAlgorithmProtection algorithmProtection = CMSAlgorithmProtection.getInstance(attr.getAttributeValues()[0]); + + if (!CMSUtils.isEquivalent(algorithmProtection.getDigestAlgorithm(), authData.getDigestAlgorithm())) + { + throw new CMSException("CMS Algorithm Identifier Protection check failed for digestAlgorithm"); + } + + if (!CMSUtils.isEquivalent(algorithmProtection.getMacAlgorithm(), macAlg)) + { + throw new CMSException("CMS Algorithm Identifier Protection check failed for macAlgorithm"); + } + } try { CMSSecureReadable secureReadable = new CMSEnvelopedHelper.CMSDigestAuthenticatedSecureReadable(digestCalculatorProvider.get(authData.getDigestAlgorithm()), readable); @@ -207,6 +237,7 @@ public class CMSAuthenticatedData /** * return the ContentInfo + * @deprecated use toASN1Structure() */ public ContentInfo getContentInfo() { @@ -214,6 +245,14 @@ public class CMSAuthenticatedData } /** + * return the ContentInfo + */ + public ContentInfo toASN1Structure() + { + return contentInfo; + } + + /** * return a table of the digested attributes indexed by * the OID of the attribute. */ diff --git a/bcpkix/src/main/java/org/bouncycastle/cms/CMSAuthenticatedDataGenerator.java b/bcpkix/src/main/java/org/bouncycastle/cms/CMSAuthenticatedDataGenerator.java index 82f8294c..44dd8d3b 100644 --- a/bcpkix/src/main/java/org/bouncycastle/cms/CMSAuthenticatedDataGenerator.java +++ b/bcpkix/src/main/java/org/bouncycastle/cms/CMSAuthenticatedDataGenerator.java @@ -107,7 +107,7 @@ public class CMSAuthenticatedDataGenerator throw new CMSException("unable to perform digest calculation: " + e.getMessage(), e); } - Map parameters = getBaseParameters(typedData.getContentType(), digestCalculator.getAlgorithmIdentifier(), digestCalculator.getDigest()); + Map parameters = getBaseParameters(typedData.getContentType(), digestCalculator.getAlgorithmIdentifier(), macCalculator.getAlgorithmIdentifier(), digestCalculator.getDigest()); if (authGen == null) { diff --git a/bcpkix/src/main/java/org/bouncycastle/cms/CMSAuthenticatedDataStreamGenerator.java b/bcpkix/src/main/java/org/bouncycastle/cms/CMSAuthenticatedDataStreamGenerator.java index f32666d1..c35097c7 100644 --- a/bcpkix/src/main/java/org/bouncycastle/cms/CMSAuthenticatedDataStreamGenerator.java +++ b/bcpkix/src/main/java/org/bouncycastle/cms/CMSAuthenticatedDataStreamGenerator.java @@ -274,7 +274,7 @@ public class CMSAuthenticatedDataStreamGenerator if (digestCalculator != null) { - parameters = Collections.unmodifiableMap(getBaseParameters(contentType, digestCalculator.getAlgorithmIdentifier(), digestCalculator.getDigest())); + parameters = Collections.unmodifiableMap(getBaseParameters(contentType, digestCalculator.getAlgorithmIdentifier(), macCalculator.getAlgorithmIdentifier(), digestCalculator.getDigest())); if (authGen == null) { diff --git a/bcpkix/src/main/java/org/bouncycastle/cms/CMSAuthenticatedGenerator.java b/bcpkix/src/main/java/org/bouncycastle/cms/CMSAuthenticatedGenerator.java index 6aadf1ec..e50e03aa 100644 --- a/bcpkix/src/main/java/org/bouncycastle/cms/CMSAuthenticatedGenerator.java +++ b/bcpkix/src/main/java/org/bouncycastle/cms/CMSAuthenticatedGenerator.java @@ -30,12 +30,13 @@ public class CMSAuthenticatedGenerator this.unauthGen = unauthGen; } - protected Map getBaseParameters(ASN1ObjectIdentifier contentType, AlgorithmIdentifier digAlgId, byte[] hash) + protected Map getBaseParameters(ASN1ObjectIdentifier contentType, AlgorithmIdentifier digAlgId, AlgorithmIdentifier macAlgId, byte[] hash) { Map param = new HashMap(); param.put(CMSAttributeTableGenerator.CONTENT_TYPE, contentType); param.put(CMSAttributeTableGenerator.DIGEST_ALGORITHM_IDENTIFIER, digAlgId); param.put(CMSAttributeTableGenerator.DIGEST, Arrays.clone(hash)); + param.put(CMSAttributeTableGenerator.MAC_ALGORITHM_IDENTIFIER, macAlgId); return param; } } diff --git a/bcpkix/src/main/java/org/bouncycastle/cms/CMSSignedData.java b/bcpkix/src/main/java/org/bouncycastle/cms/CMSSignedData.java index d9223c3e..84b5edca 100644 --- a/bcpkix/src/main/java/org/bouncycastle/cms/CMSSignedData.java +++ b/bcpkix/src/main/java/org/bouncycastle/cms/CMSSignedData.java @@ -5,10 +5,15 @@ import java.io.InputStream; import java.io.OutputStream; import java.util.ArrayList; import java.util.Collection; +import java.util.Collections; +import java.util.Enumeration; +import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Map; +import java.util.Set; +import org.bouncycastle.asn1.ASN1Encodable; import org.bouncycastle.asn1.ASN1EncodableVector; import org.bouncycastle.asn1.ASN1InputStream; import org.bouncycastle.asn1.ASN1ObjectIdentifier; @@ -20,9 +25,8 @@ import org.bouncycastle.asn1.DERSet; import org.bouncycastle.asn1.cms.ContentInfo; import org.bouncycastle.asn1.cms.SignedData; import org.bouncycastle.asn1.cms.SignerInfo; -import org.bouncycastle.operator.DefaultSignatureAlgorithmIdentifierFinder; +import org.bouncycastle.asn1.x509.AlgorithmIdentifier; import org.bouncycastle.operator.OperatorCreationException; -import org.bouncycastle.operator.SignatureAlgorithmIdentifierFinder; import org.bouncycastle.util.Encodable; import org.bouncycastle.util.Store; @@ -184,11 +188,18 @@ public class CMSSignedData // this can happen if the signed message is sent simply to send a // certificate chain. // - if (signedData.getEncapContentInfo().getContent() != null) + ASN1Encodable content = signedData.getEncapContentInfo().getContent(); + if (content != null) { - this.signedContent = new CMSProcessableByteArray(signedData.getEncapContentInfo().getContentType(), - ((ASN1OctetString)(signedData.getEncapContentInfo() - .getContent())).getOctets()); + if (content instanceof ASN1OctetString) + { + this.signedContent = new CMSProcessableByteArray(signedData.getEncapContentInfo().getContentType(), + ((ASN1OctetString)content).getOctets()); + } + else + { + this.signedContent = new PKCS7ProcessableObject(signedData.getEncapContentInfo().getContentType(), content); + } } else { @@ -231,7 +242,6 @@ public class CMSSignedData { ASN1Set s = signedData.getSignerInfos(); List signerInfos = new ArrayList(); - SignatureAlgorithmIdentifierFinder sigAlgFinder = new DefaultSignatureAlgorithmIdentifierFinder(); for (int i = 0; i != s.size(); i++) { @@ -258,6 +268,26 @@ public class CMSSignedData } /** + * Return if this is object represents a detached signature. + * + * @return true if this message represents a detached signature, false otherwise. + */ + public boolean isDetachedSignature() + { + return signedData.getEncapContentInfo().getContent() == null && signedData.getSignerInfos().size() > 0; + } + + /** + * Return if this is object represents a certificate management message. + * + * @return true if the message has no signers or content, false otherwise. + */ + public boolean isCertificateManagementMessage() + { + return signedData.getEncapContentInfo().getContent() == null && signedData.getSignerInfos().size() == 0; + } + + /** * Return any X.509 certificate objects in this SignedData structure as a Store of X509CertificateHolder objects. * * @return a Store of X509CertificateHolder objects. @@ -301,6 +331,23 @@ public class CMSSignedData } /** + * Return the digest algorithm identifiers for the SignedData object + * + * @return the set of digest algorithm identifiers + */ + public Set<AlgorithmIdentifier> getDigestAlgorithmIDs() + { + Set<AlgorithmIdentifier> digests = new HashSet<AlgorithmIdentifier>(signedData.getDigestAlgorithms().size()); + + for (Enumeration en = signedData.getDigestAlgorithms().getObjects(); en.hasMoreElements();) + { + digests.add(AlgorithmIdentifier.getInstance(en.nextElement())); + } + + return Collections.unmodifiableSet(digests); + } + + /** * Return the a string representation of the OID associated with the * encapsulated content info structure carried in the signed data. * diff --git a/bcpkix/src/main/java/org/bouncycastle/cms/CMSSignedDataParser.java b/bcpkix/src/main/java/org/bouncycastle/cms/CMSSignedDataParser.java index 329f089b..2cf40d0d 100644 --- a/bcpkix/src/main/java/org/bouncycastle/cms/CMSSignedDataParser.java +++ b/bcpkix/src/main/java/org/bouncycastle/cms/CMSSignedDataParser.java @@ -5,10 +5,13 @@ import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.util.ArrayList; +import java.util.Collections; import java.util.HashMap; +import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Map; +import java.util.Set; import org.bouncycastle.asn1.ASN1Encodable; import org.bouncycastle.asn1.ASN1EncodableVector; @@ -89,6 +92,7 @@ public class CMSSignedDataParser private ASN1ObjectIdentifier _signedContentType; private CMSTypedStream _signedContent; private Map digests; + private Set<AlgorithmIdentifier> digestAlgorithms; private SignerInformationStore _signerInfoStore; private ASN1Set _certSet, _crlSet; @@ -145,10 +149,15 @@ public class CMSSignedDataParser ASN1SetParser digAlgs = _signedData.getDigestAlgorithms(); ASN1Encodable o; - + + Set<AlgorithmIdentifier> algSet = new HashSet<AlgorithmIdentifier>(); + while ((o = digAlgs.readObject()) != null) { AlgorithmIdentifier algId = AlgorithmIdentifier.getInstance(o); + + algSet.add(algId); + try { DigestCalculator calculator = digestCalculatorProvider.get(algId); @@ -164,28 +173,50 @@ public class CMSSignedDataParser } } + digestAlgorithms = Collections.unmodifiableSet(algSet); + // // If the message is simply a certificate chain message getContent() may return null. // ContentInfoParser cont = _signedData.getEncapContentInfo(); - ASN1OctetStringParser octs = (ASN1OctetStringParser) - cont.getContent(BERTags.OCTET_STRING); + ASN1Encodable contentParser = cont.getContent(BERTags.OCTET_STRING); - if (octs != null) + if (contentParser instanceof ASN1OctetStringParser) + { + ASN1OctetStringParser octs = (ASN1OctetStringParser)contentParser; + + if (octs != null) + { + CMSTypedStream ctStr = new CMSTypedStream( + cont.getContentType(), octs.getOctetStream()); + + if (_signedContent == null) + { + _signedContent = ctStr; + } + else + { + // + // content passed in, need to read past empty encapsulated content info object if present + // + ctStr.drain(); + } + } + } + else if (contentParser != null) { - CMSTypedStream ctStr = new CMSTypedStream( - cont.getContentType().getId(), octs.getOctetStream()); + PKCS7TypedStream pkcs7Stream = new PKCS7TypedStream(cont.getContentType(), contentParser); if (_signedContent == null) { - _signedContent = ctStr; + _signedContent = pkcs7Stream; } else { // // content passed in, need to read past empty encapsulated content info object if present // - ctStr.drain(); + pkcs7Stream.drain(); } } @@ -215,6 +246,16 @@ public class CMSSignedDataParser } /** + * Return the digest algorithm identifiers for the SignedData object + * + * @return the set of digest algorithm identifiers + */ + public Set<AlgorithmIdentifier> getDigestAlgorithmIDs() + { + return digestAlgorithms; + } + + /** * return the collection of signers that are associated with the * signatures for the message. * @throws CMSException diff --git a/bcpkix/src/main/java/org/bouncycastle/cms/CMSTypedStream.java b/bcpkix/src/main/java/org/bouncycastle/cms/CMSTypedStream.java index eda3bde3..78379a50 100644 --- a/bcpkix/src/main/java/org/bouncycastle/cms/CMSTypedStream.java +++ b/bcpkix/src/main/java/org/bouncycastle/cms/CMSTypedStream.java @@ -14,7 +14,8 @@ public class CMSTypedStream private static final int BUF_SIZ = 32 * 1024; private final ASN1ObjectIdentifier _oid; - private final InputStream _in; + + protected InputStream _in; public CMSTypedStream( InputStream in) @@ -53,6 +54,12 @@ public class CMSTypedStream _in = new FullReaderStream(new BufferedInputStream(in, bufSize)); } + protected CMSTypedStream( + ASN1ObjectIdentifier oid) + { + _oid = oid; + } + public ASN1ObjectIdentifier getContentType() { return _oid; diff --git a/bcpkix/src/main/java/org/bouncycastle/cms/CMSUtils.java b/bcpkix/src/main/java/org/bouncycastle/cms/CMSUtils.java index 41f2c001..d0e7d493 100644 --- a/bcpkix/src/main/java/org/bouncycastle/cms/CMSUtils.java +++ b/bcpkix/src/main/java/org/bouncycastle/cms/CMSUtils.java @@ -5,8 +5,10 @@ import java.io.InputStream; import java.io.OutputStream; import java.util.ArrayList; import java.util.Collection; +import java.util.HashSet; import java.util.Iterator; import java.util.List; +import java.util.Set; import org.bouncycastle.asn1.ASN1Encodable; import org.bouncycastle.asn1.ASN1EncodableVector; @@ -16,6 +18,7 @@ import org.bouncycastle.asn1.ASN1Set; import org.bouncycastle.asn1.ASN1TaggedObject; import org.bouncycastle.asn1.BEROctetStringGenerator; import org.bouncycastle.asn1.BERSet; +import org.bouncycastle.asn1.DERNull; import org.bouncycastle.asn1.DERSet; import org.bouncycastle.asn1.DERTaggedObject; import org.bouncycastle.asn1.cms.CMSObjectIdentifiers; @@ -23,6 +26,9 @@ import org.bouncycastle.asn1.cms.ContentInfo; import org.bouncycastle.asn1.cms.OtherRevocationInfoFormat; import org.bouncycastle.asn1.ocsp.OCSPResponse; import org.bouncycastle.asn1.ocsp.OCSPResponseStatus; +import org.bouncycastle.asn1.oiw.OIWObjectIdentifiers; +import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers; +import org.bouncycastle.asn1.x509.AlgorithmIdentifier; import org.bouncycastle.cert.X509AttributeCertificateHolder; import org.bouncycastle.cert.X509CRLHolder; import org.bouncycastle.cert.X509CertificateHolder; @@ -35,6 +41,47 @@ import org.bouncycastle.util.io.TeeOutputStream; class CMSUtils { + private static final Set<String> des = new HashSet<String>(); + + static + { + des.add("DES"); + des.add("DESEDE"); + des.add(OIWObjectIdentifiers.desCBC.getId()); + des.add(PKCSObjectIdentifiers.des_EDE3_CBC.getId()); + des.add(PKCSObjectIdentifiers.des_EDE3_CBC.getId()); + des.add(PKCSObjectIdentifiers.id_alg_CMS3DESwrap.getId()); + } + + static boolean isDES(String algorithmID) + { + String name = Strings.toUpperCase(algorithmID); + + return des.contains(name); + } + + static boolean isEquivalent(AlgorithmIdentifier algId1, AlgorithmIdentifier algId2) + { + if (algId1 == null || algId2 == null) + { + return false; + } + + if (!algId1.getAlgorithm().equals(algId2.getAlgorithm())) + { + return false; + } + + ASN1Encodable params1 = algId1.getParameters(); + ASN1Encodable params2 = algId2.getParameters(); + if (params1 != null) + { + return params1.equals(params2) || (params1.equals(DERNull.INSTANCE) && params2 == null); + } + + return params2 == null || params2.equals(DERNull.INSTANCE); + } + static ContentInfo readContentInfo( byte[] input) throws CMSException @@ -224,63 +271,6 @@ class CMSUtils } } - static byte[] getPasswordBytes(int scheme, char[] password) - { - if (scheme == PasswordRecipient.PKCS5_SCHEME2) - { - return PKCS5PasswordToBytes(password); - } - - return PKCS5PasswordToUTF8Bytes(password); - } - - /** - * converts a password to a byte array according to the scheme in - * PKCS5 (ascii, no padding) - * - * @param password a character array representing the password. - * @return a byte array representing the password. - */ - private static byte[] PKCS5PasswordToBytes( - char[] password) - { - if (password != null) - { - byte[] bytes = new byte[password.length]; - - for (int i = 0; i != bytes.length; i++) - { - bytes[i] = (byte)password[i]; - } - - return bytes; - } - else - { - return new byte[0]; - } - } - - /** - * converts a password to a byte array according to the scheme in - * PKCS5 (UTF-8, no padding) - * - * @param password a character array representing the password. - * @return a byte array representing the password. - */ - private static byte[] PKCS5PasswordToUTF8Bytes( - char[] password) - { - if (password != null) - { - return Strings.toUTF8ByteArray(password); - } - else - { - return new byte[0]; - } - } - public static byte[] streamToByteArray( InputStream in) throws IOException diff --git a/bcpkix/src/main/java/org/bouncycastle/cms/DefaultAuthenticatedAttributeTableGenerator.java b/bcpkix/src/main/java/org/bouncycastle/cms/DefaultAuthenticatedAttributeTableGenerator.java index fb37b4d8..6cfb7e3e 100644 --- a/bcpkix/src/main/java/org/bouncycastle/cms/DefaultAuthenticatedAttributeTableGenerator.java +++ b/bcpkix/src/main/java/org/bouncycastle/cms/DefaultAuthenticatedAttributeTableGenerator.java @@ -9,7 +9,9 @@ import org.bouncycastle.asn1.DEROctetString; import org.bouncycastle.asn1.DERSet; import org.bouncycastle.asn1.cms.Attribute; import org.bouncycastle.asn1.cms.AttributeTable; +import org.bouncycastle.asn1.cms.CMSAlgorithmProtection; import org.bouncycastle.asn1.cms.CMSAttributes; +import org.bouncycastle.asn1.x509.AlgorithmIdentifier; /** * Default authenticated attributes generator. @@ -85,6 +87,14 @@ public class DefaultAuthenticatedAttributeTableGenerator std.put(attr.getAttrType(), attr); } + if (!std.contains(CMSAttributes.cmsAlgorithmProtect)) + { + Attribute attr = new Attribute(CMSAttributes.cmsAlgorithmProtect, new DERSet(new CMSAlgorithmProtection( + (AlgorithmIdentifier)parameters.get(CMSAttributeTableGenerator.DIGEST_ALGORITHM_IDENTIFIER), + CMSAlgorithmProtection.MAC, (AlgorithmIdentifier)parameters.get(CMSAttributeTableGenerator.MAC_ALGORITHM_IDENTIFIER)))); + std.put(attr.getAttrType(), attr); + } + return std; } diff --git a/bcpkix/src/main/java/org/bouncycastle/cms/DefaultCMSSignatureAlgorithmNameGenerator.java b/bcpkix/src/main/java/org/bouncycastle/cms/DefaultCMSSignatureAlgorithmNameGenerator.java index 7d82bb4d..20e1cb54 100644 --- a/bcpkix/src/main/java/org/bouncycastle/cms/DefaultCMSSignatureAlgorithmNameGenerator.java +++ b/bcpkix/src/main/java/org/bouncycastle/cms/DefaultCMSSignatureAlgorithmNameGenerator.java @@ -161,6 +161,13 @@ public class DefaultCMSSignatureAlgorithmNameGenerator public String getSignatureName(AlgorithmIdentifier digestAlg, AlgorithmIdentifier encryptionAlg) { + String digestName = getDigestAlgName(encryptionAlg.getAlgorithm()); + + if (!digestName.equals(encryptionAlg.getAlgorithm().getId())) + { + return digestName + "with" + getEncryptionAlgName(encryptionAlg.getAlgorithm()); + } + return getDigestAlgName(digestAlg.getAlgorithm()) + "with" + getEncryptionAlgName(encryptionAlg.getAlgorithm()); } } diff --git a/bcpkix/src/main/java/org/bouncycastle/cms/DefaultSignedAttributeTableGenerator.java b/bcpkix/src/main/java/org/bouncycastle/cms/DefaultSignedAttributeTableGenerator.java index 837edd85..ddfd2ebd 100644 --- a/bcpkix/src/main/java/org/bouncycastle/cms/DefaultSignedAttributeTableGenerator.java +++ b/bcpkix/src/main/java/org/bouncycastle/cms/DefaultSignedAttributeTableGenerator.java @@ -10,8 +10,10 @@ import org.bouncycastle.asn1.DEROctetString; import org.bouncycastle.asn1.DERSet; import org.bouncycastle.asn1.cms.Attribute; import org.bouncycastle.asn1.cms.AttributeTable; +import org.bouncycastle.asn1.cms.CMSAlgorithmProtection; import org.bouncycastle.asn1.cms.CMSAttributes; import org.bouncycastle.asn1.cms.Time; +import org.bouncycastle.asn1.x509.AlgorithmIdentifier; /** * Default signed attributes generator. @@ -93,6 +95,14 @@ public class DefaultSignedAttributeTableGenerator std.put(attr.getAttrType(), attr); } + if (!std.contains(CMSAttributes.cmsAlgorithmProtect)) + { + Attribute attr = new Attribute(CMSAttributes.cmsAlgorithmProtect, new DERSet(new CMSAlgorithmProtection( + (AlgorithmIdentifier)parameters.get(CMSAttributeTableGenerator.DIGEST_ALGORITHM_IDENTIFIER), + CMSAlgorithmProtection.SIGNATURE, (AlgorithmIdentifier)parameters.get(CMSAttributeTableGenerator.SIGNATURE_ALGORITHM_IDENTIFIER)))); + std.put(attr.getAttrType(), attr); + } + return std; } diff --git a/bcpkix/src/main/java/org/bouncycastle/cms/KeyAgreeRecipientInfoGenerator.java b/bcpkix/src/main/java/org/bouncycastle/cms/KeyAgreeRecipientInfoGenerator.java index 85f5881d..23b96801 100644 --- a/bcpkix/src/main/java/org/bouncycastle/cms/KeyAgreeRecipientInfoGenerator.java +++ b/bcpkix/src/main/java/org/bouncycastle/cms/KeyAgreeRecipientInfoGenerator.java @@ -1,9 +1,5 @@ package org.bouncycastle.cms; -import java.io.IOException; - -import org.bouncycastle.asn1.ASN1Encodable; -import org.bouncycastle.asn1.ASN1EncodableVector; import org.bouncycastle.asn1.ASN1ObjectIdentifier; import org.bouncycastle.asn1.ASN1Sequence; import org.bouncycastle.asn1.DERNull; @@ -12,6 +8,7 @@ import org.bouncycastle.asn1.cms.KeyAgreeRecipientInfo; import org.bouncycastle.asn1.cms.OriginatorIdentifierOrKey; import org.bouncycastle.asn1.cms.OriginatorPublicKey; import org.bouncycastle.asn1.cms.RecipientInfo; +import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers; import org.bouncycastle.asn1.x509.AlgorithmIdentifier; import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo; import org.bouncycastle.operator.GenericKey; @@ -36,31 +33,30 @@ public abstract class KeyAgreeRecipientInfoGenerator OriginatorIdentifierOrKey originator = new OriginatorIdentifierOrKey( createOriginatorPublicKey(originatorKeyInfo)); - ASN1EncodableVector params = new ASN1EncodableVector(); - params.add(keyEncryptionOID); - params.add(DERNull.INSTANCE); - AlgorithmIdentifier keyEncAlg = new AlgorithmIdentifier(keyEncryptionOID, DERNull.INSTANCE); + AlgorithmIdentifier keyEncAlg; + if (CMSUtils.isDES(keyEncryptionOID.getId()) || keyEncryptionOID.equals(PKCSObjectIdentifiers.id_alg_CMSRC2wrap)) + { + keyEncAlg = new AlgorithmIdentifier(keyEncryptionOID, DERNull.INSTANCE); + } + else + { + keyEncAlg = new AlgorithmIdentifier(keyEncryptionOID); + } + AlgorithmIdentifier keyAgreeAlg = new AlgorithmIdentifier(keyAgreementOID, keyEncAlg); ASN1Sequence recipients = generateRecipientEncryptedKeys(keyAgreeAlg, keyEncAlg, contentEncryptionKey); - ASN1Encodable userKeyingMaterial = getUserKeyingMaterial(keyAgreeAlg); + byte[] userKeyingMaterial = getUserKeyingMaterial(keyAgreeAlg); if (userKeyingMaterial != null) { - try - { - return new RecipientInfo(new KeyAgreeRecipientInfo(originator, new DEROctetString(userKeyingMaterial), + return new RecipientInfo(new KeyAgreeRecipientInfo(originator, new DEROctetString(userKeyingMaterial), keyAgreeAlg, recipients)); - } - catch (IOException e) - { - throw new CMSException("unable to encode userKeyingMaterial: " + e.getMessage(), e); - } + } else { - return new RecipientInfo(new KeyAgreeRecipientInfo(originator, null, - keyAgreeAlg, recipients)); + return new RecipientInfo(new KeyAgreeRecipientInfo(originator, null, keyAgreeAlg, recipients)); } } @@ -74,7 +70,7 @@ public abstract class KeyAgreeRecipientInfoGenerator protected abstract ASN1Sequence generateRecipientEncryptedKeys(AlgorithmIdentifier keyAgreeAlgorithm, AlgorithmIdentifier keyEncAlgorithm, GenericKey contentEncryptionKey) throws CMSException; - protected abstract ASN1Encodable getUserKeyingMaterial(AlgorithmIdentifier keyAgreeAlgorithm) + protected abstract byte[] getUserKeyingMaterial(AlgorithmIdentifier keyAgreeAlgorithm) throws CMSException; }
\ No newline at end of file diff --git a/bcpkix/src/main/java/org/bouncycastle/cms/PasswordRecipient.java b/bcpkix/src/main/java/org/bouncycastle/cms/PasswordRecipient.java index c81c3028..7322fdcc 100644 --- a/bcpkix/src/main/java/org/bouncycastle/cms/PasswordRecipient.java +++ b/bcpkix/src/main/java/org/bouncycastle/cms/PasswordRecipient.java @@ -8,7 +8,7 @@ public interface PasswordRecipient public static final int PKCS5_SCHEME2 = 0; public static final int PKCS5_SCHEME2_UTF8 = 1; - byte[] calculateDerivedKey(byte[] encodedPassword, AlgorithmIdentifier derivationAlgorithm, int keySize) + byte[] calculateDerivedKey(int schemeID, AlgorithmIdentifier derivationAlgorithm, int keySize) throws CMSException; RecipientOperator getRecipientOperator(AlgorithmIdentifier keyEncryptionAlgorithm, AlgorithmIdentifier contentEncryptionAlgorithm, byte[] derivedKey, byte[] encryptedEncryptedContentKey) diff --git a/bcpkix/src/main/java/org/bouncycastle/cms/PasswordRecipientInfoGenerator.java b/bcpkix/src/main/java/org/bouncycastle/cms/PasswordRecipientInfoGenerator.java index b570c3cf..5c99e596 100644 --- a/bcpkix/src/main/java/org/bouncycastle/cms/PasswordRecipientInfoGenerator.java +++ b/bcpkix/src/main/java/org/bouncycastle/cms/PasswordRecipientInfoGenerator.java @@ -17,7 +17,8 @@ import org.bouncycastle.operator.GenericKey; public abstract class PasswordRecipientInfoGenerator implements RecipientInfoGenerator { - private char[] password; + protected char[] password; + private AlgorithmIdentifier keyDerivationAlgorithm; private ASN1ObjectIdentifier kekAlgorithm; private SecureRandom random; @@ -93,9 +94,7 @@ public abstract class PasswordRecipientInfoGenerator keyDerivationAlgorithm = new AlgorithmIdentifier(PKCSObjectIdentifiers.id_PBKDF2, new PBKDF2Params(salt, 1024)); } - byte[] encodedPassword = CMSUtils.getPasswordBytes(schemeID, password); - - byte[] derivedKey = calculateDerivedKey(encodedPassword, keyDerivationAlgorithm, keySize); + byte[] derivedKey = calculateDerivedKey(schemeID, keyDerivationAlgorithm, keySize); AlgorithmIdentifier kekAlgorithmId = new AlgorithmIdentifier(kekAlgorithm, new DEROctetString(iv)); @@ -114,7 +113,7 @@ public abstract class PasswordRecipientInfoGenerator keyEncryptionAlgorithm, encryptedKey)); } - protected abstract byte[] calculateDerivedKey(byte[] encodedPassword, AlgorithmIdentifier derivationAlgorithm, int keySize) + protected abstract byte[] calculateDerivedKey(int schemeID, AlgorithmIdentifier derivationAlgorithm, int keySize) throws CMSException; protected abstract byte[] generateEncryptedBytes(AlgorithmIdentifier algorithm, byte[] derivedKey, GenericKey contentEncryptionKey) diff --git a/bcpkix/src/main/java/org/bouncycastle/cms/PasswordRecipientInformation.java b/bcpkix/src/main/java/org/bouncycastle/cms/PasswordRecipientInformation.java index 2eef186a..a12d8a7c 100644 --- a/bcpkix/src/main/java/org/bouncycastle/cms/PasswordRecipientInformation.java +++ b/bcpkix/src/main/java/org/bouncycastle/cms/PasswordRecipientInformation.java @@ -105,11 +105,9 @@ public class PasswordRecipientInformation AlgorithmIdentifier kekAlg = AlgorithmIdentifier.getInstance(info.getKeyEncryptionAlgorithm()); AlgorithmIdentifier kekAlgParams = AlgorithmIdentifier.getInstance(kekAlg.getParameters()); - byte[] passwordBytes = CMSUtils.getPasswordBytes(pbeRecipient.getPasswordConversionScheme(), pbeRecipient.getPassword()); - int keySize = ((Integer)KEYSIZES.get(kekAlgParams.getAlgorithm())).intValue(); - byte[] derivedKey = pbeRecipient.calculateDerivedKey(passwordBytes, this.getKeyDerivationAlgorithm(), keySize); + byte[] derivedKey = pbeRecipient.calculateDerivedKey(pbeRecipient.getPasswordConversionScheme(), this.getKeyDerivationAlgorithm(), keySize); return pbeRecipient.getRecipientOperator(kekAlgParams, messageAlgorithm, derivedKey, info.getEncryptedKey().getOctets()); } diff --git a/bcpkix/src/main/java/org/bouncycastle/cms/SignerInfoGenerator.java b/bcpkix/src/main/java/org/bouncycastle/cms/SignerInfoGenerator.java index f264729c..e1b0ce1f 100644 --- a/bcpkix/src/main/java/org/bouncycastle/cms/SignerInfoGenerator.java +++ b/bcpkix/src/main/java/org/bouncycastle/cms/SignerInfoGenerator.java @@ -183,13 +183,15 @@ public class SignerInfoGenerator */ ASN1Set signedAttr = null; + AlgorithmIdentifier digestEncryptionAlgorithm = sigEncAlgFinder.findEncryptionAlgorithm(signer.getAlgorithmIdentifier()); + AlgorithmIdentifier digestAlg = null; if (sAttrGen != null) { digestAlg = digester.getAlgorithmIdentifier(); calculatedDigest = digester.getDigest(); - Map parameters = getBaseParameters(contentType, digester.getAlgorithmIdentifier(), calculatedDigest); + Map parameters = getBaseParameters(contentType, digester.getAlgorithmIdentifier(), digestEncryptionAlgorithm, calculatedDigest); AttributeTable signed = sAttrGen.getAttributes(Collections.unmodifiableMap(parameters)); signedAttr = getAttributeSet(signed); @@ -220,7 +222,7 @@ public class SignerInfoGenerator ASN1Set unsignedAttr = null; if (unsAttrGen != null) { - Map parameters = getBaseParameters(contentType, digestAlg, calculatedDigest); + Map parameters = getBaseParameters(contentType, digestAlg, digestEncryptionAlgorithm, calculatedDigest); parameters.put(CMSAttributeTableGenerator.SIGNATURE, Arrays.clone(sigBytes)); AttributeTable unsigned = unsAttrGen.getAttributes(Collections.unmodifiableMap(parameters)); @@ -228,8 +230,6 @@ public class SignerInfoGenerator unsignedAttr = getAttributeSet(unsigned); } - AlgorithmIdentifier digestEncryptionAlgorithm = sigEncAlgFinder.findEncryptionAlgorithm(signer.getAlgorithmIdentifier()); - return new SignerInfo(signerIdentifier, digestAlg, signedAttr, digestEncryptionAlgorithm, new DEROctetString(sigBytes), unsignedAttr); } @@ -255,7 +255,7 @@ public class SignerInfoGenerator return null; } - private Map getBaseParameters(ASN1ObjectIdentifier contentType, AlgorithmIdentifier digAlgId, byte[] hash) + private Map getBaseParameters(ASN1ObjectIdentifier contentType, AlgorithmIdentifier digAlgId, AlgorithmIdentifier sigAlgId, byte[] hash) { Map param = new HashMap(); @@ -265,7 +265,9 @@ public class SignerInfoGenerator } param.put(CMSAttributeTableGenerator.DIGEST_ALGORITHM_IDENTIFIER, digAlgId); + param.put(CMSAttributeTableGenerator.SIGNATURE_ALGORITHM_IDENTIFIER, sigAlgId); param.put(CMSAttributeTableGenerator.DIGEST, Arrays.clone(hash)); + return param; } diff --git a/bcpkix/src/main/java/org/bouncycastle/cms/SignerInformation.java b/bcpkix/src/main/java/org/bouncycastle/cms/SignerInformation.java index 081d1218..ac6dd0f9 100644 --- a/bcpkix/src/main/java/org/bouncycastle/cms/SignerInformation.java +++ b/bcpkix/src/main/java/org/bouncycastle/cms/SignerInformation.java @@ -18,6 +18,7 @@ import org.bouncycastle.asn1.DERNull; import org.bouncycastle.asn1.DERSet; import org.bouncycastle.asn1.cms.Attribute; import org.bouncycastle.asn1.cms.AttributeTable; +import org.bouncycastle.asn1.cms.CMSAlgorithmProtection; import org.bouncycastle.asn1.cms.CMSAttributes; import org.bouncycastle.asn1.cms.IssuerAndSerialNumber; import org.bouncycastle.asn1.cms.SignerIdentifier; @@ -38,21 +39,22 @@ import org.bouncycastle.util.io.TeeOutputStream; */ public class SignerInformation { - private SignerId sid; - private SignerInfo info; - private AlgorithmIdentifier digestAlgorithm; - private AlgorithmIdentifier encryptionAlgorithm; - private final ASN1Set signedAttributeSet; - private final ASN1Set unsignedAttributeSet; - private CMSProcessable content; - private byte[] signature; - private ASN1ObjectIdentifier contentType; - private byte[] resultDigest; + private final SignerId sid; + private final CMSProcessable content; + private final byte[] signature; + private final ASN1ObjectIdentifier contentType; + private final boolean isCounterSignature; // Derived - private AttributeTable signedAttributeValues; - private AttributeTable unsignedAttributeValues; - private boolean isCounterSignature; + private AttributeTable signedAttributeValues; + private AttributeTable unsignedAttributeValues; + private byte[] resultDigest; + + protected final SignerInfo info; + protected final AlgorithmIdentifier digestAlgorithm; + protected final AlgorithmIdentifier encryptionAlgorithm; + protected final ASN1Set signedAttributeSet; + protected final ASN1Set unsignedAttributeSet; SignerInformation( SignerInfo info, @@ -89,6 +91,28 @@ public class SignerInformation this.resultDigest = resultDigest; } + /** + * Protected constructor. In some cases clients have their own idea about how to encode + * the signed attributes and calculate the signature. This constructor is to allow developers + * to deal with that by extending off the class and overridng methods like getSignedAttributes(). + * + * @param baseInfo the SignerInformation to base this one on. + */ + protected SignerInformation(SignerInformation baseInfo) + { + this.info = baseInfo.info; + this.contentType = baseInfo.contentType; + this.isCounterSignature = baseInfo.isCounterSignature(); + this.sid = baseInfo.getSID(); + this.digestAlgorithm = info.getDigestAlgorithm(); + this.signedAttributeSet = info.getAuthenticatedAttributes(); + this.unsignedAttributeSet = info.getUnauthenticatedAttributes(); + this.encryptionAlgorithm = info.getDigestEncryptionAlgorithm(); + this.signature = info.getEncryptedDigest().getOctets(); + this.content = baseInfo.content; + this.resultDigest = baseInfo.resultDigest; + } + public boolean isCounterSignature() { return isCounterSignature; @@ -428,6 +452,46 @@ public class SignerInformation } } + AttributeTable signedAttrTable = this.getSignedAttributes(); + + // RFC 6211 Validate Algorithm Identifier protection attribute if present + { + AttributeTable unsignedAttrTable = this.getUnsignedAttributes(); + if (unsignedAttrTable != null && unsignedAttrTable.getAll(CMSAttributes.cmsAlgorithmProtect).size() > 0) + { + throw new CMSException("A cmsAlgorithmProtect attribute MUST be a signed attribute"); + } + if (signedAttrTable != null) + { + ASN1EncodableVector protectionAttributes = signedAttrTable.getAll(CMSAttributes.cmsAlgorithmProtect); + if (protectionAttributes.size() > 1) + { + throw new CMSException("Only one instance of a cmsAlgorithmProtect attribute can be present"); + } + + if (protectionAttributes.size() > 0) + { + Attribute attr = Attribute.getInstance(protectionAttributes.get(0)); + if (attr.getAttrValues().size() != 1) + { + throw new CMSException("A cmsAlgorithmProtect attribute MUST contain exactly one value"); + } + + CMSAlgorithmProtection algorithmProtection = CMSAlgorithmProtection.getInstance(attr.getAttributeValues()[0]); + + if (!CMSUtils.isEquivalent(algorithmProtection.getDigestAlgorithm(), info.getDigestAlgorithm())) + { + throw new CMSException("CMS Algorithm Identifier Protection check failed for digestAlgorithm"); + } + + if (!CMSUtils.isEquivalent(algorithmProtection.getSignatureAlgorithm(), info.getDigestEncryptionAlgorithm())) + { + throw new CMSException("CMS Algorithm Identifier Protection check failed for signatureAlgorithm"); + } + } + } + } + // RFC 3852 11.2 Check the message-digest attribute is correct { ASN1Primitive validMessageDigest = getSingleValuedSignedAttribute( @@ -457,7 +521,6 @@ public class SignerInformation // RFC 3852 11.4 Validate countersignature attribute(s) { - AttributeTable signedAttrTable = this.getSignedAttributes(); if (signedAttrTable != null && signedAttrTable.getAll(CMSAttributes.counterSignature).size() > 0) { @@ -470,7 +533,7 @@ public class SignerInformation ASN1EncodableVector csAttrs = unsignedAttrTable.getAll(CMSAttributes.counterSignature); for (int i = 0; i < csAttrs.size(); ++i) { - Attribute csAttr = (Attribute)csAttrs.get(i); + Attribute csAttr = Attribute.getInstance(csAttrs.get(i)); if (csAttr.getAttrValues().size() < 1) { throw new CMSException("A countersignature attribute MUST contain at least one AttributeValue"); diff --git a/bcpkix/src/main/java/org/bouncycastle/cms/bc/BcPasswordRecipient.java b/bcpkix/src/main/java/org/bouncycastle/cms/bc/BcPasswordRecipient.java index 50f9c6c0..56f2db64 100644 --- a/bcpkix/src/main/java/org/bouncycastle/cms/bc/BcPasswordRecipient.java +++ b/bcpkix/src/main/java/org/bouncycastle/cms/bc/BcPasswordRecipient.java @@ -6,6 +6,7 @@ import org.bouncycastle.asn1.x509.AlgorithmIdentifier; import org.bouncycastle.cms.CMSException; import org.bouncycastle.cms.PasswordRecipient; import org.bouncycastle.crypto.InvalidCipherTextException; +import org.bouncycastle.crypto.PBEParametersGenerator; import org.bouncycastle.crypto.Wrapper; import org.bouncycastle.crypto.generators.PKCS5S2ParametersGenerator; import org.bouncycastle.crypto.params.KeyParameter; @@ -51,10 +52,11 @@ public abstract class BcPasswordRecipient } } - public byte[] calculateDerivedKey(byte[] encodedPassword, AlgorithmIdentifier derivationAlgorithm, int keySize) + public byte[] calculateDerivedKey(int schemeID, AlgorithmIdentifier derivationAlgorithm, int keySize) throws CMSException { PBKDF2Params params = PBKDF2Params.getInstance(derivationAlgorithm.getParameters()); + byte[] encodedPassword = (schemeID == PasswordRecipient.PKCS5_SCHEME2) ? PBEParametersGenerator.PKCS5PasswordToBytes(password) : PBEParametersGenerator.PKCS5PasswordToUTF8Bytes(password); PKCS5S2ParametersGenerator gen = new PKCS5S2ParametersGenerator(); diff --git a/bcpkix/src/main/java/org/bouncycastle/cms/bc/BcPasswordRecipientInfoGenerator.java b/bcpkix/src/main/java/org/bouncycastle/cms/bc/BcPasswordRecipientInfoGenerator.java index 6e1bfdb7..b279ce2c 100644 --- a/bcpkix/src/main/java/org/bouncycastle/cms/bc/BcPasswordRecipientInfoGenerator.java +++ b/bcpkix/src/main/java/org/bouncycastle/cms/bc/BcPasswordRecipientInfoGenerator.java @@ -5,7 +5,9 @@ import org.bouncycastle.asn1.ASN1OctetString; import org.bouncycastle.asn1.pkcs.PBKDF2Params; import org.bouncycastle.asn1.x509.AlgorithmIdentifier; import org.bouncycastle.cms.CMSException; +import org.bouncycastle.cms.PasswordRecipient; import org.bouncycastle.cms.PasswordRecipientInfoGenerator; +import org.bouncycastle.crypto.PBEParametersGenerator; import org.bouncycastle.crypto.Wrapper; import org.bouncycastle.crypto.generators.PKCS5S2ParametersGenerator; import org.bouncycastle.crypto.params.KeyParameter; @@ -20,10 +22,11 @@ public class BcPasswordRecipientInfoGenerator super(kekAlgorithm, password); } - protected byte[] calculateDerivedKey(byte[] encodedPassword, AlgorithmIdentifier derivationAlgorithm, int keySize) + protected byte[] calculateDerivedKey(int schemeID, AlgorithmIdentifier derivationAlgorithm, int keySize) throws CMSException { PBKDF2Params params = PBKDF2Params.getInstance(derivationAlgorithm.getParameters()); + byte[] encodedPassword = (schemeID == PasswordRecipient.PKCS5_SCHEME2) ? PBEParametersGenerator.PKCS5PasswordToBytes(password) : PBEParametersGenerator.PKCS5PasswordToUTF8Bytes(password); PKCS5S2ParametersGenerator gen = new PKCS5S2ParametersGenerator(); diff --git a/bcpkix/src/main/java/org/bouncycastle/cms/bc/EnvelopedDataHelper.java b/bcpkix/src/main/java/org/bouncycastle/cms/bc/EnvelopedDataHelper.java index bb7c3cd6..d04e9772 100644 --- a/bcpkix/src/main/java/org/bouncycastle/cms/bc/EnvelopedDataHelper.java +++ b/bcpkix/src/main/java/org/bouncycastle/cms/bc/EnvelopedDataHelper.java @@ -12,6 +12,7 @@ import org.bouncycastle.asn1.DERNull; import org.bouncycastle.asn1.DEROctetString; import org.bouncycastle.asn1.kisa.KISAObjectIdentifiers; import org.bouncycastle.asn1.misc.CAST5CBCParameters; +import org.bouncycastle.asn1.misc.MiscObjectIdentifiers; import org.bouncycastle.asn1.nist.NISTObjectIdentifiers; import org.bouncycastle.asn1.ntt.NTTObjectIdentifiers; import org.bouncycastle.asn1.oiw.OIWObjectIdentifiers; @@ -28,6 +29,7 @@ import org.bouncycastle.crypto.KeyGenerationParameters; import org.bouncycastle.crypto.StreamCipher; import org.bouncycastle.crypto.Wrapper; import org.bouncycastle.crypto.engines.AESEngine; +import org.bouncycastle.crypto.engines.CAST5Engine; import org.bouncycastle.crypto.engines.DESEngine; import org.bouncycastle.crypto.engines.DESedeEngine; import org.bouncycastle.crypto.engines.RC2Engine; @@ -45,7 +47,6 @@ import org.bouncycastle.crypto.params.RC2Parameters; class EnvelopedDataHelper { protected static final Map BASE_CIPHER_NAMES = new HashMap(); - protected static final Map CIPHER_ALG_NAMES = new HashMap(); protected static final Map MAC_ALG_NAMES = new HashMap(); static @@ -55,17 +56,6 @@ class EnvelopedDataHelper BASE_CIPHER_NAMES.put(CMSAlgorithm.AES192_CBC, "AES"); BASE_CIPHER_NAMES.put(CMSAlgorithm.AES256_CBC, "AES"); - CIPHER_ALG_NAMES.put(CMSAlgorithm.DES_EDE3_CBC, "DESEDE/CBC/PKCS5Padding"); - CIPHER_ALG_NAMES.put(CMSAlgorithm.AES128_CBC, "AES/CBC/PKCS5Padding"); - CIPHER_ALG_NAMES.put(CMSAlgorithm.AES192_CBC, "AES/CBC/PKCS5Padding"); - CIPHER_ALG_NAMES.put(CMSAlgorithm.AES256_CBC, "AES/CBC/PKCS5Padding"); - CIPHER_ALG_NAMES.put(new ASN1ObjectIdentifier(PKCSObjectIdentifiers.rsaEncryption.getId()), "RSA/ECB/PKCS1Padding"); - CIPHER_ALG_NAMES.put(CMSAlgorithm.CAST5_CBC, "CAST5/CBC/PKCS5Padding"); - CIPHER_ALG_NAMES.put(CMSAlgorithm.CAMELLIA128_CBC, "Camellia/CBC/PKCS5Padding"); - CIPHER_ALG_NAMES.put(CMSAlgorithm.CAMELLIA192_CBC, "Camellia/CBC/PKCS5Padding"); - CIPHER_ALG_NAMES.put(CMSAlgorithm.CAMELLIA256_CBC, "Camellia/CBC/PKCS5Padding"); - CIPHER_ALG_NAMES.put(CMSAlgorithm.SEED_CBC, "SEED/CBC/PKCS5Padding"); - MAC_ALG_NAMES.put(CMSAlgorithm.DES_EDE3_CBC, "DESEDEMac"); MAC_ALG_NAMES.put(CMSAlgorithm.AES128_CBC, "AESMac"); MAC_ALG_NAMES.put(CMSAlgorithm.AES192_CBC, "AESMac"); @@ -150,6 +140,10 @@ class EnvelopedDataHelper { cipher = new CBCBlockCipher(new RC2Engine()); } + else if (MiscObjectIdentifiers.cast5CBC.equals(algorithm)) + { + cipher = new CBCBlockCipher(new CAST5Engine()); + } else { throw new CMSException("cannot recognise cipher: " + algorithm); @@ -295,6 +289,16 @@ class EnvelopedDataHelper { return new AlgorithmIdentifier(encryptionOID, DERNull.INSTANCE); } + else if (encryptionOID.equals(PKCSObjectIdentifiers.RC2_CBC)) + { + byte[] iv = new byte[8]; + + random.nextBytes(iv); + + RC2CBCParameter cbcParams = new RC2CBCParameter(rc2Table[128], iv); + + return new AlgorithmIdentifier(encryptionOID, cbcParams); + } else { throw new CMSException("unable to match algorithm"); @@ -356,10 +360,10 @@ class EnvelopedDataHelper { return createCipherKeyGenerator(random, 128); } -// else if (PKCSObjectIdentifiers.RC2_CBC.equals(algorithm)) -// { -// cipher = new CBCBlockCipher(new RC2Engine()); -// } + else if (PKCSObjectIdentifiers.RC2_CBC.equals(algorithm)) + { + return createCipherKeyGenerator(random, 128); + } else { throw new CMSException("cannot recognise cipher: " + algorithm); diff --git a/bcpkix/src/main/java/org/bouncycastle/cms/jcajce/CMSUtils.java b/bcpkix/src/main/java/org/bouncycastle/cms/jcajce/CMSUtils.java index 1596caee..20f9ebb0 100644 --- a/bcpkix/src/main/java/org/bouncycastle/cms/jcajce/CMSUtils.java +++ b/bcpkix/src/main/java/org/bouncycastle/cms/jcajce/CMSUtils.java @@ -5,23 +5,59 @@ import java.security.AlgorithmParameters; import java.security.Provider; import java.security.cert.CertificateEncodingException; import java.security.cert.X509Certificate; +import java.util.HashSet; +import java.util.Set; import org.bouncycastle.asn1.ASN1Encodable; +import org.bouncycastle.asn1.ASN1ObjectIdentifier; import org.bouncycastle.asn1.ASN1OctetString; import org.bouncycastle.asn1.cms.IssuerAndSerialNumber; +import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers; +import org.bouncycastle.asn1.sec.SECObjectIdentifiers; import org.bouncycastle.asn1.x509.Certificate; import org.bouncycastle.asn1.x509.Extension; -import org.bouncycastle.asn1.x509.TBSCertificateStructure; +import org.bouncycastle.asn1.x9.X9ObjectIdentifiers; import org.bouncycastle.cms.CMSException; -import org.bouncycastle.jcajce.util.JcaJceUtils; +import org.bouncycastle.jcajce.util.AlgorithmParametersUtils; class CMSUtils { - static TBSCertificateStructure getTBSCertificateStructure( - X509Certificate cert) - throws CertificateEncodingException + private static final Set mqvAlgs = new HashSet(); + private static final Set ecAlgs = new HashSet(); + + static { - return TBSCertificateStructure.getInstance(cert.getTBSCertificate()); + mqvAlgs.add(X9ObjectIdentifiers.mqvSinglePass_sha1kdf_scheme); + mqvAlgs.add(SECObjectIdentifiers.mqvSinglePass_sha224kdf_scheme); + mqvAlgs.add(SECObjectIdentifiers.mqvSinglePass_sha256kdf_scheme); + mqvAlgs.add(SECObjectIdentifiers.mqvSinglePass_sha384kdf_scheme); + mqvAlgs.add(SECObjectIdentifiers.mqvSinglePass_sha512kdf_scheme); + + ecAlgs.add(X9ObjectIdentifiers.dhSinglePass_cofactorDH_sha1kdf_scheme); + ecAlgs.add(X9ObjectIdentifiers.dhSinglePass_stdDH_sha1kdf_scheme); + ecAlgs.add(SECObjectIdentifiers.dhSinglePass_cofactorDH_sha224kdf_scheme); + ecAlgs.add(SECObjectIdentifiers.dhSinglePass_stdDH_sha224kdf_scheme); + ecAlgs.add(SECObjectIdentifiers.dhSinglePass_cofactorDH_sha256kdf_scheme); + ecAlgs.add(SECObjectIdentifiers.dhSinglePass_stdDH_sha256kdf_scheme); + ecAlgs.add(SECObjectIdentifiers.dhSinglePass_cofactorDH_sha384kdf_scheme); + ecAlgs.add(SECObjectIdentifiers.dhSinglePass_stdDH_sha384kdf_scheme); + ecAlgs.add(SECObjectIdentifiers.dhSinglePass_cofactorDH_sha512kdf_scheme); + ecAlgs.add(SECObjectIdentifiers.dhSinglePass_stdDH_sha512kdf_scheme); + } + + static boolean isMQV(ASN1ObjectIdentifier algorithm) + { + return mqvAlgs.contains(algorithm); + } + + static boolean isEC(ASN1ObjectIdentifier algorithm) + { + return ecAlgs.contains(algorithm); + } + + static boolean isRFC2631(ASN1ObjectIdentifier algorithm) + { + return algorithm.equals(PKCSObjectIdentifiers.id_alg_ESDH) || algorithm.equals(PKCSObjectIdentifiers.id_alg_SSDH); } static IssuerAndSerialNumber getIssuerAndSerialNumber(X509Certificate cert) @@ -32,7 +68,6 @@ class CMSUtils return new IssuerAndSerialNumber(certStruct.getIssuer(), cert.getSerialNumber()); } - static byte[] getSubjectKeyId(X509Certificate cert) { byte[] ext = cert.getExtensionValue(Extension.subjectKeyIdentifier.getId()); @@ -76,7 +111,7 @@ class CMSUtils { try { - return JcaJceUtils.extractParameters(params); + return AlgorithmParametersUtils.extractParameters(params); } catch (IOException e) { @@ -89,7 +124,7 @@ class CMSUtils { try { - JcaJceUtils.loadParameters(params, sParams); + AlgorithmParametersUtils.loadParameters(params, sParams); } catch (IOException e) { diff --git a/bcpkix/src/main/java/org/bouncycastle/cms/jcajce/DefaultJcaJceExtHelper.java b/bcpkix/src/main/java/org/bouncycastle/cms/jcajce/DefaultJcaJceExtHelper.java index c6cd8257..c2a753cb 100644 --- a/bcpkix/src/main/java/org/bouncycastle/cms/jcajce/DefaultJcaJceExtHelper.java +++ b/bcpkix/src/main/java/org/bouncycastle/cms/jcajce/DefaultJcaJceExtHelper.java @@ -8,6 +8,7 @@ import org.bouncycastle.asn1.x509.AlgorithmIdentifier; import org.bouncycastle.jcajce.util.DefaultJcaJceHelper; import org.bouncycastle.operator.SymmetricKeyUnwrapper; import org.bouncycastle.operator.jcajce.JceAsymmetricKeyUnwrapper; +import org.bouncycastle.operator.jcajce.JceKTSKeyUnwrapper; import org.bouncycastle.operator.jcajce.JceSymmetricKeyUnwrapper; class DefaultJcaJceExtHelper @@ -19,6 +20,11 @@ class DefaultJcaJceExtHelper return new JceAsymmetricKeyUnwrapper(keyEncryptionAlgorithm, keyEncryptionKey); } + public JceKTSKeyUnwrapper createAsymmetricUnwrapper(AlgorithmIdentifier keyEncryptionAlgorithm, PrivateKey keyEncryptionKey, byte[] partyUInfo, byte[] partyVInfo) + { + return new JceKTSKeyUnwrapper(keyEncryptionAlgorithm, keyEncryptionKey, partyUInfo, partyVInfo); + } + public SymmetricKeyUnwrapper createSymmetricUnwrapper(AlgorithmIdentifier keyEncryptionAlgorithm, SecretKey keyEncryptionKey) { return new JceSymmetricKeyUnwrapper(keyEncryptionAlgorithm, keyEncryptionKey); diff --git a/bcpkix/src/main/java/org/bouncycastle/cms/jcajce/EnvelopedDataHelper.java b/bcpkix/src/main/java/org/bouncycastle/cms/jcajce/EnvelopedDataHelper.java index b0810515..5278b2eb 100644 --- a/bcpkix/src/main/java/org/bouncycastle/cms/jcajce/EnvelopedDataHelper.java +++ b/bcpkix/src/main/java/org/bouncycastle/cms/jcajce/EnvelopedDataHelper.java @@ -23,7 +23,9 @@ import javax.crypto.KeyGenerator; import javax.crypto.Mac; import javax.crypto.NoSuchPaddingException; import javax.crypto.SecretKey; +import javax.crypto.SecretKeyFactory; import javax.crypto.spec.IvParameterSpec; +import javax.crypto.spec.PBEKeySpec; import javax.crypto.spec.RC2ParameterSpec; import javax.crypto.spec.SecretKeySpec; @@ -33,17 +35,20 @@ import org.bouncycastle.asn1.ASN1ObjectIdentifier; import org.bouncycastle.asn1.ASN1OctetString; import org.bouncycastle.asn1.DERNull; import org.bouncycastle.asn1.DEROctetString; +import org.bouncycastle.asn1.pkcs.PBKDF2Params; import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers; import org.bouncycastle.asn1.pkcs.RC2CBCParameter; import org.bouncycastle.asn1.x509.AlgorithmIdentifier; import org.bouncycastle.cms.CMSAlgorithm; import org.bouncycastle.cms.CMSEnvelopedDataGenerator; import org.bouncycastle.cms.CMSException; +import org.bouncycastle.cms.PasswordRecipient; import org.bouncycastle.operator.DefaultSecretKeySizeProvider; import org.bouncycastle.operator.GenericKey; import org.bouncycastle.operator.SecretKeySizeProvider; import org.bouncycastle.operator.SymmetricKeyUnwrapper; import org.bouncycastle.operator.jcajce.JceAsymmetricKeyUnwrapper; +import org.bouncycastle.operator.jcajce.JceKTSKeyUnwrapper; public class EnvelopedDataHelper { @@ -302,7 +307,7 @@ public class EnvelopedDataHelper } catch (GeneralSecurityException e) { - throw new CMSException("cannot create key pair generator: " + e.getMessage(), e); + throw new CMSException("cannot create key agreement: " + e.getMessage(), e); } } @@ -619,6 +624,11 @@ public class EnvelopedDataHelper return helper.createAsymmetricUnwrapper(keyEncryptionAlgorithm, keyEncryptionKey); } + public JceKTSKeyUnwrapper createAsymmetricUnwrapper(AlgorithmIdentifier keyEncryptionAlgorithm, PrivateKey keyEncryptionKey, byte[] partyUInfo, byte[] partyVInfo) + { + return helper.createAsymmetricUnwrapper(keyEncryptionAlgorithm, keyEncryptionKey, partyUInfo, partyVInfo); + } + public SymmetricKeyUnwrapper createSymmetricUnwrapper(AlgorithmIdentifier keyEncryptionAlgorithm, SecretKey keyEncryptionKey) { return helper.createSymmetricUnwrapper(keyEncryptionAlgorithm, keyEncryptionKey); @@ -659,6 +669,40 @@ public class EnvelopedDataHelper throw new IllegalStateException("unknown parameter spec: " + paramSpec); } + SecretKeyFactory createSecretKeyFactory(String keyFactoryAlgorithm) + throws NoSuchProviderException, NoSuchAlgorithmException + { + return helper.createSecretKeyFactory(keyFactoryAlgorithm); + } + + byte[] calculateDerivedKey(int schemeID, char[] password, AlgorithmIdentifier derivationAlgorithm, int keySize) + throws CMSException + { + PBKDF2Params params = PBKDF2Params.getInstance(derivationAlgorithm.getParameters()); + + try + { + SecretKeyFactory keyFact; + + if (schemeID == PasswordRecipient.PKCS5_SCHEME2) + { + keyFact = helper.createSecretKeyFactory("PBKDF2with8BIT"); + } + else + { + keyFact = helper.createSecretKeyFactory("PBKDF2"); + } + + SecretKey key = keyFact.generateSecret(new PBEKeySpec(password, params.getSalt(), params.getIterationCount().intValue(), keySize)); + + return key.getEncoded(); + } + catch (GeneralSecurityException e) + { + throw new CMSException("Unable to calculate dervied key from password: " + e.getMessage(), e); + } + } + static interface JCECallback { Object doInJCE() diff --git a/bcpkix/src/main/java/org/bouncycastle/cms/jcajce/JcaJceExtHelper.java b/bcpkix/src/main/java/org/bouncycastle/cms/jcajce/JcaJceExtHelper.java index 3eb54a10..8548ee6e 100644 --- a/bcpkix/src/main/java/org/bouncycastle/cms/jcajce/JcaJceExtHelper.java +++ b/bcpkix/src/main/java/org/bouncycastle/cms/jcajce/JcaJceExtHelper.java @@ -8,11 +8,14 @@ import org.bouncycastle.asn1.x509.AlgorithmIdentifier; import org.bouncycastle.jcajce.util.JcaJceHelper; import org.bouncycastle.operator.SymmetricKeyUnwrapper; import org.bouncycastle.operator.jcajce.JceAsymmetricKeyUnwrapper; +import org.bouncycastle.operator.jcajce.JceKTSKeyUnwrapper; public interface JcaJceExtHelper extends JcaJceHelper { JceAsymmetricKeyUnwrapper createAsymmetricUnwrapper(AlgorithmIdentifier keyEncryptionAlgorithm, PrivateKey keyEncryptionKey); + JceKTSKeyUnwrapper createAsymmetricUnwrapper(AlgorithmIdentifier keyEncryptionAlgorithm, PrivateKey keyEncryptionKey, byte[] partyUInfo, byte[] partyVInfo); + SymmetricKeyUnwrapper createSymmetricUnwrapper(AlgorithmIdentifier keyEncryptionAlgorithm, SecretKey keyEncryptionKey); } diff --git a/bcpkix/src/main/java/org/bouncycastle/cms/jcajce/JceCMSContentEncryptorBuilder.java b/bcpkix/src/main/java/org/bouncycastle/cms/jcajce/JceCMSContentEncryptorBuilder.java index 93d8b72c..379917be 100644 --- a/bcpkix/src/main/java/org/bouncycastle/cms/jcajce/JceCMSContentEncryptorBuilder.java +++ b/bcpkix/src/main/java/org/bouncycastle/cms/jcajce/JceCMSContentEncryptorBuilder.java @@ -12,6 +12,7 @@ import javax.crypto.KeyGenerator; import javax.crypto.SecretKey; import org.bouncycastle.asn1.ASN1ObjectIdentifier; +import org.bouncycastle.asn1.oiw.OIWObjectIdentifiers; import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers; import org.bouncycastle.asn1.x509.AlgorithmIdentifier; import org.bouncycastle.cms.CMSException; @@ -40,7 +41,6 @@ public class JceCMSContentEncryptorBuilder public JceCMSContentEncryptorBuilder(ASN1ObjectIdentifier encryptionOID, int keySize) { this.encryptionOID = encryptionOID; - this.keySize = keySize; int fixedSize = KEY_SIZE_PROVIDER.getKeySize(encryptionOID); @@ -50,6 +50,15 @@ public class JceCMSContentEncryptorBuilder { throw new IllegalArgumentException("incorrect keySize for encryptionOID passed to builder."); } + this.keySize = 168; + } + else if (encryptionOID.equals(OIWObjectIdentifiers.desCBC)) + { + if (keySize != 56 && keySize != fixedSize) + { + throw new IllegalArgumentException("incorrect keySize for encryptionOID passed to builder."); + } + this.keySize = 56; } else { @@ -57,6 +66,7 @@ public class JceCMSContentEncryptorBuilder { throw new IllegalArgumentException("incorrect keySize for encryptionOID passed to builder."); } + this.keySize = keySize; } } @@ -110,10 +120,6 @@ public class JceCMSContentEncryptorBuilder } else { - if (encryptionOID.equals(PKCSObjectIdentifiers.des_EDE3_CBC) && keySize == 192) - { - keySize = 168; - } keyGen.init(keySize, random); } diff --git a/bcpkix/src/main/java/org/bouncycastle/cms/jcajce/JceKEKEnvelopedRecipient.java b/bcpkix/src/main/java/org/bouncycastle/cms/jcajce/JceKEKEnvelopedRecipient.java index a7293794..c9d2fc28 100644 --- a/bcpkix/src/main/java/org/bouncycastle/cms/jcajce/JceKEKEnvelopedRecipient.java +++ b/bcpkix/src/main/java/org/bouncycastle/cms/jcajce/JceKEKEnvelopedRecipient.java @@ -4,12 +4,12 @@ import java.io.InputStream; import java.security.Key; import javax.crypto.Cipher; -import javax.crypto.CipherInputStream; import javax.crypto.SecretKey; import org.bouncycastle.asn1.x509.AlgorithmIdentifier; import org.bouncycastle.cms.CMSException; import org.bouncycastle.cms.RecipientOperator; +import org.bouncycastle.jcajce.io.CipherInputStream; import org.bouncycastle.operator.InputDecryptor; public class JceKEKEnvelopedRecipient diff --git a/bcpkix/src/main/java/org/bouncycastle/cms/jcajce/JceKeyAgreeEnvelopedRecipient.java b/bcpkix/src/main/java/org/bouncycastle/cms/jcajce/JceKeyAgreeEnvelopedRecipient.java index fe647d7d..e0b99277 100644 --- a/bcpkix/src/main/java/org/bouncycastle/cms/jcajce/JceKeyAgreeEnvelopedRecipient.java +++ b/bcpkix/src/main/java/org/bouncycastle/cms/jcajce/JceKeyAgreeEnvelopedRecipient.java @@ -5,13 +5,13 @@ import java.security.Key; import java.security.PrivateKey; import javax.crypto.Cipher; -import javax.crypto.CipherInputStream; import org.bouncycastle.asn1.ASN1OctetString; import org.bouncycastle.asn1.x509.AlgorithmIdentifier; import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo; import org.bouncycastle.cms.CMSException; import org.bouncycastle.cms.RecipientOperator; +import org.bouncycastle.jcajce.io.CipherInputStream; import org.bouncycastle.operator.InputDecryptor; public class JceKeyAgreeEnvelopedRecipient diff --git a/bcpkix/src/main/java/org/bouncycastle/cms/jcajce/JceKeyAgreeRecipient.java b/bcpkix/src/main/java/org/bouncycastle/cms/jcajce/JceKeyAgreeRecipient.java index 8c41f914..14217d2c 100644 --- a/bcpkix/src/main/java/org/bouncycastle/cms/jcajce/JceKeyAgreeRecipient.java +++ b/bcpkix/src/main/java/org/bouncycastle/cms/jcajce/JceKeyAgreeRecipient.java @@ -11,31 +11,48 @@ import java.security.Provider; import java.security.PublicKey; import java.security.spec.InvalidKeySpecException; import java.security.spec.X509EncodedKeySpec; +import java.util.HashSet; +import java.util.Set; import javax.crypto.Cipher; import javax.crypto.KeyAgreement; import javax.crypto.NoSuchPaddingException; import javax.crypto.SecretKey; +import org.bouncycastle.asn1.ASN1Encoding; import org.bouncycastle.asn1.ASN1ObjectIdentifier; import org.bouncycastle.asn1.ASN1OctetString; -import org.bouncycastle.asn1.ASN1Primitive; +import org.bouncycastle.asn1.DERNull; +import org.bouncycastle.asn1.cms.ecc.ECCCMSSharedInfo; import org.bouncycastle.asn1.cms.ecc.MQVuserKeyingMaterial; import org.bouncycastle.asn1.pkcs.PrivateKeyInfo; import org.bouncycastle.asn1.x509.AlgorithmIdentifier; import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo; -import org.bouncycastle.cms.CMSEnvelopedGenerator; +import org.bouncycastle.asn1.x9.X9ObjectIdentifiers; import org.bouncycastle.cms.CMSException; import org.bouncycastle.cms.KeyAgreeRecipient; -import org.bouncycastle.jce.spec.MQVPrivateKeySpec; -import org.bouncycastle.jce.spec.MQVPublicKeySpec; +import org.bouncycastle.jcajce.spec.MQVParameterSpec; +import org.bouncycastle.jcajce.spec.UserKeyingMaterialSpec; +import org.bouncycastle.operator.DefaultSecretKeySizeProvider; +import org.bouncycastle.operator.SecretKeySizeProvider; +import org.bouncycastle.util.Pack; public abstract class JceKeyAgreeRecipient implements KeyAgreeRecipient { + private static final Set possibleOldMessages = new HashSet(); + + static + { + possibleOldMessages.add(X9ObjectIdentifiers.dhSinglePass_stdDH_sha1kdf_scheme); + possibleOldMessages.add(X9ObjectIdentifiers.mqvSinglePass_sha1kdf_scheme); + } + private PrivateKey recipientKey; protected EnvelopedDataHelper helper = new EnvelopedDataHelper(new DefaultJcaJceExtHelper()); protected EnvelopedDataHelper contentHelper = helper; + private SecretKeySizeProvider keySizeProvider = new DefaultSecretKeySizeProvider(); + public JceKeyAgreeRecipient(PrivateKey recipientKey) { @@ -98,17 +115,13 @@ public abstract class JceKeyAgreeRecipient return this; } - private SecretKey calculateAgreedWrapKey(AlgorithmIdentifier keyEncAlg, ASN1ObjectIdentifier wrapAlg, - PublicKey senderPublicKey, ASN1OctetString userKeyingMaterial, PrivateKey receiverPrivateKey) + private SecretKey calculateAgreedWrapKey(AlgorithmIdentifier keyEncAlg, AlgorithmIdentifier wrapAlg, + PublicKey senderPublicKey, ASN1OctetString userKeyingMaterial, PrivateKey receiverPrivateKey, KeyMaterialGenerator kmGen) throws CMSException, GeneralSecurityException, IOException { - String agreeAlg = keyEncAlg.getAlgorithm().getId(); - - if (agreeAlg.equals(CMSEnvelopedGenerator.ECMQV_SHA1KDF)) + if (CMSUtils.isMQV(keyEncAlg.getAlgorithm())) { - byte[] ukmEncoding = userKeyingMaterial.getOctets(); - MQVuserKeyingMaterial ukm = MQVuserKeyingMaterial.getInstance( - ASN1Primitive.fromByteArray(ukmEncoding)); + MQVuserKeyingMaterial ukm = MQVuserKeyingMaterial.getInstance(userKeyingMaterial.getOctets()); SubjectPublicKeyInfo pubInfo = new SubjectPublicKeyInfo( getPrivateKeyAlgorithmIdentifier(), @@ -118,16 +131,58 @@ public abstract class JceKeyAgreeRecipient KeyFactory fact = helper.createKeyFactory(keyEncAlg.getAlgorithm()); PublicKey ephemeralKey = fact.generatePublic(pubSpec); - senderPublicKey = new MQVPublicKeySpec(senderPublicKey, ephemeralKey); - receiverPrivateKey = new MQVPrivateKeySpec(receiverPrivateKey, receiverPrivateKey); + KeyAgreement agreement = helper.createKeyAgreement(keyEncAlg.getAlgorithm()); + + byte[] ukmKeyingMaterial = (ukm.getAddedukm() != null) ? ukm.getAddedukm().getOctets() : null; + if (kmGen == old_ecc_cms_Generator) + { + ukmKeyingMaterial = old_ecc_cms_Generator.generateKDFMaterial(wrapAlg, keySizeProvider.getKeySize(wrapAlg), ukmKeyingMaterial); + } + + agreement.init(receiverPrivateKey, new MQVParameterSpec(receiverPrivateKey, ephemeralKey, ukmKeyingMaterial)); + agreement.doPhase(senderPublicKey, true); + + return agreement.generateSecret(wrapAlg.getAlgorithm().getId()); } + else + { + KeyAgreement agreement = helper.createKeyAgreement(keyEncAlg.getAlgorithm()); + + UserKeyingMaterialSpec userKeyingMaterialSpec = null; + + if (CMSUtils.isEC(keyEncAlg.getAlgorithm())) + { + if (userKeyingMaterial != null) + { + byte[] ukmKeyingMaterial = kmGen.generateKDFMaterial(wrapAlg, keySizeProvider.getKeySize(wrapAlg), userKeyingMaterial.getOctets()); - KeyAgreement agreement = helper.createKeyAgreement(keyEncAlg.getAlgorithm()); + userKeyingMaterialSpec = new UserKeyingMaterialSpec(ukmKeyingMaterial); + } + else + { + byte[] ukmKeyingMaterial = kmGen.generateKDFMaterial(wrapAlg, keySizeProvider.getKeySize(wrapAlg), null); - agreement.init(receiverPrivateKey); - agreement.doPhase(senderPublicKey, true); + userKeyingMaterialSpec = new UserKeyingMaterialSpec(ukmKeyingMaterial); + } + } + else if (CMSUtils.isRFC2631(keyEncAlg.getAlgorithm())) + { + if (userKeyingMaterial != null) + { + userKeyingMaterialSpec = new UserKeyingMaterialSpec(userKeyingMaterial.getOctets()); + } + } + else + { + throw new CMSException("Unknown key agreement algorithm: " + keyEncAlg.getAlgorithm()); + } - return agreement.generateSecret(wrapAlg.getId()); + agreement.init(receiverPrivateKey, userKeyingMaterialSpec); + + agreement.doPhase(senderPublicKey, true); + + return agreement.generateSecret(wrapAlg.getAlgorithm().getId()); + } } private Key unwrapSessionKey(ASN1ObjectIdentifier wrapAlg, SecretKey agreedKey, ASN1ObjectIdentifier contentEncryptionAlgorithm, byte[] encryptedContentEncryptionKey) @@ -143,17 +198,32 @@ public abstract class JceKeyAgreeRecipient { try { - ASN1ObjectIdentifier wrapAlg = - AlgorithmIdentifier.getInstance(keyEncryptionAlgorithm.getParameters()).getAlgorithm(); + AlgorithmIdentifier wrapAlg = + AlgorithmIdentifier.getInstance(keyEncryptionAlgorithm.getParameters()); X509EncodedKeySpec pubSpec = new X509EncodedKeySpec(senderKey.getEncoded()); - KeyFactory fact = helper.createKeyFactory(keyEncryptionAlgorithm.getAlgorithm()); + KeyFactory fact = helper.createKeyFactory(senderKey.getAlgorithm().getAlgorithm()); PublicKey senderPublicKey = fact.generatePublic(pubSpec); - SecretKey agreedWrapKey = calculateAgreedWrapKey(keyEncryptionAlgorithm, wrapAlg, - senderPublicKey, userKeyingMaterial, recipientKey); + try + { + SecretKey agreedWrapKey = calculateAgreedWrapKey(keyEncryptionAlgorithm, wrapAlg, + senderPublicKey, userKeyingMaterial, recipientKey, ecc_cms_Generator); - return unwrapSessionKey(wrapAlg, agreedWrapKey, contentEncryptionAlgorithm.getAlgorithm(), encryptedContentEncryptionKey); + return unwrapSessionKey(wrapAlg.getAlgorithm(), agreedWrapKey, contentEncryptionAlgorithm.getAlgorithm(), encryptedContentEncryptionKey); + } + catch (InvalidKeyException e) + { + // might be a pre-RFC 5753 message + if (possibleOldMessages.contains(keyEncryptionAlgorithm.getAlgorithm())) + { + SecretKey agreedWrapKey = calculateAgreedWrapKey(keyEncryptionAlgorithm, wrapAlg, + senderPublicKey, userKeyingMaterial, recipientKey, old_ecc_cms_Generator); + + return unwrapSessionKey(wrapAlg.getAlgorithm(), agreedWrapKey, contentEncryptionAlgorithm.getAlgorithm(), encryptedContentEncryptionKey); + } + throw e; + } } catch (NoSuchAlgorithmException e) { @@ -181,4 +251,26 @@ public abstract class JceKeyAgreeRecipient { return PrivateKeyInfo.getInstance(recipientKey.getEncoded()).getPrivateKeyAlgorithm(); } + + private static KeyMaterialGenerator old_ecc_cms_Generator = new KeyMaterialGenerator() + { + public byte[] generateKDFMaterial(AlgorithmIdentifier keyAlgorithm, int keySize, byte[] userKeyMaterialParameters) + { + ECCCMSSharedInfo eccInfo; + + // this isn't correct with AES and RFC 5753, but we have messages predating it... + eccInfo = new ECCCMSSharedInfo(new AlgorithmIdentifier(keyAlgorithm.getAlgorithm(), DERNull.INSTANCE), userKeyMaterialParameters, Pack.intToBigEndian(keySize)); + + try + { + return eccInfo.getEncoded(ASN1Encoding.DER); + } + catch (IOException e) + { + throw new IllegalStateException("Unable to create KDF material: " + e); + } + } + }; + + private static KeyMaterialGenerator ecc_cms_Generator = new RFC5753KeyMaterialGenerator(); } diff --git a/bcpkix/src/main/java/org/bouncycastle/cms/jcajce/JceKeyAgreeRecipientInfoGenerator.java b/bcpkix/src/main/java/org/bouncycastle/cms/jcajce/JceKeyAgreeRecipientInfoGenerator.java index 583ede2d..ec9bd10d 100644 --- a/bcpkix/src/main/java/org/bouncycastle/cms/jcajce/JceKeyAgreeRecipientInfoGenerator.java +++ b/bcpkix/src/main/java/org/bouncycastle/cms/jcajce/JceKeyAgreeRecipientInfoGenerator.java @@ -1,7 +1,8 @@ package org.bouncycastle.cms.jcajce; +import java.io.IOException; +import java.security.AlgorithmParameters; import java.security.GeneralSecurityException; -import java.security.InvalidAlgorithmParameterException; import java.security.KeyPair; import java.security.KeyPairGenerator; import java.security.PrivateKey; @@ -10,8 +11,7 @@ import java.security.PublicKey; import java.security.SecureRandom; import java.security.cert.CertificateEncodingException; import java.security.cert.X509Certificate; -import java.security.interfaces.ECPublicKey; -import java.security.spec.ECParameterSpec; +import java.security.spec.AlgorithmParameterSpec; import java.util.ArrayList; import java.util.List; @@ -19,7 +19,6 @@ import javax.crypto.Cipher; import javax.crypto.KeyAgreement; import javax.crypto.SecretKey; -import org.bouncycastle.asn1.ASN1Encodable; import org.bouncycastle.asn1.ASN1EncodableVector; import org.bouncycastle.asn1.ASN1ObjectIdentifier; import org.bouncycastle.asn1.ASN1OctetString; @@ -27,22 +26,27 @@ import org.bouncycastle.asn1.ASN1Sequence; import org.bouncycastle.asn1.DEROctetString; import org.bouncycastle.asn1.DERSequence; import org.bouncycastle.asn1.cms.KeyAgreeRecipientIdentifier; +import org.bouncycastle.asn1.cms.OriginatorPublicKey; import org.bouncycastle.asn1.cms.RecipientEncryptedKey; import org.bouncycastle.asn1.cms.RecipientKeyIdentifier; import org.bouncycastle.asn1.cms.ecc.MQVuserKeyingMaterial; +import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers; import org.bouncycastle.asn1.x509.AlgorithmIdentifier; import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo; -import org.bouncycastle.cms.CMSAlgorithm; -import org.bouncycastle.cms.CMSEnvelopedGenerator; import org.bouncycastle.cms.CMSException; import org.bouncycastle.cms.KeyAgreeRecipientInfoGenerator; -import org.bouncycastle.jce.spec.MQVPrivateKeySpec; -import org.bouncycastle.jce.spec.MQVPublicKeySpec; +import org.bouncycastle.jcajce.spec.MQVParameterSpec; +import org.bouncycastle.jcajce.spec.UserKeyingMaterialSpec; +import org.bouncycastle.operator.DefaultSecretKeySizeProvider; import org.bouncycastle.operator.GenericKey; +import org.bouncycastle.operator.SecretKeySizeProvider; +import org.bouncycastle.util.Arrays; public class JceKeyAgreeRecipientInfoGenerator extends KeyAgreeRecipientInfoGenerator { + private SecretKeySizeProvider keySizeProvider = new DefaultSecretKeySizeProvider(); + private List recipientIDs = new ArrayList(); private List recipientKeys = new ArrayList(); private PublicKey senderPublicKey; @@ -51,6 +55,7 @@ public class JceKeyAgreeRecipientInfoGenerator private EnvelopedDataHelper helper = new EnvelopedDataHelper(new DefaultJcaJceExtHelper()); private SecureRandom random; private KeyPair ephemeralKP; + private byte[] userKeyingMaterial; public JceKeyAgreeRecipientInfoGenerator(ASN1ObjectIdentifier keyAgreementOID, PrivateKey senderPrivateKey, PublicKey senderPublicKey, ASN1ObjectIdentifier keyEncryptionOID) { @@ -60,6 +65,13 @@ public class JceKeyAgreeRecipientInfoGenerator this.senderPrivateKey = senderPrivateKey; } + public JceKeyAgreeRecipientInfoGenerator setUserKeyingMaterial(byte[] userKeyingMaterial) + { + this.userKeyingMaterial = Arrays.clone(userKeyingMaterial); + + return this; + } + public JceKeyAgreeRecipientInfoGenerator setProvider(Provider provider) { this.helper = new EnvelopedDataHelper(new ProviderJcaJceExtHelper(provider)); @@ -117,35 +129,62 @@ public class JceKeyAgreeRecipientInfoGenerator public ASN1Sequence generateRecipientEncryptedKeys(AlgorithmIdentifier keyAgreeAlgorithm, AlgorithmIdentifier keyEncryptionAlgorithm, GenericKey contentEncryptionKey) throws CMSException { + if (recipientIDs.isEmpty()) + { + throw new CMSException("No recipients associated with generator - use addRecipient()"); + } + init(keyAgreeAlgorithm.getAlgorithm()); PrivateKey senderPrivateKey = this.senderPrivateKey; ASN1ObjectIdentifier keyAgreementOID = keyAgreeAlgorithm.getAlgorithm(); - if (keyAgreementOID.getId().equals(CMSEnvelopedGenerator.ECMQV_SHA1KDF)) - { - senderPrivateKey = new MQVPrivateKeySpec( - senderPrivateKey, ephemeralKP.getPrivate(), ephemeralKP.getPublic()); - } - ASN1EncodableVector recipientEncryptedKeys = new ASN1EncodableVector(); for (int i = 0; i != recipientIDs.size(); i++) { PublicKey recipientPublicKey = (PublicKey)recipientKeys.get(i); KeyAgreeRecipientIdentifier karId = (KeyAgreeRecipientIdentifier)recipientIDs.get(i); - if (keyAgreementOID.getId().equals(CMSEnvelopedGenerator.ECMQV_SHA1KDF)) - { - recipientPublicKey = new MQVPublicKeySpec(recipientPublicKey, recipientPublicKey); - } - try { + AlgorithmParameterSpec agreementParamSpec; + + if (CMSUtils.isMQV(keyAgreementOID)) + { + agreementParamSpec = new MQVParameterSpec(ephemeralKP, recipientPublicKey, userKeyingMaterial); + } + else if (CMSUtils.isEC(keyAgreementOID)) + { + byte[] ukmKeyingMaterial = ecc_cms_Generator.generateKDFMaterial(keyEncryptionAlgorithm, keySizeProvider.getKeySize(keyEncryptionAlgorithm.getAlgorithm()), userKeyingMaterial); + + agreementParamSpec = new UserKeyingMaterialSpec(ukmKeyingMaterial); + } + else if (CMSUtils.isRFC2631(keyAgreementOID)) + { + if (userKeyingMaterial != null) + { + agreementParamSpec = new UserKeyingMaterialSpec(userKeyingMaterial); + } + else + { + if (keyAgreementOID.equals(PKCSObjectIdentifiers.id_alg_SSDH)) + { + throw new CMSException("User keying material must be set for static keys."); + } + agreementParamSpec = null; + } + } + else + { + throw new CMSException("Unknown key agreement algorithm: " + keyAgreementOID); + } + // Use key agreement to choose a wrap key for this recipient KeyAgreement keyAgreement = helper.createKeyAgreement(keyAgreementOID); - keyAgreement.init(senderPrivateKey, random); + keyAgreement.init(senderPrivateKey, agreementParamSpec, random); keyAgreement.doPhase(recipientPublicKey, true); + SecretKey keyEncryptionKey = keyAgreement.generateSecret(keyEncryptionAlgorithm.getAlgorithm().getId()); // Wrap the content encryption key with the agreement key @@ -161,25 +200,40 @@ public class JceKeyAgreeRecipientInfoGenerator } catch (GeneralSecurityException e) { - throw new CMSException("cannot perform agreement step: " + e.getMessage(), e); + throw new CMSException("Cannot perform agreement step: " + e.getMessage(), e); } } return new DERSequence(recipientEncryptedKeys); } - protected ASN1Encodable getUserKeyingMaterial(AlgorithmIdentifier keyAgreeAlg) + protected byte[] getUserKeyingMaterial(AlgorithmIdentifier keyAgreeAlg) throws CMSException { init(keyAgreeAlg.getAlgorithm()); if (ephemeralKP != null) { - return new MQVuserKeyingMaterial( - createOriginatorPublicKey(SubjectPublicKeyInfo.getInstance(ephemeralKP.getPublic().getEncoded())), null); + OriginatorPublicKey originatorPublicKey = createOriginatorPublicKey(SubjectPublicKeyInfo.getInstance(ephemeralKP.getPublic().getEncoded())); + + try + { + if (userKeyingMaterial != null) + { + return new MQVuserKeyingMaterial(originatorPublicKey, new DEROctetString(userKeyingMaterial)).getEncoded(); + } + else + { + return new MQVuserKeyingMaterial(originatorPublicKey, null).getEncoded(); + } + } + catch (IOException e) + { + throw new CMSException("unable to encode user keying material: " + e.getMessage(), e); + } } - return null; + return userKeyingMaterial; } private void init(ASN1ObjectIdentifier keyAgreementOID) @@ -190,26 +244,32 @@ public class JceKeyAgreeRecipientInfoGenerator random = new SecureRandom(); } - if (keyAgreementOID.equals(CMSAlgorithm.ECMQV_SHA1KDF)) + if (CMSUtils.isMQV(keyAgreementOID)) { if (ephemeralKP == null) { try { - ECParameterSpec ecParamSpec = ((ECPublicKey)senderPublicKey).getParams(); + SubjectPublicKeyInfo pubInfo = SubjectPublicKeyInfo.getInstance(senderPublicKey.getEncoded()); + + AlgorithmParameters ecAlgParams = helper.createAlgorithmParameters(keyAgreementOID); + + ecAlgParams.init(pubInfo.getAlgorithm().getParameters().toASN1Primitive().getEncoded()); KeyPairGenerator ephemKPG = helper.createKeyPairGenerator(keyAgreementOID); - ephemKPG.initialize(ecParamSpec, random); + ephemKPG.initialize(ecAlgParams.getParameterSpec(AlgorithmParameterSpec.class), random); ephemeralKP = ephemKPG.generateKeyPair(); } - catch (InvalidAlgorithmParameterException e) + catch (Exception e) { throw new CMSException( - "cannot determine MQV ephemeral key pair parameters from public key: " + e); + "cannot determine MQV ephemeral key pair parameters from public key: " + e, e); } } } } + + private static KeyMaterialGenerator ecc_cms_Generator = new RFC5753KeyMaterialGenerator(); }
\ No newline at end of file diff --git a/bcpkix/src/main/java/org/bouncycastle/cms/jcajce/JceKeyTransAuthenticatedRecipient.java b/bcpkix/src/main/java/org/bouncycastle/cms/jcajce/JceKeyTransAuthenticatedRecipient.java index f15aadb0..b91ee9b1 100644 --- a/bcpkix/src/main/java/org/bouncycastle/cms/jcajce/JceKeyTransAuthenticatedRecipient.java +++ b/bcpkix/src/main/java/org/bouncycastle/cms/jcajce/JceKeyTransAuthenticatedRecipient.java @@ -12,6 +12,7 @@ import org.bouncycastle.cms.RecipientOperator; import org.bouncycastle.jcajce.io.MacOutputStream; import org.bouncycastle.operator.GenericKey; import org.bouncycastle.operator.MacCalculator; +import org.bouncycastle.operator.jcajce.JceGenericKey; /** @@ -43,7 +44,7 @@ public class JceKeyTransAuthenticatedRecipient public GenericKey getKey() { - return new GenericKey(secretKey); + return new JceGenericKey(contentMacAlgorithm, secretKey); } public OutputStream getOutputStream() diff --git a/bcpkix/src/main/java/org/bouncycastle/cms/jcajce/JceKeyTransEnvelopedRecipient.java b/bcpkix/src/main/java/org/bouncycastle/cms/jcajce/JceKeyTransEnvelopedRecipient.java index 1bc0188f..79e9c024 100644 --- a/bcpkix/src/main/java/org/bouncycastle/cms/jcajce/JceKeyTransEnvelopedRecipient.java +++ b/bcpkix/src/main/java/org/bouncycastle/cms/jcajce/JceKeyTransEnvelopedRecipient.java @@ -5,11 +5,11 @@ import java.security.Key; import java.security.PrivateKey; import javax.crypto.Cipher; -import javax.crypto.CipherInputStream; import org.bouncycastle.asn1.x509.AlgorithmIdentifier; import org.bouncycastle.cms.CMSException; import org.bouncycastle.cms.RecipientOperator; +import org.bouncycastle.jcajce.io.CipherInputStream; import org.bouncycastle.operator.InputDecryptor; public class JceKeyTransEnvelopedRecipient diff --git a/bcpkix/src/main/java/org/bouncycastle/cms/jcajce/JceKeyTransRecipient.java b/bcpkix/src/main/java/org/bouncycastle/cms/jcajce/JceKeyTransRecipient.java index a457ede4..61f32bbe 100644 --- a/bcpkix/src/main/java/org/bouncycastle/cms/jcajce/JceKeyTransRecipient.java +++ b/bcpkix/src/main/java/org/bouncycastle/cms/jcajce/JceKeyTransRecipient.java @@ -23,6 +23,7 @@ public abstract class JceKeyTransRecipient protected EnvelopedDataHelper contentHelper = helper; protected Map extraMappings = new HashMap(); protected boolean validateKeySize = false; + protected boolean unwrappedKeyMustBeEncodable; public JceKeyTransRecipient(PrivateKey recipientKey) { @@ -93,6 +94,21 @@ public abstract class JceKeyTransRecipient } /** + * Flag that unwrapping must produce a key that will return a meaningful value from a call to Key.getEncoded(). + * This is important if you are using a HSM for unwrapping and using a software based provider for + * decrypting the content. Default value: false. + * + * @param unwrappedKeyMustBeEncodable true if getEncoded() should return key bytes, false if not necessary. + * @return this recipient. + */ + public JceKeyTransRecipient setMustProduceEncodableUnwrappedKey(boolean unwrappedKeyMustBeEncodable) + { + this.unwrappedKeyMustBeEncodable = unwrappedKeyMustBeEncodable; + + return this; + } + + /** * Set the provider to use for content processing. If providerName is null a "no provider" search will be * used to satisfy getInstance calls. * @@ -125,7 +141,7 @@ public abstract class JceKeyTransRecipient protected Key extractSecretKey(AlgorithmIdentifier keyEncryptionAlgorithm, AlgorithmIdentifier encryptedKeyAlgorithm, byte[] encryptedEncryptionKey) throws CMSException { - JceAsymmetricKeyUnwrapper unwrapper = helper.createAsymmetricUnwrapper(keyEncryptionAlgorithm, recipientKey); + JceAsymmetricKeyUnwrapper unwrapper = helper.createAsymmetricUnwrapper(keyEncryptionAlgorithm, recipientKey).setMustProduceEncodableUnwrappedKey(unwrappedKeyMustBeEncodable); if (!extraMappings.isEmpty()) { diff --git a/bcpkix/src/main/java/org/bouncycastle/cms/jcajce/JcePasswordEnvelopedRecipient.java b/bcpkix/src/main/java/org/bouncycastle/cms/jcajce/JcePasswordEnvelopedRecipient.java index be741db4..5d478efc 100644 --- a/bcpkix/src/main/java/org/bouncycastle/cms/jcajce/JcePasswordEnvelopedRecipient.java +++ b/bcpkix/src/main/java/org/bouncycastle/cms/jcajce/JcePasswordEnvelopedRecipient.java @@ -4,11 +4,11 @@ import java.io.InputStream; import java.security.Key; import javax.crypto.Cipher; -import javax.crypto.CipherInputStream; import org.bouncycastle.asn1.x509.AlgorithmIdentifier; import org.bouncycastle.cms.CMSException; import org.bouncycastle.cms.RecipientOperator; +import org.bouncycastle.jcajce.io.CipherInputStream; import org.bouncycastle.operator.InputDecryptor; public class JcePasswordEnvelopedRecipient diff --git a/bcpkix/src/main/java/org/bouncycastle/cms/jcajce/JcePasswordRecipient.java b/bcpkix/src/main/java/org/bouncycastle/cms/jcajce/JcePasswordRecipient.java index 3c00b5ef..4875800a 100644 --- a/bcpkix/src/main/java/org/bouncycastle/cms/jcajce/JcePasswordRecipient.java +++ b/bcpkix/src/main/java/org/bouncycastle/cms/jcajce/JcePasswordRecipient.java @@ -9,12 +9,9 @@ import javax.crypto.spec.IvParameterSpec; import javax.crypto.spec.SecretKeySpec; import org.bouncycastle.asn1.ASN1OctetString; -import org.bouncycastle.asn1.pkcs.PBKDF2Params; import org.bouncycastle.asn1.x509.AlgorithmIdentifier; import org.bouncycastle.cms.CMSException; import org.bouncycastle.cms.PasswordRecipient; -import org.bouncycastle.crypto.generators.PKCS5S2ParametersGenerator; -import org.bouncycastle.crypto.params.KeyParameter; /** * the RecipientInfo class for a recipient who has been sent a message @@ -73,16 +70,10 @@ public abstract class JcePasswordRecipient } } - public byte[] calculateDerivedKey(byte[] encodedPassword, AlgorithmIdentifier derivationAlgorithm, int keySize) + public byte[] calculateDerivedKey(int schemeID, AlgorithmIdentifier derivationAlgorithm, int keySize) throws CMSException { - PBKDF2Params params = PBKDF2Params.getInstance(derivationAlgorithm.getParameters()); - - PKCS5S2ParametersGenerator gen = new PKCS5S2ParametersGenerator(); - - gen.init(encodedPassword, params.getSalt(), params.getIterationCount().intValue()); - - return ((KeyParameter)gen.generateDerivedParameters(keySize)).getKey(); + return helper.calculateDerivedKey(schemeID, password, derivationAlgorithm, keySize); } public int getPasswordConversionScheme() diff --git a/bcpkix/src/main/java/org/bouncycastle/cms/jcajce/JcePasswordRecipientInfoGenerator.java b/bcpkix/src/main/java/org/bouncycastle/cms/jcajce/JcePasswordRecipientInfoGenerator.java index fefe016e..94d8bbef 100644 --- a/bcpkix/src/main/java/org/bouncycastle/cms/jcajce/JcePasswordRecipientInfoGenerator.java +++ b/bcpkix/src/main/java/org/bouncycastle/cms/jcajce/JcePasswordRecipientInfoGenerator.java @@ -10,12 +10,9 @@ import javax.crypto.spec.SecretKeySpec; import org.bouncycastle.asn1.ASN1ObjectIdentifier; import org.bouncycastle.asn1.ASN1OctetString; -import org.bouncycastle.asn1.pkcs.PBKDF2Params; import org.bouncycastle.asn1.x509.AlgorithmIdentifier; import org.bouncycastle.cms.CMSException; import org.bouncycastle.cms.PasswordRecipientInfoGenerator; -import org.bouncycastle.crypto.generators.PKCS5S2ParametersGenerator; -import org.bouncycastle.crypto.params.KeyParameter; import org.bouncycastle.operator.GenericKey; public class JcePasswordRecipientInfoGenerator @@ -42,16 +39,10 @@ public class JcePasswordRecipientInfoGenerator return this; } - protected byte[] calculateDerivedKey(byte[] encodedPassword, AlgorithmIdentifier derivationAlgorithm, int keySize) + protected byte[] calculateDerivedKey(int schemeID, AlgorithmIdentifier derivationAlgorithm, int keySize) throws CMSException { - PBKDF2Params params = PBKDF2Params.getInstance(derivationAlgorithm.getParameters()); - - PKCS5S2ParametersGenerator gen = new PKCS5S2ParametersGenerator(); - - gen.init(encodedPassword, params.getSalt(), params.getIterationCount().intValue()); - - return ((KeyParameter)gen.generateDerivedParameters(keySize)).getKey(); + return helper.calculateDerivedKey(schemeID, password, derivationAlgorithm, keySize); } public byte[] generateEncryptedBytes(AlgorithmIdentifier keyEncryptionAlgorithm, byte[] derivedKey, GenericKey contentEncryptionKey) diff --git a/bcpkix/src/main/java/org/bouncycastle/cms/jcajce/NamedJcaJceExtHelper.java b/bcpkix/src/main/java/org/bouncycastle/cms/jcajce/NamedJcaJceExtHelper.java index fba72dc7..c6654306 100644 --- a/bcpkix/src/main/java/org/bouncycastle/cms/jcajce/NamedJcaJceExtHelper.java +++ b/bcpkix/src/main/java/org/bouncycastle/cms/jcajce/NamedJcaJceExtHelper.java @@ -8,6 +8,7 @@ import org.bouncycastle.asn1.x509.AlgorithmIdentifier; import org.bouncycastle.jcajce.util.NamedJcaJceHelper; import org.bouncycastle.operator.SymmetricKeyUnwrapper; import org.bouncycastle.operator.jcajce.JceAsymmetricKeyUnwrapper; +import org.bouncycastle.operator.jcajce.JceKTSKeyUnwrapper; import org.bouncycastle.operator.jcajce.JceSymmetricKeyUnwrapper; class NamedJcaJceExtHelper @@ -24,6 +25,11 @@ class NamedJcaJceExtHelper return new JceAsymmetricKeyUnwrapper(keyEncryptionAlgorithm, keyEncryptionKey).setProvider(providerName); } + public JceKTSKeyUnwrapper createAsymmetricUnwrapper(AlgorithmIdentifier keyEncryptionAlgorithm, PrivateKey keyEncryptionKey, byte[] partyUInfo, byte[] partyVInfo) + { + return new JceKTSKeyUnwrapper(keyEncryptionAlgorithm, keyEncryptionKey, partyUInfo, partyVInfo).setProvider(providerName); + } + public SymmetricKeyUnwrapper createSymmetricUnwrapper(AlgorithmIdentifier keyEncryptionAlgorithm, SecretKey keyEncryptionKey) { return new JceSymmetricKeyUnwrapper(keyEncryptionAlgorithm, keyEncryptionKey).setProvider(providerName); diff --git a/bcpkix/src/main/java/org/bouncycastle/cms/jcajce/ProviderJcaJceExtHelper.java b/bcpkix/src/main/java/org/bouncycastle/cms/jcajce/ProviderJcaJceExtHelper.java index f6991a89..f0e10221 100644 --- a/bcpkix/src/main/java/org/bouncycastle/cms/jcajce/ProviderJcaJceExtHelper.java +++ b/bcpkix/src/main/java/org/bouncycastle/cms/jcajce/ProviderJcaJceExtHelper.java @@ -9,6 +9,7 @@ import org.bouncycastle.asn1.x509.AlgorithmIdentifier; import org.bouncycastle.jcajce.util.ProviderJcaJceHelper; import org.bouncycastle.operator.SymmetricKeyUnwrapper; import org.bouncycastle.operator.jcajce.JceAsymmetricKeyUnwrapper; +import org.bouncycastle.operator.jcajce.JceKTSKeyUnwrapper; import org.bouncycastle.operator.jcajce.JceSymmetricKeyUnwrapper; class ProviderJcaJceExtHelper @@ -25,6 +26,11 @@ class ProviderJcaJceExtHelper return new JceAsymmetricKeyUnwrapper(keyEncryptionAlgorithm, keyEncryptionKey).setProvider(provider); } + public JceKTSKeyUnwrapper createAsymmetricUnwrapper(AlgorithmIdentifier keyEncryptionAlgorithm, PrivateKey keyEncryptionKey, byte[] partyUInfo, byte[] partyVInfo) + { + return new JceKTSKeyUnwrapper(keyEncryptionAlgorithm, keyEncryptionKey, partyUInfo, partyVInfo).setProvider(provider); + } + public SymmetricKeyUnwrapper createSymmetricUnwrapper(AlgorithmIdentifier keyEncryptionAlgorithm, SecretKey keyEncryptionKey) { return new JceSymmetricKeyUnwrapper(keyEncryptionAlgorithm, keyEncryptionKey).setProvider(provider); diff --git a/bcpkix/src/main/java/org/bouncycastle/cms/test/AllTests.java b/bcpkix/src/main/java/org/bouncycastle/cms/test/AllTests.java index 9cc2b0ec..4841d290 100644 --- a/bcpkix/src/main/java/org/bouncycastle/cms/test/AllTests.java +++ b/bcpkix/src/main/java/org/bouncycastle/cms/test/AllTests.java @@ -3,9 +3,11 @@ package org.bouncycastle.cms.test; import javax.crypto.Cipher; import junit.framework.Test; +import junit.framework.TestCase; import junit.framework.TestSuite; -public class AllTests +public class AllTests + extends TestCase { public static void main (String[] args) throws Exception diff --git a/bcpkix/src/main/java/org/bouncycastle/cms/test/BcEnvelopedDataTest.java b/bcpkix/src/main/java/org/bouncycastle/cms/test/BcEnvelopedDataTest.java index 366e9cb2..0495f4b1 100644 --- a/bcpkix/src/main/java/org/bouncycastle/cms/test/BcEnvelopedDataTest.java +++ b/bcpkix/src/main/java/org/bouncycastle/cms/test/BcEnvelopedDataTest.java @@ -23,11 +23,13 @@ import junit.framework.Test; import junit.framework.TestCase; import junit.framework.TestSuite; import org.bouncycastle.asn1.ASN1ObjectIdentifier; +import org.bouncycastle.asn1.ASN1Sequence; import org.bouncycastle.asn1.DEROctetString; import org.bouncycastle.asn1.DERSet; import org.bouncycastle.asn1.DERUTF8String; import org.bouncycastle.asn1.cms.Attribute; import org.bouncycastle.asn1.cms.AttributeTable; +import org.bouncycastle.asn1.misc.MiscObjectIdentifiers; import org.bouncycastle.asn1.nist.NISTObjectIdentifiers; import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers; import org.bouncycastle.asn1.pkcs.PrivateKeyInfo; @@ -486,6 +488,18 @@ public class BcEnvelopedDataTest } } + public void testKeyTransCAST5() + throws Exception + { + tryKeyTrans(CMSAlgorithm.CAST5_CBC, MiscObjectIdentifiers.cast5CBC, 16, ASN1Sequence.class); + } + + public void testKeyTransRC2() + throws Exception + { + tryKeyTrans(CMSAlgorithm.RC2_CBC, PKCSObjectIdentifiers.RC2_CBC, 16, ASN1Sequence.class); + } + public void testKeyTransAES128() throws Exception { diff --git a/bcpkix/src/main/java/org/bouncycastle/cms/test/CMSTestUtil.java b/bcpkix/src/main/java/org/bouncycastle/cms/test/CMSTestUtil.java index 3a1517af..01cccf33 100644 --- a/bcpkix/src/main/java/org/bouncycastle/cms/test/CMSTestUtil.java +++ b/bcpkix/src/main/java/org/bouncycastle/cms/test/CMSTestUtil.java @@ -18,6 +18,7 @@ import java.util.Date; import javax.crypto.KeyGenerator; import javax.crypto.SecretKey; +import javax.crypto.spec.DHParameterSpec; import org.bouncycastle.asn1.cryptopro.CryptoProObjectIdentifiers; import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers; @@ -54,6 +55,7 @@ public class CMSTestUtil public static KeyPairGenerator gostKpg; public static KeyPairGenerator dsaKpg; + public static KeyPairGenerator dhKpg; public static KeyPairGenerator ecGostKpg; public static KeyPairGenerator ecDsaKpg; public static KeyGenerator aes192kg; @@ -137,6 +139,9 @@ public class CMSTestUtil dsaKpg.initialize(dsaSpec, new SecureRandom()); + dhKpg = KeyPairGenerator.getInstance("DH", "BC"); + dhKpg.initialize(new DHParameterSpec(dsaSpec.getP(), dsaSpec.getG()), new SecureRandom()); + ecGostKpg = KeyPairGenerator.getInstance("ECGOST3410", "BC"); ecGostKpg.initialize(ECGOST3410NamedCurveTable.getParameterSpec("GostR3410-2001-CryptoPro-A"), new SecureRandom()); @@ -224,6 +229,11 @@ public class CMSTestUtil return ecDsaKpg.generateKeyPair(); } + public static KeyPair makeDhKeyPair() + { + return dhKpg.generateKeyPair(); + } + public static KeyPair makeEcGostKeyPair() { return ecGostKpg.generateKeyPair(); @@ -364,6 +374,46 @@ public class CMSTestUtil return _cert; } + public static X509Certificate makeCertificate(KeyPair subKP, String _subDN, KeyPair issKP, String _issDN, AlgorithmIdentifier keyAlgID) + throws GeneralSecurityException, IOException, OperatorCreationException + { + PrivateKey issPriv = issKP.getPrivate(); + PublicKey issPub = issKP.getPublic(); + SubjectPublicKeyInfo subPub = SubjectPublicKeyInfo.getInstance(subKP.getPublic().getEncoded()); + + 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(keyAlgID, 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(false)); + + X509Certificate _cert = new JcaX509CertificateConverter().setProvider("BC").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 { diff --git a/bcpkix/src/main/java/org/bouncycastle/cms/test/NewAuthenticatedDataTest.java b/bcpkix/src/main/java/org/bouncycastle/cms/test/NewAuthenticatedDataTest.java index 8d788b58..a0222d2b 100644 --- a/bcpkix/src/main/java/org/bouncycastle/cms/test/NewAuthenticatedDataTest.java +++ b/bcpkix/src/main/java/org/bouncycastle/cms/test/NewAuthenticatedDataTest.java @@ -11,12 +11,18 @@ import java.util.Iterator; import javax.crypto.SecretKey; +import junit.framework.Assert; import junit.framework.Test; import junit.framework.TestCase; import junit.framework.TestSuite; import org.bouncycastle.asn1.ASN1ObjectIdentifier; +import org.bouncycastle.asn1.DERNull; +import org.bouncycastle.asn1.cms.AuthenticatedData; +import org.bouncycastle.asn1.cms.CMSObjectIdentifiers; +import org.bouncycastle.asn1.cms.ContentInfo; import org.bouncycastle.asn1.oiw.OIWObjectIdentifiers; import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers; +import org.bouncycastle.asn1.teletrust.TeleTrusTObjectIdentifiers; import org.bouncycastle.asn1.x509.AlgorithmIdentifier; import org.bouncycastle.cert.X509CertificateHolder; import org.bouncycastle.cms.CMSAlgorithm; @@ -49,23 +55,23 @@ public class NewAuthenticatedDataTest { private static final String BC = BouncyCastleProvider.PROVIDER_NAME; - private static String _signDN; + private static String _signDN; private static KeyPair _signKP; private static X509Certificate _signCert; - private static String _origDN; - private static KeyPair _origKP; + private static String _origDN; + private static KeyPair _origKP; private static X509Certificate _origCert; - private static String _reciDN; - private static KeyPair _reciKP; + private static String _reciDN; + private static KeyPair _reciKP; private static X509Certificate _reciCert; - private static KeyPair _origEcKP; - private static KeyPair _reciEcKP; + private static KeyPair _origEcKP; + private static KeyPair _reciEcKP; private static X509Certificate _reciEcCert; - private static boolean _initialised = false; + private static boolean _initialised = false; public boolean DEBUG = true; @@ -77,16 +83,16 @@ public class NewAuthenticatedDataTest _initialised = true; Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider()); - _signDN = "O=Bouncy Castle, C=AU"; - _signKP = CMSTestUtil.makeKeyPair(); + _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(); + _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(); + _reciDN = "CN=Doug, OU=Sales, O=Bouncy Castle, C=AU"; + _reciKP = CMSTestUtil.makeKeyPair(); _reciCert = CMSTestUtil.makeCertificate(_reciKP, _reciDN, _signKP, _signDN); _origEcKP = CMSTestUtil.makeEcDsaKeyPair(); @@ -169,20 +175,20 @@ public class NewAuthenticatedDataTest adGen.addRecipientInfoGenerator(recipientGenerator); CMSAuthenticatedData ad = adGen.generate( - new CMSProcessableByteArray(data), - new JceCMSMacCalculatorBuilder(CMSAlgorithm.DES_EDE3_CBC).setProvider(BC).build()); + new CMSProcessableByteArray(data), + new JceCMSMacCalculatorBuilder(CMSAlgorithm.DES_EDE3_CBC).setProvider(BC).build()); - RecipientInformationStore recipients = ad.getRecipientInfos(); + RecipientInformationStore recipients = ad.getRecipientInfos(); assertEquals(ad.getMacAlgOID(), - CMSAuthenticatedDataGenerator.DES_EDE3_CBC); + CMSAuthenticatedDataGenerator.DES_EDE3_CBC); - Collection c = recipients.getRecipients(); - Iterator it = c.iterator(); + Collection c = recipients.getRecipients(); + Iterator it = c.iterator(); if (it.hasNext()) { - RecipientInformation recipient = (RecipientInformation)it.next(); + RecipientInformation recipient = (RecipientInformation)it.next(); byte[] recData = recipient.getContent(new JceKeyAgreeAuthenticatedRecipient(_reciEcKP.getPrivate()).setProvider(BC)); assertTrue(Arrays.equals(data, recData)); @@ -197,18 +203,18 @@ public class NewAuthenticatedDataTest public void testEncoding() throws Exception { - byte[] data = "Eric H. Echidna".getBytes(); + 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()); + 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()); @@ -235,7 +241,7 @@ public class NewAuthenticatedDataTest public void testOriginatorInfo() throws Exception { - byte[] data = "Eric H. Echidna".getBytes(); + byte[] data = "Eric H. Echidna".getBytes(); ASN1ObjectIdentifier macAlg = CMSAlgorithm.DES_EDE3_CBC; CMSAuthenticatedDataGenerator adGen = new CMSAuthenticatedDataGenerator(); @@ -247,8 +253,8 @@ public class NewAuthenticatedDataTest adGen.addRecipientInfoGenerator(new JceKeyTransRecipientInfoGenerator(_reciCert).setProvider(BC)); CMSAuthenticatedData ad = adGen.generate( - new CMSProcessableByteArray(data), - new JceCMSMacCalculatorBuilder(macAlg).setProvider(BC).build()); + new CMSProcessableByteArray(data), + new JceCMSMacCalculatorBuilder(macAlg).setProvider(BC).build()); assertTrue(ad.getOriginatorInfo().getCertificates().getMatches(null).contains(origCert)); @@ -275,18 +281,103 @@ public class NewAuthenticatedDataTest } } + public void testCMSAlgorithmProtection() + throws Exception + { + 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}; + SecretKey kek = CMSTestUtil.makeDesede192Key(); + + 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))); + + checkData(data, kek, ad); + + ContentInfo adInfo = ad.toASN1Structure(); + AuthenticatedData iAd = AuthenticatedData.getInstance(adInfo.getContent().toASN1Primitive().getEncoded()); + + try + { + new CMSAuthenticatedData(new ContentInfo(CMSObjectIdentifiers.authenticatedData, + new AuthenticatedData(iAd.getOriginatorInfo(), iAd.getRecipientInfos(), iAd.getMacAlgorithm(), new AlgorithmIdentifier(TeleTrusTObjectIdentifiers.ripemd160, DERNull.INSTANCE), iAd.getEncapsulatedContentInfo(), iAd.getAuthAttrs(), iAd.getMac(), iAd.getUnauthAttrs())), calcProvider); + } + catch (CMSException e) + { + Assert.assertEquals(e.getMessage(), "CMS Algorithm Identifier Protection check failed for digestAlgorithm"); + } + + AlgorithmIdentifier newDigAlgId = new AlgorithmIdentifier(OIWObjectIdentifiers.idSHA1, DERNull.INSTANCE); + Assert.assertFalse(iAd.getDigestAlgorithm().equals(newDigAlgId)); + checkData(data, kek, new CMSAuthenticatedData(new ContentInfo(CMSObjectIdentifiers.authenticatedData, + new AuthenticatedData(iAd.getOriginatorInfo(), iAd.getRecipientInfos(), iAd.getMacAlgorithm(), newDigAlgId, iAd.getEncapsulatedContentInfo(), iAd.getAuthAttrs(), iAd.getMac(), iAd.getUnauthAttrs())), calcProvider)); + + try + { + new CMSAuthenticatedData(new ContentInfo(CMSObjectIdentifiers.authenticatedData, + new AuthenticatedData(iAd.getOriginatorInfo(), iAd.getRecipientInfos(), new AlgorithmIdentifier(CMSAlgorithm.AES192_CBC), iAd.getDigestAlgorithm(), iAd.getEncapsulatedContentInfo(), iAd.getAuthAttrs(), iAd.getMac(), iAd.getUnauthAttrs())), calcProvider); + } + catch (CMSException e) + { + Assert.assertEquals(e.getMessage(), "CMS Algorithm Identifier Protection check failed for macAlgorithm"); + } + + try + { + AlgorithmIdentifier newMacAlgId = new AlgorithmIdentifier(CMSAlgorithm.DES_EDE3_CBC); + Assert.assertFalse(iAd.getMacAlgorithm().equals(newMacAlgId)); + new CMSAuthenticatedData(new ContentInfo(CMSObjectIdentifiers.authenticatedData, + new AuthenticatedData(iAd.getOriginatorInfo(), iAd.getRecipientInfos(), newMacAlgId, iAd.getDigestAlgorithm(), iAd.getEncapsulatedContentInfo(), iAd.getAuthAttrs(), iAd.getMac(), iAd.getUnauthAttrs())), calcProvider); + } + catch (CMSException e) + { + Assert.assertEquals(e.getMessage(), "CMS Algorithm Identifier Protection check failed for macAlgorithm"); + } + } + + private void checkData(byte[] data, SecretKey kek, CMSAuthenticatedData ad) + throws CMSException + { + RecipientInformationStore recipients = ad.getRecipientInfos(); + + Collection c = recipients.getRecipients(); + Iterator it = c.iterator(); + + if (it.hasNext()) + { + RecipientInformation recipient = (RecipientInformation)it.next(); + + 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 tryKeyTrans(ASN1ObjectIdentifier macAlg) throws Exception { - byte[] data = "Eric H. Echidna".getBytes(); + 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()); + new CMSProcessableByteArray(data), + new JceCMSMacCalculatorBuilder(macAlg).setProvider(BC).build()); RecipientInformationStore recipients = ad.getRecipientInfos(); @@ -314,7 +405,7 @@ public class NewAuthenticatedDataTest private void tryKeyTransWithDigest(ASN1ObjectIdentifier macAlg) throws Exception { - byte[] data = "Eric H. Echidna".getBytes(); + byte[] data = "Eric H. Echidna".getBytes(); CMSAuthenticatedDataGenerator adGen = new CMSAuthenticatedDataGenerator(); DigestCalculatorProvider calcProvider = new JcaDigestCalculatorProviderBuilder().setProvider(BC).build(); @@ -322,9 +413,9 @@ public class NewAuthenticatedDataTest 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))); + new CMSProcessableByteArray(data), + new JceCMSMacCalculatorBuilder(macAlg).setProvider(BC).build(), + calcProvider.get(new AlgorithmIdentifier(OIWObjectIdentifiers.idSHA1))); RecipientInformationStore recipients = ad.getRecipientInfos(); @@ -353,17 +444,17 @@ public class NewAuthenticatedDataTest private void tryKekAlgorithm(SecretKey kek, ASN1ObjectIdentifier algOid) throws NoSuchAlgorithmException, NoSuchProviderException, CMSException, OperatorCreationException { - byte[] data = "Eric H. Echidna".getBytes(); + byte[] data = "Eric H. Echidna".getBytes(); CMSAuthenticatedDataGenerator adGen = new CMSAuthenticatedDataGenerator(); - - byte[] kekId = new byte[] { 1, 2, 3, 4, 5 }; + + 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()); + new CMSProcessableByteArray(data), + new JceCMSMacCalculatorBuilder(CMSAlgorithm.DES_EDE3_CBC).setProvider(BC).build()); RecipientInformationStore recipients = ad.getRecipientInfos(); @@ -392,45 +483,44 @@ public class NewAuthenticatedDataTest private void tryKekAlgorithmWithDigest(SecretKey kek, ASN1ObjectIdentifier algOid) throws NoSuchAlgorithmException, NoSuchProviderException, CMSException, OperatorCreationException { - byte[] data = "Eric H. Echidna".getBytes(); + byte[] data = "Eric H. Echidna".getBytes(); - CMSAuthenticatedDataGenerator adGen = new CMSAuthenticatedDataGenerator(); - DigestCalculatorProvider calcProvider = new JcaDigestCalculatorProviderBuilder().setProvider(BC).build(); + CMSAuthenticatedDataGenerator adGen = new CMSAuthenticatedDataGenerator(); + DigestCalculatorProvider calcProvider = new JcaDigestCalculatorProviderBuilder().setProvider(BC).build(); - byte[] kekId = new byte[] { 1, 2, 3, 4, 5 }; + byte[] kekId = new byte[]{1, 2, 3, 4, 5}; - adGen.addRecipientInfoGenerator(new JceKEKRecipientInfoGenerator(kekId, kek).setProvider(BC)); + 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))); + 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(); + RecipientInformationStore recipients = ad.getRecipientInfos(); - Collection c = recipients.getRecipients(); - Iterator it = c.iterator(); + Collection c = recipients.getRecipients(); + Iterator it = c.iterator(); - assertEquals(ad.getMacAlgOID(), CMSAuthenticatedDataGenerator.DES_EDE3_CBC); + assertEquals(ad.getMacAlgOID(), CMSAuthenticatedDataGenerator.DES_EDE3_CBC); - if (it.hasNext()) - { - RecipientInformation recipient = (RecipientInformation)it.next(); + if (it.hasNext()) + { + RecipientInformation recipient = (RecipientInformation)it.next(); - assertEquals(recipient.getKeyEncryptionAlgOID(), algOid.getId()); + assertEquals(recipient.getKeyEncryptionAlgOID(), algOid.getId()); - byte[] recData = recipient.getContent(new JceKEKAuthenticatedRecipient(kek).setProvider(BC)); + 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"); - } + 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 @@ -442,16 +532,16 @@ public class NewAuthenticatedDataTest 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()); + new CMSProcessableByteArray(data), + new JceCMSMacCalculatorBuilder(CMSAlgorithm.DES_EDE3_CBC).setProvider(BC).build()); - RecipientInformationStore recipients = ad.getRecipientInfos(); + RecipientInformationStore recipients = ad.getRecipientInfos(); assertEquals(ad.getMacAlgOID(), - CMSAuthenticatedDataGenerator.DES_EDE3_CBC); + CMSAuthenticatedDataGenerator.DES_EDE3_CBC); - Collection c = recipients.getRecipients(); - Iterator it = c.iterator(); + Collection c = recipients.getRecipients(); + Iterator it = c.iterator(); if (it.hasNext()) { diff --git a/bcpkix/src/main/java/org/bouncycastle/cms/test/NewEnvelopedDataTest.java b/bcpkix/src/main/java/org/bouncycastle/cms/test/NewEnvelopedDataTest.java index f5f47ad3..310ee01d 100644 --- a/bcpkix/src/main/java/org/bouncycastle/cms/test/NewEnvelopedDataTest.java +++ b/bcpkix/src/main/java/org/bouncycastle/cms/test/NewEnvelopedDataTest.java @@ -1,9 +1,18 @@ package org.bouncycastle.cms.test; import java.io.IOException; -import java.security.*; +import java.io.InputStreamReader; +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.interfaces.ECPrivateKey; import java.security.spec.MGF1ParameterSpec; import java.security.spec.PKCS8EncodedKeySpec; import java.util.Arrays; @@ -16,6 +25,7 @@ import javax.crypto.spec.OAEPParameterSpec; import javax.crypto.spec.PSource; import javax.crypto.spec.SecretKeySpec; +import junit.framework.Assert; import junit.framework.Test; import junit.framework.TestCase; import junit.framework.TestSuite; @@ -23,10 +33,15 @@ import org.bouncycastle.asn1.ASN1InputStream; import org.bouncycastle.asn1.ASN1ObjectIdentifier; import org.bouncycastle.asn1.ASN1OctetString; import org.bouncycastle.asn1.ASN1Sequence; +import org.bouncycastle.asn1.DERNull; import org.bouncycastle.asn1.DEROctetString; import org.bouncycastle.asn1.DERSet; import org.bouncycastle.asn1.DERUTF8String; -import org.bouncycastle.asn1.cms.*; +import org.bouncycastle.asn1.cms.Attribute; +import org.bouncycastle.asn1.cms.AttributeTable; +import org.bouncycastle.asn1.cms.ContentInfo; +import org.bouncycastle.asn1.cms.EncryptedContentInfo; +import org.bouncycastle.asn1.cms.EnvelopedData; import org.bouncycastle.asn1.kisa.KISAObjectIdentifiers; import org.bouncycastle.asn1.nist.NISTObjectIdentifiers; import org.bouncycastle.asn1.ntt.NTTObjectIdentifiers; @@ -36,12 +51,14 @@ import org.bouncycastle.asn1.x500.X500Name; import org.bouncycastle.asn1.x509.AlgorithmIdentifier; import org.bouncycastle.asn1.x509.Extension; import org.bouncycastle.cert.X509CertificateHolder; +import org.bouncycastle.cert.jcajce.JcaX509CertificateConverter; import org.bouncycastle.cert.jcajce.JcaX509CertificateHolder; import org.bouncycastle.cms.CMSAlgorithm; import org.bouncycastle.cms.CMSEnvelopedData; import org.bouncycastle.cms.CMSEnvelopedDataGenerator; import org.bouncycastle.cms.CMSException; import org.bouncycastle.cms.CMSProcessableByteArray; +import org.bouncycastle.cms.KeyAgreeRecipientInformation; import org.bouncycastle.cms.KeyTransRecipientInformation; import org.bouncycastle.cms.OriginatorInfoGenerator; import org.bouncycastle.cms.OriginatorInformation; @@ -65,8 +82,11 @@ import org.bouncycastle.cms.jcajce.JceKeyTransRecipientInfoGenerator; import org.bouncycastle.cms.jcajce.JcePasswordEnvelopedRecipient; import org.bouncycastle.cms.jcajce.JcePasswordRecipientInfoGenerator; import org.bouncycastle.jce.provider.BouncyCastleProvider; +import org.bouncycastle.openssl.PEMKeyPair; +import org.bouncycastle.openssl.PEMParser; import org.bouncycastle.operator.OutputEncryptor; import org.bouncycastle.operator.jcajce.JcaAlgorithmParametersConverter; +import org.bouncycastle.util.Strings; import org.bouncycastle.util.encoders.Base64; import org.bouncycastle.util.encoders.Hex; @@ -95,6 +115,12 @@ public class NewEnvelopedDataTest private static X509Certificate _reciEcCert; private static KeyPair _reciEcKP2; private static X509Certificate _reciEcCert2; + private static KeyPair _reciKemsKP; + private static X509Certificate _reciKemsCert; + + private static KeyPair _origDhKP; + private static KeyPair _reciDhKP; + private static X509Certificate _reciDhCert; private static boolean _initialised = false; @@ -215,6 +241,12 @@ public class NewEnvelopedDataTest { } + public void setUp() + throws Exception + { + init(); + } + private static void init() throws Exception { @@ -242,6 +274,13 @@ public class NewEnvelopedDataTest _reciEcCert = CMSTestUtil.makeCertificate(_reciEcKP, _reciDN, _signKP, _signDN); _reciEcKP2 = CMSTestUtil.makeEcDsaKeyPair(); _reciEcCert2 = CMSTestUtil.makeCertificate(_reciEcKP2, _reciDN2, _signKP, _signDN); + + _origDhKP = CMSTestUtil.makeDhKeyPair(); + _reciDhKP = CMSTestUtil.makeDhKeyPair(); + _reciDhCert = CMSTestUtil.makeCertificate(_reciDhKP, _reciDN, _signKP, _signDN); + + _reciKemsKP = CMSTestUtil.makeKeyPair(); + _reciKemsCert = CMSTestUtil.makeCertificate(_reciKemsKP, _reciDN, _signKP, _signDN, new AlgorithmIdentifier(PKCSObjectIdentifiers.id_rsa_KEM)); } } @@ -311,6 +350,52 @@ public class NewEnvelopedDataTest } } + // TODO: add KEMS to provider. +// public void testRsaKEMS() +// throws Exception +// { +// byte[] data = "WallaWallaWashington".getBytes(); +// +// CMSEnvelopedDataGenerator edGen = new CMSEnvelopedDataGenerator(); +// +// edGen.addRecipientInfoGenerator(new JceKeyTransRecipientInfoGenerator(_reciKemsCert).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 testKeyTrans() throws Exception { @@ -1233,14 +1318,178 @@ public class NewEnvelopedDataTest confirmNumberRecipients(recipients, 1); } - public void testECMQVKeyAgree() + public void testFaultyAgreementRecipient() + throws Exception + { + ASN1ObjectIdentifier algorithm = CMSAlgorithm.ECDH_SHA1KDF; + byte[] data = Hex.decode("504b492d4320434d5320456e76656c6f706564446174612053616d706c65"); + + CMSEnvelopedDataGenerator edGen = new CMSEnvelopedDataGenerator(); + + edGen.addRecipientInfoGenerator(new JceKeyAgreeRecipientInfoGenerator(algorithm, + _origEcKP.getPrivate(), _origEcKP.getPublic(), + CMSAlgorithm.AES128_WRAP).setProvider(BC)); + + try + { + edGen.generate( + new CMSProcessableByteArray(data), + new JceCMSContentEncryptorBuilder(CMSAlgorithm.AES128_CBC).setProvider(BC).build()); + } + catch (CMSException e) + { + assertEquals(e.getMessage(), "No recipients associated with generator - use addRecipient()"); + } + } + + public void testKeyWrapAlgorithmIdentifiers() + throws Exception + { + byte[] data = Hex.decode("504b492d4320434d5320456e76656c6f706564446174612053616d706c65"); + + doVerifyKeyWrap(data, CMSAlgorithm.DES_EDE3_WRAP, false); + doVerifyKeyWrap(data, CMSAlgorithm.AES128_WRAP, true); + doVerifyKeyWrap(data, CMSAlgorithm.AES192_WRAP, true); + doVerifyKeyWrap(data, CMSAlgorithm.AES256_WRAP, true); + doVerifyKeyWrap(data, CMSAlgorithm.CAMELLIA128_WRAP, true); + doVerifyKeyWrap(data, CMSAlgorithm.CAMELLIA192_WRAP, true); + doVerifyKeyWrap(data, CMSAlgorithm.CAMELLIA256_WRAP, true); + doVerifyKeyWrap(data, CMSAlgorithm.SEED_WRAP, true); + } + + private void doVerifyKeyWrap(byte[] data, ASN1ObjectIdentifier wrapAlgorithm, boolean paramsAbsent) + throws CertificateEncodingException, CMSException, NoSuchProviderException, IOException + { + CMSEnvelopedDataGenerator edGen = new CMSEnvelopedDataGenerator(); + + edGen.addRecipientInfoGenerator(new JceKeyAgreeRecipientInfoGenerator(CMSAlgorithm.ECDH_SHA256KDF, + _origEcKP.getPrivate(), _origEcKP.getPublic(), + wrapAlgorithm).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(); + + KeyAgreeRecipientInformation recipientInformation = (KeyAgreeRecipientInformation)recipients.get(new JceKeyAgreeRecipientId(_reciEcCert)); + AlgorithmIdentifier keyWrapAlg = AlgorithmIdentifier.getInstance(recipientInformation.getKeyEncryptionAlgorithm().getParameters()); + + assertEquals(wrapAlgorithm, keyWrapAlg.getAlgorithm()); + if (paramsAbsent) + { + assertNull(keyWrapAlg.getParameters()); + } + else + { + assertNotNull(keyWrapAlg.getParameters()); + } + + assertEquals(ed.getEncryptionAlgOID(), CMSEnvelopedDataGenerator.AES128_CBC); + + confirmDataReceived(recipients, data, _reciEcCert, _reciEcKP.getPrivate(), BC); + confirmNumberRecipients(recipients, 1); + } + + public void testEphemeralStaticDHAgreement() + throws Exception + { + byte[] data = Hex.decode("504b492d4320434d5320456e76656c6f706564446174612053616d706c65"); + + CMSEnvelopedDataGenerator edGen = new CMSEnvelopedDataGenerator(); + + edGen.addRecipientInfoGenerator(new JceKeyAgreeRecipientInfoGenerator(PKCSObjectIdentifiers.id_alg_ESDH, + _origDhKP.getPrivate(), _origDhKP.getPublic(), + CMSAlgorithm.AES128_WRAP).addRecipient(_reciDhCert).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, _reciDhCert, _reciDhKP.getPrivate(), BC); + confirmNumberRecipients(recipients, 1); + } + + public void testStaticStaticDHAgreement() throws Exception { byte[] data = Hex.decode("504b492d4320434d5320456e76656c6f706564446174612053616d706c65"); CMSEnvelopedDataGenerator edGen = new CMSEnvelopedDataGenerator(); - edGen.addRecipientInfoGenerator(new JceKeyAgreeRecipientInfoGenerator(CMSAlgorithm.ECMQV_SHA1KDF, + edGen.addRecipientInfoGenerator(new JceKeyAgreeRecipientInfoGenerator(PKCSObjectIdentifiers.id_alg_SSDH, + _origDhKP.getPrivate(), _origDhKP.getPublic(), + CMSAlgorithm.AES128_WRAP) + .setUserKeyingMaterial(data) + .addRecipient(_reciDhCert) + .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, _reciDhCert, _reciDhKP.getPrivate(), BC); + confirmNumberRecipients(recipients, 1); + + try + { + edGen = new CMSEnvelopedDataGenerator(); + + edGen.addRecipientInfoGenerator(new JceKeyAgreeRecipientInfoGenerator(PKCSObjectIdentifiers.id_alg_SSDH, + _origDhKP.getPrivate(), _origDhKP.getPublic(), + CMSAlgorithm.AES128_WRAP).addRecipient(_reciDhCert).setProvider(BC)); + + edGen.generate( + new CMSProcessableByteArray(data), + new JceCMSContentEncryptorBuilder(CMSAlgorithm.AES128_CBC).setProvider(BC).build()); + fail("no UKM uncaught"); + } + catch (CMSException e) + { + Assert.assertEquals("User keying material must be set for static keys.", e.getMessage()); + } + } + + public void testKDFAgreements() + throws Exception + { + byte[] data = Hex.decode("504b492d4320434d5320456e76656c6f706564446174612053616d706c65"); + + doTryAgreement(data, CMSAlgorithm.ECDH_SHA1KDF); + doTryAgreement(data, CMSAlgorithm.ECDH_SHA224KDF); + doTryAgreement(data, CMSAlgorithm.ECDH_SHA256KDF); + doTryAgreement(data, CMSAlgorithm.ECDH_SHA384KDF); + doTryAgreement(data, CMSAlgorithm.ECDH_SHA512KDF); + + doTryAgreement(data, CMSAlgorithm.ECCDH_SHA1KDF); + doTryAgreement(data, CMSAlgorithm.ECCDH_SHA224KDF); + doTryAgreement(data, CMSAlgorithm.ECCDH_SHA256KDF); + doTryAgreement(data, CMSAlgorithm.ECCDH_SHA384KDF); + doTryAgreement(data, CMSAlgorithm.ECCDH_SHA512KDF); + + doTryAgreement(data, CMSAlgorithm.ECMQV_SHA1KDF); + doTryAgreement(data, CMSAlgorithm.ECMQV_SHA224KDF); + doTryAgreement(data, CMSAlgorithm.ECMQV_SHA256KDF); + doTryAgreement(data, CMSAlgorithm.ECMQV_SHA384KDF); + doTryAgreement(data, CMSAlgorithm.ECMQV_SHA512KDF); + } + + private void doTryAgreement(byte[] data, ASN1ObjectIdentifier algorithm) + throws CertificateEncodingException, CMSException, NoSuchProviderException, IOException + { + CMSEnvelopedDataGenerator edGen = new CMSEnvelopedDataGenerator(); + + edGen.addRecipientInfoGenerator(new JceKeyAgreeRecipientInfoGenerator(algorithm, _origEcKP.getPrivate(), _origEcKP.getPublic(), CMSAlgorithm.AES128_WRAP).addRecipient(_reciEcCert).setProvider(BC)); @@ -1420,6 +1669,61 @@ public class NewEnvelopedDataTest assertEquals(CMSEnvelopedDataGenerator.DES_EDE3_CBC, env.getEncryptionAlgOID()); } + public void testOpenSSLVectors() + throws Exception + { + byte[] expected = Strings.toByteArray("abcdefghijklmnopqrstuvwxyz0123456789\r\n"); + + PEMParser pemParser = new PEMParser(new InputStreamReader(getClass().getResourceAsStream("ecdh/ecc.key"))); + + pemParser.readObject(); // skip the curve definition + + PEMKeyPair kp = (PEMKeyPair)pemParser.readObject(); + + KeyFactory keyFactory = KeyFactory.getInstance("EC", "BC"); + + ECPrivateKey ecKey = (ECPrivateKey)keyFactory.generatePrivate(new PKCS8EncodedKeySpec(kp.getPrivateKeyInfo().getEncoded())); + + pemParser = new PEMParser(new InputStreamReader(getClass().getResourceAsStream("ecdh/ecc.crt"))); + + X509Certificate x509Certificate = new JcaX509CertificateConverter().setProvider("BC").getCertificate((X509CertificateHolder)pemParser.readObject()); + + processInput(ecKey, expected, "ecdh/encSess1.asc", new AlgorithmIdentifier(PKCSObjectIdentifiers.id_alg_CMS3DESwrap, DERNull.INSTANCE)); + processInput(ecKey, expected, "ecdh/encSess2.asc", new AlgorithmIdentifier(PKCSObjectIdentifiers.id_alg_CMS3DESwrap, DERNull.INSTANCE)); + processInput(ecKey, expected, "ecdh/encSess3.asc", new AlgorithmIdentifier(CMSAlgorithm.AES128_WRAP, DERNull.INSTANCE)); + processInput(ecKey, expected, "ecdh/encSess4.asc", new AlgorithmIdentifier(CMSAlgorithm.AES128_WRAP, DERNull.INSTANCE)); + processInput(ecKey, expected, "ecdh/encSess5.asc", new AlgorithmIdentifier(CMSAlgorithm.AES192_WRAP, DERNull.INSTANCE)); + processInput(ecKey, expected, "ecdh/encSess6.asc", new AlgorithmIdentifier(CMSAlgorithm.AES192_WRAP, DERNull.INSTANCE)); + processInput(ecKey, expected, "ecdh/encSess7.asc", new AlgorithmIdentifier(CMSAlgorithm.AES256_WRAP, DERNull.INSTANCE)); + processInput(ecKey, expected, "ecdh/encSess8.asc", new AlgorithmIdentifier(CMSAlgorithm.AES256_WRAP, DERNull.INSTANCE)); + + processInput(ecKey, expected, "ecdh/encSessA.asc", new AlgorithmIdentifier(PKCSObjectIdentifiers.id_alg_CMS3DESwrap, DERNull.INSTANCE)); + processInput(ecKey, expected, "ecdh/encSessB.asc", new AlgorithmIdentifier(PKCSObjectIdentifiers.id_alg_CMS3DESwrap, DERNull.INSTANCE)); + processInput(ecKey, expected, "ecdh/encSessC.asc", new AlgorithmIdentifier(CMSAlgorithm.AES128_WRAP)); + processInput(ecKey, expected, "ecdh/encSessD.asc", new AlgorithmIdentifier(CMSAlgorithm.AES128_WRAP)); + processInput(ecKey, expected, "ecdh/encSessE.asc", new AlgorithmIdentifier(CMSAlgorithm.AES192_WRAP)); + processInput(ecKey, expected, "ecdh/encSessF.asc", new AlgorithmIdentifier(CMSAlgorithm.AES192_WRAP)); + processInput(ecKey, expected, "ecdh/encSessG.asc", new AlgorithmIdentifier(CMSAlgorithm.AES256_WRAP)); + processInput(ecKey, expected, "ecdh/encSessH.asc", new AlgorithmIdentifier(CMSAlgorithm.AES256_WRAP)); + } + + private void processInput(ECPrivateKey ecKey, byte[] expected, String input, AlgorithmIdentifier wrapAlg) + throws CMSException, IOException + { + PEMParser pemParser; + pemParser = new PEMParser(new InputStreamReader(getClass().getResourceAsStream(input))); + + CMSEnvelopedData envData = new CMSEnvelopedData((ContentInfo)pemParser.readObject()); + + KeyAgreeRecipientInformation recip = (KeyAgreeRecipientInformation)envData.getRecipientInfos().getRecipients().iterator().next(); + + TestCase.assertEquals(wrapAlg, AlgorithmIdentifier.getInstance(recip.getKeyEncryptionAlgorithm().getParameters())); + + byte[] decrypted = recip.getContent(new JceKeyAgreeEnvelopedRecipient(ecKey).setProvider("BC")); + + TestCase.assertTrue(Arrays.equals(expected, decrypted)); + } + private void passwordTest(String algorithm) throws Exception { diff --git a/bcpkix/src/main/java/org/bouncycastle/cms/test/NewSignedDataStreamTest.java b/bcpkix/src/main/java/org/bouncycastle/cms/test/NewSignedDataStreamTest.java index 8a92caeb..fcd1266a 100644 --- a/bcpkix/src/main/java/org/bouncycastle/cms/test/NewSignedDataStreamTest.java +++ b/bcpkix/src/main/java/org/bouncycastle/cms/test/NewSignedDataStreamTest.java @@ -3,6 +3,7 @@ package org.bouncycastle.cms.test; import java.io.BufferedOutputStream; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; +import java.io.IOException; import java.io.OutputStream; import java.security.KeyPair; import java.security.MessageDigest; @@ -12,10 +13,12 @@ import java.security.cert.X509Certificate; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; +import java.util.HashSet; import java.util.Hashtable; import java.util.Iterator; import java.util.List; import java.util.Map; +import java.util.Set; import junit.framework.Test; import junit.framework.TestCase; @@ -58,6 +61,7 @@ import org.bouncycastle.operator.jcajce.JcaDigestCalculatorProviderBuilder; import org.bouncycastle.util.CollectionStore; import org.bouncycastle.util.Store; import org.bouncycastle.util.encoders.Base64; +import org.bouncycastle.util.io.Streams; public class NewSignedDataStreamTest extends TestCase @@ -124,7 +128,13 @@ public class NewSignedDataStreamTest { super(name); } - + + public void setUp() + throws Exception + { + init(); + } + private static void init() throws Exception { @@ -163,7 +173,11 @@ public class NewSignedDataStreamTest Store certStore = sp.getCertificates(); Store crlStore = sp.getCRLs(); SignerInformationStore signers = sp.getSignerInfos(); - + + Set digestIDs = new HashSet(sp.getDigestAlgorithmIDs()); + + assertTrue(digestIDs.size() > 0); + Collection c = signers.getSigners(); Iterator it = c.iterator(); @@ -176,13 +190,16 @@ public class NewSignedDataStreamTest X509CertificateHolder cert = (X509CertificateHolder)certIt.next(); assertEquals(true, signer.verify(new JcaSimpleSignerInfoVerifierBuilder().setProvider(BC).build(cert))); - + + digestIDs.remove(signer.getDigestAlgorithmID()); + if (contentDigest != null) { assertTrue(MessageDigest.isEqual(contentDigest, signer.getContentDigest())); } } + assertTrue(digestIDs.size() == 0); assertEquals(certStore.getMatches(null).size(), sp.getCertificates().getMatches(null).size()); assertEquals(crlStore.getMatches(null).size(), sp.getCRLs().getMatches(null).size()); } @@ -222,40 +239,6 @@ public class NewSignedDataStreamTest 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 { @@ -976,13 +959,13 @@ public class NewSignedDataStreamTest assertEquals(4, sp.getVersion()); -// store = sp.getAttributeCertificates(); -// -// Collection coll = store.getMatches(null); -// -// assertEquals(1, coll.size()); -// -// assertTrue(coll.contains(new JcaX509AttributeCertificateHolder(attrCert))); + store = sp.getAttributeCertificates(); + + Collection coll = store.getMatches(null); + + assertEquals(1, coll.size()); + + assertTrue(coll.contains(attrCert)); } public void testSignerStoreReplacement() @@ -1301,6 +1284,39 @@ public class NewSignedDataStreamTest checkSigParseable(bOut.toByteArray()); } + public void testMSPKCS7() + throws Exception + { + byte[] data = getInput("SignedMSPkcs7.sig"); + + CMSSignedDataParser sp = new CMSSignedDataParser(new JcaDigestCalculatorProviderBuilder().setProvider("BC").build(), data); + + sp.getSignedContent().drain(); + + 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("BC").build(cert))); + } + } + + private byte[] getInput(String name) + throws IOException + { + return Streams.readAll(getClass().getResourceAsStream(name)); + } + public static Test suite() throws Exception { diff --git a/bcpkix/src/main/java/org/bouncycastle/cms/test/NewSignedDataTest.java b/bcpkix/src/main/java/org/bouncycastle/cms/test/NewSignedDataTest.java index 290449e3..9d6e0186 100644 --- a/bcpkix/src/main/java/org/bouncycastle/cms/test/NewSignedDataTest.java +++ b/bcpkix/src/main/java/org/bouncycastle/cms/test/NewSignedDataTest.java @@ -14,17 +14,23 @@ import java.security.spec.X509EncodedKeySpec; import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; +import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Map; +import java.util.Set; import junit.framework.Test; import junit.framework.TestCase; import junit.framework.TestSuite; import org.bouncycastle.asn1.ASN1EncodableVector; +import org.bouncycastle.asn1.ASN1Encoding; import org.bouncycastle.asn1.ASN1InputStream; import org.bouncycastle.asn1.ASN1ObjectIdentifier; import org.bouncycastle.asn1.ASN1OctetString; +import org.bouncycastle.asn1.ASN1Primitive; +import org.bouncycastle.asn1.DERApplicationSpecific; +import org.bouncycastle.asn1.DERNull; import org.bouncycastle.asn1.DEROctetString; import org.bouncycastle.asn1.DERSet; import org.bouncycastle.asn1.cms.Attribute; @@ -32,8 +38,11 @@ import org.bouncycastle.asn1.cms.AttributeTable; import org.bouncycastle.asn1.cms.CMSAttributes; import org.bouncycastle.asn1.cms.CMSObjectIdentifiers; import org.bouncycastle.asn1.cms.ContentInfo; +import org.bouncycastle.asn1.cms.SignedData; +import org.bouncycastle.asn1.cms.SignerInfo; import org.bouncycastle.asn1.ocsp.OCSPResponse; import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers; +import org.bouncycastle.asn1.teletrust.TeleTrusTObjectIdentifiers; import org.bouncycastle.asn1.x509.AlgorithmIdentifier; import org.bouncycastle.cert.X509AttributeCertificateHolder; import org.bouncycastle.cert.X509CertificateHolder; @@ -45,6 +54,7 @@ import org.bouncycastle.cert.jcajce.JcaX509CertificateHolder; import org.bouncycastle.cert.ocsp.OCSPResp; import org.bouncycastle.cms.CMSAbsentContent; import org.bouncycastle.cms.CMSAlgorithm; +import org.bouncycastle.cms.CMSException; import org.bouncycastle.cms.CMSProcessableByteArray; import org.bouncycastle.cms.CMSSignedData; import org.bouncycastle.cms.CMSSignedDataGenerator; @@ -63,9 +73,7 @@ import org.bouncycastle.cms.jcajce.JcaSignerId; import org.bouncycastle.cms.jcajce.JcaSignerInfoGeneratorBuilder; import org.bouncycastle.cms.jcajce.JcaSimpleSignerInfoGeneratorBuilder; import org.bouncycastle.cms.jcajce.JcaSimpleSignerInfoVerifierBuilder; -import org.bouncycastle.crypto.Signer; import org.bouncycastle.crypto.params.AsymmetricKeyParameter; -import org.bouncycastle.crypto.tls.SignatureAndHashAlgorithm; import org.bouncycastle.crypto.util.PrivateKeyFactory; import org.bouncycastle.jce.provider.BouncyCastleProvider; import org.bouncycastle.operator.ContentSigner; @@ -513,6 +521,48 @@ public class NewSignedDataTest + "KWleklnIImS3zqiPrq6tl2Bm8DZj7vXlTOwmraSQxUwzCKwYob1yGvNOUQTq" + "pG6jxn7jgDawHU1+WjWQe4Q34/pWeGLysxTraMa+Ug9kPe+jy/qRX2xwvKBZ"); + private static byte[] mixedSignedData = Base64.decode( + "d4IHBDCCBwAGCSqGSIb3DQEHAqCCBvEwggbtAgEDMQ8wDQYJYIZIAWUDBAID" + + "BQAwgbcGCSqEEAGHbgEUAaCBqQSBpjCBowIBADANBglghkgBZQMEAgMFADCB" + + "jjBFAgEBBEBIqiDnc0uJgjc1nZX/CyEaB3/j3fbR5Pjxs2/jSQhBy71N0Oh9" + + "i5+ZbfvoeUjHeMz0Q4m71H6XuoCIlsQJOor0MEUCAQIEQHhPBcHkCK5QugOE" + + "1GPQN/oRNpKlAp1l6Lr/LvSewiKbnWRKT2o3GmIZwuFflzblyiKZwxV+c8kj" + + "i4oQmOEhQvSgggQKMIIEBjCCAm6gAwIBAgIBPTANBgkqhkiG9w0BAQsFADBw" + + "MQswCQYDVQQGEwJQTDESMBAGA1UECgwJSUNBTyBDU0NBMQ4wDAYDVQQLDAVN" + + "U1dpQTE9MDsGA1UEAww0U3lzdGVtIFd5ZGF3YW5pYSBQYXN6cG9ydMOzdyB6" + + "IERhbnltaSBCaW9tZXRyeWN6bnltaTAeFw0wNzAzMjcwOTA4MDlaFw0xODAz" + + "MjYyMzU5NTlaMFoxCzAJBgNVBAYTAlBMMRIwEAYDVQQKDAlJQ0FPIENTQ0Ex" + + "ITAfBgNVBAsMGFBhc3Nwb3J0IERvY3VtZW50IFNpZ25lcjEUMBIGA1UEAwwL" + + "Q1BEIE1TV0lBXzgwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCP" + + "IvVr66gZQUpLVLxwMedLZMkYqUFhR+qxrDjGYJgy0fVYvds8u6QF+WyLRvGQ" + + "BJGjZ+hqXiDVtM2+ljmZm4C4wpDfZVE1e5w6lv8pKctnr1ZTorI0GsbdWIgi" + + "oi21WIRdpY9Rwc6gxjVLVlhwqNGhp9NRS2RDnoqy5iCLWXQ7BzlvuALqK0E1" + + "e/k96j3kCQ4SOES1fOreR6chFxOfhSrlo5ed6+z+YiM+rErtKAHZtYTUS6qk" + + "uC5SMEMDchbPd6eoYJtN5g0IEyyREm9EdLSK38L2Ln29hnVPqlMJ3ewfIRG9" + + "+LZ0mv3Bno9yle56tT9Vt2OBZs2MAOsFZQ66Q7+3AgMBAAGjQTA/MA4GA1Ud" + + "DwEB/wQEAwIHgDAMBgNVHRMBAf8EAjAAMB8GA1UdIwQYMBaAFEdS9KeSt+Ls" + + "eDNSRSjve8QVpj2WMA0GCSqGSIb3DQEBCwUAA4IBgQA7NXSJWoYIuRJANJVR" + + "+DhsvA/NOIE0c4W++xUZVY+2/abKXU7AJHdzI4pS6AOtYav2JxOnISITi3D6" + + "s453T/Z0gwRY6p1kUjXtHiVj6iCIal8DCYB0voAZrKl1rZWyINiMKjugNGyy" + + "vD6RHMuoKer07uKkgmusV23FIZaCQTPsP6sb2N5QDmfIp5lywJ+rMpJKXKoY" + + "Dtu7Aouhveg7DgOpUvIKFdc4eY1MYAzPTD8w2vTGTDuNjaL5cZD2HHvYl9i+" + + "vhD99nQWTbKStVI6Q0C2Dw3oFONKkH5O7L5bD38C6x9EBW5nGOWrSs+yP9Q1" + + "FNEE49snnayvctrRga2qRBK9av8c406GyFOGfnJcl82cl9KWkLGf8aIfnSzq" + + "FnhkDHKd9KocRX+dRFdBB5uxC0zm/XtIqB1TbTx3J88O5Ool55zFw0ECz/NX" + + "ecpKwk42uKOEOUcN4Etx09OuSn2+WU2ngW/CHc/T5kS3U61U5vsoTVJT3uTS" + + "1uRRYzcMcDc8+kwxggINMIICCQIBATB1MHAxCzAJBgNVBAYTAlBMMRIwEAYD" + + "VQQKDAlJQ0FPIENTQ0ExDjAMBgNVBAsMBU1TV2lBMT0wOwYDVQQDDDRTeXN0" + + "ZW0gV3lkYXdhbmlhIFBhc3pwb3J0w7N3IHogRGFueW1pIEJpb21ldHJ5Y3pu" + + "eW1pAgE9MA0GCWCGSAFlAwQCAwUAoGswGAYJKoZIhvcNAQkDMQsGCSqEEAGH" + + "bgEUATBPBgkqhkiG9w0BCQQxQgRAc6WCN4gqBWPSabO9SgkLfD2hTZeYU+cQ" + + "vbMeZW/em0v4/r0ggaustPjLW1Qmx8QWnfMHgEuojCVpyPLOYEBpZzANBgkq" + + "hkiG9w0BAQUFAASCAQAQBbSJOZFDx7uU2sQE1zkB5Vvds329kO+NY7ueWnGN" + + "a5GaIs2ri1g1xZSDsz+QWRoT4sIIV5CmiWx6lPHxWv3be1xtfVux9KqRZgEy" + + "xPQdANyDHaqqJr01ROQuKUJfqVSqiGe4/Udd0nFcBT9DyQWLn3HinOriEZga" + + "HxxN0ZjpoIEiPa+NIth1W+W3Z7yt4JUM/zX0iyhza/bPHbPOLrsXZAhGy/qn" + + "/JNmKBiVxuxZYYHI20CZHrgjb+ARczWuOJuBVEGEgbW/t7hMVX8X+MPAzZek" + + "Ndi9ZfkurEeYdDpGluYBH910/P95ibG8nrJyTaoxhmOJhJ/o/SO54m8oDlI0"); + public NewSignedDataTest(String name) { super(name); @@ -539,6 +589,12 @@ public class NewSignedDataTest return new CMSTestSetup(new TestSuite(NewSignedDataTest.class)); } + public void setUp() + throws Exception + { + init(); + } + private static void init() throws Exception { @@ -941,10 +997,115 @@ public class NewSignedDataTest // compute expected content digest // + assertTrue(s.isDetachedSignature()); + assertFalse(s.isCertificateManagementMessage()); + verifySignatures(s, md.digest("Hello world!".getBytes())); verifyRSASignatures(s, md.digest("Hello world!".getBytes())); } + public void testCMSAlgorithmProtection() + 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); + + gen.addSignerInfoGenerator(builder.build("SHA1withRSA", _origKP.getPrivate(), _origCert)); + + gen.addCertificates(certs); + + CMSSignedData s = gen.generate(msg, true); + + s = new CMSSignedData(s.getEncoded()); + + assertFalse(s.isDetachedSignature()); + assertFalse(s.isCertificateManagementMessage()); + + verifySignatures(s, true, null); + + // tamper, change signerInfo message digest + ContentInfo cI = s.toASN1Structure(); + SignedData sd = SignedData.getInstance(cI.getContent()); + SignerInfo sI = SignerInfo.getInstance(sd.getSignerInfos().getObjectAt(0)); + + SignerInfo sInew = new SignerInfo(sI.getSID(), new AlgorithmIdentifier(TeleTrusTObjectIdentifiers.ripemd128, DERNull.INSTANCE), sI.getAuthenticatedAttributes(), sI.getDigestEncryptionAlgorithm(), sI.getEncryptedDigest(), sI.getUnauthenticatedAttributes()); + + verifySignatures(getCorruptedSignedData(sd, sInew), false, "CMS Algorithm Identifier Protection check failed for digestAlgorithm"); + + sInew = new SignerInfo(sI.getSID(), sI.getDigestAlgorithm(), sI.getAuthenticatedAttributes(), new AlgorithmIdentifier(PKCSObjectIdentifiers.id_RSASSA_PSS), sI.getEncryptedDigest(), sI.getUnauthenticatedAttributes()); + + verifySignatures(getCorruptedSignedData(sd, sInew), false, "CMS Algorithm Identifier Protection check failed for signatureAlgorithm"); + + // check equivalence + AlgorithmIdentifier newAlgId = new AlgorithmIdentifier(sI.getDigestAlgorithm().getAlgorithm()); + assertFalse(newAlgId.equals(sI.getDigestAlgorithm())); + + sInew = new SignerInfo(sI.getSID(), newAlgId, sI.getAuthenticatedAttributes(), sI.getDigestEncryptionAlgorithm(), sI.getEncryptedDigest(), sI.getUnauthenticatedAttributes()); + + verifySignatures(getCorruptedSignedData(sd, sInew), true, null); + + newAlgId = new AlgorithmIdentifier(sI.getDigestEncryptionAlgorithm().getAlgorithm()); + assertFalse(newAlgId.equals(sI.getDigestEncryptionAlgorithm())); + + sInew = new SignerInfo(sI.getSID(), sI.getDigestAlgorithm(), sI.getAuthenticatedAttributes(), newAlgId, sI.getEncryptedDigest(), sI.getUnauthenticatedAttributes()); + + verifySignatures(getCorruptedSignedData(sd, sInew), true, null); + } + + private CMSSignedData getCorruptedSignedData(SignedData sd, SignerInfo sI) + throws CMSException + { + return new CMSSignedData(new ContentInfo(CMSObjectIdentifiers.signedData, new SignedData(sd.getDigestAlgorithms(), sd.getEncapContentInfo(), sd.getCertificates(), sd.getCRLs(), new DERSet(sI)))); + } + + private void verifySignatures(CMSSignedData s, boolean shouldPass, String message) + 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(); + + if (shouldPass) + { + assertEquals(true, signer.verify(new JcaSimpleSignerInfoVerifierBuilder().setProvider(BC).build(cert))); + } + else + { + try + { + assertEquals(false, signer.verify(new JcaSimpleSignerInfoVerifierBuilder().setProvider(BC).build(cert))); + if (message != null) + { + fail("No exception thrown"); + } + } + catch (CMSException e) + { + assertEquals(message, e.getMessage()); + } + } + } + } + public void testSHA1WithRSAAndAttributeTable() throws Exception { @@ -992,6 +1153,97 @@ public class NewSignedDataTest verifyRSASignatures(s, md.digest("Hello world!".getBytes())); } + public void testSignerInformationExtension() + 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(); + + 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); + + CMSSignedData s = gen.generate(msg, true); + + // + // the signature is detached, so need to add msg before passing on + // + s = new CMSSignedData(msg, s.getEncoded()); + + 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(); + + SignerInformationVerifier verifier = new JcaSimpleSignerInfoVerifierBuilder().setProvider(BC).build(cert); + + assertEquals(false, new MyWrongSignerInformation(signer).verify(verifier)); + + MyRightSignerInformation rSigner = new MyRightSignerInformation(signer); + + assertTrue(rSigner.verify(verifier)); + assertTrue(rSigner.isUsed()); + } + } + + private class MyWrongSignerInformation + extends SignerInformation + { + protected MyWrongSignerInformation(SignerInformation baseInfo) + { + super(baseInfo); + } + + public byte[] getEncodedSignedAttributes() + throws IOException + { + return new byte[signedAttributeSet.getEncoded(ASN1Encoding.DL).length]; + } + } + + private class MyRightSignerInformation + extends SignerInformation + { + private boolean used; + + protected MyRightSignerInformation(SignerInformation baseInfo) + { + super(baseInfo); + } + + boolean isUsed() + { + return used; + } + + public byte[] getEncodedSignedAttributes() + throws IOException + { + used = true; + return signedAttributeSet.getEncoded(ASN1Encoding.DL); + } + } + public void testLwSHA1WithRSAAndAttributeTable() throws Exception { @@ -1495,6 +1747,7 @@ public class NewSignedDataTest gen.addSignerInfoGenerator(new JcaSignerInfoGeneratorBuilder(new JcaDigestCalculatorProviderBuilder().setProvider(BC).build()).build(contentSigner, signatureCert)); + gen.addCertificates(certs); CMSSignedData s = gen.generate(msg, true); @@ -1503,7 +1756,11 @@ public class NewSignedDataTest ASN1InputStream aIn = new ASN1InputStream(bIn); s = new CMSSignedData(ContentInfo.getInstance(aIn.readObject())); - + + Set digestAlgorithms = new HashSet(s.getDigestAlgorithmIDs()); + + assertTrue(digestAlgorithms.size() > 0); + certs = s.getCertificates(); SignerInformationStore signers = s.getSignerInfos(); @@ -1517,10 +1774,14 @@ public class NewSignedDataTest Iterator certIt = certCollection.iterator(); X509CertificateHolder cert = (X509CertificateHolder)certIt.next(); - + + digestAlgorithms.remove(signer.getDigestAlgorithmID()); + assertEquals(true, signer.verify(new JcaSimpleSignerInfoVerifierBuilder().setProvider(BC).build(cert))); } + assertTrue(digestAlgorithms.size() == 0); + // // check signer information lookup // @@ -2005,9 +2266,98 @@ public class NewSignedDataTest CMSSignedData rsData = new CMSSignedData(sData.getEncoded()); + assertTrue(sData.isCertificateManagementMessage()); + assertFalse(sData.isDetachedSignature()); + assertEquals(2, rsData.getCertificates().getMatches(null).size()); } + public void testMixed() + throws Exception + { + DERApplicationSpecific derApplicationSpecific = (DERApplicationSpecific)ASN1Primitive.fromByteArray(mixedSignedData); + + CMSSignedData s = new CMSSignedData(new ByteArrayInputStream(derApplicationSpecific.getContents())); + + 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 testMSPKCS7() + throws Exception + { + byte[] data = getInput("SignedMSPkcs7.sig"); + + CMSSignedData sData = new CMSSignedData(data); + + Store certStore = sData.getCertificates(); + SignerInformationStore signers = sData.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))); + } + + // try generation from it. + 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 local = gen.generate(sData.getSignedContent(), true); + + certStore = local.getCertificates(); + signers = local.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))); + } + } + private void testSample(String sigName) throws Exception { diff --git a/bcpkix/src/main/java/org/bouncycastle/dvcs/CCPDRequestBuilder.java b/bcpkix/src/main/java/org/bouncycastle/dvcs/CCPDRequestBuilder.java index d8ed653a..2f59a9e2 100644 --- a/bcpkix/src/main/java/org/bouncycastle/dvcs/CCPDRequestBuilder.java +++ b/bcpkix/src/main/java/org/bouncycastle/dvcs/CCPDRequestBuilder.java @@ -19,8 +19,8 @@ public class CCPDRequestBuilder * Builds CCPD request. * * @param messageImprint - the message imprint to include. - * @return - * @throws DVCSException + * @return a new DVCSRequest based on the state of this builder. + * @throws DVCSException if an issue occurs during construction. */ public DVCSRequest build(MessageImprint messageImprint) throws DVCSException diff --git a/bcpkix/src/main/java/org/bouncycastle/dvcs/CCPDRequestData.java b/bcpkix/src/main/java/org/bouncycastle/dvcs/CCPDRequestData.java index f97ff9d4..dcf5b10c 100644 --- a/bcpkix/src/main/java/org/bouncycastle/dvcs/CCPDRequestData.java +++ b/bcpkix/src/main/java/org/bouncycastle/dvcs/CCPDRequestData.java @@ -40,7 +40,7 @@ public class CCPDRequestData /** * Get MessageImprint value * - * @return + * @return the message imprint data as a MessageImprint object. */ public MessageImprint getMessageImprint() { diff --git a/bcpkix/src/main/java/org/bouncycastle/dvcs/CPDRequestBuilder.java b/bcpkix/src/main/java/org/bouncycastle/dvcs/CPDRequestBuilder.java index 3d671f2e..b8e8fffe 100644 --- a/bcpkix/src/main/java/org/bouncycastle/dvcs/CPDRequestBuilder.java +++ b/bcpkix/src/main/java/org/bouncycastle/dvcs/CPDRequestBuilder.java @@ -1,7 +1,5 @@ package org.bouncycastle.dvcs; -import java.io.IOException; - import org.bouncycastle.asn1.dvcs.DVCSRequestInformationBuilder; import org.bouncycastle.asn1.dvcs.Data; import org.bouncycastle.asn1.dvcs.ServiceType; @@ -21,11 +19,11 @@ public class CPDRequestBuilder * Build CPD request. * * @param messageBytes - data to be certified - * @return - * @throws DVCSException + * @return a DVSCRequest based on the builder's current state and messageBytes. + * @throws DVCSException on a build issue. */ public DVCSRequest build(byte[] messageBytes) - throws DVCSException, IOException + throws DVCSException { Data data = new Data(messageBytes); diff --git a/bcpkix/src/main/java/org/bouncycastle/dvcs/CPDRequestData.java b/bcpkix/src/main/java/org/bouncycastle/dvcs/CPDRequestData.java index 703de529..c1717307 100644 --- a/bcpkix/src/main/java/org/bouncycastle/dvcs/CPDRequestData.java +++ b/bcpkix/src/main/java/org/bouncycastle/dvcs/CPDRequestData.java @@ -32,7 +32,7 @@ public class CPDRequestData /** * Get contained message (data to be certified). * - * @return + * @return the contained message. */ public byte[] getMessage() { diff --git a/bcpkix/src/main/java/org/bouncycastle/dvcs/DVCSRequestBuilder.java b/bcpkix/src/main/java/org/bouncycastle/dvcs/DVCSRequestBuilder.java index aab45707..a914ac7c 100644 --- a/bcpkix/src/main/java/org/bouncycastle/dvcs/DVCSRequestBuilder.java +++ b/bcpkix/src/main/java/org/bouncycastle/dvcs/DVCSRequestBuilder.java @@ -97,7 +97,6 @@ public abstract class DVCSRequestBuilder * @param oid the OID defining the extension type. * @param isCritical true if the extension is critical, false otherwise. * @param value the ASN.1 structure that forms the extension's value. - * @return this builder object. * @throws DVCSException if there is an issue encoding the extension for adding. */ public void addExtension( diff --git a/bcpkix/src/main/java/org/bouncycastle/dvcs/DVCSRequestData.java b/bcpkix/src/main/java/org/bouncycastle/dvcs/DVCSRequestData.java index 811306b2..8f6fbc7e 100644 --- a/bcpkix/src/main/java/org/bouncycastle/dvcs/DVCSRequestData.java +++ b/bcpkix/src/main/java/org/bouncycastle/dvcs/DVCSRequestData.java @@ -20,7 +20,7 @@ public abstract class DVCSRequestData /** * The constructor is accessible by subclasses. * - * @param data + * @param data the data piece for this request. */ protected DVCSRequestData(Data data) { @@ -30,7 +30,7 @@ public abstract class DVCSRequestData /** * Convert to ASN.1 structure (Data). * - * @return + * @return a Data object. */ public Data toASN1Structure() { diff --git a/bcpkix/src/main/java/org/bouncycastle/dvcs/DVCSRequestInfo.java b/bcpkix/src/main/java/org/bouncycastle/dvcs/DVCSRequestInfo.java index 4d0767d8..da65a7d3 100644 --- a/bcpkix/src/main/java/org/bouncycastle/dvcs/DVCSRequestInfo.java +++ b/bcpkix/src/main/java/org/bouncycastle/dvcs/DVCSRequestInfo.java @@ -21,7 +21,7 @@ public class DVCSRequestInfo /** * Constructs DVCRequestInfo from byte array (DER encoded DVCSRequestInformation). * - * @param in + * @param in a byte array holding the encoding of a DVCSRequestInformation structure. */ public DVCSRequestInfo(byte[] in) { @@ -31,7 +31,7 @@ public class DVCSRequestInfo /** * Constructs DVCRequestInfo from DVCSRequestInformation ASN.1 structure. * - * @param data + * @param data a DVCSRequestInformation to populate this object with. */ public DVCSRequestInfo(DVCSRequestInformation data) { @@ -41,7 +41,7 @@ public class DVCSRequestInfo /** * Converts to corresponding ASN.1 structure (DVCSRequestInformation). * - * @return + * @return a DVCSRequestInformation object. */ public DVCSRequestInformation toASN1Structure() { @@ -55,7 +55,7 @@ public class DVCSRequestInfo /** * Get DVCS version of request. * - * @return + * @return the version number of the request. */ public int getVersion() { @@ -121,7 +121,7 @@ public class DVCSRequestInfo /** * Get names of requesting entity, if set. * - * @return + * @return the requesting entity, or null. */ public GeneralNames getRequester() { @@ -146,7 +146,7 @@ public class DVCSRequestInfo * Get names of DVCS servers. * Note: this field can be set by DVCS. * - * @return + * @return the DVCS names object, or null if not set. */ public GeneralNames getDVCSNames() { @@ -158,7 +158,7 @@ public class DVCSRequestInfo * Note: the exact meaning of field is up to applications. * Note: this field can be set by DVCS. * - * @return + * @return the DVCS dataLocations object, or null if not set. */ public GeneralNames getDataLocations() { diff --git a/bcpkix/src/main/java/org/bouncycastle/dvcs/VPKCRequestBuilder.java b/bcpkix/src/main/java/org/bouncycastle/dvcs/VPKCRequestBuilder.java index 51e0307f..1bc22198 100644 --- a/bcpkix/src/main/java/org/bouncycastle/dvcs/VPKCRequestBuilder.java +++ b/bcpkix/src/main/java/org/bouncycastle/dvcs/VPKCRequestBuilder.java @@ -64,7 +64,8 @@ public class VPKCRequestBuilder /** * Build DVCS request to VPKC service. * - * @throws DVCSException + * @return a new DVCSRequest based on the state of this builder. + * @throws DVCSException if an issue occurs during construction. */ public DVCSRequest build() throws DVCSException diff --git a/bcpkix/src/main/java/org/bouncycastle/dvcs/VSDRequestBuilder.java b/bcpkix/src/main/java/org/bouncycastle/dvcs/VSDRequestBuilder.java index 52ca3203..a2444274 100644 --- a/bcpkix/src/main/java/org/bouncycastle/dvcs/VSDRequestBuilder.java +++ b/bcpkix/src/main/java/org/bouncycastle/dvcs/VSDRequestBuilder.java @@ -28,9 +28,9 @@ public class VSDRequestBuilder /** * Build VSD request from CMS SignedData object. * - * @param document - * @return - * @throws DVCSException + * @param document the CMS SignedData to include in the request. + * @return a new DVCSRequest based on the state of this builder. + * @throws DVCSException if an issue occurs during construction. */ public DVCSRequest build(CMSSignedData document) throws DVCSException diff --git a/bcpkix/src/main/java/org/bouncycastle/dvcs/VSDRequestData.java b/bcpkix/src/main/java/org/bouncycastle/dvcs/VSDRequestData.java index 17deb225..fb120463 100644 --- a/bcpkix/src/main/java/org/bouncycastle/dvcs/VSDRequestData.java +++ b/bcpkix/src/main/java/org/bouncycastle/dvcs/VSDRequestData.java @@ -48,7 +48,7 @@ public class VSDRequestData /** * Get contained message (data to be certified). * - * @return + * @return the contained message. */ public byte[] getMessage() { @@ -58,7 +58,7 @@ public class VSDRequestData /** * Get the CMS SignedData object represented by the encoded message. * - * @return + * @return the parsed contents of the contained message as a CMS SignedData object. */ public CMSSignedData getParsedMessage() { diff --git a/bcpkix/src/main/java/org/bouncycastle/eac/jcajce/JcaPublicKeyConverter.java b/bcpkix/src/main/java/org/bouncycastle/eac/jcajce/JcaPublicKeyConverter.java index f47709b7..79e312fe 100644 --- a/bcpkix/src/main/java/org/bouncycastle/eac/jcajce/JcaPublicKeyConverter.java +++ b/bcpkix/src/main/java/org/bouncycastle/eac/jcajce/JcaPublicKeyConverter.java @@ -8,7 +8,10 @@ import java.security.Provider; import java.security.PublicKey; import java.security.interfaces.ECPublicKey; import java.security.spec.ECField; +import java.security.spec.ECFieldF2m; import java.security.spec.ECFieldFp; +import java.security.spec.ECParameterSpec; +import java.security.spec.ECPublicKeySpec; import java.security.spec.EllipticCurve; import java.security.spec.InvalidKeySpecException; import java.security.spec.RSAPublicKeySpec; @@ -19,10 +22,13 @@ import org.bouncycastle.asn1.eac.ECDSAPublicKey; import org.bouncycastle.asn1.eac.PublicKeyDataObject; import org.bouncycastle.asn1.eac.RSAPublicKey; import org.bouncycastle.eac.EACException; -import org.bouncycastle.jce.spec.ECParameterSpec; -import org.bouncycastle.jce.spec.ECPublicKeySpec; +import org.bouncycastle.math.ec.ECAlgorithms; import org.bouncycastle.math.ec.ECCurve; import org.bouncycastle.math.ec.ECPoint; +import org.bouncycastle.math.field.FiniteField; +import org.bouncycastle.math.field.Polynomial; +import org.bouncycastle.math.field.PolynomialExtensionField; +import org.bouncycastle.util.Arrays; public class JcaPublicKeyConverter { @@ -75,10 +81,8 @@ public class JcaPublicKeyConverter throws EACException, InvalidKeySpecException { ECParameterSpec spec = getParams(key); - ECCurve curve = spec.getCurve(); - - ECPoint point = curve.decodePoint(key.getPublicPointY()); - ECPublicKeySpec pubKeySpec = new ECPublicKeySpec(point, spec); + java.security.spec.ECPoint publicPoint = getPublicPoint(key); + ECPublicKeySpec pubKeySpec = new ECPublicKeySpec(publicPoint, spec); KeyFactory factk; try @@ -97,6 +101,21 @@ public class JcaPublicKeyConverter return factk.generatePublic(pubKeySpec); } + private java.security.spec.ECPoint getPublicPoint(ECDSAPublicKey key) + { + if (!key.hasParameters()) + { + throw new IllegalArgumentException("Public key does not contains EC Params"); + } + + BigInteger p = key.getPrimeModulusP(); + ECCurve.Fp curve = new ECCurve.Fp(p, key.getFirstCoefA(), key.getSecondCoefB(), key.getOrderOfBasePointR(), key.getCofactorF()); + + ECPoint.Fp pubY = (ECPoint.Fp)curve.decodePoint(key.getPublicPointY()); + + return new java.security.spec.ECPoint(pubY.getAffineXCoord().toBigInteger(), pubY.getAffineYCoord().toBigInteger()); + } + private ECParameterSpec getParams(ECDSAPublicKey key) { if (!key.hasParameters()) @@ -105,16 +124,16 @@ public class JcaPublicKeyConverter } BigInteger p = key.getPrimeModulusP(); - ECCurve.Fp curve = new ECCurve.Fp(p, key.getFirstCoefA(), key.getSecondCoefB()); + ECCurve.Fp curve = new ECCurve.Fp(p, key.getFirstCoefA(), key.getSecondCoefB(), key.getOrderOfBasePointR(), key.getCofactorF()); ECPoint G = curve.decodePoint(key.getBasePointG()); BigInteger order = key.getOrderOfBasePointR(); BigInteger coFactor = key.getCofactorF(); - // TODO: update to use JDK 1.5 EC API - ECParameterSpec ecspec = new ECParameterSpec(curve, G, order, coFactor); - return ecspec; + EllipticCurve jcaCurve = convertCurve(curve); + + return new ECParameterSpec(jcaCurve, new java.security.spec.ECPoint(G.getAffineXCoord().toBigInteger(), G.getAffineYCoord().toBigInteger()), order, coFactor.intValue()); } public PublicKeyDataObject getPublicKeyDataObject(ASN1ObjectIdentifier usage, PublicKey publicKey) @@ -134,23 +153,22 @@ public class JcaPublicKeyConverter usage, ((ECFieldFp)params.getCurve().getField()).getP(), params.getCurve().getA(), params.getCurve().getB(), - convertPoint(convertCurve(params.getCurve()), params.getGenerator(), false).getEncoded(), + convertPoint(convertCurve(params.getCurve(), params.getOrder(), params.getCofactor()), params.getGenerator()).getEncoded(), params.getOrder(), - convertPoint(convertCurve(params.getCurve()), pubKey.getW(), false).getEncoded(), + convertPoint(convertCurve(params.getCurve(), params.getOrder(), params.getCofactor()), pubKey.getW()).getEncoded(), params.getCofactor()); } } private static org.bouncycastle.math.ec.ECPoint convertPoint( ECCurve curve, - java.security.spec.ECPoint point, - boolean withCompression) + java.security.spec.ECPoint point) { - return curve.createPoint(point.getAffineX(), point.getAffineY(), withCompression); + return curve.createPoint(point.getAffineX(), point.getAffineY()); } private static ECCurve convertCurve( - EllipticCurve ec) + EllipticCurve ec, BigInteger order, int coFactor) { ECField field = ec.getField(); BigInteger a = ec.getA(); @@ -158,11 +176,37 @@ public class JcaPublicKeyConverter if (field instanceof ECFieldFp) { - return new ECCurve.Fp(((ECFieldFp)field).getP(), a, b); + return new ECCurve.Fp(((ECFieldFp)field).getP(), a, b, order, BigInteger.valueOf(coFactor)); } else { throw new IllegalStateException("not implemented yet!!!"); } } + + private static EllipticCurve convertCurve( + ECCurve curve) + { + ECField field = convertField(curve.getField()); + BigInteger a = curve.getA().toBigInteger(), b = curve.getB().toBigInteger(); + + // TODO: the Sun EC implementation doesn't currently handle the seed properly + // so at the moment it's set to null. Should probably look at making this configurable + return new EllipticCurve(field, a, b, null); + } + + private static ECField convertField(FiniteField field) + { + if (ECAlgorithms.isFpField(field)) + { + return new ECFieldFp(field.getCharacteristic()); + } + else //if (ECAlgorithms.isF2mField(curveField)) + { + Polynomial poly = ((PolynomialExtensionField)field).getMinimalPolynomial(); + int[] exponents = poly.getExponentsPresent(); + int[] ks = Arrays.reverse(Arrays.copyOfRange(exponents, 1, exponents.length - 1)); + return new ECFieldF2m(poly.getDegree(), ks); + } + } } diff --git a/bcpkix/src/main/java/org/bouncycastle/mozilla/SignedPublicKeyAndChallenge.java b/bcpkix/src/main/java/org/bouncycastle/mozilla/SignedPublicKeyAndChallenge.java index f9c4bcad..bedd2daf 100644 --- a/bcpkix/src/main/java/org/bouncycastle/mozilla/SignedPublicKeyAndChallenge.java +++ b/bcpkix/src/main/java/org/bouncycastle/mozilla/SignedPublicKeyAndChallenge.java @@ -1,6 +1,7 @@ package org.bouncycastle.mozilla; -import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.OutputStream; import java.security.InvalidKeyException; import java.security.KeyFactory; import java.security.NoSuchAlgorithmException; @@ -10,14 +11,16 @@ import java.security.Signature; import java.security.SignatureException; import java.security.spec.X509EncodedKeySpec; -import org.bouncycastle.asn1.ASN1InputStream; -import org.bouncycastle.asn1.ASN1Object; import org.bouncycastle.asn1.ASN1Primitive; -import org.bouncycastle.asn1.ASN1Sequence; import org.bouncycastle.asn1.DERBitString; +import org.bouncycastle.asn1.DEROutputStream; import org.bouncycastle.asn1.mozilla.PublicKeyAndChallenge; import org.bouncycastle.asn1.x509.AlgorithmIdentifier; import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo; +import org.bouncycastle.operator.ContentVerifier; +import org.bouncycastle.operator.ContentVerifierProvider; +import org.bouncycastle.operator.OperatorCreationException; +import org.bouncycastle.util.Encodable; /** * This is designed to parse the SignedPublicKeyAndChallenge created by the @@ -36,54 +39,71 @@ import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo; * </pre> */ public class SignedPublicKeyAndChallenge - extends ASN1Object + implements Encodable { - private static ASN1Sequence toDERSequence(byte[] bytes) - { - try - { - ByteArrayInputStream bIn = new ByteArrayInputStream(bytes); - ASN1InputStream aIn = new ASN1InputStream(bIn); + protected final org.bouncycastle.asn1.mozilla.SignedPublicKeyAndChallenge spkacSeq; - return (ASN1Sequence)aIn.readObject(); - } - catch (Exception e) - { - throw new IllegalArgumentException("badly encoded request"); - } + public SignedPublicKeyAndChallenge(byte[] bytes) + { + spkacSeq = org.bouncycastle.asn1.mozilla.SignedPublicKeyAndChallenge.getInstance(bytes); } - private ASN1Sequence spkacSeq; - private PublicKeyAndChallenge pkac; - private AlgorithmIdentifier signatureAlgorithm; - private DERBitString signature; + protected SignedPublicKeyAndChallenge(org.bouncycastle.asn1.mozilla.SignedPublicKeyAndChallenge struct) + { + this.spkacSeq = struct; + } - public SignedPublicKeyAndChallenge(byte[] bytes) + /** + * Return the underlying ASN.1 structure for this challenge. + * + * @return a SignedPublicKeyAndChallenge object. + */ + public org.bouncycastle.asn1.mozilla.SignedPublicKeyAndChallenge toASN1Structure() { - spkacSeq = toDERSequence(bytes); - pkac = PublicKeyAndChallenge.getInstance(spkacSeq.getObjectAt(0)); - signatureAlgorithm = - AlgorithmIdentifier.getInstance(spkacSeq.getObjectAt(1)); - signature = (DERBitString)spkacSeq.getObjectAt(2); + return spkacSeq; } + /** + * @deprecated use toASN1Structure + */ public ASN1Primitive toASN1Primitive() { - return spkacSeq; + return spkacSeq.toASN1Primitive(); } public PublicKeyAndChallenge getPublicKeyAndChallenge() { - return pkac; + return spkacSeq.getPublicKeyAndChallenge(); + } + + public boolean isSignatureValid(ContentVerifierProvider verifierProvider) + throws OperatorCreationException, IOException + { + ContentVerifier verifier = verifierProvider.get(spkacSeq.getSignatureAlgorithm()); + + OutputStream sOut = verifier.getOutputStream(); + DEROutputStream dOut = new DEROutputStream(sOut); + + dOut.writeObject(spkacSeq.getPublicKeyAndChallenge()); + + sOut.close(); + + return verifier.verify(spkacSeq.getSignature().getOctets()); } + /** + * @deprecated use ContentVerifierProvider method + */ public boolean verify() throws NoSuchAlgorithmException, SignatureException, NoSuchProviderException, InvalidKeyException { - return verify(null); + return verify((String)null); } + /** + * @deprecated use ContentVerifierProvider method + */ public boolean verify(String provider) throws NoSuchAlgorithmException, SignatureException, NoSuchProviderException, InvalidKeyException @@ -91,20 +111,19 @@ public class SignedPublicKeyAndChallenge Signature sig = null; if (provider == null) { - sig = Signature.getInstance(signatureAlgorithm.getAlgorithm().getId()); + sig = Signature.getInstance(spkacSeq.getSignatureAlgorithm().getAlgorithm().getId()); } else { - sig = Signature.getInstance(signatureAlgorithm.getAlgorithm().getId(), provider); + sig = Signature.getInstance(spkacSeq.getSignatureAlgorithm().getAlgorithm().getId(), provider); } PublicKey pubKey = this.getPublicKey(provider); sig.initVerify(pubKey); try { - DERBitString pkBytes = new DERBitString(pkac); - sig.update(pkBytes.getBytes()); + sig.update(spkacSeq.getPublicKeyAndChallenge().getEncoded()); - return sig.verify(signature.getBytes()); + return sig.verify(spkacSeq.getSignature().getBytes()); } catch (Exception e) { @@ -112,15 +131,28 @@ public class SignedPublicKeyAndChallenge } } + public SubjectPublicKeyInfo getSubjectPublicKeyInfo() + { + return spkacSeq.getPublicKeyAndChallenge().getSubjectPublicKeyInfo(); + } + + public String getChallenge() + { + return spkacSeq.getPublicKeyAndChallenge().getChallenge().getString(); + } + + /** + * @deprecated use JcaSignedPublicKeyAndChallenge.getPublicKey() + */ public PublicKey getPublicKey(String provider) throws NoSuchAlgorithmException, NoSuchProviderException, InvalidKeyException { - SubjectPublicKeyInfo subjectPKInfo = pkac.getSubjectPublicKeyInfo(); + SubjectPublicKeyInfo subjectPKInfo = spkacSeq.getPublicKeyAndChallenge().getSubjectPublicKeyInfo(); try { DERBitString bStr = new DERBitString(subjectPKInfo); - X509EncodedKeySpec xspec = new X509EncodedKeySpec(bStr.getBytes()); + X509EncodedKeySpec xspec = new X509EncodedKeySpec(bStr.getOctets()); AlgorithmIdentifier keyAlg = subjectPKInfo.getAlgorithm(); @@ -136,4 +168,10 @@ public class SignedPublicKeyAndChallenge throw new InvalidKeyException("error encoding public key"); } } + + public byte[] getEncoded() + throws IOException + { + return toASN1Structure().getEncoded(); + } } diff --git a/bcpkix/src/main/java/org/bouncycastle/mozilla/test/AllTests.java b/bcpkix/src/main/java/org/bouncycastle/mozilla/test/AllTests.java index 3c0dcc60..fb5dd3cb 100644 --- a/bcpkix/src/main/java/org/bouncycastle/mozilla/test/AllTests.java +++ b/bcpkix/src/main/java/org/bouncycastle/mozilla/test/AllTests.java @@ -2,11 +2,13 @@ package org.bouncycastle.mozilla.test; import java.security.Security; +import junit.extensions.TestSetup; +import junit.framework.Test; +import junit.framework.TestCase; +import junit.framework.TestSuite; import org.bouncycastle.jce.provider.BouncyCastleProvider; import org.bouncycastle.util.test.SimpleTestResult; -import junit.framework.*; - public class AllTests extends TestCase { @@ -38,6 +40,26 @@ public class AllTests suite.addTestSuite(AllTests.class); - return suite; + return new BCTestSetup(suite); } + + static class BCTestSetup + extends TestSetup + { + public BCTestSetup(Test test) + { + super(test); + } + + protected void setUp() + { + + } + + protected void tearDown() + { + + } + } + } diff --git a/bcpkix/src/main/java/org/bouncycastle/mozilla/test/SPKACTest.java b/bcpkix/src/main/java/org/bouncycastle/mozilla/test/SPKACTest.java index 192bfd86..d9440bb6 100644 --- a/bcpkix/src/main/java/org/bouncycastle/mozilla/test/SPKACTest.java +++ b/bcpkix/src/main/java/org/bouncycastle/mozilla/test/SPKACTest.java @@ -13,101 +13,175 @@ import org.bouncycastle.asn1.mozilla.PublicKeyAndChallenge; import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo; import org.bouncycastle.jce.provider.BouncyCastleProvider; import org.bouncycastle.mozilla.SignedPublicKeyAndChallenge; +import org.bouncycastle.mozilla.jcajce.JcaSignedPublicKeyAndChallenge; +import org.bouncycastle.operator.jcajce.JcaContentVerifierProviderBuilder; import org.bouncycastle.util.encoders.Base64; import org.bouncycastle.util.test.SimpleTest; public class SPKACTest extends SimpleTest { - byte[] spkac = Base64.decode( - "MIIBOjCBpDCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEApne7ti0ibPhV8Iht"+ - "7Pws5iRckM7x4mtZYxEpeX5/IO8tDsBFdY86ewuY2f2KCca0oMWr43kdkZbPyzf4"+ - "CSV+0fZm9MJyNMywygZjoOCC+rS8kr0Ef31iHChhYsyejJnjw116Jnn96syhdHY6"+ - "lVD1rK0nn5ZkHjxU74gjoZu6BJMCAwEAARYAMA0GCSqGSIb3DQEBBAUAA4GBAKFL"+ - "g/luv0C7gMTI8ZKfFoSyi7Q7kiSQcmSj1WJgT56ouIRJO5NdvB/1n4GNik8VOAU0"+ - "NRztvGy3ZGqgbSav7lrxcNEvXH+dLbtS97s7yiaozpsOcEHqsBribpLOTRzYa8ci"+ - "CwkPmIiYqcby11diKLpd+W9RFYNme2v0rrbM2CyV"); - - - public String getName() - { - return "SignedPubicKeyAndChallenge"; - } - - public void spkacTest(String testName, byte[] req) - throws Exception - { - SignedPublicKeyAndChallenge spkac; - - spkac = new SignedPublicKeyAndChallenge(req); - - PublicKeyAndChallenge pkac = spkac.getPublicKeyAndChallenge(); - PublicKey pubKey = spkac.getPublicKey("BC"); - ASN1Primitive obj = pkac.toASN1Primitive(); - if (obj == null) - { - fail("Error - " + testName + " PKAC ASN1Primitive was null."); - } - - obj = spkac.toASN1Primitive(); - if (obj == null) - { - fail("Error - "+testName+ " SPKAC ASN1Primitive was null."); - } - - SubjectPublicKeyInfo spki = pkac.getSubjectPublicKeyInfo(); - if (spki == null) - { - fail("Error - "+testName + " SubjectPublicKeyInfo was null."); - } - - DERIA5String challenge = pkac.getChallenge(); - // Most cases this will be a string of length zero. - if (challenge == null) - { - fail(":Error - "+testName+ " challenge was null."); - } - - ByteArrayInputStream bIn = new ByteArrayInputStream(req); - ASN1InputStream dIn = new ASN1InputStream(bIn); - - - ByteArrayOutputStream bOut = new ByteArrayOutputStream(); - DEROutputStream dOut = new DEROutputStream(bOut); - - dOut.writeObject(spkac.toASN1Primitive()); - - byte[] bytes = bOut.toByteArray(); - - if (bytes.length != req.length) - { - fail(testName + " failed length test"); - } - - for (int i = 0; i != req.length; i++) - { - if (bytes[i] != req[i]) - { - fail(testName + " failed comparison test"); - } - } - - if (!spkac.verify("BC")) - { - fail(testName + " verification failed"); - } - } - - public void performTest() - throws Exception - { - spkacTest("spkac", spkac); - } - - public static void main(String[] args) - { - Security.addProvider(new BouncyCastleProvider()); - - runTest(new SPKACTest()); - } + byte[] spkac = Base64.decode( + "MIIBOjCBpDCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEApne7ti0ibPhV8Iht" + + "7Pws5iRckM7x4mtZYxEpeX5/IO8tDsBFdY86ewuY2f2KCca0oMWr43kdkZbPyzf4" + + "CSV+0fZm9MJyNMywygZjoOCC+rS8kr0Ef31iHChhYsyejJnjw116Jnn96syhdHY6" + + "lVD1rK0nn5ZkHjxU74gjoZu6BJMCAwEAARYAMA0GCSqGSIb3DQEBBAUAA4GBAKFL" + + "g/luv0C7gMTI8ZKfFoSyi7Q7kiSQcmSj1WJgT56ouIRJO5NdvB/1n4GNik8VOAU0" + + "NRztvGy3ZGqgbSav7lrxcNEvXH+dLbtS97s7yiaozpsOcEHqsBribpLOTRzYa8ci" + + "CwkPmIiYqcby11diKLpd+W9RFYNme2v0rrbM2CyV"); + + + public String getName() + { + return "SignedPubicKeyAndChallenge"; + } + + public void spkacTest(String testName, byte[] req) + throws Exception + { + SignedPublicKeyAndChallenge spkac; + + spkac = new SignedPublicKeyAndChallenge(req); + + PublicKeyAndChallenge pkac = spkac.getPublicKeyAndChallenge(); + PublicKey pubKey = spkac.getPublicKey("BC"); + ASN1Primitive obj = pkac.toASN1Primitive(); + if (obj == null) + { + fail("Error - " + testName + " PKAC ASN1Primitive was null."); + } + + obj = spkac.toASN1Primitive(); + if (obj == null) + { + fail("Error - " + testName + " SPKAC ASN1Primitive was null."); + } + + SubjectPublicKeyInfo spki = pkac.getSubjectPublicKeyInfo(); + if (spki == null) + { + fail("Error - " + testName + " SubjectPublicKeyInfo was null."); + } + + DERIA5String challenge = pkac.getChallenge(); + // Most cases this will be a string of length zero. + if (challenge == null) + { + fail(":Error - " + testName + " challenge was null."); + } + + ByteArrayInputStream bIn = new ByteArrayInputStream(req); + ASN1InputStream dIn = new ASN1InputStream(bIn); + + + ByteArrayOutputStream bOut = new ByteArrayOutputStream(); + DEROutputStream dOut = new DEROutputStream(bOut); + + dOut.writeObject(spkac.toASN1Primitive()); + + byte[] bytes = bOut.toByteArray(); + + if (bytes.length != req.length) + { + fail(testName + " failed length test"); + } + + for (int i = 0; i != req.length; i++) + { + if (bytes[i] != req[i]) + { + fail(testName + " failed comparison test"); + } + } + + if (!spkac.verify("BC")) + { + fail(testName + " verification failed"); + } + } + + public void spkacNewTest(String testName, byte[] req) + throws Exception + { + SignedPublicKeyAndChallenge spkac; + + spkac = new SignedPublicKeyAndChallenge(req); + + PublicKeyAndChallenge pkac = spkac.getPublicKeyAndChallenge(); + PublicKey pubKey = spkac.getPublicKey("BC"); + ASN1Primitive obj = pkac.toASN1Primitive(); + if (obj == null) + { + fail("Error - " + testName + " PKAC ASN1Primitive was null."); + } + + obj = spkac.toASN1Structure().toASN1Primitive(); + if (obj == null) + { + fail("Error - " + testName + " SPKAC ASN1Primitive was null."); + } + + SubjectPublicKeyInfo spki = pkac.getSubjectPublicKeyInfo(); + if (spki == null) + { + fail("Error - " + testName + " SubjectPublicKeyInfo was null."); + } + + DERIA5String challenge = pkac.getChallenge(); + // Most cases this will be a string of length zero. + if (challenge == null) + { + fail(":Error - " + testName + " challenge was null."); + } + + ByteArrayInputStream bIn = new ByteArrayInputStream(req); + ASN1InputStream dIn = new ASN1InputStream(bIn); + + + ByteArrayOutputStream bOut = new ByteArrayOutputStream(); + DEROutputStream dOut = new DEROutputStream(bOut); + + dOut.writeObject(spkac.toASN1Structure()); + + byte[] bytes = bOut.toByteArray(); + + if (bytes.length != req.length) + { + fail(testName + " failed length test"); + } + + for (int i = 0; i != req.length; i++) + { + if (bytes[i] != req[i]) + { + fail(testName + " failed comparison test"); + } + } + + if (!spkac.isSignatureValid(new JcaContentVerifierProviderBuilder().setProvider("BC").build(spkac.getSubjectPublicKeyInfo()))) + { + fail(testName + " verification failed"); + } + + JcaSignedPublicKeyAndChallenge jcaSignedPublicKeyAndChallenge = new JcaSignedPublicKeyAndChallenge(req); + + if (!spkac.isSignatureValid(new JcaContentVerifierProviderBuilder().setProvider("BC").build(jcaSignedPublicKeyAndChallenge.getPublicKey()))) + { + fail(testName + " verification failed"); + } + } + + public void performTest() + throws Exception + { + spkacTest("spkac", spkac); + spkacNewTest("spkac", spkac); + } + + public static void main(String[] args) + { + Security.addProvider(new BouncyCastleProvider()); + + runTest(new SPKACTest()); + } } diff --git a/bcpkix/src/main/java/org/bouncycastle/openssl/MiscPEMGenerator.java b/bcpkix/src/main/java/org/bouncycastle/openssl/MiscPEMGenerator.java index 02866883..54988fe0 100644 --- a/bcpkix/src/main/java/org/bouncycastle/openssl/MiscPEMGenerator.java +++ b/bcpkix/src/main/java/org/bouncycastle/openssl/MiscPEMGenerator.java @@ -85,6 +85,12 @@ public class MiscPEMGenerator encoding = ((X509CRLHolder)o).getEncoded(); } + else if (o instanceof X509TrustedCertificateBlock) + { + type = "TRUSTED CERTIFICATE"; + + encoding = ((X509TrustedCertificateBlock)o).getEncoded(); + } else if (o instanceof PrivateKeyInfo) { PrivateKeyInfo info = (PrivateKeyInfo)o; diff --git a/bcpkix/src/main/java/org/bouncycastle/openssl/PEMDecryptor.java b/bcpkix/src/main/java/org/bouncycastle/openssl/PEMDecryptor.java index 09cef5b7..0f12cd10 100644 --- a/bcpkix/src/main/java/org/bouncycastle/openssl/PEMDecryptor.java +++ b/bcpkix/src/main/java/org/bouncycastle/openssl/PEMDecryptor.java @@ -1,7 +1,18 @@ package org.bouncycastle.openssl; +/** + * Base interface for decryption operations. + */ public interface PEMDecryptor { - byte[] decrypt(byte[] keyBytes, byte[] iv) + /** + * Decrypt the passed in data using the associated IV and the decryptor's key state. + * + * @param data the encrypted data + * @param iv the initialisation vector associated with the decryption. + * @return the decrypted data. + * @throws PEMException in the event of an issue. + */ + byte[] decrypt(byte[] data, byte[] iv) throws PEMException; } diff --git a/bcpkix/src/main/java/org/bouncycastle/openssl/PEMParser.java b/bcpkix/src/main/java/org/bouncycastle/openssl/PEMParser.java index dacdba44..e1f9c351 100644 --- a/bcpkix/src/main/java/org/bouncycastle/openssl/PEMParser.java +++ b/bcpkix/src/main/java/org/bouncycastle/openssl/PEMParser.java @@ -63,10 +63,11 @@ public class PEMParser parsers.put("CERTIFICATE REQUEST", new PKCS10CertificationRequestParser()); parsers.put("NEW CERTIFICATE REQUEST", new PKCS10CertificationRequestParser()); parsers.put("CERTIFICATE", new X509CertificateParser()); - parsers.put("TRUSTED CERTIFICATE", new X509CertificateParser()); + parsers.put("TRUSTED CERTIFICATE", new X509TrustedCertificateParser()); parsers.put("X509 CERTIFICATE", new X509CertificateParser()); parsers.put("X509 CRL", new X509CRLParser()); parsers.put("PKCS7", new PKCS7Parser()); + parsers.put("CMS", new PKCS7Parser()); parsers.put("ATTRIBUTE CERTIFICATE", new X509AttributeCertificateParser()); parsers.put("EC PARAMETERS", new ECCurveParamsParser()); parsers.put("PUBLIC KEY", new PublicKeyParser()); @@ -344,6 +345,29 @@ public class PEMParser } } + private class X509TrustedCertificateParser + implements PemObjectParser + { + /** + * Reads in a X509Certificate. + * + * @return the X509Certificate + * @throws java.io.IOException if an I/O error occured + */ + public Object parseObject(PemObject obj) + throws IOException + { + try + { + return new X509TrustedCertificateBlock(obj.getContent()); + } + catch (Exception e) + { + throw new PEMException("problem parsing cert: " + e.toString(), e); + } + } + } + private class X509CRLParser implements PemObjectParser { diff --git a/bcpkix/src/main/java/org/bouncycastle/openssl/jcajce/JcaMiscPEMGenerator.java b/bcpkix/src/main/java/org/bouncycastle/openssl/jcajce/JcaMiscPEMGenerator.java index 6547078d..247c53bc 100644 --- a/bcpkix/src/main/java/org/bouncycastle/openssl/jcajce/JcaMiscPEMGenerator.java +++ b/bcpkix/src/main/java/org/bouncycastle/openssl/jcajce/JcaMiscPEMGenerator.java @@ -14,14 +14,10 @@ import java.security.cert.X509Certificate; import org.bouncycastle.asn1.pkcs.PrivateKeyInfo; import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo; -import org.bouncycastle.cert.jcajce.JcaX509AttributeCertificateHolder; import org.bouncycastle.cert.jcajce.JcaX509CRLHolder; import org.bouncycastle.cert.jcajce.JcaX509CertificateHolder; -import org.bouncycastle.jce.PKCS10CertificationRequest; import org.bouncycastle.openssl.MiscPEMGenerator; import org.bouncycastle.openssl.PEMEncryptor; -import org.bouncycastle.x509.X509AttributeCertificate; -import org.bouncycastle.x509.X509V2AttributeCertificate; /** * PEM generator for the original set of PEM objects used in Open SSL. @@ -84,14 +80,6 @@ public class JcaMiscPEMGenerator { return SubjectPublicKeyInfo.getInstance(((PublicKey)o).getEncoded()); } - else if (o instanceof X509AttributeCertificate) - { - return new JcaX509AttributeCertificateHolder((X509V2AttributeCertificate)o); - } - else if (o instanceof PKCS10CertificationRequest) - { - return new org.bouncycastle.pkcs.PKCS10CertificationRequest(((PKCS10CertificationRequest)o).getEncoded()); - } return o; } diff --git a/bcpkix/src/main/java/org/bouncycastle/openssl/jcajce/JceOpenSSLPKCS8DecryptorProviderBuilder.java b/bcpkix/src/main/java/org/bouncycastle/openssl/jcajce/JceOpenSSLPKCS8DecryptorProviderBuilder.java index 46cca30d..c2877d23 100644 --- a/bcpkix/src/main/java/org/bouncycastle/openssl/jcajce/JceOpenSSLPKCS8DecryptorProviderBuilder.java +++ b/bcpkix/src/main/java/org/bouncycastle/openssl/jcajce/JceOpenSSLPKCS8DecryptorProviderBuilder.java @@ -9,9 +9,6 @@ import java.security.Provider; import javax.crypto.Cipher; import javax.crypto.CipherInputStream; import javax.crypto.SecretKey; -import javax.crypto.SecretKeyFactory; -import javax.crypto.spec.PBEKeySpec; -import javax.crypto.spec.PBEParameterSpec; import org.bouncycastle.asn1.pkcs.EncryptionScheme; import org.bouncycastle.asn1.pkcs.KeyDerivationFunc; @@ -20,6 +17,9 @@ import org.bouncycastle.asn1.pkcs.PBES2Parameters; import org.bouncycastle.asn1.pkcs.PBKDF2Params; import org.bouncycastle.asn1.pkcs.PKCS12PBEParams; import org.bouncycastle.asn1.x509.AlgorithmIdentifier; +import org.bouncycastle.crypto.CharToByteConverter; +import org.bouncycastle.jcajce.PBKDF1KeyWithParameters; +import org.bouncycastle.jcajce.PKCS12KeyWithParameters; import org.bouncycastle.jcajce.util.DefaultJcaJceHelper; import org.bouncycastle.jcajce.util.JcaJceHelper; import org.bouncycastle.jcajce.util.NamedJcaJceHelper; @@ -28,6 +28,7 @@ import org.bouncycastle.openssl.PEMException; import org.bouncycastle.operator.InputDecryptor; import org.bouncycastle.operator.InputDecryptorProvider; import org.bouncycastle.operator.OperatorCreationException; +import org.bouncycastle.util.Strings; public class JceOpenSSLPKCS8DecryptorProviderBuilder { @@ -76,7 +77,7 @@ public class JceOpenSSLPKCS8DecryptorProviderBuilder String oid = scheme.getAlgorithm().getId(); - SecretKey key = PEMUtilities.generateSecretKeyForPKCS5Scheme2(oid, password, salt, iterationCount); + SecretKey key = PEMUtilities.generateSecretKeyForPKCS5Scheme2(helper, oid, password, salt, iterationCount); cipher = helper.createCipher(oid); AlgorithmParameters algParams = helper.createAlgorithmParameters(oid); @@ -88,26 +89,29 @@ public class JceOpenSSLPKCS8DecryptorProviderBuilder else if (PEMUtilities.isPKCS12(algorithm.getAlgorithm())) { PKCS12PBEParams params = PKCS12PBEParams.getInstance(algorithm.getParameters()); - PBEKeySpec pbeSpec = new PBEKeySpec(password); - - SecretKeyFactory secKeyFact = helper.createSecretKeyFactory(algorithm.getAlgorithm().getId()); - PBEParameterSpec defParams = new PBEParameterSpec(params.getIV(), params.getIterations().intValue()); cipher = helper.createCipher(algorithm.getAlgorithm().getId()); - cipher.init(Cipher.DECRYPT_MODE, secKeyFact.generateSecret(pbeSpec), defParams); + cipher.init(Cipher.DECRYPT_MODE, new PKCS12KeyWithParameters(password, params.getIV(), params.getIterations().intValue())); } else if (PEMUtilities.isPKCS5Scheme1(algorithm.getAlgorithm())) { PBEParameter params = PBEParameter.getInstance(algorithm.getParameters()); - PBEKeySpec pbeSpec = new PBEKeySpec(password); - - SecretKeyFactory secKeyFact = helper.createSecretKeyFactory(algorithm.getAlgorithm().getId()); - PBEParameterSpec defParams = new PBEParameterSpec(params.getSalt(), params.getIterationCount().intValue()); cipher = helper.createCipher(algorithm.getAlgorithm().getId()); - cipher.init(Cipher.DECRYPT_MODE, secKeyFact.generateSecret(pbeSpec), defParams); + cipher.init(Cipher.DECRYPT_MODE, new PBKDF1KeyWithParameters(password, new CharToByteConverter() + { + public String getType() + { + return "ASCII"; + } + + public byte[] convert(char[] password) + { + return Strings.toByteArray(password); // just drop hi-order byte. + } + }, params.getSalt(), params.getIterationCount().intValue())); } else { diff --git a/bcpkix/src/main/java/org/bouncycastle/openssl/jcajce/JceOpenSSLPKCS8EncryptorBuilder.java b/bcpkix/src/main/java/org/bouncycastle/openssl/jcajce/JceOpenSSLPKCS8EncryptorBuilder.java index 09f8807b..95d08839 100644 --- a/bcpkix/src/main/java/org/bouncycastle/openssl/jcajce/JceOpenSSLPKCS8EncryptorBuilder.java +++ b/bcpkix/src/main/java/org/bouncycastle/openssl/jcajce/JceOpenSSLPKCS8EncryptorBuilder.java @@ -11,9 +11,6 @@ import java.security.SecureRandom; import javax.crypto.Cipher; import javax.crypto.CipherOutputStream; import javax.crypto.SecretKey; -import javax.crypto.SecretKeyFactory; -import javax.crypto.spec.PBEKeySpec; -import javax.crypto.spec.PBEParameterSpec; import org.bouncycastle.asn1.ASN1EncodableVector; import org.bouncycastle.asn1.ASN1Integer; @@ -28,6 +25,7 @@ import org.bouncycastle.asn1.pkcs.PBKDF2Params; import org.bouncycastle.asn1.pkcs.PKCS12PBEParams; import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers; import org.bouncycastle.asn1.x509.AlgorithmIdentifier; +import org.bouncycastle.jcajce.PKCS12KeyWithParameters; import org.bouncycastle.jcajce.util.DefaultJcaJceHelper; import org.bouncycastle.jcajce.util.JcaJceHelper; import org.bouncycastle.jcajce.util.NamedJcaJceHelper; @@ -61,7 +59,6 @@ public class JceOpenSSLPKCS8EncryptorBuilder private Cipher cipher; private SecureRandom random; private AlgorithmParameterGenerator paramGen; - private SecretKeyFactory secKeyFact; private char[] password; private SecretKey key; @@ -130,10 +127,6 @@ public class JceOpenSSLPKCS8EncryptorBuilder { this.paramGen = helper.createAlgorithmParameterGenerator(algOID.getId()); } - else - { - this.secKeyFact = helper.createSecretKeyFactory(algOID.getId()); - } } catch (GeneralSecurityException e) { @@ -161,10 +154,10 @@ public class JceOpenSSLPKCS8EncryptorBuilder throw new OperatorCreationException(e.getMessage(), e); } - key = PEMUtilities.generateSecretKeyForPKCS5Scheme2(algOID.getId(), password, salt, iterationCount); - try { + key = PEMUtilities.generateSecretKeyForPKCS5Scheme2(helper, algOID.getId(), password, salt, iterationCount); + cipher.init(Cipher.ENCRYPT_MODE, key, params); } catch (GeneralSecurityException e) @@ -183,12 +176,7 @@ public class JceOpenSSLPKCS8EncryptorBuilder try { - PBEKeySpec pbeSpec = new PBEKeySpec(password); - PBEParameterSpec defParams = new PBEParameterSpec(salt, iterationCount); - - key = secKeyFact.generateSecret(pbeSpec); - - cipher.init(Cipher.ENCRYPT_MODE, key, defParams); + cipher.init(Cipher.ENCRYPT_MODE, new PKCS12KeyWithParameters(password, salt, iterationCount)); } catch (GeneralSecurityException e) { diff --git a/bcpkix/src/main/java/org/bouncycastle/openssl/jcajce/PEMUtilities.java b/bcpkix/src/main/java/org/bouncycastle/openssl/jcajce/PEMUtilities.java index a5a88a90..83d2098c 100644 --- a/bcpkix/src/main/java/org/bouncycastle/openssl/jcajce/PEMUtilities.java +++ b/bcpkix/src/main/java/org/bouncycastle/openssl/jcajce/PEMUtilities.java @@ -1,7 +1,11 @@ package org.bouncycastle.openssl.jcajce; +import java.security.GeneralSecurityException; import java.security.Key; +import java.security.NoSuchAlgorithmException; +import java.security.NoSuchProviderException; import java.security.spec.AlgorithmParameterSpec; +import java.security.spec.InvalidKeySpecException; import java.util.HashMap; import java.util.HashSet; import java.util.Map; @@ -9,17 +13,15 @@ import java.util.Set; import javax.crypto.Cipher; import javax.crypto.SecretKey; +import javax.crypto.SecretKeyFactory; import javax.crypto.spec.IvParameterSpec; +import javax.crypto.spec.PBEKeySpec; import javax.crypto.spec.RC2ParameterSpec; import javax.crypto.spec.SecretKeySpec; import org.bouncycastle.asn1.ASN1ObjectIdentifier; import org.bouncycastle.asn1.nist.NISTObjectIdentifiers; import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers; -import org.bouncycastle.crypto.PBEParametersGenerator; -import org.bouncycastle.crypto.generators.OpenSSLPBEParametersGenerator; -import org.bouncycastle.crypto.generators.PKCS5S2ParametersGenerator; -import org.bouncycastle.crypto.params.KeyParameter; import org.bouncycastle.jcajce.util.JcaJceHelper; import org.bouncycastle.openssl.EncryptionException; import org.bouncycastle.openssl.PEMException; @@ -50,6 +52,12 @@ class PEMUtilities KEYSIZES.put(NISTObjectIdentifiers.id_aes128_CBC.getId(), Integers.valueOf(128)); KEYSIZES.put(NISTObjectIdentifiers.id_aes192_CBC.getId(), Integers.valueOf(192)); KEYSIZES.put(NISTObjectIdentifiers.id_aes256_CBC.getId(), Integers.valueOf(256)); + KEYSIZES.put(PKCSObjectIdentifiers.pbeWithSHAAnd128BitRC4.getId(), Integers.valueOf(128)); + KEYSIZES.put(PKCSObjectIdentifiers.pbeWithSHAAnd40BitRC4, Integers.valueOf(40)); + KEYSIZES.put(PKCSObjectIdentifiers.pbeWithSHAAnd2_KeyTripleDES_CBC, Integers.valueOf(128)); + KEYSIZES.put(PKCSObjectIdentifiers.pbeWithSHAAnd3_KeyTripleDES_CBC, Integers.valueOf(192)); + KEYSIZES.put(PKCSObjectIdentifiers.pbeWithSHAAnd128BitRC2_CBC, Integers.valueOf(128)); + KEYSIZES.put(PKCSObjectIdentifiers.pbeWithSHAAnd40BitRC2_CBC, Integers.valueOf(40)); } static int getKeySize(String algorithm) @@ -77,16 +85,14 @@ class PEMUtilities return algOid.getId().startsWith(PKCSObjectIdentifiers.pkcs_12PbeIds.getId()); } - public static SecretKey generateSecretKeyForPKCS5Scheme2(String algorithm, char[] password, byte[] salt, int iterationCount) + public static SecretKey generateSecretKeyForPKCS5Scheme2(JcaJceHelper helper, String algorithm, char[] password, byte[] salt, int iterationCount) + throws NoSuchProviderException, NoSuchAlgorithmException, InvalidKeySpecException { - PBEParametersGenerator generator = new PKCS5S2ParametersGenerator(); + SecretKeyFactory keyGen = helper.createSecretKeyFactory("PBKDF2with8BIT"); - generator.init( - PBEParametersGenerator.PKCS5PasswordToBytes(password), - salt, - iterationCount); + SecretKey sKey = keyGen.generateSecret(new PBEKeySpec(password, salt, iterationCount, PEMUtilities.getKeySize(algorithm))); - return new SecretKeySpec(((KeyParameter)generator.generateDerivedParameters(PEMUtilities.getKeySize(algorithm))).getKey(), algorithm); + return new SecretKeySpec(sKey.getEncoded(), algorithm); } static byte[] crypt( @@ -125,7 +131,6 @@ class PEMUtilities padding = "NoPadding"; } - // Figure out algorithm and key size. if (dekAlgName.startsWith("DES-EDE")) { @@ -133,17 +138,17 @@ class PEMUtilities // "DES-EDE" is actually des2 in OpenSSL-speak! // "DES-EDE3" is des3. boolean des2 = !dekAlgName.startsWith("DES-EDE3"); - sKey = getKey(password, alg, 24, iv, des2); + sKey = getKey(helper, password, alg, 24, iv, des2); } else if (dekAlgName.startsWith("DES-")) { alg = "DES"; - sKey = getKey(password, alg, 8, iv); + sKey = getKey(helper, password, alg, 8, iv); } else if (dekAlgName.startsWith("BF-")) { alg = "Blowfish"; - sKey = getKey(password, alg, 16, iv); + sKey = getKey(helper, password, alg, 16, iv); } else if (dekAlgName.startsWith("RC2-")) { @@ -157,7 +162,7 @@ class PEMUtilities { keyBits = 64; } - sKey = getKey(password, alg, keyBits / 8, iv); + sKey = getKey(helper, password, alg, keyBits / 8, iv); if (paramSpec == null) // ECB block mode { paramSpec = new RC2ParameterSpec(keyBits); @@ -194,7 +199,7 @@ class PEMUtilities { throw new EncryptionException("unknown AES encryption with private key"); } - sKey = getKey(password, "AES", keyBits / 8, salt); + sKey = getKey(helper, password, "AES", keyBits / 8, salt); } else { @@ -225,33 +230,43 @@ class PEMUtilities } private static SecretKey getKey( + JcaJceHelper helper, char[] password, String algorithm, int keyLength, byte[] salt) + throws PEMException { - return getKey(password, algorithm, keyLength, salt, false); + return getKey(helper, password, algorithm, keyLength, salt, false); } private static SecretKey getKey( + JcaJceHelper helper, char[] password, String algorithm, int keyLength, byte[] salt, boolean des2) + throws PEMException { - OpenSSLPBEParametersGenerator pGen = new OpenSSLPBEParametersGenerator(); + try + { + PBEKeySpec spec = new PBEKeySpec(password, salt, 1, keyLength * 8); + SecretKeyFactory keyFactory = helper.createSecretKeyFactory("PBKDF-OpenSSL"); - pGen.init(PBEParametersGenerator.PKCS5PasswordToBytes(password), salt); + byte[] key = keyFactory.generateSecret(spec).getEncoded(); - KeyParameter keyParam; - keyParam = (KeyParameter) pGen.generateDerivedParameters(keyLength * 8); - byte[] key = keyParam.getKey(); - if (des2 && key.length >= 24) + if (des2 && key.length >= 24) + { + // For DES2, we must copy first 8 bytes into the last 8 bytes. + System.arraycopy(key, 0, key, 16, 8); + } + + return new SecretKeySpec(key, algorithm); + } + catch (GeneralSecurityException e) { - // For DES2, we must copy first 8 bytes into the last 8 bytes. - System.arraycopy(key, 0, key, 16, 8); + throw new PEMException("Unable to create OpenSSL PBDKF: " + e.getMessage(), e); } - return new SecretKeySpec(key, algorithm); } } diff --git a/bcpkix/src/main/java/org/bouncycastle/openssl/test/AllTests.java b/bcpkix/src/main/java/org/bouncycastle/openssl/test/AllTests.java index faae18e8..b7b25c35 100644 --- a/bcpkix/src/main/java/org/bouncycastle/openssl/test/AllTests.java +++ b/bcpkix/src/main/java/org/bouncycastle/openssl/test/AllTests.java @@ -11,6 +11,7 @@ import java.security.NoSuchProviderException; import java.security.PrivateKey; import java.security.Security; +import junit.extensions.TestSetup; import junit.framework.Test; import junit.framework.TestCase; import junit.framework.TestSuite; @@ -18,21 +19,31 @@ import org.bouncycastle.asn1.ASN1ObjectIdentifier; import org.bouncycastle.asn1.pkcs.PrivateKeyInfo; import org.bouncycastle.jce.provider.BouncyCastleProvider; import org.bouncycastle.openssl.PEMParser; -import org.bouncycastle.openssl.PEMWriter; import org.bouncycastle.openssl.PKCS8Generator; import org.bouncycastle.openssl.jcajce.JcaPEMKeyConverter; +import org.bouncycastle.openssl.jcajce.JcaPEMWriter; import org.bouncycastle.openssl.jcajce.JcaPKCS8Generator; import org.bouncycastle.openssl.jcajce.JceOpenSSLPKCS8DecryptorProviderBuilder; import org.bouncycastle.openssl.jcajce.JceOpenSSLPKCS8EncryptorBuilder; import org.bouncycastle.operator.OperatorCreationException; import org.bouncycastle.pkcs.PKCS8EncryptedPrivateKeyInfo; import org.bouncycastle.pkcs.PKCSException; +import org.bouncycastle.util.encoders.Base64; import org.bouncycastle.util.test.SimpleTestResult; public class AllTests extends TestCase { + private static final byte[] aesVec = Base64.decode( + "MIIC2zBVBgkqhkiG9w0BBQ0wSDAnBgkqhkiG9w0BBQwwGgQUJCXGcAtNlIKnbOigO9dFiEax0VACAggAMB0GCWCGSAFlAwQBKgQQHc1vpUS4cErEZut/nwhkSQSCAoACXZhhr0lx1Ww3d6t+ALjEbX8KopM/odVnYn8QWIvwDwKm+1eYL9e72XAu7pDM8yiYctnnFR9n+RfRj19b3GXIJkhxtLcIb0LqmRgy/Gna07PhrNXcWZ8i5kzt/wpxbgKI06k2bqCovYmfMkrLOnRIUNx8hRMvzQosjp32enKoeYRVPRii0VrKgzwPv1Qqyaq6uW4NErkMqoYJU3asFhB/OH6vSwOEVW69U13Ort8g0mmZJGDDHhctRbu29HMNROxGlGwt4t/EBOXTM2PHFS34zQK128Z2Zc6X7q7tSo1ENcNQqL9fnyoK4iXMu7bHKe0fslGw+s55b5KysSu6fcQfxIHA/GYpn5AKutdLTCzIiaPCdd5f5kWoijrTfcNKn9r8eWpgpSEFU5n96RNevGr7sYO3P0xL2wQQKb/V9AIIdFwyMfL0e5gR85ToG66AqK2pXSSfX7hqQYMyndeP9CRmhefG6/8cSUzrXXpx1WZ1U/U3E/asNlXwJ9AfFESLnT32s6es+1qLbHMZ7vkCxFyXZb2oK7+eduUB+5QbddEDlHhbpUpxbBkjpRq7rHO+T1m+ZWbjgD6EhVhmS5BXrlPHdWIfTUBdB0mwcvM4qVgEnEHqE+JGq71Xl12XhDH8sQHcd1NDLtVPY8GMIxFghvL7cPdfs8HccCdDv3dDcJw54Dn5xqWYPYitn/eMeJB5pnfekR/ko+zZd7dJlfU9JqjGyfpy3KnsShERSJd2LZDAvdb1Xp54ZsujblMc1kPyyzJfxBWDvoygCag0/42eHDp6vTIpYI3v+Wm/nWuVpq6JMAip0XFHEMhdMKW0SNp8gZxKTuDfCpVWvuF2WBVG1rKu"); + + private static final byte[] desEDEVec = Base64.decode( + "MIIC0jBMBgkqhkiG9w0BBQ0wPzAnBgkqhkiG9w0BBQwwGgQUaFB4TMBDEqCMfFRIb2G8Hc72p7wCAggAMBQGCCqGSIb3DQMHBAiMXRDFMwbnhwSCAoBLCzHx112fm3JTTOrYy9eiNrbb6dcAqYGBM+3uJm9D6/QOJ1dQOJKmZXFKebs057X6Uy7dpntpBC23golF53Mx7I+cM50xb3VzAXRWfLBZ7DmxgVojF4YgPFSFoOsdpaw1wTkCqU16O5q4zIk6uVjbPYcK9WhGxSYBmnw7ih38a3nBpehTWrWjbjP9QjK2TV79RRlLkU//QVrTJdDuOUhyFthfigWrNvPuC1nM62JbgsVrIFfNqmn63Du2356NVk4ZbI+0rnVxRG4LhFZix1xqj5BvYpUpMSjU4JwzcBFWhImoIq0RqXcFIKpaVqxLU/fNG8qq0v5ydb5Bfa/Ln2vUk/+yc7Y6eS/aD0kQXoaq+06h81FRBkkmeFFTMxMCrMCuycq6Rgufq9X2h4e+6dmWfc/d+CwpMY5BrVEc04jeVF0gOKevrfIHa7bhJJUNtGKO5hpHmIBvcqcC6NhaX+CvFS/RWNknxqb+aobyr/N/+bvA5h5UDRPKbUlyUWOIpkl9TGKNGrNwe7UnhmB6XYe5h2Dc/X2VFeRn43QqCTHbjSMX+o3yjS51Uqd8ufBFplV7o4dvw+46097G113Pbn/Bbqpl5w90r+G6+w0jpK9pB51ZfY9oAgKKhtFJVh1UFm6sXG+TTK1g7Yq4/BFjDRSMlnaIgGI8WaSWYSluxHes/Ek6Tmybsin+YXajmdfCg4LLxQJ/1UXksmQ19gtytXjXFtNtnFHiTqI5cWSfWkYoY7LLJw8qKzc2eRX3rLPmAnlOgyHRZ732V05CmYayHN/n440BU0GmuEqmTeINqrLpnUeq7Y6UrXV8wusgWaEhqSMn4fW7a0HvjTKdrWHhq8gP"); + + private static final byte[] desEDEpkcs12Vec = Base64.decode( + "MIICrjAoBgoqhkiG9w0BDAEDMBoEFA0yd6BYRViRmzBKN/MHaXcKT4hkAgIIAASCAoD5Z3YR8tVD4d+fyGVvvx3f+ePw/FRuB91fjJNukDAPpGbhVXm33b81GrrzucjTBHv5YciVQdyrhkRoqVNN77rOPJkMGENKkggJt+DuFcjqoMFB6Tkug7QhtwRn0n3jMjw7LraCOSuHg1bZm0vKmrRvzlvk+fcFWoa0+GKunbzM/b8/mg3nViOkxrrGEx5fcaXB97hwxniTz7tKmlj+BnV72XMt/RUh/IsXlDNX9iUfmm0cMKjKPz4Kll31GGbt4vG/iWsYJ0rF6XP8Dd5ZlUy+1q9GMM9M2/w6kffH8QxkWELbitUAaba3QV8+dzQrkAgW8yzThY3fEeg3dYGS1oKHdP8r+OiRQEkh196xAs8aFidAbkpWS76UoI/R7yMrphRa2u2P+0AySkOKLbbF9sCEUXEDupif2uSMxW39rIX1E8Nn4MW/onL0UxRNQ4ufiQdQX1UmNSVs5GyPm7iGH5FfouFGkH3oZeIcXHJEAGt1BkKFDwQyH0CbS6ynvOBGku7P5SlmNogqy2IgLl3o4emyJc8Xi1S7Ygt+LdWNrSVmOIMAOJlrjVlVezOCAEGbsZyU/HgskZPVSbDTZydCvY9rY3htbnq+sm+4Ug8lrDsxkP+5NOu2YEcegPItj/EV0AWH6r96gzYuNPtkp+ij1MJn5He1Ms5Th6yhSL5Opuq20TNSS61Cml3Put7H402x+R+W+eLkf/7V10uKOZxT9RNKe6pd5HbO17nuY1/yMdq6WL5+B2YTOkBUl96Pn4frlOnu3Ll0h+27t/1rgeWWgXTU4YTxOrolI/ZIvIfaDAl34NeqmZQbRFy0wnLTH6fgOaBa+rgiOfHTc/PXMkALMHiu"); + public void testOpenSSL() { if (Security.getProvider("BC") == null) @@ -80,7 +91,7 @@ public class throws NoSuchProviderException, NoSuchAlgorithmException, IOException, OperatorCreationException, PKCSException { ByteArrayOutputStream bOut = new ByteArrayOutputStream(); - PEMWriter pWrt = new PEMWriter(new OutputStreamWriter(bOut)); + JcaPEMWriter pWrt = new JcaPEMWriter(new OutputStreamWriter(bOut)); JceOpenSSLPKCS8EncryptorBuilder encryptorBuilder = new JceOpenSSLPKCS8EncryptorBuilder(algorithm); @@ -103,6 +114,31 @@ public class assertEquals(key, rdKey); } + public void testVectors() + throws Exception + { + if (Security.getProvider("BC") == null) + { + Security.addProvider(new BouncyCastleProvider()); + } + + PKCS8EncryptedPrivateKeyInfo encInfo = new PKCS8EncryptedPrivateKeyInfo(aesVec); + + PrivateKey key = new JcaPEMKeyConverter().setProvider("BC").getPrivateKey(encInfo.decryptPrivateKeyInfo(new JceOpenSSLPKCS8DecryptorProviderBuilder().setProvider("BC").build("hello".toCharArray()))); + + encInfo = new PKCS8EncryptedPrivateKeyInfo(desEDEVec); + + PrivateKey rdKey = new JcaPEMKeyConverter().setProvider("BC").getPrivateKey(encInfo.decryptPrivateKeyInfo(new JceOpenSSLPKCS8DecryptorProviderBuilder().setProvider("BC").build("hello".toCharArray()))); + + TestCase.assertEquals(key, rdKey); + + encInfo = new PKCS8EncryptedPrivateKeyInfo(desEDEpkcs12Vec); + + rdKey = new JcaPEMKeyConverter().setProvider("BC").getPrivateKey(encInfo.decryptPrivateKeyInfo(new JceOpenSSLPKCS8DecryptorProviderBuilder().setProvider("BC").build("hello".toCharArray()))); + + TestCase.assertEquals(key, rdKey); + } + public void testPKCS8PlainNew() throws Exception { @@ -117,7 +153,7 @@ public class PrivateKey key = kpGen.generateKeyPair().getPrivate(); ByteArrayOutputStream bOut = new ByteArrayOutputStream(); - PEMWriter pWrt = new PEMWriter(new OutputStreamWriter(bOut)); + JcaPEMWriter pWrt = new JcaPEMWriter(new OutputStreamWriter(bOut)); PKCS8Generator pkcs8 = new JcaPKCS8Generator(key, null); pWrt.writeObject(pkcs8); @@ -146,6 +182,25 @@ public class suite.addTestSuite(AllTests.class); - return suite; + return new BCTestSetup(suite); + } + + static class BCTestSetup + extends TestSetup + { + public BCTestSetup(Test test) + { + super(test); + } + + protected void setUp() + { + + } + + protected void tearDown() + { + + } } } diff --git a/bcpkix/src/main/java/org/bouncycastle/openssl/test/ParserTest.java b/bcpkix/src/main/java/org/bouncycastle/openssl/test/ParserTest.java index 521106b1..054abdef 100644 --- a/bcpkix/src/main/java/org/bouncycastle/openssl/test/ParserTest.java +++ b/bcpkix/src/main/java/org/bouncycastle/openssl/test/ParserTest.java @@ -8,6 +8,8 @@ import java.io.InputStream; import java.io.InputStreamReader; import java.io.OutputStreamWriter; import java.io.Reader; +import java.io.StringReader; +import java.io.StringWriter; import java.math.BigInteger; import java.security.KeyPair; import java.security.KeyPairGenerator; @@ -24,18 +26,22 @@ import org.bouncycastle.asn1.ASN1ObjectIdentifier; import org.bouncycastle.asn1.cms.CMSObjectIdentifiers; import org.bouncycastle.asn1.cms.ContentInfo; import org.bouncycastle.asn1.pkcs.PrivateKeyInfo; +import org.bouncycastle.asn1.x509.KeyPurposeId; import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo; import org.bouncycastle.asn1.x9.ECNamedCurveTable; import org.bouncycastle.asn1.x9.X9ECParameters; import org.bouncycastle.cert.X509CertificateHolder; import org.bouncycastle.jce.provider.BouncyCastleProvider; +import org.bouncycastle.openssl.CertificateTrustBlock; import org.bouncycastle.openssl.PEMDecryptorProvider; import org.bouncycastle.openssl.PEMEncryptedKeyPair; import org.bouncycastle.openssl.PEMKeyPair; import org.bouncycastle.openssl.PEMParser; -import org.bouncycastle.openssl.PEMWriter; import org.bouncycastle.openssl.PasswordFinder; +import org.bouncycastle.openssl.X509TrustedCertificateBlock; +import org.bouncycastle.openssl.bc.BcPEMDecryptorProvider; import org.bouncycastle.openssl.jcajce.JcaPEMKeyConverter; +import org.bouncycastle.openssl.jcajce.JcaPEMWriter; import org.bouncycastle.openssl.jcajce.JceOpenSSLPKCS8DecryptorProviderBuilder; import org.bouncycastle.openssl.jcajce.JcePEMDecryptorProviderBuilder; import org.bouncycastle.operator.InputDecryptorProvider; @@ -226,7 +232,7 @@ public class ParserTest // PKCS7 // ByteArrayOutputStream bOut = new ByteArrayOutputStream(); - PEMWriter pWrt = new PEMWriter(new OutputStreamWriter(bOut)); + JcaPEMWriter pWrt = new JcaPEMWriter(new OutputStreamWriter(bOut)); pWrt.writeObject(d); @@ -272,7 +278,7 @@ public class ParserTest doDudPasswordTest("3ee7a8", 10, "DER length more than 4 bytes: 57"); doDudPasswordTest("41af75", 11, "unknown tag 16 encountered"); doDudPasswordTest("1704a5", 12, "corrupted stream detected"); - doDudPasswordTest("1c5822", 13, "unknown object in getInstance: org.bouncycastle.asn1.DERUTF8String"); + doDudPasswordTest("1c5822", 13, "Extra data detected in stream"); doDudPasswordTest("5a3d16", 14, "corrupted stream detected"); doDudPasswordTest("8d0c97", 15, "corrupted stream detected"); doDudPasswordTest("bc0daf", 16, "corrupted stream detected"); @@ -281,7 +287,7 @@ public class ParserTest doNoPasswordTest(); // encrypted private key test - InputDecryptorProvider pkcs8Prov = new JceOpenSSLPKCS8DecryptorProviderBuilder().build("password".toCharArray()); + InputDecryptorProvider pkcs8Prov = new JceOpenSSLPKCS8DecryptorProviderBuilder().setProvider("BC").build("password".toCharArray()); pemRd = openPEMResource("enckey.pem"); PKCS8EncryptedPrivateKeyInfo encPrivKeyInfo = (PKCS8EncryptedPrivateKeyInfo)pemRd.readObject(); @@ -315,6 +321,54 @@ public class ParserTest fail("decryption of private key data check failed"); } } + + pemRd = openPEMResource("trusted_cert.pem"); + + X509TrustedCertificateBlock trusted = (X509TrustedCertificateBlock)pemRd.readObject(); + + checkTrustedCert(trusted); + + StringWriter stringWriter = new StringWriter(); + + pWrt = new JcaPEMWriter(stringWriter); + + pWrt.writeObject(trusted); + + pWrt.close(); + + pemRd = new PEMParser(new StringReader(stringWriter.toString())); + + trusted = (X509TrustedCertificateBlock)pemRd.readObject(); + + checkTrustedCert(trusted); + } + + private void checkTrustedCert(X509TrustedCertificateBlock trusted) + { + CertificateTrustBlock trustBlock = trusted.getTrustBlock(); + + if (!"Fred".equals(trustBlock.getAlias())) + { + fail("alias not found"); + } + + if (trustBlock.getUses().size() != 3) + { + fail("key purpose usages wrong size"); + } + if (!trustBlock.getUses().contains(KeyPurposeId.id_kp_OCSPSigning)) + { + fail("key purpose use not found"); + } + + if (trustBlock.getProhibitions().size() != 1) + { + fail("key purpose prohibitions wrong size"); + } + if (!trustBlock.getProhibitions().contains(KeyPurposeId.id_kp_clientAuth)) + { + fail("key purpose prohibition not found"); + } } private void keyPairTest( @@ -324,7 +378,7 @@ public class ParserTest { PEMParser pemRd; ByteArrayOutputStream bOut = new ByteArrayOutputStream(); - PEMWriter pWrt = new PEMWriter(new OutputStreamWriter(bOut)); + JcaPEMWriter pWrt = new JcaPEMWriter(new OutputStreamWriter(bOut)); pWrt.writeObject(pair.getPublic()); @@ -343,7 +397,7 @@ public class ParserTest } bOut = new ByteArrayOutputStream(); - pWrt = new PEMWriter(new OutputStreamWriter(bOut)); + pWrt = new JcaPEMWriter(new OutputStreamWriter(bOut)); pWrt.writeObject(pair.getPrivate()); @@ -414,8 +468,13 @@ public class ParserTest Class expectedPrivKeyClass) throws IOException { - JcaPEMKeyConverter converter = new JcaPEMKeyConverter().setProvider("BC"); - PEMDecryptorProvider decProv = new JcePEMDecryptorProviderBuilder().setProvider("BC").build("changeit".toCharArray()); + keyDecryptTest(fileName, expectedPrivKeyClass, new JcePEMDecryptorProviderBuilder().setProvider("BC").build("changeit".toCharArray())); + keyDecryptTest(fileName, expectedPrivKeyClass, new BcPEMDecryptorProvider("changeit".toCharArray())); + } + + private void keyDecryptTest(String fileName, Class expectedPrivKeyClass, PEMDecryptorProvider decProv) + throws IOException + { PEMParser pr = openPEMResource("data/" + fileName); Object o = pr.readObject(); @@ -424,6 +483,7 @@ public class ParserTest fail("Didn't find OpenSSL key"); } + JcaPEMKeyConverter converter = new JcaPEMKeyConverter().setProvider("BC"); KeyPair kp = (o instanceof PEMEncryptedKeyPair) ? converter.getKeyPair(((PEMEncryptedKeyPair)o).decryptKeyPair(decProv)) : converter.getKeyPair((PEMKeyPair)o); diff --git a/bcpkix/src/main/java/org/bouncycastle/openssl/test/WriterTest.java b/bcpkix/src/main/java/org/bouncycastle/openssl/test/WriterTest.java index e41efd6f..783bce5a 100644 --- a/bcpkix/src/main/java/org/bouncycastle/openssl/test/WriterTest.java +++ b/bcpkix/src/main/java/org/bouncycastle/openssl/test/WriterTest.java @@ -21,10 +21,11 @@ import org.bouncycastle.jce.provider.BouncyCastleProvider; import org.bouncycastle.openssl.PEMEncryptedKeyPair; import org.bouncycastle.openssl.PEMKeyPair; import org.bouncycastle.openssl.PEMParser; -import org.bouncycastle.openssl.PEMWriter; import org.bouncycastle.openssl.PasswordFinder; +import org.bouncycastle.openssl.bc.BcPEMDecryptorProvider; import org.bouncycastle.openssl.jcajce.JcaMiscPEMGenerator; import org.bouncycastle.openssl.jcajce.JcaPEMKeyConverter; +import org.bouncycastle.openssl.jcajce.JcaPEMWriter; import org.bouncycastle.openssl.jcajce.JcePEMDecryptorProviderBuilder; import org.bouncycastle.openssl.jcajce.JcePEMEncryptorBuilder; import org.bouncycastle.util.encoders.Base64; @@ -133,7 +134,7 @@ public class WriterTest doWriteReadTests(privKey, "BC", algorithms); // override test - PEMWriter pWrt = new PEMWriter(new OutputStreamWriter(new ByteArrayOutputStream())); + JcaPEMWriter pWrt = new JcaPEMWriter(new OutputStreamWriter(new ByteArrayOutputStream())); Object o = new PemObject("FRED", new byte[100]); pWrt.writeObject(o); @@ -159,7 +160,7 @@ public class WriterTest throws IOException { StringWriter sw = new StringWriter(); - PEMWriter pw = new PEMWriter(sw); + JcaPEMWriter pw = new JcaPEMWriter(sw); pw.writeObject(akp); pw.close(); @@ -191,7 +192,7 @@ public class WriterTest throws IOException { StringWriter sw = new StringWriter(); - PEMWriter pw = new PEMWriter(sw); + JcaPEMWriter pw = new JcaPEMWriter(sw); pw.writeObject(new JcaMiscPEMGenerator(akp, new JcePEMEncryptorBuilder(algorithm).setSecureRandom(random).build(testPassword))); pw.close(); @@ -236,6 +237,14 @@ public class WriterTest { fail("Failed to read back test key encoded with: " + algorithm); } + + kp = new JcaPEMKeyConverter().setProvider("BC").getKeyPair(((PEMEncryptedKeyPair)o).decryptKeyPair(new BcPEMDecryptorProvider(testPassword))); + privKey = kp.getPrivate(); + + if (!akp.equals(privKey)) + { + fail("BC failed to read back test key encoded with: " + algorithm); + } } public static void main( diff --git a/bcpkix/src/main/java/org/bouncycastle/operator/AlgorithmNameFinder.java b/bcpkix/src/main/java/org/bouncycastle/operator/AlgorithmNameFinder.java index c196cfc6..bacb3595 100644 --- a/bcpkix/src/main/java/org/bouncycastle/operator/AlgorithmNameFinder.java +++ b/bcpkix/src/main/java/org/bouncycastle/operator/AlgorithmNameFinder.java @@ -12,7 +12,7 @@ public interface AlgorithmNameFinder * Return true if the passed in objectIdentifier has a "human friendly" name associated with it. * * @param objectIdentifier the OID of interest. - * @boolean true if a name lookup exists for the OID, false otherwise. + * @return true if a name lookup exists for the OID, false otherwise. */ boolean hasAlgorithmName(ASN1ObjectIdentifier objectIdentifier); diff --git a/bcpkix/src/main/java/org/bouncycastle/operator/DefaultAlgorithmNameFinder.java b/bcpkix/src/main/java/org/bouncycastle/operator/DefaultAlgorithmNameFinder.java index 6defb27f..a0bba2a5 100644 --- a/bcpkix/src/main/java/org/bouncycastle/operator/DefaultAlgorithmNameFinder.java +++ b/bcpkix/src/main/java/org/bouncycastle/operator/DefaultAlgorithmNameFinder.java @@ -7,6 +7,7 @@ import org.bouncycastle.asn1.ASN1ObjectIdentifier; import org.bouncycastle.asn1.bsi.BSIObjectIdentifiers; import org.bouncycastle.asn1.cryptopro.CryptoProObjectIdentifiers; import org.bouncycastle.asn1.eac.EACObjectIdentifiers; +import org.bouncycastle.asn1.gnu.GNUObjectIdentifiers; import org.bouncycastle.asn1.kisa.KISAObjectIdentifiers; import org.bouncycastle.asn1.misc.MiscObjectIdentifiers; import org.bouncycastle.asn1.nist.NISTObjectIdentifiers; @@ -16,7 +17,6 @@ import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers; import org.bouncycastle.asn1.teletrust.TeleTrusTObjectIdentifiers; import org.bouncycastle.asn1.x509.AlgorithmIdentifier; import org.bouncycastle.asn1.x9.X9ObjectIdentifiers; -import org.bouncycastle.cms.CMSEnvelopedGenerator; public class DefaultAlgorithmNameFinder implements AlgorithmNameFinder @@ -78,6 +78,7 @@ public class DefaultAlgorithmNameFinder algorithms.put(X9ObjectIdentifiers.ecdsa_with_SHA384, "SHA384WITHECDSA"); algorithms.put(X9ObjectIdentifiers.ecdsa_with_SHA512, "SHA512WITHECDSA"); algorithms.put(X9ObjectIdentifiers.id_dsa_with_sha1, "SHA1WITHDSA"); + algorithms.put(GNUObjectIdentifiers.Tiger_192, "Tiger"); algorithms.put(PKCSObjectIdentifiers.RC2_CBC, "RC2/CBC"); algorithms.put(PKCSObjectIdentifiers.des_EDE3_CBC, "DESEDE-3KEY/CBC"); @@ -87,10 +88,34 @@ public class DefaultAlgorithmNameFinder algorithms.put(NISTObjectIdentifiers.id_aes128_CBC, "AES-128/CBC"); algorithms.put(NISTObjectIdentifiers.id_aes192_CBC, "AES-192/CBC"); algorithms.put(NISTObjectIdentifiers.id_aes256_CBC, "AES-256/CBC"); + algorithms.put(NISTObjectIdentifiers.id_aes128_CFB, "AES-128/CFB"); + algorithms.put(NISTObjectIdentifiers.id_aes192_CFB, "AES-192/CFB"); + algorithms.put(NISTObjectIdentifiers.id_aes256_CFB, "AES-256/CFB"); + algorithms.put(NISTObjectIdentifiers.id_aes128_OFB, "AES-128/OFB"); + algorithms.put(NISTObjectIdentifiers.id_aes192_OFB, "AES-192/OFB"); + algorithms.put(NISTObjectIdentifiers.id_aes256_OFB, "AES-256/OFB"); algorithms.put(NTTObjectIdentifiers.id_camellia128_cbc, "CAMELLIA-128/CBC"); - algorithms.put(NTTObjectIdentifiers.id_camellia192_cbc, "CAMELLIA-128/CBC"); - algorithms.put(NTTObjectIdentifiers.id_camellia256_cbc, "CAMELLIA-128/CBC"); + algorithms.put(NTTObjectIdentifiers.id_camellia192_cbc, "CAMELLIA-192/CBC"); + algorithms.put(NTTObjectIdentifiers.id_camellia256_cbc, "CAMELLIA-256/CBC"); algorithms.put(KISAObjectIdentifiers.id_seedCBC, "SEED/CBC"); + algorithms.put(MiscObjectIdentifiers.as_sys_sec_alg_ideaCBC, "IDEA/CBC"); + algorithms.put(MiscObjectIdentifiers.cast5CBC, "CAST5/CBC"); + algorithms.put(MiscObjectIdentifiers.cryptlib_algorithm_blowfish_ECB, "Blowfish/ECB"); + algorithms.put(MiscObjectIdentifiers.cryptlib_algorithm_blowfish_CBC, "Blowfish/CBC"); + algorithms.put(MiscObjectIdentifiers.cryptlib_algorithm_blowfish_CFB, "Blowfish/CFB"); + algorithms.put(MiscObjectIdentifiers.cryptlib_algorithm_blowfish_OFB, "Blowfish/OFB"); + algorithms.put(GNUObjectIdentifiers.Serpent_128_ECB, "Serpent-128/ECB"); + algorithms.put(GNUObjectIdentifiers.Serpent_128_CBC, "Serpent-128/CBC"); + algorithms.put(GNUObjectIdentifiers.Serpent_128_CFB, "Serpent-128/CFB"); + algorithms.put(GNUObjectIdentifiers.Serpent_128_OFB, "Serpent-128/OFB"); + algorithms.put(GNUObjectIdentifiers.Serpent_192_ECB, "Serpent-192/ECB"); + algorithms.put(GNUObjectIdentifiers.Serpent_192_CBC, "Serpent-192/CBC"); + algorithms.put(GNUObjectIdentifiers.Serpent_192_CFB, "Serpent-192/CFB"); + algorithms.put(GNUObjectIdentifiers.Serpent_192_OFB, "Serpent-192/OFB"); + algorithms.put(GNUObjectIdentifiers.Serpent_256_ECB, "Serpent-256/ECB"); + algorithms.put(GNUObjectIdentifiers.Serpent_256_CBC, "Serpent-256/CBC"); + algorithms.put(GNUObjectIdentifiers.Serpent_256_CFB, "Serpent-256/CFB"); + algorithms.put(GNUObjectIdentifiers.Serpent_256_OFB, "Serpent-256/OFB"); } public boolean hasAlgorithmName(ASN1ObjectIdentifier objectIdentifier) diff --git a/bcpkix/src/main/java/org/bouncycastle/operator/DefaultDigestAlgorithmIdentifierFinder.java b/bcpkix/src/main/java/org/bouncycastle/operator/DefaultDigestAlgorithmIdentifierFinder.java index c03b5d3f..fca5693c 100644 --- a/bcpkix/src/main/java/org/bouncycastle/operator/DefaultDigestAlgorithmIdentifierFinder.java +++ b/bcpkix/src/main/java/org/bouncycastle/operator/DefaultDigestAlgorithmIdentifierFinder.java @@ -63,6 +63,20 @@ public class DefaultDigestAlgorithmIdentifierFinder digestNameToOids.put("SHA-384", NISTObjectIdentifiers.id_sha384); digestNameToOids.put("SHA-512", NISTObjectIdentifiers.id_sha512); + digestNameToOids.put("SHA1", OIWObjectIdentifiers.idSHA1); + digestNameToOids.put("SHA224", NISTObjectIdentifiers.id_sha224); + digestNameToOids.put("SHA256", NISTObjectIdentifiers.id_sha256); + digestNameToOids.put("SHA384", NISTObjectIdentifiers.id_sha384); + digestNameToOids.put("SHA512", NISTObjectIdentifiers.id_sha512); + + digestNameToOids.put("SHA3-224", NISTObjectIdentifiers.id_sha3_224); + digestNameToOids.put("SHA3-256", NISTObjectIdentifiers.id_sha3_256); + digestNameToOids.put("SHA3-384", NISTObjectIdentifiers.id_sha3_384); + digestNameToOids.put("SHA3-512", NISTObjectIdentifiers.id_sha3_512); + + digestNameToOids.put("SHAKE-128", NISTObjectIdentifiers.id_shake128); + digestNameToOids.put("SHAKE-256", NISTObjectIdentifiers.id_shake256); + digestNameToOids.put("GOST3411", CryptoProObjectIdentifiers.gostR3411); digestNameToOids.put("MD2", PKCSObjectIdentifiers.md2); diff --git a/bcpkix/src/main/java/org/bouncycastle/operator/DefaultSecretKeySizeProvider.java b/bcpkix/src/main/java/org/bouncycastle/operator/DefaultSecretKeySizeProvider.java index a1c6ba11..49e5027b 100644 --- a/bcpkix/src/main/java/org/bouncycastle/operator/DefaultSecretKeySizeProvider.java +++ b/bcpkix/src/main/java/org/bouncycastle/operator/DefaultSecretKeySizeProvider.java @@ -6,8 +6,10 @@ import java.util.Map; import org.bouncycastle.asn1.ASN1ObjectIdentifier; import org.bouncycastle.asn1.cryptopro.CryptoProObjectIdentifiers; +import org.bouncycastle.asn1.kisa.KISAObjectIdentifiers; import org.bouncycastle.asn1.nist.NISTObjectIdentifiers; import org.bouncycastle.asn1.ntt.NTTObjectIdentifiers; +import org.bouncycastle.asn1.oiw.OIWObjectIdentifiers; import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers; import org.bouncycastle.asn1.x509.AlgorithmIdentifier; import org.bouncycastle.util.Integers; @@ -26,14 +28,32 @@ public class DefaultSecretKeySizeProvider keySizes.put(new ASN1ObjectIdentifier("1.2.840.113533.7.66.10"), Integers.valueOf(128)); keySizes.put(PKCSObjectIdentifiers.des_EDE3_CBC, Integers.valueOf(192)); + keySizes.put(PKCSObjectIdentifiers.id_alg_CMS3DESwrap, Integers.valueOf(192)); + keySizes.put(PKCSObjectIdentifiers.des_EDE3_CBC, Integers.valueOf(192)); keySizes.put(NISTObjectIdentifiers.id_aes128_CBC, Integers.valueOf(128)); keySizes.put(NISTObjectIdentifiers.id_aes192_CBC, Integers.valueOf(192)); keySizes.put(NISTObjectIdentifiers.id_aes256_CBC, Integers.valueOf(256)); + keySizes.put(NISTObjectIdentifiers.id_aes128_GCM, Integers.valueOf(128)); + keySizes.put(NISTObjectIdentifiers.id_aes192_GCM, Integers.valueOf(192)); + keySizes.put(NISTObjectIdentifiers.id_aes256_GCM, Integers.valueOf(256)); + keySizes.put(NISTObjectIdentifiers.id_aes128_CCM, Integers.valueOf(128)); + keySizes.put(NISTObjectIdentifiers.id_aes192_CCM, Integers.valueOf(192)); + keySizes.put(NISTObjectIdentifiers.id_aes256_CCM, Integers.valueOf(256)); + keySizes.put(NISTObjectIdentifiers.id_aes128_wrap, Integers.valueOf(128)); + keySizes.put(NISTObjectIdentifiers.id_aes192_wrap, Integers.valueOf(192)); + keySizes.put(NISTObjectIdentifiers.id_aes256_wrap, Integers.valueOf(256)); keySizes.put(NTTObjectIdentifiers.id_camellia128_cbc, Integers.valueOf(128)); keySizes.put(NTTObjectIdentifiers.id_camellia192_cbc, Integers.valueOf(192)); keySizes.put(NTTObjectIdentifiers.id_camellia256_cbc, Integers.valueOf(256)); + keySizes.put(NTTObjectIdentifiers.id_camellia128_wrap, Integers.valueOf(128)); + keySizes.put(NTTObjectIdentifiers.id_camellia192_wrap, Integers.valueOf(192)); + keySizes.put(NTTObjectIdentifiers.id_camellia256_wrap, Integers.valueOf(256)); + + keySizes.put(KISAObjectIdentifiers.id_seedCBC, Integers.valueOf(128)); + + keySizes.put(OIWObjectIdentifiers.desCBC, Integers.valueOf(64)); keySizes.put(CryptoProObjectIdentifiers.gostR28147_gcfb, Integers.valueOf(256)); diff --git a/bcpkix/src/main/java/org/bouncycastle/operator/DefaultSignatureAlgorithmIdentifierFinder.java b/bcpkix/src/main/java/org/bouncycastle/operator/DefaultSignatureAlgorithmIdentifierFinder.java index 5eb18d45..3de36a13 100644 --- a/bcpkix/src/main/java/org/bouncycastle/operator/DefaultSignatureAlgorithmIdentifierFinder.java +++ b/bcpkix/src/main/java/org/bouncycastle/operator/DefaultSignatureAlgorithmIdentifierFinder.java @@ -88,7 +88,7 @@ public class DefaultSignatureAlgorithmIdentifierFinder algorithms.put("SHA512WITHPLAIN-ECDSA", BSIObjectIdentifiers.ecdsa_plain_SHA512); algorithms.put("RIPEMD160WITHPLAIN-ECDSA", BSIObjectIdentifiers.ecdsa_plain_RIPEMD160); algorithms.put("SHA1WITHCVC-ECDSA", EACObjectIdentifiers.id_TA_ECDSA_SHA_1); - algorithms.put("SHA224WITHPCVC-ECDSA", EACObjectIdentifiers.id_TA_ECDSA_SHA_224); + algorithms.put("SHA224WITHCVC-ECDSA", EACObjectIdentifiers.id_TA_ECDSA_SHA_224); algorithms.put("SHA256WITHCVC-ECDSA", EACObjectIdentifiers.id_TA_ECDSA_SHA_256); algorithms.put("SHA384WITHCVC-ECDSA", EACObjectIdentifiers.id_TA_ECDSA_SHA_384); algorithms.put("SHA512WITHCVC-ECDSA", EACObjectIdentifiers.id_TA_ECDSA_SHA_512); diff --git a/bcpkix/src/main/java/org/bouncycastle/operator/bc/BcAsymmetricKeyWrapper.java b/bcpkix/src/main/java/org/bouncycastle/operator/bc/BcAsymmetricKeyWrapper.java index f9c78087..2cac2278 100644 --- a/bcpkix/src/main/java/org/bouncycastle/operator/bc/BcAsymmetricKeyWrapper.java +++ b/bcpkix/src/main/java/org/bouncycastle/operator/bc/BcAsymmetricKeyWrapper.java @@ -47,7 +47,7 @@ public abstract class BcAsymmetricKeyWrapper try { byte[] keyEnc = OperatorUtils.getKeyBytes(encryptionKey); - keyEncryptionCipher.init(true, publicKey); + keyEncryptionCipher.init(true, params); return keyEncryptionCipher.processBlock(keyEnc, 0, keyEnc.length); } catch (InvalidCipherTextException e) diff --git a/bcpkix/src/main/java/org/bouncycastle/operator/jcajce/JceAsymmetricKeyUnwrapper.java b/bcpkix/src/main/java/org/bouncycastle/operator/jcajce/JceAsymmetricKeyUnwrapper.java index 8e0ea75e..2bbdd5fd 100644 --- a/bcpkix/src/main/java/org/bouncycastle/operator/jcajce/JceAsymmetricKeyUnwrapper.java +++ b/bcpkix/src/main/java/org/bouncycastle/operator/jcajce/JceAsymmetricKeyUnwrapper.java @@ -30,6 +30,7 @@ public class JceAsymmetricKeyUnwrapper private OperatorHelper helper = new OperatorHelper(new DefaultJcaJceHelper()); private Map extraMappings = new HashMap(); private PrivateKey privKey; + private boolean unwrappedKeyMustBeEncodable; public JceAsymmetricKeyUnwrapper(AlgorithmIdentifier algorithmIdentifier, PrivateKey privKey) { @@ -53,6 +54,21 @@ public class JceAsymmetricKeyUnwrapper } /** + * Flag that unwrapping must produce a key that will return a meaningful value from a call to Key.getEncoded(). + * This is important if you are using a HSM for unwrapping and using a software based provider for + * with the unwrapped key. Default value: false. + * + * @param unwrappedKeyMustBeEncodable true if getEncoded() should return key bytes, false if not necessary. + * @return this recipient. + */ + public JceAsymmetricKeyUnwrapper setMustProduceEncodableUnwrappedKey(boolean unwrappedKeyMustBeEncodable) + { + this.unwrappedKeyMustBeEncodable = unwrappedKeyMustBeEncodable; + + return this; + } + + /** * Internally algorithm ids are converted into cipher names using a lookup table. For some providers * the standard lookup table won't work. Use this method to establish a specific mapping from an * algorithm identifier to a specific algorithm. @@ -93,19 +109,38 @@ public class JceAsymmetricKeyUnwrapper { keyCipher.init(Cipher.UNWRAP_MODE, privKey); } + sKey = keyCipher.unwrap(encryptedKey, helper.getKeyAlgorithmName(encryptedKeyAlgorithm.getAlgorithm()), Cipher.SECRET_KEY); + + // check key will work with a software provider. + if (unwrappedKeyMustBeEncodable) + { + try + { + byte[] keyBytes = sKey.getEncoded(); + + if (keyBytes == null || keyBytes.length == 0) + { + sKey = null; + } + } + catch (Exception e) + { + sKey = null; // try doing a decrypt + } + } } catch (GeneralSecurityException e) - { + { // try decrypt } catch (IllegalStateException e) - { + { // try decrypt } catch (UnsupportedOperationException e) - { + { // try decrypt } catch (ProviderException e) - { + { // try decrypt } // some providers do not support UNWRAP (this appears to be only for asymmetric algorithms) diff --git a/bcpkix/src/main/java/org/bouncycastle/operator/jcajce/JceSymmetricKeyWrapper.java b/bcpkix/src/main/java/org/bouncycastle/operator/jcajce/JceSymmetricKeyWrapper.java index a8f712a5..18dabce5 100644 --- a/bcpkix/src/main/java/org/bouncycastle/operator/jcajce/JceSymmetricKeyWrapper.java +++ b/bcpkix/src/main/java/org/bouncycastle/operator/jcajce/JceSymmetricKeyWrapper.java @@ -14,6 +14,7 @@ import org.bouncycastle.asn1.DERNull; import org.bouncycastle.asn1.kisa.KISAObjectIdentifiers; import org.bouncycastle.asn1.nist.NISTObjectIdentifiers; import org.bouncycastle.asn1.ntt.NTTObjectIdentifiers; +import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers; import org.bouncycastle.asn1.x509.AlgorithmIdentifier; import org.bouncycastle.jcajce.util.DefaultJcaJceHelper; import org.bouncycastle.jcajce.util.NamedJcaJceHelper; @@ -78,12 +79,14 @@ public class JceSymmetricKeyWrapper private static AlgorithmIdentifier determineKeyEncAlg(SecretKey key) { - String algorithm = key.getAlgorithm(); + return determineKeyEncAlg(key.getAlgorithm(), key.getEncoded().length * 8); + } - if (algorithm.startsWith("DES")) + static AlgorithmIdentifier determineKeyEncAlg(String algorithm, int keySizeInBits) + { + if (algorithm.startsWith("DES") || algorithm.startsWith("TripleDES")) { - return new AlgorithmIdentifier(new ASN1ObjectIdentifier( - "1.2.840.113549.1.9.16.3.6"), DERNull.INSTANCE); + return new AlgorithmIdentifier(PKCSObjectIdentifiers.id_alg_CMS3DESwrap, DERNull.INSTANCE); } else if (algorithm.startsWith("RC2")) { @@ -92,18 +95,17 @@ public class JceSymmetricKeyWrapper } else if (algorithm.startsWith("AES")) { - int length = key.getEncoded().length * 8; ASN1ObjectIdentifier wrapOid; - if (length == 128) + if (keySizeInBits == 128) { wrapOid = NISTObjectIdentifiers.id_aes128_wrap; } - else if (length == 192) + else if (keySizeInBits == 192) { wrapOid = NISTObjectIdentifiers.id_aes192_wrap; } - else if (length == 256) + else if (keySizeInBits == 256) { wrapOid = NISTObjectIdentifiers.id_aes256_wrap; } @@ -122,18 +124,17 @@ public class JceSymmetricKeyWrapper } else if (algorithm.startsWith("Camellia")) { - int length = key.getEncoded().length * 8; ASN1ObjectIdentifier wrapOid; - if (length == 128) + if (keySizeInBits == 128) { wrapOid = NTTObjectIdentifiers.id_camellia128_wrap; } - else if (length == 192) + else if (keySizeInBits == 192) { wrapOid = NTTObjectIdentifiers.id_camellia192_wrap; } - else if (length == 256) + else if (keySizeInBits == 256) { wrapOid = NTTObjectIdentifiers.id_camellia256_wrap; } diff --git a/bcpkix/src/main/java/org/bouncycastle/operator/jcajce/OperatorHelper.java b/bcpkix/src/main/java/org/bouncycastle/operator/jcajce/OperatorHelper.java index f33b84a4..65a771f4 100644 --- a/bcpkix/src/main/java/org/bouncycastle/operator/jcajce/OperatorHelper.java +++ b/bcpkix/src/main/java/org/bouncycastle/operator/jcajce/OperatorHelper.java @@ -38,9 +38,11 @@ import org.bouncycastle.asn1.x509.AlgorithmIdentifier; import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo; import org.bouncycastle.asn1.x9.X9ObjectIdentifiers; import org.bouncycastle.cert.X509CertificateHolder; +import org.bouncycastle.jcajce.util.AlgorithmParametersUtils; import org.bouncycastle.jcajce.util.JcaJceHelper; -import org.bouncycastle.jcajce.util.JcaJceUtils; +import org.bouncycastle.jcajce.util.MessageDigestUtils; import org.bouncycastle.operator.OperatorCreationException; +import org.bouncycastle.util.Integers; class OperatorHelper { @@ -48,6 +50,7 @@ class OperatorHelper private static final Map asymmetricWrapperAlgNames = new HashMap(); private static final Map symmetricWrapperAlgNames = new HashMap(); private static final Map symmetricKeyAlgNames = new HashMap(); + private static final Map symmetricWrapperKeySizes = new HashMap(); static { @@ -108,6 +111,16 @@ class OperatorHelper symmetricWrapperAlgNames.put(KISAObjectIdentifiers.id_npki_app_cmsSeed_wrap, "SEEDWrap"); symmetricWrapperAlgNames.put(PKCSObjectIdentifiers.des_EDE3_CBC, "DESede"); + symmetricWrapperKeySizes.put(PKCSObjectIdentifiers.id_alg_CMS3DESwrap, Integers.valueOf(192)); + symmetricWrapperKeySizes.put(NISTObjectIdentifiers.id_aes128_wrap, Integers.valueOf(128)); + symmetricWrapperKeySizes.put(NISTObjectIdentifiers.id_aes192_wrap, Integers.valueOf(192)); + symmetricWrapperKeySizes.put(NISTObjectIdentifiers.id_aes256_wrap, Integers.valueOf(256)); + symmetricWrapperKeySizes.put(NTTObjectIdentifiers.id_camellia128_wrap, Integers.valueOf(128)); + symmetricWrapperKeySizes.put(NTTObjectIdentifiers.id_camellia192_wrap, Integers.valueOf(192)); + symmetricWrapperKeySizes.put(NTTObjectIdentifiers.id_camellia256_wrap, Integers.valueOf(256)); + symmetricWrapperKeySizes.put(KISAObjectIdentifiers.id_npki_app_cmsSeed_wrap, Integers.valueOf(128)); + symmetricWrapperKeySizes.put(PKCSObjectIdentifiers.des_EDE3_CBC, Integers.valueOf(192)); + symmetricKeyAlgNames.put(NISTObjectIdentifiers.aes, "AES"); symmetricKeyAlgNames.put(NISTObjectIdentifiers.id_aes128_CBC, "AES"); symmetricKeyAlgNames.put(NISTObjectIdentifiers.id_aes192_CBC, "AES"); @@ -123,6 +136,16 @@ class OperatorHelper this.helper = helper; } + String getWrappingAlgorithmName(ASN1ObjectIdentifier algOid) + { + return (String)symmetricWrapperAlgNames.get(algOid); + } + + int getKeySizeInBits(ASN1ObjectIdentifier algOid) + { + return ((Integer)symmetricWrapperKeySizes.get(algOid)).intValue(); + } + Cipher createAsymmetricWrapper(ASN1ObjectIdentifier algorithm, Map extraAlgNames) throws OperatorCreationException { @@ -242,7 +265,7 @@ class OperatorHelper try { - dig = helper.createDigest(JcaJceUtils.getDigestAlgName(digAlgId.getAlgorithm())); + dig = helper.createDigest(MessageDigestUtils.getDigestName(digAlgId.getAlgorithm())); } catch (NoSuchAlgorithmException e) { @@ -312,7 +335,7 @@ class OperatorHelper { AlgorithmParameters params = helper.createAlgorithmParameters(algName); - JcaJceUtils.loadParameters(params, algorithm.getParameters()); + AlgorithmParametersUtils.loadParameters(params, algorithm.getParameters()); PSSParameterSpec spec = (PSSParameterSpec)params.getParameterSpec(PSSParameterSpec.class); sig.setParameter(spec); @@ -336,7 +359,7 @@ class OperatorHelper if (sigAlgId.getAlgorithm().equals(PKCSObjectIdentifiers.id_RSASSA_PSS)) { RSASSAPSSparams rsaParams = RSASSAPSSparams.getInstance(params); - return JcaJceUtils.getDigestAlgName(rsaParams.getHashAlgorithm().getAlgorithm()) + "WITHRSAANDMGF1"; + return getDigestName(rsaParams.getHashAlgorithm().getAlgorithm()) + "WITHRSAANDMGF1"; } } @@ -348,6 +371,20 @@ class OperatorHelper return sigAlgId.getAlgorithm().getId(); } + // we need to remove the - to create a correct signature name + private static String getDigestName(ASN1ObjectIdentifier oid) + { + String name = MessageDigestUtils.getDigestName(oid); + + int dIndex = name.indexOf('-'); + if (dIndex > 0) + { + return name.substring(0, dIndex) + name.substring(dIndex + 1); + } + + return MessageDigestUtils.getDigestName(oid); + } + public X509Certificate convertCertificate(X509CertificateHolder certHolder) throws CertificateException { diff --git a/bcpkix/src/main/java/org/bouncycastle/operator/test/AllTests.java b/bcpkix/src/main/java/org/bouncycastle/operator/test/AllTests.java index ad19503e..2065ebd5 100644 --- a/bcpkix/src/main/java/org/bouncycastle/operator/test/AllTests.java +++ b/bcpkix/src/main/java/org/bouncycastle/operator/test/AllTests.java @@ -1,10 +1,6 @@ package org.bouncycastle.operator.test; -import java.security.Security; - -import junit.framework.Test; import junit.framework.TestCase; -import junit.framework.TestSuite; import org.bouncycastle.asn1.DERNull; import org.bouncycastle.asn1.nist.NISTObjectIdentifiers; import org.bouncycastle.asn1.oiw.OIWObjectIdentifiers; @@ -23,31 +19,6 @@ public class AllTests private static final String BC = BouncyCastleProvider.PROVIDER_NAME; private static final String TEST_DATA_HOME = "bc.test.data.home"; - public AllTests(String name) - { - super(name); - } - - public static void main(String args[]) - { - junit.textui.TestRunner.run(AllTests.class); - } - - public static Test suite() - { - return new TestSuite(AllTests.class); - } - - public void setUp() - { - Security.addProvider(new BouncyCastleProvider()); - } - - public void tearDown() - { - - } - public void testAlgorithmNameFinder() throws Exception { diff --git a/bcpkix/src/main/java/org/bouncycastle/pkcs/PKCS10CertificationRequest.java b/bcpkix/src/main/java/org/bouncycastle/pkcs/PKCS10CertificationRequest.java index 88e430d4..d32e2067 100644 --- a/bcpkix/src/main/java/org/bouncycastle/pkcs/PKCS10CertificationRequest.java +++ b/bcpkix/src/main/java/org/bouncycastle/pkcs/PKCS10CertificationRequest.java @@ -103,7 +103,7 @@ public class PKCS10CertificationRequest */ public byte[] getSignature() { - return certificationRequest.getSignature().getBytes(); + return certificationRequest.getSignature().getOctets(); } /** @@ -209,7 +209,7 @@ public class PKCS10CertificationRequest throw new PKCSException("unable to process signature: " + e.getMessage(), e); } - return verifier.verify(certificationRequest.getSignature().getBytes()); + return verifier.verify(this.getSignature()); } public boolean equals(Object o) diff --git a/bcpkix/src/main/java/org/bouncycastle/pkcs/PKCS12SafeBag.java b/bcpkix/src/main/java/org/bouncycastle/pkcs/PKCS12SafeBag.java index 6f053bae..ce652a44 100644 --- a/bcpkix/src/main/java/org/bouncycastle/pkcs/PKCS12SafeBag.java +++ b/bcpkix/src/main/java/org/bouncycastle/pkcs/PKCS12SafeBag.java @@ -85,7 +85,7 @@ public class PKCS12SafeBag { CRLBag crlBag = CRLBag.getInstance(safeBag.getBagValue()); - return new X509CRLHolder(CertificateList.getInstance(ASN1OctetString.getInstance(crlBag.getCRLValue()).getOctets())); + return new X509CRLHolder(CertificateList.getInstance(ASN1OctetString.getInstance(crlBag.getCrlValue()).getOctets())); } return safeBag.getBagValue(); diff --git a/bcpkix/src/main/java/org/bouncycastle/pkcs/jcajce/JcePKCS12MacCalculatorBuilder.java b/bcpkix/src/main/java/org/bouncycastle/pkcs/jcajce/JcePKCS12MacCalculatorBuilder.java index f04dc85d..0b937090 100644 --- a/bcpkix/src/main/java/org/bouncycastle/pkcs/jcajce/JcePKCS12MacCalculatorBuilder.java +++ b/bcpkix/src/main/java/org/bouncycastle/pkcs/jcajce/JcePKCS12MacCalculatorBuilder.java @@ -6,8 +6,6 @@ import java.security.SecureRandom; import javax.crypto.Mac; import javax.crypto.SecretKey; -import javax.crypto.SecretKeyFactory; -import javax.crypto.spec.PBEKeySpec; import javax.crypto.spec.PBEParameterSpec; import org.bouncycastle.asn1.ASN1ObjectIdentifier; @@ -15,8 +13,7 @@ import org.bouncycastle.asn1.DERNull; import org.bouncycastle.asn1.oiw.OIWObjectIdentifiers; import org.bouncycastle.asn1.pkcs.PKCS12PBEParams; import org.bouncycastle.asn1.x509.AlgorithmIdentifier; -import org.bouncycastle.crypto.ExtendedDigest; -import org.bouncycastle.crypto.generators.PKCS12ParametersGenerator; +import org.bouncycastle.jcajce.PKCS12Key; import org.bouncycastle.jcajce.io.MacOutputStream; import org.bouncycastle.jcajce.util.DefaultJcaJceHelper; import org.bouncycastle.jcajce.util.JcaJceHelper; @@ -31,7 +28,6 @@ public class JcePKCS12MacCalculatorBuilder implements PKCS12MacCalculatorBuilder { private JcaJceHelper helper = new DefaultJcaJceHelper(); - private ExtendedDigest digest; private ASN1ObjectIdentifier algorithm; private SecureRandom random; @@ -91,10 +87,8 @@ public class JcePKCS12MacCalculatorBuilder random.nextBytes(salt); - SecretKeyFactory keyFact = helper.createSecretKeyFactory(algorithm.getId()); PBEParameterSpec defParams = new PBEParameterSpec(salt, iterationCount); - PBEKeySpec pbeSpec = new PBEKeySpec(password); - SecretKey key = keyFact.generateSecret(pbeSpec); + final SecretKey key = new PKCS12Key(password); mac.init(key, defParams); @@ -117,7 +111,7 @@ public class JcePKCS12MacCalculatorBuilder public GenericKey getKey() { - return new GenericKey(getAlgorithmIdentifier(), PKCS12ParametersGenerator.PKCS12PasswordToBytes(password)); + return new GenericKey(getAlgorithmIdentifier(), key.getEncoded()); } }; } diff --git a/bcpkix/src/main/java/org/bouncycastle/pkcs/jcajce/JcePKCS12MacCalculatorBuilderProvider.java b/bcpkix/src/main/java/org/bouncycastle/pkcs/jcajce/JcePKCS12MacCalculatorBuilderProvider.java index ca666d1c..8b453f2f 100644 --- a/bcpkix/src/main/java/org/bouncycastle/pkcs/jcajce/JcePKCS12MacCalculatorBuilderProvider.java +++ b/bcpkix/src/main/java/org/bouncycastle/pkcs/jcajce/JcePKCS12MacCalculatorBuilderProvider.java @@ -5,15 +5,13 @@ import java.security.Provider; import javax.crypto.Mac; import javax.crypto.SecretKey; -import javax.crypto.SecretKeyFactory; -import javax.crypto.spec.PBEKeySpec; import javax.crypto.spec.PBEParameterSpec; import org.bouncycastle.asn1.ASN1ObjectIdentifier; import org.bouncycastle.asn1.DERNull; import org.bouncycastle.asn1.pkcs.PKCS12PBEParams; import org.bouncycastle.asn1.x509.AlgorithmIdentifier; -import org.bouncycastle.crypto.generators.PKCS12ParametersGenerator; +import org.bouncycastle.jcajce.PKCS12Key; import org.bouncycastle.jcajce.io.MacOutputStream; import org.bouncycastle.jcajce.util.DefaultJcaJceHelper; import org.bouncycastle.jcajce.util.JcaJceHelper; @@ -63,10 +61,9 @@ public class JcePKCS12MacCalculatorBuilderProvider final Mac mac = helper.createMac(algorithm.getId()); - SecretKeyFactory keyFact = helper.createSecretKeyFactory(algorithm.getId()); PBEParameterSpec defParams = new PBEParameterSpec(pbeParams.getIV(), pbeParams.getIterations().intValue()); - PBEKeySpec pbeSpec = new PBEKeySpec(password); - SecretKey key = keyFact.generateSecret(pbeSpec); + + final SecretKey key = new PKCS12Key(password); mac.init(key, defParams); @@ -89,7 +86,7 @@ public class JcePKCS12MacCalculatorBuilderProvider public GenericKey getKey() { - return new GenericKey(getAlgorithmIdentifier(), PKCS12ParametersGenerator.PKCS12PasswordToBytes(password)); + return new GenericKey(getAlgorithmIdentifier(), key.getEncoded()); } }; } diff --git a/bcpkix/src/main/java/org/bouncycastle/pkcs/jcajce/JcePKCSPBEInputDecryptorProviderBuilder.java b/bcpkix/src/main/java/org/bouncycastle/pkcs/jcajce/JcePKCSPBEInputDecryptorProviderBuilder.java index 1b6d0669..d7627ea2 100644 --- a/bcpkix/src/main/java/org/bouncycastle/pkcs/jcajce/JcePKCSPBEInputDecryptorProviderBuilder.java +++ b/bcpkix/src/main/java/org/bouncycastle/pkcs/jcajce/JcePKCSPBEInputDecryptorProviderBuilder.java @@ -20,7 +20,7 @@ import org.bouncycastle.asn1.pkcs.PBKDF2Params; import org.bouncycastle.asn1.pkcs.PKCS12PBEParams; import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers; import org.bouncycastle.asn1.x509.AlgorithmIdentifier; -import org.bouncycastle.jcajce.provider.symmetric.util.BCPBEKey; +import org.bouncycastle.jcajce.PKCS12KeyWithParameters; import org.bouncycastle.jcajce.spec.GOST28147ParameterSpec; import org.bouncycastle.jcajce.spec.PBKDF2KeySpec; import org.bouncycastle.jcajce.util.DefaultJcaJceHelper; @@ -84,12 +84,12 @@ public class JcePKCSPBEInputDecryptorProviderBuilder return new InputDecryptorProvider() { private Cipher cipher; - private SecretKey key; private AlgorithmIdentifier encryptionAlg; public InputDecryptor get(final AlgorithmIdentifier algorithmIdentifier) throws OperatorCreationException { + SecretKey key; ASN1ObjectIdentifier algorithm = algorithmIdentifier.getAlgorithm(); try @@ -98,24 +98,9 @@ public class JcePKCSPBEInputDecryptorProviderBuilder { PKCS12PBEParams pbeParams = PKCS12PBEParams.getInstance(algorithmIdentifier.getParameters()); - PBEKeySpec pbeSpec = new PBEKeySpec(password); - - SecretKeyFactory keyFact = helper.createSecretKeyFactory(algorithm.getId()); - - PBEParameterSpec defParams = new PBEParameterSpec( - pbeParams.getIV(), - pbeParams.getIterations().intValue()); - - key = keyFact.generateSecret(pbeSpec); - - if (key instanceof BCPBEKey) - { - ((BCPBEKey)key).setTryWrongPKCS12Zero(wrongPKCS12Zero); - } - cipher = helper.createCipher(algorithm.getId()); - cipher.init(Cipher.DECRYPT_MODE, key, defParams); + cipher.init(Cipher.DECRYPT_MODE, new PKCS12KeyWithParameters(password, wrongPKCS12Zero, pbeParams.getIV(), pbeParams.getIterations().intValue())); encryptionAlg = algorithmIdentifier; } diff --git a/bcpkix/src/main/java/org/bouncycastle/pkcs/jcajce/JcePKCSPBEOutputEncryptorBuilder.java b/bcpkix/src/main/java/org/bouncycastle/pkcs/jcajce/JcePKCSPBEOutputEncryptorBuilder.java index 34a8883a..361be0ce 100644 --- a/bcpkix/src/main/java/org/bouncycastle/pkcs/jcajce/JcePKCSPBEOutputEncryptorBuilder.java +++ b/bcpkix/src/main/java/org/bouncycastle/pkcs/jcajce/JcePKCSPBEOutputEncryptorBuilder.java @@ -21,7 +21,7 @@ import org.bouncycastle.asn1.pkcs.PBKDF2Params; import org.bouncycastle.asn1.pkcs.PKCS12PBEParams; import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers; import org.bouncycastle.asn1.x509.AlgorithmIdentifier; -import org.bouncycastle.crypto.PBEParametersGenerator; +import org.bouncycastle.jcajce.PKCS12KeyWithParameters; import org.bouncycastle.jcajce.util.DefaultJcaJceHelper; import org.bouncycastle.jcajce.util.JcaJceHelper; import org.bouncycastle.jcajce.util.NamedJcaJceHelper; @@ -117,17 +117,9 @@ public class JcePKCSPBEOutputEncryptorBuilder { if (algorithm.on(PKCSObjectIdentifiers.pkcs_12PbeIds)) { - PBEKeySpec pbeSpec = new PBEKeySpec(password); - - SecretKeyFactory keyFact = helper.createSecretKeyFactory(algorithm.getId()); - - PBEParameterSpec defParams = new PBEParameterSpec(salt, iterationCount); - - key = keyFact.generateSecret(pbeSpec); - cipher = helper.createCipher(algorithm.getId()); - cipher.init(Cipher.ENCRYPT_MODE, key, defParams); + cipher.init(Cipher.ENCRYPT_MODE, new PKCS12KeyWithParameters(password, salt, iterationCount)); encryptionAlg = new AlgorithmIdentifier(algorithm, new PKCS12PBEParams(salt, iterationCount)); } @@ -168,11 +160,11 @@ public class JcePKCSPBEOutputEncryptorBuilder { if (isPKCS12(encryptionAlg.getAlgorithm())) { - return new GenericKey(encryptionAlg, PBEParametersGenerator.PKCS5PasswordToBytes(password)); + return new GenericKey(encryptionAlg, PKCS5PasswordToBytes(password)); } else { - return new GenericKey(encryptionAlg, PBEParametersGenerator.PKCS12PasswordToBytes(password)); + return new GenericKey(encryptionAlg, PKCS12PasswordToBytes(password)); } } }; @@ -189,4 +181,60 @@ public class JcePKCSPBEOutputEncryptorBuilder || algorithm.on(BCObjectIdentifiers.bc_pbe_sha1_pkcs12) || algorithm.on(BCObjectIdentifiers.bc_pbe_sha256_pkcs12); } + + /** + * converts a password to a byte array according to the scheme in + * PKCS5 (ascii, no padding) + * + * @param password a character array representing the password. + * @return a byte array representing the password. + */ + private static byte[] PKCS5PasswordToBytes( + char[] password) + { + if (password != null) + { + byte[] bytes = new byte[password.length]; + + for (int i = 0; i != bytes.length; i++) + { + bytes[i] = (byte)password[i]; + } + + return bytes; + } + else + { + return new byte[0]; + } + } + + /** + * converts a password to a byte array according to the scheme in + * PKCS12 (unicode, big endian, 2 zero pad bytes at the end). + * + * @param password a character array representing the password. + * @return a byte array representing the password. + */ + private static byte[] PKCS12PasswordToBytes( + char[] password) + { + if (password != null && password.length > 0) + { + // +1 for extra 2 pad bytes. + byte[] bytes = new byte[(password.length + 1) * 2]; + + for (int i = 0; i != password.length; i ++) + { + bytes[i * 2] = (byte)(password[i] >>> 8); + bytes[i * 2 + 1] = (byte)password[i]; + } + + return bytes; + } + else + { + return new byte[0]; + } + } } diff --git a/bcpkix/src/main/java/org/bouncycastle/pkcs/test/PfxPduTest.java b/bcpkix/src/main/java/org/bouncycastle/pkcs/test/PfxPduTest.java index 931ed128..d1665e74 100644 --- a/bcpkix/src/main/java/org/bouncycastle/pkcs/test/PfxPduTest.java +++ b/bcpkix/src/main/java/org/bouncycastle/pkcs/test/PfxPduTest.java @@ -3,7 +3,12 @@ package org.bouncycastle.pkcs.test; import java.io.ByteArrayInputStream; import java.io.IOException; import java.math.BigInteger; -import java.security.*; +import java.security.KeyFactory; +import java.security.KeyStore; +import java.security.NoSuchAlgorithmException; +import java.security.PrivateKey; +import java.security.PublicKey; +import java.security.Security; import java.security.cert.Certificate; import java.security.cert.X509Certificate; import java.security.spec.RSAPrivateCrtKeySpec; @@ -13,10 +18,12 @@ import java.util.Date; import junit.framework.TestCase; import org.bouncycastle.asn1.ASN1Encodable; import org.bouncycastle.asn1.ASN1Encoding; +import org.bouncycastle.asn1.ASN1ObjectIdentifier; import org.bouncycastle.asn1.DERBMPString; import org.bouncycastle.asn1.DERSequence; import org.bouncycastle.asn1.cryptopro.CryptoProObjectIdentifiers; import org.bouncycastle.asn1.nist.NISTObjectIdentifiers; +import org.bouncycastle.asn1.oiw.OIWObjectIdentifiers; import org.bouncycastle.asn1.pkcs.Attribute; import org.bouncycastle.asn1.pkcs.ContentInfo; import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers; @@ -452,6 +459,8 @@ public class PfxPduTest + "LgBvAHIAZzAxMCEwCQYFKw4DAhoFAAQUc8hyg5aq/58lH3whwo66zJkWY28E" + "CKHZUIQsQX9hAgIIAA=="); + private byte[] pkcs5TripleDesPfx = Base64.decode( + "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"); private byte[] gostPfx = Base64.decode( "MIIHEgIBAzCCBssGCSqGSIb3DQEHAaCCBrwEgga4MIIGtDCCBYEGCSqGSIb3" + "DQEHBqCCBXIwggVuAgEAMIIFZwYJKoZIhvcNAQcBMFUGCSqGSIb3DQEFDTBI" @@ -776,9 +785,9 @@ public class PfxPduTest PKCS8EncryptedPrivateKeyInfoBuilder builder = new JcaPKCS8EncryptedPrivateKeyInfoBuilder(privKey); - PKCS8EncryptedPrivateKeyInfo priv = builder.build(new JcePKCSPBEOutputEncryptorBuilder(NISTObjectIdentifiers.id_aes256_CBC).build(passwd)); + PKCS8EncryptedPrivateKeyInfo priv = builder.build(new JcePKCSPBEOutputEncryptorBuilder(NISTObjectIdentifiers.id_aes256_CBC).setProvider("BC").build(passwd)); - PrivateKeyInfo info = priv.decryptPrivateKeyInfo(new JcePKCSPBEInputDecryptorProviderBuilder().build(passwd)); + PrivateKeyInfo info = priv.decryptPrivateKeyInfo(new JcePKCSPBEInputDecryptorProviderBuilder().setProvider("BC").build(passwd)); assertTrue(Arrays.areEqual(info.getEncoded(), privKey.getEncoded())); } @@ -978,10 +987,22 @@ public class PfxPduTest } } + public void testCreateTripleDESAndSHA1() + throws Exception + { + testCipherAndDigest(PKCSObjectIdentifiers.des_EDE3_CBC, OIWObjectIdentifiers.idSHA1); + } + public void testCreateAES256andSHA256() throws Exception { - OutputEncryptor encOut = new JcePKCSPBEOutputEncryptorBuilder(NISTObjectIdentifiers.id_aes256_CBC).setProvider("BC").build(passwd); + testCipherAndDigest(NISTObjectIdentifiers.id_aes256_CBC, NISTObjectIdentifiers.id_sha256); + } + + private void testCipherAndDigest(ASN1ObjectIdentifier cipherOid, ASN1ObjectIdentifier digestOid) + throws Exception + { + OutputEncryptor encOut = new JcePKCSPBEOutputEncryptorBuilder(cipherOid).setProvider("BC").build(passwd); KeyFactory fact = KeyFactory.getInstance("RSA", BC); PrivateKey privKey = fact.generatePrivate(privKeySpec); @@ -1015,7 +1036,7 @@ public class PfxPduTest builder.addEncryptedData(new JcePKCSPBEOutputEncryptorBuilder(PKCSObjectIdentifiers.pbeWithSHAAnd128BitRC2_CBC).setProvider("BC").build(passwd), new PKCS12SafeBag[] { eeCertBagBuilder.build(), caCertBagBuilder.build(), taCertBagBuilder.build() }); - PKCS12PfxPdu pfx = builder.build(new JcePKCS12MacCalculatorBuilder(NISTObjectIdentifiers.id_sha256), passwd); + PKCS12PfxPdu pfx = builder.build(new JcePKCS12MacCalculatorBuilder(digestOid), passwd); assertTrue(pfx.hasMac()); assertTrue(pfx.isMacValid(new JcePKCS12MacCalculatorBuilderProvider().setProvider("BC"), passwd)); @@ -1074,6 +1095,7 @@ public class PfxPduTest doPKCS5Test(pkcs5Camellia128Pfx); doPKCS5Test(pkcs5Camellia256Pfx); doPKCS5Test(pkcs5Cast5Pfx); + doPKCS5Test(pkcs5TripleDesPfx); } private void doPKCS5Test(byte[] keyStore) @@ -1110,6 +1132,11 @@ public class PfxPduTest PrivateKeyInfo info = encInfo.decryptPrivateKeyInfo(inputDecryptorProvider); } } + + // BC key store check + KeyStore ks = KeyStore.getInstance("PKCS12", "BC"); + + ks.load(new ByteArrayInputStream(pfx.getEncoded(ASN1Encoding.DL)), pkcs5Pass.toCharArray()); } public void testGOST1() diff --git a/bcpkix/src/main/java/org/bouncycastle/tsp/TimeStampTokenGenerator.java b/bcpkix/src/main/java/org/bouncycastle/tsp/TimeStampTokenGenerator.java index 91586c50..40c1f7f2 100644 --- a/bcpkix/src/main/java/org/bouncycastle/tsp/TimeStampTokenGenerator.java +++ b/bcpkix/src/main/java/org/bouncycastle/tsp/TimeStampTokenGenerator.java @@ -317,7 +317,7 @@ public class TimeStampTokenGenerator ASN1Boolean derOrdering = null; if (ordering) { - derOrdering = new ASN1Boolean(ordering); + derOrdering = ASN1Boolean.getInstance(ordering); } ASN1Integer nonce = null; diff --git a/bcpkix/src/main/java/org/bouncycastle/tsp/TimeStampTokenInfo.java b/bcpkix/src/main/java/org/bouncycastle/tsp/TimeStampTokenInfo.java index 98011a03..196088b2 100644 --- a/bcpkix/src/main/java/org/bouncycastle/tsp/TimeStampTokenInfo.java +++ b/bcpkix/src/main/java/org/bouncycastle/tsp/TimeStampTokenInfo.java @@ -107,7 +107,6 @@ public class TimeStampTokenInfo /** * @deprecated use toASN1Structure - * @return */ public TSTInfo toTSTInfo() { diff --git a/bcpkix/src/main/java/org/bouncycastle/tsp/test/AllTests.java b/bcpkix/src/main/java/org/bouncycastle/tsp/test/AllTests.java index 19fc664d..7446490e 100644 --- a/bcpkix/src/main/java/org/bouncycastle/tsp/test/AllTests.java +++ b/bcpkix/src/main/java/org/bouncycastle/tsp/test/AllTests.java @@ -2,10 +2,10 @@ package org.bouncycastle.tsp.test; import java.security.Security; +import junit.extensions.TestSetup; import junit.framework.Test; import junit.framework.TestCase; import junit.framework.TestSuite; -import org.bouncycastle.jce.provider.BouncyCastleProvider; public class AllTests extends TestCase @@ -17,8 +17,6 @@ public class AllTests public static Test suite() { - Security.addProvider(new BouncyCastleProvider()); - TestSuite suite = new TestSuite("TSP Tests"); suite.addTestSuite(ParseTest.class); @@ -26,7 +24,28 @@ public class AllTests suite.addTestSuite(CMSTimeStampedDataTest.class); suite.addTestSuite(CMSTimeStampedDataParserTest.class); suite.addTestSuite(CMSTimeStampedDataGeneratorTest.class); - - return suite; + suite.addTestSuite(GenTimeAccuracyUnitTest.class); + suite.addTestSuite(TimeStampTokenInfoUnitTest.class); + + return new BCTestSetup(suite); + } + + static class BCTestSetup + extends TestSetup + { + public BCTestSetup(Test test) + { + super(test); + } + + protected void setUp() + { + Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider()); + } + + protected void tearDown() + { + Security.removeProvider("BC"); + } } } diff --git a/bcpkix/src/main/java/org/bouncycastle/voms/VOMSAttribute.java b/bcpkix/src/main/java/org/bouncycastle/voms/VOMSAttribute.java index 9c062f34..390f8261 100644 --- a/bcpkix/src/main/java/org/bouncycastle/voms/VOMSAttribute.java +++ b/bcpkix/src/main/java/org/bouncycastle/voms/VOMSAttribute.java @@ -3,12 +3,12 @@ package org.bouncycastle.voms; import java.util.List; import java.util.ArrayList; +import org.bouncycastle.asn1.ASN1ObjectIdentifier; import org.bouncycastle.asn1.ASN1OctetString; import org.bouncycastle.asn1.DERIA5String; +import org.bouncycastle.asn1.x509.Attribute; import org.bouncycastle.asn1.x509.IetfAttrSyntax; -import org.bouncycastle.x509.X509Attribute; -import org.bouncycastle.x509.X509AttributeCertificate; - +import org.bouncycastle.cert.X509AttributeCertificateHolder; /** * Representation of the authorization information (VO, server address @@ -22,7 +22,7 @@ public class VOMSAttribute * The ASN.1 object identifier for VOMS attributes */ public static final String VOMS_ATTR_OID = "1.3.6.1.4.1.8005.100.100.4"; - private X509AttributeCertificate myAC; + private X509AttributeCertificateHolder myAC; private String myHostPort; private String myVo; private List myStringList = new ArrayList(); @@ -34,7 +34,7 @@ public class VOMSAttribute * * @param ac the attribute certificate to parse for VOMS attributes */ - public VOMSAttribute(X509AttributeCertificate ac) + public VOMSAttribute(X509AttributeCertificateHolder ac) { if (ac == null) { @@ -43,7 +43,7 @@ public class VOMSAttribute myAC = ac; - X509Attribute[] l = ac.getAttributes(VOMS_ATTR_OID); + Attribute[] l = ac.getAttributes(new ASN1ObjectIdentifier(VOMS_ATTR_OID)); if (l == null) { @@ -54,7 +54,7 @@ public class VOMSAttribute { for (int i = 0; i != l.length; i++) { - IetfAttrSyntax attr = IetfAttrSyntax.getInstance(l[i].getValues()[0]); + IetfAttrSyntax attr = IetfAttrSyntax.getInstance(l[i].getAttributeValues()[0]); // policyAuthority is on the format <vo>/<host>:<port> String url = ((DERIA5String)attr.getPolicyAuthority().getNames()[0].getName()).getString(); @@ -102,7 +102,7 @@ public class VOMSAttribute /** * @return The AttributeCertificate containing the VOMS information */ - public X509AttributeCertificate getAC() + public X509AttributeCertificateHolder getAC() { return myAC; } |