Java tutorial
/* * Copyright (c) 2008-2011, Martijn Brinkers, Djigzo. * * This file is part of Djigzo email encryption. * * Djigzo is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License * version 3, 19 November 2007 as published by the Free Software * Foundation. * * Djigzo is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public * License along with Djigzo. If not, see <http://www.gnu.org/licenses/> * * Additional permission under GNU AGPL version 3 section 7 * * If you modify this Program, or any covered work, by linking or * combining it with aspectjrt.jar, aspectjweaver.jar, tyrex-1.0.3.jar, * freemarker.jar, dom4j.jar, mx4j-jmx.jar, mx4j-tools.jar, * spice-classman-1.0.jar, spice-loggerstore-0.5.jar, spice-salt-0.8.jar, * spice-xmlpolicy-1.0.jar, saaj-api-1.3.jar, saaj-impl-1.3.jar, * wsdl4j-1.6.1.jar (or modified versions of these libraries), * containing parts covered by the terms of Eclipse Public License, * tyrex license, freemarker license, dom4j license, mx4j license, * Spice Software License, Common Development and Distribution License * (CDDL), Common Public License (CPL) the licensors of this Program grant * you additional permission to convey the resulting work. */ package mitm.common.security.certpath; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; import java.io.File; import java.io.FileNotFoundException; import java.io.IOException; import java.security.NoSuchProviderException; import java.security.cert.CRLException; import java.security.cert.CertPathBuilderException; import java.security.cert.CertPathBuilderResult; import java.security.cert.CertPathValidatorException; import java.security.cert.CertStore; import java.security.cert.CertStoreException; import java.security.cert.Certificate; import java.security.cert.CertificateException; import java.security.cert.CollectionCertStoreParameters; import java.security.cert.TrustAnchor; import java.security.cert.X509CRL; import java.security.cert.X509CertSelector; import java.security.cert.X509Certificate; import java.util.Collection; import java.util.List; import java.util.Set; import mitm.common.hibernate.HibernateSessionSource; import mitm.common.hibernate.SessionManager; import mitm.common.hibernate.SessionManagerImpl; import mitm.common.hibernate.StandardHibernateSessionSourceImpl; import mitm.common.security.SecurityFactoryFactoryException; import mitm.common.security.bouncycastle.InitializeBouncycastle; import mitm.common.security.certificate.CertificateUtils; import mitm.common.security.certificate.X509CertificateInspector; import mitm.common.security.certstore.X509CertStoreExt; import mitm.common.security.certstore.hibernate.X509CertStoreExtAutoCommitFactory; import mitm.common.security.certstore.hibernate.X509CertStoreExtHibernate; import mitm.common.security.certstore.jce.X509CertStoreParameters; import mitm.common.security.crlstore.CRLStoreException; import mitm.common.security.crlstore.X509CRLStoreExt; import mitm.common.security.crlstore.hibernate.X509CRLStoreExtAutoCommitFactory; import mitm.common.security.provider.MITMProvider; import mitm.common.util.BigIntegerUtils; import mitm.test.TestUtils; import org.apache.commons.lang.exception.ExceptionUtils; import org.apache.log4j.PropertyConfigurator; import org.hibernate.Session; import org.hibernate.Transaction; import org.junit.Before; import org.junit.BeforeClass; import org.junit.Test; public class CertPathBuilderTest { private static final File hibernateConfig = new File("test/resources/hibernate.cfg.xml"); private static HibernateSessionSource sessionSource; private static SessionManager sessionManager; private static CertStore certStore; private static CertStore rootStore; private static X509CertStoreParameters certStoreParams; private static X509CertStoreParameters rootStoreParams; private static Set<TrustAnchor> trustAnchors; @BeforeClass public static void setUpBeforeClass() throws Exception { PropertyConfigurator.configure("conf/log4j.properties"); InitializeBouncycastle.initialize(); sessionSource = new StandardHibernateSessionSourceImpl(hibernateConfig); sessionManager = new SessionManagerImpl(sessionSource); MITMProvider.initialize(sessionManager); certStoreParams = new X509CertStoreParameters( new X509CertStoreExtAutoCommitFactory(sessionSource, "certificates").create(), new X509CRLStoreExtAutoCommitFactory(sessionSource, "certificates").create()); certStore = CertStore.getInstance(MITMProvider.DATABASE_CERTSTORE, certStoreParams, "mitm"); rootStoreParams = new X509CertStoreParameters( new X509CertStoreExtAutoCommitFactory(sessionSource, "roots").create()); rootStore = CertStore.getInstance(MITMProvider.DATABASE_CERTSTORE, rootStoreParams, "mitm"); } @Before public void setup() throws Exception { certStoreParams.getCertStore().removeAllEntries(); certStoreParams.getCRLStore().removeAllEntries(); rootStoreParams.getCertStore().removeAllEntries(); } private static void addCRL(String filename, X509CRLStoreExt crlStore) throws CRLStoreException { File crlFile = new File("test/resources/testdata/crls", filename); X509CRL crl; try { crl = TestUtils.loadX509CRL(crlFile); } catch (CertificateException e) { throw new CRLStoreException(e); } catch (NoSuchProviderException e) { throw new CRLStoreException(e); } catch (SecurityFactoryFactoryException e) { throw new CRLStoreException(e); } catch (CRLException e) { throw new CRLStoreException(e); } catch (FileNotFoundException e) { throw new CRLStoreException(e); } crlStore.addCRL(crl); } private static void addCertificates(String filename, X509CertStoreExt certStore) throws CertificateException, NoSuchProviderException, CertStoreException, IOException { File file = new File("test/resources/testdata/certificates", filename); Collection<? extends Certificate> certificates = CertificateUtils.readCertificates(file); for (Certificate certificate : certificates) { if (certificate instanceof X509Certificate) { if (!certStore.contains((X509Certificate) certificate)) { certStore.addCertificate((X509Certificate) certificate); } } } } /* * Test if flush/clear improves import and it does. Don't know why the fastest setting is * when flush/clear is done every iteration */ private static void addCertificatesBulk(String filename) throws CertificateException, NoSuchProviderException, CertStoreException, IOException { File file = new File("test/resources/testdata/certificates", filename); Collection<? extends Certificate> certificates = CertificateUtils.readCertificates(file); int i = 0; Session session = sessionSource.newSession(); sessionManager.setSession(session); X509CertStoreExt certStore = new X509CertStoreExtHibernate("certificates", sessionManager); Transaction tx = session.beginTransaction(); try { for (Certificate certificate : certificates) { if (i % 1 == 0) { session.flush(); session.clear(); } if (i % 100 == 0) { tx.commit(); tx = session.beginTransaction(); } if (certificate instanceof X509Certificate) { if (!certStore.contains((X509Certificate) certificate)) { certStore.addCertificate((X509Certificate) certificate); } } i++; } tx.commit(); } finally { sessionSource.closeSession(session); } } private static Set<TrustAnchor> getTrustAnchors() throws CertStoreException { TrustAnchorBuilder builder = new SimpleTrustAnchorBuilder(); builder.addCertificates(rootStore); Set<TrustAnchor> trustAnchors = builder.getTrustAnchors(); return trustAnchors; } /* * This tests checks whether a certificate is accepted which has a missing AlgorithmIdentifier parameter * for the outer cert and a NULL parameter for the inner TBS cert. This is strange but most PKI implementation * accept such a certificate. * * According to RFC 3370 * * The parameter should be absent when generating a certificate but applications must accept a NULL parameter. * *" There are two possible encodings for the SHA-1 AlgorithmIdentifier * parameters field. The two alternatives arise from the fact that when * the 1988 syntax for AlgorithmIdentifier was translated into the 1997 * syntax, the OPTIONAL associated with the AlgorithmIdentifier * parameters got lost. Later the OPTIONAL was recovered via a defect * report, but by then many people thought that algorithm parameters * were mandatory. Because of this history some implementations encode * parameters as a NULL element and others omit them entirely. The * correct encoding is to omit the parameters field; however, * implementations MUST also handle a SHA-1 AlgorithmIdentifier * parameters field which contains a NULL. * * The AlgorithmIdentifier parameters field is OPTIONAL. If present, * the parameters field MUST contain a NULL. Implementations MUST * accept SHA-1 AlgorithmIdentifiers with absent parameters. * Implementations MUST accept SHA-1 AlgorithmIdentifiers with NULL * parameters. Implementations SHOULD generate SHA-1 * AlgorithmIdentifiers with absent parameters. */ @Test public void testAlgorithmIdentifierComparisonFailed() throws Exception { addCertificates("AC_MINEFI_DPMA.cer", certStoreParams.getCertStore()); addCertificates("MINEFI_AUTORITE_DE_CERTIFICATION_RACINE.cer", rootStoreParams.getCertStore()); CertificatePathBuilder builder = new PKIXCertificatePathBuilder(); builder.addCertStore(certStore); builder.setTrustAnchors(getTrustAnchors()); X509CertSelector selector = new X509CertSelector(); selector.setSerialNumber(BigIntegerUtils.hexDecode("30303031303935373731383130383135")); selector.setIssuer("CN=MINEFI-AUTORITE DE CERTIFICATION RACINE, OU=AGENCE AUTORITE, O=MINEFI, C=FR"); CertPathBuilderResult results = builder.buildPath(selector); assertNotNull(results.getCertPath()); assertEquals(1, results.getCertPath().getCertificates().size()); } @Test public void testNoTrustAnchors() throws Exception { addCertificates("windows-xp-all-intermediates.p7b", certStoreParams.getCertStore()); addCertificates("mitm-test-ca.cer", certStoreParams.getCertStore()); addCertificates("testCertificates.p7b", certStoreParams.getCertStore()); CertificatePathBuilder builder = new PKIXCertificatePathBuilder(); builder.addCertStore(certStore); X509CertSelector selector = new X509CertSelector(); selector.setSerialNumber(BigIntegerUtils.hexDecode("115FD110A82F742D0AE14A71B651962")); selector.setIssuer("EMAILADDRESS=ca@example.com, CN=MITM Test CA, L=Amsterdam, ST=NH, C=NL"); try { builder.buildPath(selector); fail("Should have failed"); } catch (CertPathBuilderException e) { assertEquals(PKIXCertificatePathBuilder.NO_ROOTS_ERROR_MESSAGE, e.getMessage()); } } /* * The CRL is not signed with the CA private key but by another private key */ @Test public void testBuildPathCRLSignedByIncorrectKey() throws Exception { // add roots addCertificates("windows-xp-all-roots.p7b", rootStoreParams.getCertStore()); addCertificates("mitm-test-root.cer", rootStoreParams.getCertStore()); addCertificates("windows-xp-all-intermediates.p7b", certStoreParams.getCertStore()); addCertificates("mitm-test-ca.cer", certStoreParams.getCertStore()); addCertificates("testCertificates.p7b", certStoreParams.getCertStore()); addCRL("test-root-ca-not-revoked.crl", certStoreParams.getCRLStore()); addCRL("test-ca-signed-incorrect-key.crl", certStoreParams.getCRLStore()); trustAnchors = getTrustAnchors(); X509CertSelector selector = new X509CertSelector(); selector.setSerialNumber(BigIntegerUtils.hexDecode("115FD110A82F742D0AE14A71B651962")); selector.setIssuer("EMAILADDRESS=ca@example.com, CN=MITM Test CA, L=Amsterdam, ST=NH, C=NL"); CertificatePathBuilder builder = new PKIXCertificatePathBuilder(); builder.setTrustAnchors(trustAnchors); builder.addCertPathChecker(new SMIMEExtendedKeyUsageCertPathChecker()); builder.addCertStore(certStore); builder.setRevocationEnabled(true); try { builder.buildPath(selector); fail(); } catch (CertPathBuilderException e) { // should be thrown because the crl was not signed by the CA but the issuer is the CA Throwable rootCause = ExceptionUtils.getRootCause(e); assertEquals("CRL does not verify with supplied public key.", rootCause.getMessage()); } } /* * Same test as above but now there is also the correct CRL. This should succeed. */ @Test public void testBuildPathCRLSignedByIncorrectKeyAndCorrectKey() throws Exception { // add roots addCertificates("windows-xp-all-roots.p7b", rootStoreParams.getCertStore()); addCertificates("mitm-test-root.cer", rootStoreParams.getCertStore()); addCertificates("windows-xp-all-intermediates.p7b", certStoreParams.getCertStore()); addCertificates("mitm-test-ca.cer", certStoreParams.getCertStore()); addCertificates("testCertificates.p7b", certStoreParams.getCertStore()); addCRL("test-root-ca-not-revoked.crl", certStoreParams.getCRLStore()); addCRL("test-ca.crl", certStoreParams.getCRLStore()); addCRL("test-ca-signed-incorrect-key.crl", certStoreParams.getCRLStore()); trustAnchors = getTrustAnchors(); X509CertSelector selector = new X509CertSelector(); selector.setSerialNumber(BigIntegerUtils.hexDecode("115FD110A82F742D0AE14A71B651962")); selector.setIssuer("EMAILADDRESS=ca@example.com, CN=MITM Test CA, L=Amsterdam, ST=NH, C=NL"); CertificatePathBuilder builder = new PKIXCertificatePathBuilder(); builder.setTrustAnchors(trustAnchors); builder.addCertPathChecker(new SMIMEExtendedKeyUsageCertPathChecker()); builder.addCertStore(certStore); builder.setRevocationEnabled(true); CertPathBuilderResult result = builder.buildPath(selector); assertEquals(2, result.getCertPath().getCertificates().size()); } /* * Test path building for a certificate with critical extended key usage containing EMAILPROTECTION when * SMIMEExtendedKeyUsageCertPathChecker is added to the path checkers */ @Test public void testBuildPathManyCertificates() throws Exception { // add roots addCertificates("windows-xp-all-roots.p7b", rootStoreParams.getCertStore()); addCertificates("mitm-test-root.cer", rootStoreParams.getCertStore()); long start = System.currentTimeMillis(); addCertificatesBulk("random-self-signed-1000.p7b"); //addCertificatesBulk("random-self-signed-10000.p7b"); //addCertificatesBulk("random-self-signed-40000.p7b"); System.out.println("Seconds : " + (System.currentTimeMillis() - start) * 0.001); addCertificates("mitm-test-ca.cer", certStoreParams.getCertStore()); addCertificates("testCertificates.p7b", certStoreParams.getCertStore()); addCRL("test-ca.crl", certStoreParams.getCRLStore()); addCRL("test-root-ca-not-revoked.crl", certStoreParams.getCRLStore()); int tries = 100; start = System.currentTimeMillis(); TrustAnchorBuilder trustAnchorBuilder = new CertStoreTrustAnchorBuilder(rootStoreParams.getCertStore(), 0 /* milliseconds */); for (int i = 0; i < tries; i++) { X509CertSelector selector = new X509CertSelector(); selector.setSerialNumber(BigIntegerUtils.hexDecode("116A448F117FF69FE4F2D4D38F689D7")); selector.setIssuer("EMAILADDRESS=ca@example.com, CN=MITM Test CA, L=Amsterdam, ST=NH, C=NL"); CertificatePathBuilder builder = new PKIXCertificatePathBuilder(); builder.setTrustAnchors(trustAnchorBuilder.getTrustAnchors()); builder.addCertPathChecker(new SMIMEExtendedKeyUsageCertPathChecker()); builder.addCertStore(certStore); builder.setRevocationEnabled(true); CertPathBuilderResult result = builder.buildPath(selector); assertEquals(2, result.getCertPath().getCertificates().size()); } double end = (System.currentTimeMillis() - start) * 0.001 / tries; System.out.println("Seconds / build: " + end); start = System.currentTimeMillis(); Collection<? extends Certificate> certificates = certStore.getCertificates(new X509CertSelector()); end = (System.currentTimeMillis() - start) * 0.001 / certificates.size(); System.out.println("Seconds / certificate: " + end); } @Test public void testBuildPathCRLUnavailable() throws Exception { // add roots addCertificates("windows-xp-all-roots.p7b", rootStoreParams.getCertStore()); addCertificates("mitm-test-root.cer", rootStoreParams.getCertStore()); addCertificates("windows-xp-all-intermediates.p7b", certStoreParams.getCertStore()); addCertificates("mitm-test-ca.cer", certStoreParams.getCertStore()); addCertificates("testCertificates.p7b", certStoreParams.getCertStore()); trustAnchors = getTrustAnchors(); X509CertSelector selector = new X509CertSelector(); selector.setSerialNumber(BigIntegerUtils.hexDecode("115FD110A82F742D0AE14A71B651962")); selector.setIssuer("EMAILADDRESS=ca@example.com, CN=MITM Test CA, L=Amsterdam, ST=NH, C=NL"); CertificatePathBuilder builder = new PKIXCertificatePathBuilder(); builder.setTrustAnchors(trustAnchors); builder.addCertPathChecker(new SMIMEExtendedKeyUsageCertPathChecker()); builder.addCertStore(certStore); builder.setRevocationEnabled(true); try { builder.buildPath(selector); fail(); } catch (CertPathBuilderException e) { Throwable cause = ExceptionUtils.getCause(e); assertTrue(cause.getMessage().startsWith("No CRLs found")); } } @Test public void testBuildPathCRLUnavailableButCRLCheckOff() throws Exception { // add roots addCertificates("windows-xp-all-roots.p7b", rootStoreParams.getCertStore()); addCertificates("mitm-test-root.cer", rootStoreParams.getCertStore()); addCertificates("windows-xp-all-intermediates.p7b", certStoreParams.getCertStore()); addCertificates("mitm-test-ca.cer", certStoreParams.getCertStore()); addCertificates("testCertificates.p7b", certStoreParams.getCertStore()); trustAnchors = getTrustAnchors(); X509CertSelector selector = new X509CertSelector(); selector.setSerialNumber(BigIntegerUtils.hexDecode("115FD110A82F742D0AE14A71B651962")); selector.setIssuer("EMAILADDRESS=ca@example.com, CN=MITM Test CA, L=Amsterdam, ST=NH, C=NL"); CertificatePathBuilder builder = new PKIXCertificatePathBuilder(); builder.setTrustAnchors(trustAnchors); builder.addCertPathChecker(new SMIMEExtendedKeyUsageCertPathChecker()); builder.addCertStore(certStore); builder.setRevocationEnabled(false); CertPathBuilderResult result = builder.buildPath(selector); List<? extends Certificate> certificates = result.getCertPath().getCertificates(); assertEquals(2, certificates.size()); CertStore store = CertStore.getInstance("Collection", new CollectionCertStoreParameters(certificates)); Collection<? extends Certificate> foundCertificates = store.getCertificates(selector); assertEquals(1, foundCertificates.size()); } @Test public void testBuildPathRootNotFound() throws Exception { // root store cannot be empty so we just load something addCertificates("dod-mega-crl.cer", rootStoreParams.getCertStore()); addCertificates("mitm-test-ca.cer", certStoreParams.getCertStore()); addCertificates("testCertificates.p7b", certStoreParams.getCertStore()); addCRL("test-ca.crl", certStoreParams.getCRLStore()); addCRL("test-root-ca-not-revoked.crl", certStoreParams.getCRLStore()); trustAnchors = getTrustAnchors(); X509CertSelector selector = new X509CertSelector(); selector.setSerialNumber(BigIntegerUtils.hexDecode("115FCD741088707366E9727452C9770")); selector.setIssuer("EMAILADDRESS=ca@example.com, CN=MITM Test CA, L=Amsterdam, ST=NH, C=NL"); CertificatePathBuilder builder = new PKIXCertificatePathBuilder(); builder.setTrustAnchors(trustAnchors); builder.addCertStore(certStore); try { builder.buildPath(selector); fail(); } catch (CertPathBuilderException e) { assertEquals("No issuer certificate for certificate in certification path found.", e.getMessage()); } } @Test public void testBuildPathTargetNotFound() throws Exception { // add roots addCertificates("mitm-test-root.cer", rootStoreParams.getCertStore()); addCertificates("mitm-test-ca.cer", certStoreParams.getCertStore()); addCertificates("testCertificates.p7b", certStoreParams.getCertStore()); addCRL("test-ca.crl", certStoreParams.getCRLStore()); addCRL("test-root-ca-not-revoked.crl", certStoreParams.getCRLStore()); trustAnchors = getTrustAnchors(); X509CertSelector selector = new X509CertSelector(); selector.setSerialNumber(BigIntegerUtils.hexDecode("123")); selector.setIssuer("EMAILADDRESS=ca@example.com, CN=MITM Test CA, L=Amsterdam, ST=NH, C=NL"); CertificatePathBuilder builder = new PKIXCertificatePathBuilder(); builder.setTrustAnchors(trustAnchors); builder.addCertStore(certStore); try { builder.buildPath(selector); fail(); } catch (CertPathBuilderException e) { assertEquals("No certificate found matching targetContraints.", e.getMessage()); } } @Test public void testBuildPathEndCertRevoked() throws Exception { // add roots addCertificates("mitm-test-root.cer", rootStoreParams.getCertStore()); addCertificates("mitm-test-ca.cer", certStoreParams.getCertStore()); addCertificates("testCertificates.p7b", certStoreParams.getCertStore()); addCRL("test-ca.crl", certStoreParams.getCRLStore()); addCRL("test-root-ca-not-revoked.crl", certStoreParams.getCRLStore()); trustAnchors = getTrustAnchors(); X509CertSelector selector = new X509CertSelector(); selector.setSerialNumber(BigIntegerUtils.hexDecode("115FCD741088707366E9727452C9770")); selector.setIssuer("EMAILADDRESS=ca@example.com, CN=MITM Test CA, L=Amsterdam, ST=NH, C=NL"); CertificatePathBuilder builder = new PKIXCertificatePathBuilder(); builder.setTrustAnchors(trustAnchors); builder.addCertPathChecker(new SMIMEExtendedKeyUsageCertPathChecker()); builder.addCertStore(certStore); builder.setRevocationEnabled(true); try { builder.buildPath(selector); fail(); } catch (CertPathBuilderException e) { // CertPathValidatorException should have been thrown because the certificate is revoked Throwable cause = ExceptionUtils.getCause(e); assertTrue(cause.getMessage().startsWith("Certificate revocation after Fri Nov 30")); assertTrue(cause.getMessage().endsWith("2007, reason: privilegeWithdrawn")); } } @Test public void testBuildPathCACertRevoked() throws Exception { // add roots addCertificates("mitm-test-root.cer", rootStoreParams.getCertStore()); addCertificates("mitm-test-ca.cer", certStoreParams.getCertStore()); addCertificates("testCertificates.p7b", certStoreParams.getCertStore()); addCRL("test-ca.crl", certStoreParams.getCRLStore()); addCRL("test-root-ca-revoked.crl", certStoreParams.getCRLStore()); trustAnchors = getTrustAnchors(); X509CertSelector selector = new X509CertSelector(); selector.setSerialNumber(BigIntegerUtils.hexDecode("115FD110A82F742D0AE14A71B651962")); selector.setIssuer("EMAILADDRESS=ca@example.com, CN=MITM Test CA, L=Amsterdam, ST=NH, C=NL"); CertificatePathBuilder builder = new PKIXCertificatePathBuilder(); builder.setTrustAnchors(trustAnchors); builder.addCertPathChecker(new SMIMEExtendedKeyUsageCertPathChecker()); builder.addCertStore(certStore); builder.setRevocationEnabled(true); try { builder.buildPath(selector); fail(); } catch (CertPathBuilderException e) { // CertPathValidatorException should have been thrown because the certificate has a // key usage extension that is critical. Throwable cause = ExceptionUtils.getCause(e); assertTrue(cause.getMessage().startsWith("Certificate revocation after Fri Nov 30")); assertTrue(cause.getMessage().endsWith("2007, reason: cACompromise")); } } @Test public void testBuildPath() throws Exception { // add roots addCertificates("windows-xp-all-roots.p7b", rootStoreParams.getCertStore()); addCertificates("mitm-test-root.cer", rootStoreParams.getCertStore()); addCertificates("windows-xp-all-intermediates.p7b", certStoreParams.getCertStore()); addCertificates("mitm-test-ca.cer", certStoreParams.getCertStore()); addCertificates("testCertificates.p7b", certStoreParams.getCertStore()); addCRL("intel-basic-enterprise-issuing-CA.crl", certStoreParams.getCRLStore()); addCRL("itrus.com.cn.crl", certStoreParams.getCRLStore()); addCRL("test-ca.crl", certStoreParams.getCRLStore()); addCRL("test-root-ca-not-revoked.crl", certStoreParams.getCRLStore()); addCRL("ThawteSGCCA.crl", certStoreParams.getCRLStore()); final int tries = 5; long start = System.currentTimeMillis(); for (int i = 0; i < tries; i++) { trustAnchors = getTrustAnchors(); X509CertSelector selector = new X509CertSelector(); selector.setSerialNumber(BigIntegerUtils.hexDecode("115FD110A82F742D0AE14A71B651962")); selector.setIssuer("EMAILADDRESS=ca@example.com, CN=MITM Test CA, L=Amsterdam, ST=NH, C=NL"); CertificatePathBuilder builder = new PKIXCertificatePathBuilder(); builder.setTrustAnchors(trustAnchors); builder.addCertPathChecker(new SMIMEExtendedKeyUsageCertPathChecker()); builder.addCertStore(certStore); builder.setRevocationEnabled(true); CertPathBuilderResult result = builder.buildPath(selector); List<? extends Certificate> certificates = result.getCertPath().getCertificates(); assertEquals(2, certificates.size()); assertEquals("115FD110A82F742D0AE14A71B651962", X509CertificateInspector.getSerialNumberHex((X509Certificate) certificates.get(0))); assertEquals("115FCAD6B536FD8D49E72922CD1F0DA", X509CertificateInspector.getSerialNumberHex((X509Certificate) certificates.get(1))); } System.out.println("testBuildPath. Seconds / try: " + (System.currentTimeMillis() - start) * 0.001 / tries); } /* * Test a certificate path building with a certificate containing a critical extended key usage. Default * version of BC path builder does not understand this critical extension. */ @Test public void testBuildPathEKUCriticalNoEmailProtection() throws Exception { // add roots addCertificates("mitm-test-root.cer", rootStoreParams.getCertStore()); addCertificates("mitm-test-ca.cer", certStoreParams.getCertStore()); addCertificates("testCertificates.p7b", certStoreParams.getCertStore()); addCRL("test-ca.crl", certStoreParams.getCRLStore()); addCRL("test-root-ca-not-revoked.crl", certStoreParams.getCRLStore()); trustAnchors = getTrustAnchors(); X509CertSelector selector = new X509CertSelector(); selector.setSerialNumber(BigIntegerUtils.hexDecode("116A448F117FF69FE4F2D4D38F689D7")); selector.setIssuer("EMAILADDRESS=ca@example.com, CN=MITM Test CA, L=Amsterdam, ST=NH, C=NL"); CertificatePathBuilder builder = new PKIXCertificatePathBuilder(); builder.setTrustAnchors(trustAnchors); builder.addCertStore(certStore); builder.setRevocationEnabled(true); try { builder.buildPath(selector); fail(); } catch (CertPathBuilderException e) { // CertPathValidatorException should have been thrown because the certificate has a // key usage extension that is critical. Throwable cause = ExceptionUtils.getCause(e); assertTrue(cause instanceof CertPathValidatorException); assertNotNull(cause); assertEquals("Certificate has unsupported critical extension", cause.getMessage()); } } /* * Test path building for a certificate with critical extended key usage containing EMAILPROTECTION when * SMIMEExtendedKeyUsageCertPathChecker is added to the path checkers */ @Test public void testBuildPathEKUCriticalCertPathCheckerAdded() throws Exception { // add roots addCertificates("mitm-test-root.cer", rootStoreParams.getCertStore()); addCertificates("mitm-test-ca.cer", certStoreParams.getCertStore()); addCertificates("testCertificates.p7b", certStoreParams.getCertStore()); addCRL("test-ca.crl", certStoreParams.getCRLStore()); addCRL("test-root-ca-not-revoked.crl", certStoreParams.getCRLStore()); trustAnchors = getTrustAnchors(); X509CertSelector selector = new X509CertSelector(); selector.setSerialNumber(BigIntegerUtils.hexDecode("116A448F117FF69FE4F2D4D38F689D7")); selector.setIssuer("EMAILADDRESS=ca@example.com, CN=MITM Test CA, L=Amsterdam, ST=NH, C=NL"); CertificatePathBuilder builder = new PKIXCertificatePathBuilder(); builder.setTrustAnchors(trustAnchors); builder.addCertPathChecker(new SMIMEExtendedKeyUsageCertPathChecker()); builder.addCertStore(certStore); builder.setRevocationEnabled(true); CertPathBuilderResult result = builder.buildPath(selector); assertEquals(2, result.getCertPath().getCertificates().size()); } /* * Test a certificate path building with a certificate containing a critical extended key usage without the * EMAILPROTECTION parameter. Default version of BC path builder does not understand this critical extension so * we add a SMIMEExtendedKeyUsageCertPathChecker. The certificate does not contain EMAILPROTECTION so the * CertPath checker will throw an exception. */ @Test public void testBuildPathEKUCriticalNoEmailProtectionCertPathCheckerAdded() throws Exception { // add roots addCertificates("mitm-test-root.cer", rootStoreParams.getCertStore()); addCertificates("mitm-test-ca.cer", certStoreParams.getCertStore()); addCertificates("testCertificates.p7b", certStoreParams.getCertStore()); addCRL("test-ca.crl", certStoreParams.getCRLStore()); addCRL("test-root-ca-not-revoked.crl", certStoreParams.getCRLStore()); trustAnchors = getTrustAnchors(); X509CertSelector selector = new X509CertSelector(); selector.setSerialNumber(BigIntegerUtils.hexDecode("115FD035BA042503BCC6CA44680F9F8")); selector.setIssuer("EMAILADDRESS=ca@example.com, CN=MITM Test CA, L=Amsterdam, ST=NH, C=NL"); CertificatePathBuilder builder = new PKIXCertificatePathBuilder(); builder.setTrustAnchors(trustAnchors); builder.addCertPathChecker(new SMIMEExtendedKeyUsageCertPathChecker()); builder.addCertStore(certStore); builder.setRevocationEnabled(true); try { builder.buildPath(selector); fail(); } catch (CertPathBuilderException e) { // CertPathValidatorException should have been thrown because the certificate has a // key usage extension that is critical. Throwable cause = ExceptionUtils.getRootCause(e); assertTrue(cause instanceof CertPathValidatorException); assertEquals(SMIMEExtendedKeyUsageCertPathChecker.MISSING_SMIME_EXTENDED_KEY_USAGE, cause.getMessage()); } } }