mitm.common.security.certpath.CertPathBuilderSpeedTest.java Source code

Java tutorial

Introduction

Here is the source code for mitm.common.security.certpath.CertPathBuilderSpeedTest.java

Source

/*
 * 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.IOException;
import java.security.NoSuchProviderException;
import java.security.cert.CertPathBuilderResult;
import java.security.cert.CertStore;
import java.security.cert.CertStoreException;
import java.security.cert.Certificate;
import java.security.cert.CertificateException;
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.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.bouncycastle.InitializeBouncycastle;
import mitm.common.security.certificate.CertificateUtils;
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.X509CRLStoreExt;
import mitm.common.security.crlstore.hibernate.X509CRLStoreExtAutoCommitFactory;
import mitm.common.security.provider.MITMProvider;
import mitm.common.util.BigIntegerUtils;
import mitm.common.util.CloseableIterator;
import mitm.test.TestUtils;

import org.apache.commons.lang.time.DateUtils;
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 CertPathBuilderSpeedTest {
    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 X509CertStoreParameters certStoreParams;
    private static X509CertStoreParameters rootStoreParams;

    @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());
    }

    @Before
    public void setup() throws Exception {
        importCertificatesAndCRLs();
    }

    private static void addCRL(String filename, X509CRLStoreExt crlStore) throws Exception {
        File crlFile = new File("test/resources/testdata/crls", filename);

        X509CRL crl = TestUtils.loadX509CRL(crlFile);

        if (!crlStore.contains(crl)) {
            crlStore.addCRL(crl);
        }
    }

    /*
     * 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, String storeName)
            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(storeName, 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 long getCertStoreSize(String storeName) {
        Session session = sessionSource.newSession();

        sessionManager.setSession(session);

        X509CertStoreExt certStore = new X509CertStoreExtHibernate(storeName, sessionManager);

        Transaction tx = session.beginTransaction();

        try {
            tx.commit();

            return certStore.size();
        } finally {
            sessionSource.closeSession(session);
        }
    }

    private void clearCertStore(String storeName) throws CertStoreException {
        Session session = sessionSource.newSession();

        sessionManager.setSession(session);

        X509CertStoreExt certStore = new X509CertStoreExtHibernate(storeName, sessionManager);

        Transaction tx = session.beginTransaction();

        try {
            certStore.removeAllEntries();

            tx.commit();
        } finally {
            sessionSource.closeSession(session);
        }
    }

    private void importCertificatesAndCRLs() throws Exception {
        clearCertStore("roots");
        clearCertStore("certificates");

        // add roots
        addCertificatesBulk("windows-xp-all-roots.p7b", "roots");
        addCertificatesBulk("mitm-test-root.cer", "roots");

        long start = System.currentTimeMillis();

        long certStoreSize = getCertStoreSize("certificates");

        addCertificatesBulk("random-self-signed-1000.p7b", "certificates");
        //addCertificatesBulk("random-self-signed-10000.p7b", "certificates");
        //addCertificatesBulk("random-self-signed-40000.p7b", "certificates");

        long imported = getCertStoreSize("certificates") - certStoreSize;

        assertEquals(1000, imported);

        long diff = System.currentTimeMillis() - start;

        double timePerCertificate = diff * 0.001 / imported;

        System.out.println("Import seconds/certificate : " + timePerCertificate);

        if (timePerCertificate > 0.02) {
            /***************************************************
             * Note: This might fail on slower systems!!
             ***************************************************/
            fail("Import seconds/certificate too slow. Note: This might fail on slower systems!!!");
        }

        addCertificatesBulk("mitm-test-ca.cer", "certificates");
        addCertificatesBulk("testCertificates.p7b", "certificates");

        addCRL("test-ca.crl", certStoreParams.getCRLStore());
        addCRL("test-root-ca-not-revoked.crl", certStoreParams.getCRLStore());
    }

    @Test
    public void testLoadCertificates() throws Exception {
        long start = System.currentTimeMillis();

        X509CertSelector selector = new X509CertSelector();

        CloseableIterator<X509Certificate> it = certStoreParams.getCertStore().getCertificateIterator(selector);

        int i = 0;

        while (it.hasNext()) {
            X509Certificate certificate = it.next();

            assertNotNull(certificate);

            i++;

            if (i == 10000) {
                break;
            }
        }
        // close it again (should not be a problem);
        it.close();

        assertTrue(it.isClosed());

        // close it again (should not be a problem);
        it.close();

        double secondsPerCertificate = ((System.currentTimeMillis() - start) * 0.001 / i);

        System.out.println("Total certificates: " + i + ". seconds / certificate: " + secondsPerCertificate);

        if (secondsPerCertificate > 9E-4) {
            /***************************************************
             * Note: This might fail on slower systems!!
             ***************************************************/
            fail("Seconds / certificate too slow. Note: This might fail on slower systems!!!");
        }
    }

    /*
     * 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 {
        int tries = 1000;

        TrustAnchorBuilder trustAnchorBuilder = new CertStoreTrustAnchorBuilder(rootStoreParams.getCertStore(),
                10 * DateUtils.MILLIS_PER_SECOND);

        long start = System.currentTimeMillis();

        Set<TrustAnchor> trustAnchors = trustAnchorBuilder.getTrustAnchors();

        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();

            //Set<TrustAnchor> trustAnchors = trustAnchorBuilder.getTrustAnchors(); 
            trustAnchors = trustAnchorBuilder.getTrustAnchors();
            builder.setTrustAnchors(trustAnchors);

            builder.addCertPathChecker(new SMIMEExtendedKeyUsageCertPathChecker());
            builder.addCertStore(certStore);
            builder.setRevocationEnabled(false);

            CertPathBuilderResult result = builder.buildPath(selector);

            assertEquals(2, result.getCertPath().getCertificates().size());
        }

        long diff = System.currentTimeMillis() - start;

        double secondsPerBuild = diff * 0.001 / tries;

        System.out.println("Seconds / build: " + secondsPerBuild);

        if (secondsPerBuild > 0.03) {
            /***************************************************
             * Note: This might fail on slower systems!!
             ***************************************************/
            fail("Seconds / build too slow. Note: This might fail on slower systems!!!");
        }
    }
}