mitm.common.security.certificate.GenerateTestCertificates.java Source code

Java tutorial

Introduction

Here is the source code for mitm.common.security.certificate.GenerateTestCertificates.java

Source

/*
 * Copyright (c) 2008-2012, 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.certificate;

import static org.junit.Assert.assertNotNull;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.math.BigInteger;
import java.security.KeyFactory;
import java.security.KeyStore;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.cert.Certificate;
import java.security.cert.X509CertSelector;
import java.security.cert.X509Certificate;
import java.security.spec.KeySpec;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.text.DateFormat;
import java.util.Collection;
import java.util.Date;
import java.util.LinkedList;
import java.util.List;
import java.util.Locale;
import java.util.Set;
import java.util.TreeSet;

import javax.security.auth.x500.X500Principal;

import mitm.common.security.SecurityFactory;
import mitm.common.security.SecurityFactoryFactory;
import mitm.common.security.certstore.BasicCertStoreKeyStore;
import mitm.common.security.certstore.X509BasicCertStore;

import org.apache.commons.codec.binary.Hex;
import org.apache.commons.lang.time.DateUtils;
import org.apache.log4j.PropertyConfigurator;
import org.bouncycastle.asn1.x509.GeneralNames;
import org.junit.BeforeClass;
import org.junit.Test;

/**
 * This test will create a PKCS#12 file containing certificates and private keys which can
 * be used for testing purposes. The certificates are generated in such a way that they
 * will always create the exact same certificate. That is why the public/private keys
 * and serial numbers are hard-coded, dates are explicitly specified and all sets are sorted.
 * All certificates are signed by the TestCA.
 * 
 * @author Martijn Brinkers
 *
 */
public class GenerateTestCertificates {
    private static SecurityFactory securityFactory;
    private static KeyFactory keyFactory;

    private static X509Certificate rootCertificate;
    private static X509Certificate caCertificate;
    private static PrivateKey caPrivateKey;

    private static KeyStore keyStore;

    private static List<X509Certificate> certificates = new LinkedList<X509Certificate>();

    @BeforeClass
    public static void setUpBeforeClass() throws Exception {
        PropertyConfigurator.configure("conf/log4j.properties");

        securityFactory = SecurityFactoryFactory.getSecurityFactory();

        keyFactory = securityFactory.createKeyFactory("RSA");

        keyStore = securityFactory.createKeyStore("PKCS12");

        // initialize key store
        keyStore.load(null);

        loadCA();
    }

    private static void loadCA() throws Exception {
        KeyStore caKeyStore = securityFactory.createKeyStore("PKCS12");

        File file = new File("test/resources/testdata/keys/testCA.p12");

        FileInputStream input = new FileInputStream(file);

        caKeyStore.load(input, "test".toCharArray());

        rootCertificate = (X509Certificate) caKeyStore.getCertificate("root");
        caCertificate = (X509Certificate) caKeyStore.getCertificate("ca");
        caPrivateKey = (PrivateKey) caKeyStore.getKey("ca", null);

        assertNotNull(caCertificate);
        assertNotNull(caPrivateKey);
    }

    @Test
    public void generateCertificates() throws Exception {
        generateValidCertificate();
        generateCertificateCriticalExtendedKeyUsage();
        generateValidCertificateUppercaseEmail();
        generateCertificateNoEmail();
        generateCertificateEmailInSubjectNotInAltNames();
        generateCertificateEmailInAltNamesNotInSubject();
        generateCertificateXSS();
        generateCertificateNoSMIMEExtKeyUsage();
        generateCertificateNoYetValid();
        generateCertificateNoExtendedKeyUsage();
        generateCertificateNoKeyUsage();
        generateCertificateNoCN();
        generateCertificateMultipleEmail();
        generateCertificateMD5Hash();
        generateCertificateSHA256Hash();
        generateCertificateRSA2048();
        generateCertificateKeyUsageNotForEncryption();
        generateCertificateKeyUsageNotForSigning();
        generateCertificateKeyUsageOnlyNonRepudiation();
        generateCertificateNoSMIMEExtKeyUsageNonCritical();

        File p12File = new File("test/tmp/testCertificates.p12");

        FileOutputStream output = new FileOutputStream(p12File);

        keyStore.store(output, "test".toCharArray());

        File p7BFile = new File("test/tmp/testCertificates.p7b");

        exportToP7B(keyStore, p7BFile);
    }

    private void exportToP7B(KeyStore keyStore, File file) throws Exception {
        X509BasicCertStore certStore = new BasicCertStoreKeyStore(keyStore);

        X509CertSelector selector = new X509CertSelector();

        Collection<X509Certificate> certificates = certStore.getCertificates(selector);

        CertificateUtils.writeCertificates(certificates, file);
    }

    private PrivateKey decodePrivateKey(String encoded) throws Exception {
        byte[] rawKey = Hex.decodeHex(encoded.toCharArray());

        KeySpec keySpec = new PKCS8EncodedKeySpec(rawKey);

        return keyFactory.generatePrivate(keySpec);
    }

    private PublicKey decodePublicKey(String encoded) throws Exception {
        byte[] rawKey = Hex.decodeHex(encoded.toCharArray());

        KeySpec keySpec = new X509EncodedKeySpec(rawKey);

        return keyFactory.generatePublic(keySpec);
    }

    /*
     * Generates a valid certificate
     */
    private void generateValidCertificate() throws Exception {
        X509CertificateBuilder certificateBuilder = securityFactory.createX509CertificateBuilder();

        String encodedPrivateKey = "30820276020100300d06092a864886f70d0101010500048202603082025c"
                + "02010002818100a9fee3017954c99b248d1486830c71b2e0ea3f9b7a2763"
                + "1bed8a731f5bd7e1edf856bc3fb7c63dedbeb5bb0de474e7792b3aa7e7b2"
                + "274c03a47c7d89b1935eaef172c6395f2322f1ed9e61ae46d716b4b4394c"
                + "1a802db05a2d7c3d1d41a3e8afc65ff8dada7414744f1ee1540e50ee7fb8"
                + "db437b20c5ee33a82b9d575cfbc951020301000102818004f84ab2b45562"
                + "3f82e60cff91bd3f65b765a1ce6dd7d0f1f413e421ba91a92d47e161478b"
                + "9be41b9b43bce03f199bdad304b7fbf21d6bff7f439477fe150ce38c312f"
                + "c015f3c89291aaa42c4c106f623dfd9f76acad2f1c77b590f038ffbb25f9"
                + "14b6f7ead769808ddd0e2d648442620b50518d9b7fb132b2fa1fa3e9d628"
                + "41024100e69ab3765120d0e0ba5dc21bf384b2f553211b4b1902175454c6"
                + "2f1b0f8ad385d78490539308c9fd5145ae36cc2a6d364fdd97d83d9b6623"
                + "a987db239e716055024100bcb77acf1e9829ab5b2c9a5e73d343db857474"
                + "a529ba52ca256655eb7d760e85d3c68eec9500e3db0494c8f77cb8058593"
                + "6e52a9290149367392d74ecdc3510d024100bd15723b7cb024b56ffabad3"
                + "c26c3774f2b1bdb8690c0ee7060feec6088b737f56450b368be4740332e5"
                + "a8c0a3cdd1f8eba9adfd101ee0b43329036584604075024055465b9a27ea"
                + "fe394e33b375a6c4fa4ec1d943b4364cd9883aaa297d05ee48d5b4426ee6"
                + "fcd5b02091cb619c63a10bedb6170e071e5e5464e4889ffe1e007a290240"
                + "7b60d23994a2ec38db909678446ed56d32455bf684141b9ee0aec68b2025"
                + "1d4d94fd2beebf02074559b811ae1130d2e2aa3bec2e9bccb06969104856" + "00c70759";

        String encodedPublicKey = "30819f300d06092a864886f70d010101050003818d0030818902818100a9"
                + "fee3017954c99b248d1486830c71b2e0ea3f9b7a27631bed8a731f5bd7e1"
                + "edf856bc3fb7c63dedbeb5bb0de474e7792b3aa7e7b2274c03a47c7d89b1"
                + "935eaef172c6395f2322f1ed9e61ae46d716b4b4394c1a802db05a2d7c3d"
                + "1d41a3e8afc65ff8dada7414744f1ee1540e50ee7fb8db437b20c5ee33a8" + "2b9d575cfbc9510203010001";

        PrivateKey privateKey = decodePrivateKey(encodedPrivateKey);
        PublicKey publicKey = decodePublicKey(encodedPublicKey);

        X500PrincipalBuilder subjectBuilder = new X500PrincipalBuilder();

        String email = "test@example.com";

        subjectBuilder.setCommonName("Valid certificate");
        subjectBuilder.setEmail(email);
        subjectBuilder.setCountryCode("NL");
        subjectBuilder.setLocality("Amsterdam");
        subjectBuilder.setState("NH");

        AltNamesBuilder altNamesBuider = new AltNamesBuilder();
        altNamesBuider.setRFC822Names(email);

        X500Principal subject = subjectBuilder.buildPrincipal();
        GeneralNames altNames = altNamesBuider.buildAltNames();

        // use TreeSet because we want a deterministic certificate (ie. hash should not change)
        Set<KeyUsageType> keyUsage = new TreeSet<KeyUsageType>();

        keyUsage.add(KeyUsageType.DIGITALSIGNATURE);
        keyUsage.add(KeyUsageType.KEYENCIPHERMENT);
        keyUsage.add(KeyUsageType.NONREPUDIATION);

        Set<ExtendedKeyUsageType> extendedKeyUsage = new TreeSet<ExtendedKeyUsageType>();

        extendedKeyUsage.add(ExtendedKeyUsageType.CLIENTAUTH);
        extendedKeyUsage.add(ExtendedKeyUsageType.EMAILPROTECTION);

        BigInteger serialNumber = new BigInteger("115fcd741088707366e9727452c9770", 16);

        Date now = DateFormat.getDateTimeInstance(DateFormat.MEDIUM, DateFormat.MEDIUM, Locale.UK)
                .parse("21-Nov-2007 10:38:35");

        certificateBuilder.setSubject(subject);
        certificateBuilder.setAltNames(altNames, true);
        certificateBuilder.setKeyUsage(keyUsage, true);
        certificateBuilder.setExtendedKeyUsage(extendedKeyUsage, false);
        certificateBuilder.setNotBefore(DateUtils.addDays(now, -20));
        certificateBuilder.setNotAfter(DateUtils.addYears(now, 20));
        certificateBuilder.setPublicKey(publicKey);
        certificateBuilder.setSerialNumber(serialNumber);
        certificateBuilder.setSignatureAlgorithm("SHA1WithRSAEncryption");
        certificateBuilder.addSubjectKeyIdentifier(true);

        X509Certificate certificate = certificateBuilder.generateCertificate(caPrivateKey, caCertificate);

        assertNotNull(certificate);

        certificates.add(certificate);

        Certificate[] chain = new Certificate[] { certificate, caCertificate, rootCertificate };

        keyStore.setKeyEntry("ValidCertificate", privateKey, null, chain);
    }

    /*
     * Generates a valid certificate with a critical extended EMAILPROTECTION key usage
     */
    private void generateCertificateCriticalExtendedKeyUsage() throws Exception {
        X509CertificateBuilder certificateBuilder = securityFactory.createX509CertificateBuilder();

        String encodedPrivateKey = "30820276020100300d06092a864886f70d0101010500048202603082025c"
                + "0201000281810096990cdd93c7bd2ca4d406285833cd356cc668f2571338"
                + "46fb4dfc885f275bdfb9bf45d539f89e826e442c0a750206a33d40600711"
                + "09ba96eb400710edf90590604e13ff7b624001b4b75c3fd388d18bcd71b4"
                + "c3e4a06c08da3fed5365db5d08cfb10321235da904886ea0329dbf041fa1"
                + "890f97d2b53a366f643dd344cc2e69020301000102818050ee10d6e67ad9"
                + "73ab6471a6aeb7afd8bd0ae70d0cb43c7310cbf9210419afaacc3438fffc"
                + "765a2077c754ef8dafb807737c2bdec04e3d22ab6bae206ff27a05284a96"
                + "015d5437739ffdb6801f537b7b7406e6088a56324105bce1fcfc86bc8a29"
                + "e9adb0ae4152d23f695bfe585557d73da61bf7eb7c1bbdc164afed60e54e"
                + "bd024100ca4e8e4e7e905e4b273d1381f4323ce673d5d33ce5a75f46d719"
                + "8c4ea1bcc13b621f314fa6166cc6193ff912814c54a717b93804b258ec44"
                + "d0a212d371078cdf024100be9133919b1093a3d8c7afa1ff70ab769076c9"
                + "aeb5c548cdc9aef63812a57eccf77f0def9c979cfaf117d8ffb454f823de"
                + "245a1b90da34adaf57b8a561fde5b702407d8dcd51b7c89f4ca2f88bbfce"
                + "2ed38eee7ad8d3656fbf78b68c1b80bd6de8ba9305ead394af3c28a1890b"
                + "6a49a676af10d1198c08a7995287ecde242d74d31f024032a09ac5ad1f8b"
                + "49b536dfc736f8b4e4cbde7318523c366a4d9188e23eb9eee4ff3fa6f128"
                + "75f3038bf79cf3d9f1d4f69a76a7e5b8e6efa5d0f68a1c8ddb0923024100"
                + "b44f03887aa2d95203f3dee44298b12b90c163bffebdc077551208c53987"
                + "11e35c60f8d6348f7fd51f7a384bb397ead4957e37b0440addecc19f9fac" + "b129564b";

        String encodedPublicKey = "30819f300d06092a864886f70d010101050003818d003081890281810096"
                + "990cdd93c7bd2ca4d406285833cd356cc668f257133846fb4dfc885f275b"
                + "dfb9bf45d539f89e826e442c0a750206a33d4060071109ba96eb400710ed"
                + "f90590604e13ff7b624001b4b75c3fd388d18bcd71b4c3e4a06c08da3fed"
                + "5365db5d08cfb10321235da904886ea0329dbf041fa1890f97d2b53a366f" + "643dd344cc2e690203010001";

        PrivateKey privateKey = decodePrivateKey(encodedPrivateKey);
        PublicKey publicKey = decodePublicKey(encodedPublicKey);

        X500PrincipalBuilder subjectBuilder = new X500PrincipalBuilder();

        String email = "test@example.com";

        subjectBuilder.setCommonName("Valid certificate");
        subjectBuilder.setEmail(email);
        subjectBuilder.setCountryCode("NL");
        subjectBuilder.setLocality("Amsterdam");
        subjectBuilder.setState("NH");

        AltNamesBuilder altNamesBuider = new AltNamesBuilder();
        altNamesBuider.setRFC822Names(email);

        X500Principal subject = subjectBuilder.buildPrincipal();
        GeneralNames altNames = altNamesBuider.buildAltNames();

        // use TreeSet because we want a deterministic certificate (ie. hash should not change)
        Set<KeyUsageType> keyUsage = new TreeSet<KeyUsageType>();

        keyUsage.add(KeyUsageType.DIGITALSIGNATURE);
        keyUsage.add(KeyUsageType.KEYENCIPHERMENT);
        keyUsage.add(KeyUsageType.NONREPUDIATION);

        Set<ExtendedKeyUsageType> extendedKeyUsage = new TreeSet<ExtendedKeyUsageType>();

        extendedKeyUsage.add(ExtendedKeyUsageType.CLIENTAUTH);
        extendedKeyUsage.add(ExtendedKeyUsageType.EMAILPROTECTION);

        BigInteger serialNumber = new BigInteger("116a448f117ff69fe4f2d4d38f689d7", 16);

        Date now = DateFormat.getDateTimeInstance(DateFormat.MEDIUM, DateFormat.MEDIUM, Locale.UK)
                .parse("21-Nov-2007 10:38:35");

        certificateBuilder.setSubject(subject);
        certificateBuilder.setAltNames(altNames, true);
        certificateBuilder.setKeyUsage(keyUsage, true);
        certificateBuilder.setExtendedKeyUsage(extendedKeyUsage, true /* critical */);
        certificateBuilder.setNotBefore(DateUtils.addDays(now, -20));
        certificateBuilder.setNotAfter(DateUtils.addYears(now, 20));
        certificateBuilder.setPublicKey(publicKey);
        certificateBuilder.setSerialNumber(serialNumber);
        certificateBuilder.setSignatureAlgorithm("SHA1WithRSAEncryption");
        certificateBuilder.addSubjectKeyIdentifier(true);

        X509Certificate certificate = certificateBuilder.generateCertificate(caPrivateKey, caCertificate);

        assertNotNull(certificate);

        certificates.add(certificate);

        Certificate[] chain = new Certificate[] { certificate, caCertificate, rootCertificate };

        keyStore.setKeyEntry("CriticalEKU", privateKey, null, chain);
    }

    /*
     * Generates a certificate with key usage that is not suitable for encryption
     */
    private void generateCertificateKeyUsageNotForEncryption() throws Exception {
        X509CertificateBuilder certificateBuilder = securityFactory.createX509CertificateBuilder();

        String encodedPrivateKey = "30820276020100300d06092a864886f70d0101010500048202603082025c"
                + "0201000281810096383c89ad7b3c3be9dfcb24c1ba2b19f681847eaf862c"
                + "eec3cb2daf20da3f68f30221b46444c259228cc84f35095af19d2496a486"
                + "b4e818ce17241dd792a6c6ad07f8601c728f71f8016e1dbc5905fade3ecf"
                + "37b6374f4668bb3a5de16059125cea11ef3bd712a375dd33894670faa18b"
                + "8c733227a530ec569fcb5ade02523d020301000102818030202c24df934f"
                + "a4d234845c6e443a72c2ea938c12a7a5d5889c9b32341037a863d2170237"
                + "ed5f66370f6b4d14ecbe5a11c21b10f2a71a8477e22a0bf578623d5e961d"
                + "41151118d6114296baa55c479a33de26ef872f61eb59388bddb43c970614"
                + "52983edf79e71def89879820f06667b237be04b1fb18eaa203fb59d82ebc"
                + "71024100c9b7820310a62a3815564519a038bcfd99965ed9adf494214fca"
                + "d0d08019b9ba6821bcfc9faf448f1650e9e7aeba6b9ce3e7d6f9449c1897"
                + "d7dd7d0f4e8c39fb024100bea50896dc44c9cd710611e229fd7fe01c06f8"
                + "db7ea4428c99b243ba26937eaedfd9fae5eed02e292a8a4c7092320e29dc"
                + "143223b85cfeb43efbb1603ebce72702407bc7f82819575e20fc36ec4045"
                + "698bcfb327eb1c78fad4cb7c4360d0114bb805035170bf34de409bed7dc9"
                + "8b3a557b23d356b93c4d35dc81911d81589b42c17102406eb7cfc6358469"
                + "a2bb8a27e6ae364006baa03df4d396b7e389fb62a4007556745f22ec388f"
                + "3a2e24d044e361d935e2cde2b783eb04ce5549feee13b46e9b2caf024100"
                + "a8c35546c2241ce9b90b14c667d2b83512a6ad3b50f1511696c3eb7f608b"
                + "c292bad19c4fe11b466a045ebfdb92f371199369e22e5ce6a16578c9a25c" + "7b67e997";

        String encodedPublicKey = "30819f300d06092a864886f70d010101050003818d003081890281810096"
                + "383c89ad7b3c3be9dfcb24c1ba2b19f681847eaf862ceec3cb2daf20da3f"
                + "68f30221b46444c259228cc84f35095af19d2496a486b4e818ce17241dd7"
                + "92a6c6ad07f8601c728f71f8016e1dbc5905fade3ecf37b6374f4668bb3a"
                + "5de16059125cea11ef3bd712a375dd33894670faa18b8c733227a530ec56" + "9fcb5ade02523d0203010001";

        PrivateKey privateKey = decodePrivateKey(encodedPrivateKey);
        PublicKey publicKey = decodePublicKey(encodedPublicKey);

        X500PrincipalBuilder subjectBuilder = new X500PrincipalBuilder();

        String email = "test@example.com";

        subjectBuilder.setCommonName("Valid certificate");
        subjectBuilder.setEmail(email);
        subjectBuilder.setCountryCode("NL");
        subjectBuilder.setLocality("Amsterdam");
        subjectBuilder.setState("NH");

        AltNamesBuilder altNamesBuider = new AltNamesBuilder();
        altNamesBuider.setRFC822Names(email);

        X500Principal subject = subjectBuilder.buildPrincipal();
        GeneralNames altNames = altNamesBuider.buildAltNames();

        // use TreeSet because we want a deterministic certificate (ie. hash should not change)
        Set<KeyUsageType> keyUsage = new TreeSet<KeyUsageType>();

        keyUsage.add(KeyUsageType.DIGITALSIGNATURE);
        keyUsage.add(KeyUsageType.NONREPUDIATION);

        Set<ExtendedKeyUsageType> extendedKeyUsage = new TreeSet<ExtendedKeyUsageType>();

        extendedKeyUsage.add(ExtendedKeyUsageType.CLIENTAUTH);
        extendedKeyUsage.add(ExtendedKeyUsageType.EMAILPROTECTION);

        BigInteger serialNumber = new BigInteger("1178c336c7b51cadd4ccecdd14daf22", 16);

        Date now = DateFormat.getDateTimeInstance(DateFormat.MEDIUM, DateFormat.MEDIUM, Locale.UK)
                .parse("21-Nov-2007 10:38:35");

        certificateBuilder.setSubject(subject);
        certificateBuilder.setAltNames(altNames, true);
        certificateBuilder.setKeyUsage(keyUsage, true);
        certificateBuilder.setExtendedKeyUsage(extendedKeyUsage, true /* critical */);
        certificateBuilder.setNotBefore(DateUtils.addDays(now, -20));
        certificateBuilder.setNotAfter(DateUtils.addYears(now, 20));
        certificateBuilder.setPublicKey(publicKey);
        certificateBuilder.setSerialNumber(serialNumber);
        certificateBuilder.setSignatureAlgorithm("SHA1WithRSAEncryption");
        certificateBuilder.addSubjectKeyIdentifier(true);

        X509Certificate certificate = certificateBuilder.generateCertificate(caPrivateKey, caCertificate);

        assertNotNull(certificate);

        certificates.add(certificate);

        Certificate[] chain = new Certificate[] { certificate, caCertificate, rootCertificate };

        keyStore.setKeyEntry("KeyUsageNotForEncryption", privateKey, null, chain);
    }

    /*
     * Generates a certificate with key usage not valid for signing
     */
    private void generateCertificateKeyUsageNotForSigning() throws Exception {
        X509CertificateBuilder certificateBuilder = securityFactory.createX509CertificateBuilder();

        String encodedPrivateKey = "30820278020100300d06092a864886f70d0101010500048202623082025e"
                + "02010002818100c5ca31e3581e600cd09c7892837aecedc10d4b5eeb9d1d"
                + "77ac0ab497deeb842b6fe3cdd3d021bb9680691310387259acc73e6d8173"
                + "fa734069d0d9216c58eae254f68a075f8f9fa99c77c0383f1736be7e697a"
                + "859f476de03c54cb171e984f29b42813244625ff75916bb66b2839cfb661"
                + "acafbf045b08d682544c3a832e9f6102030100010281805a7f5328344f61"
                + "9f3b6bfc76fd15a78679483dee265bf2f9a88c15694fa3ef0b78dc8076a3"
                + "ca6b6c4740cc6a25899ca2435fbaf6fa3be3b3db36a5c277328ff544736c"
                + "6042e589f910f3c1df23701dec59a8e2679cde9e9984fc6032b6c8734416"
                + "07f062afdd59ac5d48a902b02915892d8b07ed222ba63986e02c7c2b3e3a"
                + "09024100f252c537b30837deb16283ac2691229a9d1a90d0832e9717a6b9"
                + "7321026d8a9ed001d0ce192794e1a1466371cec0e68f06a3def7daed21a0"
                + "32fc101021e98e3f024100d0f3fa76613b4320d47817741841c4bd36c19a"
                + "4a01bb57c39e854a4678d237e08b27ff4778eca5440e04856f64be56bc8b"
                + "67b42d32f3450fb63d2d5be1b3aa5f024100a8a1cf1af6dd063c54073188"
                + "908239a98d20da9c305e30c945be128f6b281dea6ce8868d9655c436cc4b"
                + "b69291860e2c843b6fc3de375d4a2590e200c808c7730241008e673832a5"
                + "61360691c6a6754072d21a01cf3fcf600ec569540792ef2438604c6f89fa"
                + "b842f9444875252fab1305852749fa8b18a2b8984074fa8c8729f2c01102"
                + "4100808c7c7d221cd46df7a56112b0fd424ca4b2755a416bf8ba23a7b292"
                + "253157c35eac72069a07b0145cc48bb3f15cc3f2b1e924be4af863801ba3" + "ad0d909505c8";

        String encodedPublicKey = "30819f300d06092a864886f70d010101050003818d0030818902818100c5"
                + "ca31e3581e600cd09c7892837aecedc10d4b5eeb9d1d77ac0ab497deeb84"
                + "2b6fe3cdd3d021bb9680691310387259acc73e6d8173fa734069d0d9216c"
                + "58eae254f68a075f8f9fa99c77c0383f1736be7e697a859f476de03c54cb"
                + "171e984f29b42813244625ff75916bb66b2839cfb661acafbf045b08d682" + "544c3a832e9f610203010001";

        PrivateKey privateKey = decodePrivateKey(encodedPrivateKey);
        PublicKey publicKey = decodePublicKey(encodedPublicKey);

        X500PrincipalBuilder subjectBuilder = new X500PrincipalBuilder();

        String email = "test@example.com";

        subjectBuilder.setCommonName("Valid certificate");
        subjectBuilder.setEmail(email);
        subjectBuilder.setCountryCode("NL");
        subjectBuilder.setLocality("Amsterdam");
        subjectBuilder.setState("NH");

        AltNamesBuilder altNamesBuider = new AltNamesBuilder();
        altNamesBuider.setRFC822Names(email);

        X500Principal subject = subjectBuilder.buildPrincipal();
        GeneralNames altNames = altNamesBuider.buildAltNames();

        // use TreeSet because we want a deterministic certificate (ie. hash should not change)
        Set<KeyUsageType> keyUsage = new TreeSet<KeyUsageType>();

        keyUsage.add(KeyUsageType.KEYENCIPHERMENT);

        Set<ExtendedKeyUsageType> extendedKeyUsage = new TreeSet<ExtendedKeyUsageType>();

        extendedKeyUsage.add(ExtendedKeyUsageType.CLIENTAUTH);
        extendedKeyUsage.add(ExtendedKeyUsageType.EMAILPROTECTION);

        BigInteger serialNumber = new BigInteger("1178c38151374d6c4b29f891b9b4a77", 16);

        Date now = DateFormat.getDateTimeInstance(DateFormat.MEDIUM, DateFormat.MEDIUM, Locale.UK)
                .parse("21-Nov-2007 10:38:35");

        certificateBuilder.setSubject(subject);
        certificateBuilder.setAltNames(altNames, true);
        certificateBuilder.setKeyUsage(keyUsage, true);
        certificateBuilder.setExtendedKeyUsage(extendedKeyUsage, true /* critical */);
        certificateBuilder.setNotBefore(DateUtils.addDays(now, -20));
        certificateBuilder.setNotAfter(DateUtils.addYears(now, 20));
        certificateBuilder.setPublicKey(publicKey);
        certificateBuilder.setSerialNumber(serialNumber);
        certificateBuilder.setSignatureAlgorithm("SHA1WithRSAEncryption");
        certificateBuilder.addSubjectKeyIdentifier(true);

        X509Certificate certificate = certificateBuilder.generateCertificate(caPrivateKey, caCertificate);

        assertNotNull(certificate);

        certificates.add(certificate);

        Certificate[] chain = new Certificate[] { certificate, caCertificate, rootCertificate };

        keyStore.setKeyEntry("KeyUsageNotForSigning", privateKey, null, chain);
    }

    /*
     * Generates a certificate with key usage that only has the non repudiation set
     */
    private void generateCertificateKeyUsageOnlyNonRepudiation() throws Exception {
        X509CertificateBuilder certificateBuilder = securityFactory.createX509CertificateBuilder();

        String encodedPrivateKey = "30820277020100300d06092a864886f70d0101010500048202613082025d"
                + "02010002818100b342cf47e9e631e987a91cd281303c79be1ee94355e439"
                + "4a11606b740e30752eedd3a4d4c476963be7a329d7c92ed1f818f862389b"
                + "2c6bbec1b3f37e83a19aa05444d89c0d3bf7e567368320d1c1f4f1ef53c0"
                + "cb939f1c5cd01d4a8f4f637f0c4b16ff8e6ee4ba3beb4beddfc588ae1490"
                + "414dcaf1277f9c3287c9ea77897219020301000102818059a6a813c71ea1"
                + "07b21919990d931a2ba8b1bce7382593a13f5f815de15acac055a0eb669d"
                + "7ad157d458fdac35a97cc91f73d96b85ef8953357cd1e20be2de79470d67"
                + "841c79736d3938cf751816e214c176932d1ba26158d80da6f3f5ba61ac54"
                + "c1c9446435b2a0ef12b5cf25a03eabd931995175d40fe6aaef17b7b46bb8"
                + "01024100ff909d5f9ae1d2d3317137c9a9d775c0bdbf66b88b4a5d4893a4"
                + "ad9c7be321b78f00e76525e4269f0c1529750e87a4d4d6e5ac20e86a7095"
                + "c3441663ccb5f5f9024100b390f04e1944969dc3c05a4a699e6f9ae3e28b"
                + "e88d5d749271c849f4ca044648bff99de49257d07bcde0900a46294e233b"
                + "689bd447ce1280c1f3034416b5e521024100acb70c54677504a92c39eacd"
                + "045693c30db983ef665b7c8da7125d2e6b5f8612eab75eaab21feda60161"
                + "6fe2274eaeac150ba4f79c7b0ad97bdcd110e37179e9024100a17326ed41"
                + "80cedf68bad133e8c50059c69dd1e7b4fb1b2df4c9fddcefaa6a3b4d08b5"
                + "b366f537c9a8f148f143e62d9036013762e570de68107a5c2c633306a102"
                + "400cb68f16900107b2d2db6175807a05261caa05cf5bb14bcbafd9202cc4"
                + "5f75922185187c30f95d4ce5f44481d59174548e5bddd7bfe2896e6401a8" + "ed79797fed";

        String encodedPublicKey = "30819f300d06092a864886f70d010101050003818d0030818902818100b3"
                + "42cf47e9e631e987a91cd281303c79be1ee94355e4394a11606b740e3075"
                + "2eedd3a4d4c476963be7a329d7c92ed1f818f862389b2c6bbec1b3f37e83"
                + "a19aa05444d89c0d3bf7e567368320d1c1f4f1ef53c0cb939f1c5cd01d4a"
                + "8f4f637f0c4b16ff8e6ee4ba3beb4beddfc588ae1490414dcaf1277f9c32" + "87c9ea778972190203010001";

        PrivateKey privateKey = decodePrivateKey(encodedPrivateKey);
        PublicKey publicKey = decodePublicKey(encodedPublicKey);

        X500PrincipalBuilder subjectBuilder = new X500PrincipalBuilder();

        String email = "test@example.com";

        subjectBuilder.setCommonName("Valid certificate");
        subjectBuilder.setEmail(email);
        subjectBuilder.setCountryCode("NL");
        subjectBuilder.setLocality("Amsterdam");
        subjectBuilder.setState("NH");

        AltNamesBuilder altNamesBuider = new AltNamesBuilder();
        altNamesBuider.setRFC822Names(email);

        X500Principal subject = subjectBuilder.buildPrincipal();
        GeneralNames altNames = altNamesBuider.buildAltNames();

        // use TreeSet because we want a deterministic certificate (ie. hash should not change)
        Set<KeyUsageType> keyUsage = new TreeSet<KeyUsageType>();

        keyUsage.add(KeyUsageType.NONREPUDIATION);

        Set<ExtendedKeyUsageType> extendedKeyUsage = new TreeSet<ExtendedKeyUsageType>();

        extendedKeyUsage.add(ExtendedKeyUsageType.CLIENTAUTH);
        extendedKeyUsage.add(ExtendedKeyUsageType.EMAILPROTECTION);

        BigInteger serialNumber = new BigInteger("1178c3b653829e895acb7100eb1f627", 16);

        Date now = DateFormat.getDateTimeInstance(DateFormat.MEDIUM, DateFormat.MEDIUM, Locale.UK)
                .parse("21-Nov-2007 10:38:35");

        certificateBuilder.setSubject(subject);
        certificateBuilder.setAltNames(altNames, true);
        certificateBuilder.setKeyUsage(keyUsage, true);
        certificateBuilder.setExtendedKeyUsage(extendedKeyUsage, true /* critical */);
        certificateBuilder.setNotBefore(DateUtils.addDays(now, -20));
        certificateBuilder.setNotAfter(DateUtils.addYears(now, 20));
        certificateBuilder.setPublicKey(publicKey);
        certificateBuilder.setSerialNumber(serialNumber);
        certificateBuilder.setSignatureAlgorithm("SHA1WithRSAEncryption");
        certificateBuilder.addSubjectKeyIdentifier(true);

        X509Certificate certificate = certificateBuilder.generateCertificate(caPrivateKey, caCertificate);

        assertNotNull(certificate);

        certificates.add(certificate);

        Certificate[] chain = new Certificate[] { certificate, caCertificate, rootCertificate };

        keyStore.setKeyEntry("KeyUsageOnlyNonRepudiation", privateKey, null, chain);
    }

    /**
     * Generates a valid certificate
     * 
     * @throws Exception
     */
    private void generateValidCertificateUppercaseEmail() throws Exception {
        X509CertificateBuilder certificateBuilder = securityFactory.createX509CertificateBuilder();

        String encodedPrivateKey = "30820278020100300d06092a864886f70d0101010500048202623082025e"
                + "02010002818100cc65b29afd51609fb23b4968518b54fe26f41519dfad63"
                + "1e1a5e240bbd57c133bcbf98572f533263294a31ba77b1f56abeeff2ce5e"
                + "02f0d1c07d23464a096e06ea8d643f7205b7002f9a6ba370493b27217cd0"
                + "e5e0577cf305557cdbe7c6602badba2ae297493e75f165d2d2340fad59b7"
                + "ee0d7c05b231379aad7854c873f703020301000102818100a90547e6a6a7"
                + "8e91405f8a5a7b640e8a8447bed340862eba8bef613b5bfd9f445b46cc80"
                + "fc1f7e4145b996d9ad75398e660a21ecc90d017b5203a911ccd373694628"
                + "11f5ef0e96152fa85a1e38901ef41ee675c4de1c7ce2ed2e2af84bb8f91b"
                + "9936f699071b24e58cf44746547fee72a7d869333267dbf17fa3ac4316c2"
                + "6b91024100ed1d02ad8294c88c6e1dd376080e2265b0b872c8913ec7d735"
                + "a07be89c5432b37417265e75e388122edb4d430adc116d745824e599f8c9"
                + "9e96a5ee09e8beaf7d024100dcad92821ff13e18942db08ca02d74ecb86a"
                + "1a48c9807be5a86197361851c259c89cfb46c78f51c52558230bfe0b437b"
                + "513908c6f6d0bd0b57a74edaba0b087f02410085ed81eab13c0a7ecf5fc7"
                + "65feacc51efd0f61be09d4151a68aee9edfc06ced06fbcf7ae1916587034"
                + "c927bdbb6f8be46ff7ad77865d70bc43c91b47bb8fa11d024100bfe28594"
                + "7465f692b4b60de0199fad1df1350169ed1cb59efa8cf148ee5899602c9a"
                + "a3bbe5e66f39b7c12da84ddc496f3f2f12bcbefcbe84d05100b61c335fcd"
                + "0240403c12a1c4e1536a877631b36a075bad052b8f94580b50617fe656a8"
                + "7b45d2ada4358483fea964b25500ab2579395bafe79fd315af79fe7706c9" + "1378aab9b2be";

        String encodedPublicKey = "30819f300d06092a864886f70d010101050003818d0030818902818100cc"
                + "65b29afd51609fb23b4968518b54fe26f41519dfad631e1a5e240bbd57c1"
                + "33bcbf98572f533263294a31ba77b1f56abeeff2ce5e02f0d1c07d23464a"
                + "096e06ea8d643f7205b7002f9a6ba370493b27217cd0e5e0577cf305557c"
                + "dbe7c6602badba2ae297493e75f165d2d2340fad59b7ee0d7c05b231379a" + "ad7854c873f7030203010001";

        PrivateKey privateKey = decodePrivateKey(encodedPrivateKey);
        PublicKey publicKey = decodePublicKey(encodedPublicKey);

        X500PrincipalBuilder subjectBuilder = new X500PrincipalBuilder();

        String email = "TEST@EXAMPLE.COM";

        subjectBuilder.setCommonName("Valid certificate uppercase email");
        subjectBuilder.setEmail(email);
        subjectBuilder.setCountryCode("NL");
        subjectBuilder.setLocality("Amsterdam");
        subjectBuilder.setState("NH");

        AltNamesBuilder altNamesBuider = new AltNamesBuilder();
        altNamesBuider.setRFC822Names(email);

        X500Principal subject = subjectBuilder.buildPrincipal();
        GeneralNames altNames = altNamesBuider.buildAltNames();

        Set<KeyUsageType> keyUsage = new TreeSet<KeyUsageType>();

        keyUsage.add(KeyUsageType.DIGITALSIGNATURE);
        keyUsage.add(KeyUsageType.KEYENCIPHERMENT);
        keyUsage.add(KeyUsageType.NONREPUDIATION);

        Set<ExtendedKeyUsageType> extendedKeyUsage = new TreeSet<ExtendedKeyUsageType>();

        extendedKeyUsage.add(ExtendedKeyUsageType.CLIENTAUTH);
        extendedKeyUsage.add(ExtendedKeyUsageType.EMAILPROTECTION);

        BigInteger serialNumber = new BigInteger("115fcde9dc082e7e9c8eef4cc69b94c", 16);

        Date now = DateFormat.getDateTimeInstance(DateFormat.MEDIUM, DateFormat.MEDIUM, Locale.UK)
                .parse("21-Nov-2007 10:39:35");

        certificateBuilder.setSubject(subject);
        certificateBuilder.setAltNames(altNames, true);
        certificateBuilder.setKeyUsage(keyUsage, true);
        certificateBuilder.setExtendedKeyUsage(extendedKeyUsage, false);
        certificateBuilder.setNotBefore(DateUtils.addDays(now, -20));
        certificateBuilder.setNotAfter(DateUtils.addYears(now, 20));
        certificateBuilder.setPublicKey(publicKey);
        certificateBuilder.setSerialNumber(serialNumber);
        certificateBuilder.setSignatureAlgorithm("SHA1WithRSAEncryption");
        certificateBuilder.addSubjectKeyIdentifier(true);

        X509Certificate certificate = certificateBuilder.generateCertificate(caPrivateKey, caCertificate);

        assertNotNull(certificate);

        certificates.add(certificate);

        Certificate[] chain = new Certificate[] { certificate, caCertificate, rootCertificate };

        keyStore.setKeyEntry("UppercaseEmail", privateKey, null, chain);
    }

    /**
     * Generate a certificate without an email but with S/MIME extended key usage
     * 
     * @throws Exception
     */
    private void generateCertificateNoEmail() throws Exception {
        X509CertificateBuilder certificateBuilder = securityFactory.createX509CertificateBuilder();

        String encodedPrivateKey = "30820277020100300d06092a864886f70d0101010500048202613082025d"
                + "0201000281810086246af6ba05ff48133e66771615a3e70742ff52d60db8"
                + "a4d808e73369d0c689fc21a2691ee7297311ad840fb7be841d813991f84e"
                + "9590f20a6e4d284d4d3775e646d7aed3a7142159281c9d0171bb98c1a659"
                + "b930f1e158df079136804d89864c0484e4f15482fa4c3b64c3ac58091dc4"
                + "83766b0283c2bd7c8ad12aa19c3b45020301000102818018291f0ae95e83"
                + "285c2ef50da5f0a7e0c8b20c82c3031daab32e8755ff4d17356b3033ac73"
                + "60775abe685e4ce66f6e24524e28386d0f0b584d00a8ed055f4f09ad206d"
                + "22f72a9b8b7724a43b42f0239c44e9db007652d1abf59e9d51731fda6153"
                + "3dd996c06af7761326ac57645be68f3ccc8a665aca9efc37d781c058e98f"
                + "51024100e294e1a1ddc5dbb20d09ef2113a1ddd864c444191c1b51917b69"
                + "fb9718fe6adb5bd29e9603c63d189ee79e194fa9c1484f9a5792f9a29b49"
                + "44f5efc403cd4fbb024100978f09d7c6a74c9a446510f203996b253df437"
                + "94c66e76209570ee5de5c33ee9cc09b75d06543d5b8127b7c9511253bcbf"
                + "2c74c0270c24ca36494954b02870ff024050a19eb1d594059c951b45e7c5"
                + "6ec2ddb0ee4f358855086ff7353dfd053df494df56526d1c26bdb3374941"
                + "6fcc73a27eb3253fa8e40143b58d3edff6274c36e502410088b05dfd38d2"
                + "3c5949e428f34ce1ba6bbd439c3956f9db1a2a0dcf3dea723c349a6c0cef"
                + "1e3d2d957097c4bf119a48e18b3dea123f65496d02a6f8372425653b0241"
                + "00bf58e07f459aa53487e6fb3b40caf2055e181c8505d2deb29cffffbde3"
                + "aeb5ccd0f2c353b47fe53cd3b488be85acaf55956a678ff6e37cca327f1b" + "b82044be77";

        String encodedPublicKey = "30819f300d06092a864886f70d010101050003818d003081890281810086"
                + "246af6ba05ff48133e66771615a3e70742ff52d60db8a4d808e73369d0c6"
                + "89fc21a2691ee7297311ad840fb7be841d813991f84e9590f20a6e4d284d"
                + "4d3775e646d7aed3a7142159281c9d0171bb98c1a659b930f1e158df0791"
                + "36804d89864c0484e4f15482fa4c3b64c3ac58091dc483766b0283c2bd7c" + "8ad12aa19c3b450203010001";

        PrivateKey privateKey = decodePrivateKey(encodedPrivateKey);
        PublicKey publicKey = decodePublicKey(encodedPublicKey);

        X500PrincipalBuilder subjectBuilder = new X500PrincipalBuilder();

        subjectBuilder.setCommonName("No email");
        subjectBuilder.setCountryCode("NL");
        subjectBuilder.setLocality("Amsterdam");
        subjectBuilder.setState("NH");

        X500Principal subject = subjectBuilder.buildPrincipal();

        Set<KeyUsageType> keyUsage = new TreeSet<KeyUsageType>();

        keyUsage.add(KeyUsageType.DIGITALSIGNATURE);
        keyUsage.add(KeyUsageType.KEYENCIPHERMENT);
        keyUsage.add(KeyUsageType.NONREPUDIATION);

        Set<ExtendedKeyUsageType> extendedKeyUsage = new TreeSet<ExtendedKeyUsageType>();

        extendedKeyUsage.add(ExtendedKeyUsageType.CLIENTAUTH);
        extendedKeyUsage.add(ExtendedKeyUsageType.EMAILPROTECTION);

        BigInteger serialNumber = new BigInteger("115fce43c64c3a7547678e8f0b67559", 16);

        Date now = DateFormat.getDateTimeInstance(DateFormat.MEDIUM, DateFormat.MEDIUM, Locale.UK)
                .parse("21-Nov-2007 11:39:35");

        certificateBuilder.setSubject(subject);
        certificateBuilder.setKeyUsage(keyUsage, true);
        certificateBuilder.setExtendedKeyUsage(extendedKeyUsage, false);
        certificateBuilder.setNotBefore(DateUtils.addDays(now, -20));
        certificateBuilder.setNotAfter(DateUtils.addYears(now, 20));
        certificateBuilder.setPublicKey(publicKey);
        certificateBuilder.setSerialNumber(serialNumber);
        certificateBuilder.setSignatureAlgorithm("SHA1WithRSAEncryption");
        certificateBuilder.addSubjectKeyIdentifier(true);

        X509Certificate certificate = certificateBuilder.generateCertificate(caPrivateKey, caCertificate);

        assertNotNull(certificate);

        certificates.add(certificate);

        Certificate[] chain = new Certificate[] { certificate, caCertificate, rootCertificate };

        keyStore.setKeyEntry("noEmail", privateKey, null, chain);
    }

    /**
     * Generate a certificate with email in subject but not in AltNames
     * 
     * @throws Exception
     */
    private void generateCertificateEmailInSubjectNotInAltNames() throws Exception {
        X509CertificateBuilder certificateBuilder = securityFactory.createX509CertificateBuilder();

        String encodedPrivateKey = "30820276020100300d06092a864886f70d0101010500048202603082025c"
                + "02010002818100d101622e0d0d3edb037b595281d54029fb4d5c0bc2025f"
                + "d378f7098b6cdf3a90450978cac7b699ab1457c361384d38278f62a2a3a0"
                + "42988d7ce079170c942ee8b6cbbf2cd2f85be52bd686f4b0d344c24d6acb"
                + "47f926034bfe312353893499bcb6eb6f9aa6e8b203768c93579c93e3234c"
                + "0a345dcfa5e0a3434a205f87dc6ec50203010001028180423a7d00f8b3cc"
                + "ca1bd5575d94b49d6b702d7850657ed91caac5252a202ab0650ceb4e727b"
                + "4c7a6f42b7f8ba72dbcd4283e60e81690411512c53f92afb9a6d2e4fd74d"
                + "bc4c34b73575e60b4e656f23f730a08436fb32bd89c44f120a73757e8fde"
                + "63a12fd9e7860406604acbf006fd235573be8bfb4ffcb3e55f2785cbb009"
                + "a1024100f90a4dbd692dd5948472e5d589fe52c58f85e5ec778ab22cf965"
                + "557e6ad46e08ff8e532e800fe58643c1eae5ef8c3bf1e3f746c0e51f8f97"
                + "4bfeed4dcdd89d69024100d6d8a918fffc750e02ecd443139515ce624e68"
                + "24b808f244e0aabcf00f5323fb0dfe54ffa56b1fcd5b90f6ddff639fea7b"
                + "0843debed0088a0f7dd42cb8802efd024075b569091dad8c45a654a84d45"
                + "ebef3371a2d809ec76a1c0a02045487b35eccc53fdf15309347a47fbbeac"
                + "4801f146640e5bd2155a3690a7f2438be63a6528010240772d644fcbe03d"
                + "0672b4f0e1ec80ecc1b96288fea55fc11458141e0e8451b849d16f5db31a"
                + "0d9c6c8bf894187d4cc42e8be4ffd115c3cc98d9131199651725f9024100"
                + "c74bca53cdd2650796285a3cd9ad48f25e9308532fa3ce3f366abe2a9e5c"
                + "b55dc7a1a7c9d6d30070eeb1584505e493a39515a3e306ed8299ccfcbc02" + "32984aef";

        String encodedPublicKey = "30819f300d06092a864886f70d010101050003818d0030818902818100d1"
                + "01622e0d0d3edb037b595281d54029fb4d5c0bc2025fd378f7098b6cdf3a"
                + "90450978cac7b699ab1457c361384d38278f62a2a3a042988d7ce079170c"
                + "942ee8b6cbbf2cd2f85be52bd686f4b0d344c24d6acb47f926034bfe3123"
                + "53893499bcb6eb6f9aa6e8b203768c93579c93e3234c0a345dcfa5e0a343" + "4a205f87dc6ec50203010001";

        PrivateKey privateKey = decodePrivateKey(encodedPrivateKey);
        PublicKey publicKey = decodePublicKey(encodedPublicKey);

        X500PrincipalBuilder subjectBuilder = new X500PrincipalBuilder();

        String email = "test@example.com";

        subjectBuilder.setCommonName("Email in Subject not in AltNames");
        subjectBuilder.setEmail(email);
        subjectBuilder.setCountryCode("NL");
        subjectBuilder.setLocality("Amsterdam");
        subjectBuilder.setState("NH");

        X500Principal subject = subjectBuilder.buildPrincipal();

        Set<KeyUsageType> keyUsage = new TreeSet<KeyUsageType>();

        keyUsage.add(KeyUsageType.DIGITALSIGNATURE);
        keyUsage.add(KeyUsageType.KEYENCIPHERMENT);
        keyUsage.add(KeyUsageType.NONREPUDIATION);

        Set<ExtendedKeyUsageType> extendedKeyUsage = new TreeSet<ExtendedKeyUsageType>();

        extendedKeyUsage.add(ExtendedKeyUsageType.CLIENTAUTH);
        extendedKeyUsage.add(ExtendedKeyUsageType.EMAILPROTECTION);

        BigInteger serialNumber = new BigInteger("115fceb7f46b98775dbb8287965f838", 16);

        Date now = DateFormat.getDateTimeInstance(DateFormat.MEDIUM, DateFormat.MEDIUM, Locale.UK)
                .parse("21-Nov-2007 11:40:35");

        certificateBuilder.setSubject(subject);
        certificateBuilder.setKeyUsage(keyUsage, true);
        certificateBuilder.setExtendedKeyUsage(extendedKeyUsage, false);
        certificateBuilder.setNotBefore(DateUtils.addDays(now, -20));
        certificateBuilder.setNotAfter(DateUtils.addYears(now, 20));
        certificateBuilder.setPublicKey(publicKey);
        certificateBuilder.setSerialNumber(serialNumber);
        certificateBuilder.setSignatureAlgorithm("SHA1WithRSAEncryption");
        certificateBuilder.addSubjectKeyIdentifier(true);

        X509Certificate certificate = certificateBuilder.generateCertificate(caPrivateKey, caCertificate);

        assertNotNull(certificate);

        certificates.add(certificate);

        Certificate[] chain = new Certificate[] { certificate, caCertificate, rootCertificate };

        keyStore.setKeyEntry("emailInSubjectNotInAltNames", privateKey, null, chain);
    }

    /**
     * Generate a certificate with email in AltNames but not in subject
     * 
     * @throws Exception
     */
    private void generateCertificateEmailInAltNamesNotInSubject() throws Exception {
        X509CertificateBuilder certificateBuilder = securityFactory.createX509CertificateBuilder();

        String encodedPublicKey = "30819f300d06092a864886f70d010101050003818d003081890281810088"
                + "350aa5de312b8d6d2bcb1845ae426b52f53bed933d05c1914753651911dd"
                + "2f2e449e5ebf0a9708d16bbf7ad3ff7e56bf149e26eb37112e1d92989884"
                + "ec3f9c27d4a37efe804a55e97e3ec62aa30610952b3f60f8a3f7516cf00b"
                + "1bc1d3a75f5d4f5834962d091c5676f5ecd6a12ac4e4fbb6069048684696" + "bfbf72483feb210203010001";

        String encodedPrivateKey = "30820275020100300d06092a864886f70d01010105000482025f3082025b"
                + "0201000281810088350aa5de312b8d6d2bcb1845ae426b52f53bed933d05"
                + "c1914753651911dd2f2e449e5ebf0a9708d16bbf7ad3ff7e56bf149e26eb"
                + "37112e1d92989884ec3f9c27d4a37efe804a55e97e3ec62aa30610952b3f"
                + "60f8a3f7516cf00b1bc1d3a75f5d4f5834962d091c5676f5ecd6a12ac4e4"
                + "fbb6069048684696bfbf72483feb2102030100010281802a20257be93d51"
                + "d7fab4b9aa771a8f063c710628d309e376db64b0e12aa0c0c4afcd9f2174"
                + "7a64fde02f2fd8602abbbb3e7bb4f21a7b3c8003bb6c2077b3cd741b4b83"
                + "37c1330742875962dc56a91ecd9b6ccbc54d9c86ac7533dae9d3b792844a"
                + "2135e35b7ce2720f4d2fc25e2013aaadecd35a93d74a08921f1d4991023b"
                + "05024100e5b57d7eeeef447c9ca66643f8b38d743a2e1247e0b2bbe6925f"
                + "1a6166c580d10d87dff02a15ffc963e0f192ea060862e4ad3d1a6afbd280"
                + "3e5b409ea283119b02410097cbef487d4309e5646303b1c75e88db469c8a"
                + "653f93eac9713d570fad45b85f583c2c0314f3a290e6cc8a5cce2ca60ad5"
                + "4ea549779c829429f1645530dc6ff302402daac0314d052a636fad312590"
                + "3afa034251c8769bb84cdcd0fab13eedf493e07bc52883118ae018449002"
                + "d6c749bdbf136151858001625ef686a3b925ebd2c30240698a333e55494d"
                + "121eeff0dba460880add576da9e3c07657c4d1ff3c391ee687f413320e9a"
                + "7ca2a4d8b391e7e0b98e60adda567574226f6f9091f34e8000641d024031"
                + "7135e36f1533cffe338cbd103f44cc8ca257a27682c41b50f5458f7d0fde"
                + "7fe60171fc6718614fca2a756648fe87c9b2551d54cf4162035d59e7730f" + "a0783d";

        PrivateKey privateKey = decodePrivateKey(encodedPrivateKey);
        PublicKey publicKey = decodePublicKey(encodedPublicKey);

        X500PrincipalBuilder subjectBuilder = new X500PrincipalBuilder();

        String email = "test@example.com";

        subjectBuilder.setCommonName("Email in DN not in AltNames");
        subjectBuilder.setCountryCode("NL");
        subjectBuilder.setLocality("Amsterdam");
        subjectBuilder.setState("NH");

        AltNamesBuilder altNamesBuider = new AltNamesBuilder();
        altNamesBuider.setRFC822Names(email);

        X500Principal subject = subjectBuilder.buildPrincipal();
        GeneralNames altNames = altNamesBuider.buildAltNames();

        Set<KeyUsageType> keyUsage = new TreeSet<KeyUsageType>();

        keyUsage.add(KeyUsageType.DIGITALSIGNATURE);
        keyUsage.add(KeyUsageType.KEYENCIPHERMENT);
        keyUsage.add(KeyUsageType.NONREPUDIATION);

        Set<ExtendedKeyUsageType> extendedKeyUsage = new TreeSet<ExtendedKeyUsageType>();

        extendedKeyUsage.add(ExtendedKeyUsageType.CLIENTAUTH);
        extendedKeyUsage.add(ExtendedKeyUsageType.EMAILPROTECTION);

        BigInteger serialNumber = new BigInteger("115fceeccd07fe8929f68cc6b359a5a", 16);

        Date now = DateFormat.getDateTimeInstance(DateFormat.MEDIUM, DateFormat.MEDIUM, Locale.UK)
                .parse("21-Nov-2007 11:41:35");

        certificateBuilder.setSubject(subject);
        certificateBuilder.setAltNames(altNames, true);
        certificateBuilder.setKeyUsage(keyUsage, true);
        certificateBuilder.setExtendedKeyUsage(extendedKeyUsage, false);
        certificateBuilder.setNotBefore(DateUtils.addDays(now, -20));
        certificateBuilder.setNotAfter(DateUtils.addYears(new Date(), 20));
        certificateBuilder.setPublicKey(publicKey);
        certificateBuilder.setSerialNumber(serialNumber);
        certificateBuilder.setSignatureAlgorithm("SHA1WithRSAEncryption");
        certificateBuilder.addSubjectKeyIdentifier(true);

        X509Certificate certificate = certificateBuilder.generateCertificate(caPrivateKey, caCertificate);

        assertNotNull(certificate);

        certificates.add(certificate);

        Certificate[] chain = new Certificate[] { certificate, caCertificate, rootCertificate };

        keyStore.setKeyEntry("emailInAltNamesNotInSubject", privateKey, null, chain);
    }

    /**
     * Generates a certificate with javascript in the certificate fields to test XSS injections.
     * 
     * @throws Exception
     */
    private void generateCertificateXSS() throws Exception {
        X509CertificateBuilder certificateBuilder = securityFactory.createX509CertificateBuilder();

        String encodedPublicKey = "30819f300d06092a864886f70d010101050003818d0030818902818100ab"
                + "c1cb1ce9ac2acef6ab4c6c6cfe38840f25095652038529aa34e21c36b1b9"
                + "833c8f91b34c97a803af002ed9dd6d79fc23d5e5190180a9235e61ec596d"
                + "b084ac78aef9f65e182977e918b9b8aa423c707bd4189e44eb9dfb68d585"
                + "a828ea6b16b22f382e6084140bde8a65391894b32cbd13d3b49a6a72adeb" + "49472da5995dc70203010001";

        String encodedPrivateKey = "30820278020100300d06092a864886f70d0101010500048202623082025e"
                + "02010002818100abc1cb1ce9ac2acef6ab4c6c6cfe38840f250956520385"
                + "29aa34e21c36b1b9833c8f91b34c97a803af002ed9dd6d79fc23d5e51901"
                + "80a9235e61ec596db084ac78aef9f65e182977e918b9b8aa423c707bd418"
                + "9e44eb9dfb68d585a828ea6b16b22f382e6084140bde8a65391894b32cbd"
                + "13d3b49a6a72adeb49472da5995dc702030100010281810084959e52fd56"
                + "b7dcf7b117d782f363711db7bb53750fde95611c5d86e5f99f78dd20fe99"
                + "e80011e4760cb01de1be06b24a7f6cd036c6b8c9e2abb8a4f7f59113c67c"
                + "d06b3a642d67e3a4035a8cfccf0992184451adfcfccd3157e5a2f79ee0f1"
                + "8659c6ee801c5c081876cbd2db6390b3102b656adf7e249889ee108a4fb6"
                + "23f1024100d3beeecb8841cef45343138df276eb30293489ed74855dae41"
                + "c7b713dee7e6b4a8904fc24cab09e313f9968b4db6988fc5530da7b0f1b8"
                + "e71dfe26c09aed79f5024100cfa75532fa6fb39ae86dd8f05effdf9862e3"
                + "4ad51d71a9c6f15e6ec0d5618e7dcab1cbe93e5991fed42f913faca7d115"
                + "7fdcc255b6fec086070f04a736a7374b024100a619635693471421c2629e"
                + "a73da89d2b0557aa4e7395de7bc02bfae80276251a5814040ce57951e328"
                + "1b2445982b81175e719d078b1cc2afc16e4955d2f23035024100ca854b6d"
                + "dd9c0592062fe40d82c9909bc18e25d4b5d3be1e7e177872ef69271c7e0c"
                + "6b703ed402b482e32588f16df6583e8ce2a7d042a327d4488c643cc45703"
                + "02404b3b36fd231a6eab54303121dad4a66d732cc2d7d72b4a76108e2fc6"
                + "e1ee0080dd9733046009f19a96885cdad46bcd0a1ca1f62ce7eed073ca41" + "320fa140753f";

        PrivateKey privateKey = decodePrivateKey(encodedPrivateKey);
        PublicKey publicKey = decodePublicKey(encodedPublicKey);

        X500PrincipalBuilder subjectBuilder = new X500PrincipalBuilder();

        String email = "<script>alert('test')</script>";

        subjectBuilder.setCommonName("<script>alert('test')</script>");
        subjectBuilder.setEmail(email);
        subjectBuilder.setCountryCode("NL");
        subjectBuilder.setLocality("<script>alert('test')</script>");
        subjectBuilder.setState("<script>alert('test')</script>");

        AltNamesBuilder altNamesBuider = new AltNamesBuilder();
        altNamesBuider.setRFC822Names(email);

        X500Principal subject = subjectBuilder.buildPrincipal();
        GeneralNames altNames = altNamesBuider.buildAltNames();

        Set<KeyUsageType> keyUsage = new TreeSet<KeyUsageType>();

        keyUsage.add(KeyUsageType.DIGITALSIGNATURE);
        keyUsage.add(KeyUsageType.KEYENCIPHERMENT);
        keyUsage.add(KeyUsageType.NONREPUDIATION);

        Set<ExtendedKeyUsageType> extendedKeyUsage = new TreeSet<ExtendedKeyUsageType>();

        extendedKeyUsage.add(ExtendedKeyUsageType.CLIENTAUTH);
        extendedKeyUsage.add(ExtendedKeyUsageType.EMAILPROTECTION);

        BigInteger serialNumber = new BigInteger("115fd003be5a87522cb76cfab2ec85f", 16);

        Date now = DateFormat.getDateTimeInstance(DateFormat.MEDIUM, DateFormat.MEDIUM, Locale.UK)
                .parse("21-Nov-2007 11:45:35");

        certificateBuilder.setSubject(subject);
        certificateBuilder.setAltNames(altNames, true);
        certificateBuilder.setKeyUsage(keyUsage, true);
        certificateBuilder.setExtendedKeyUsage(extendedKeyUsage, false);
        certificateBuilder.setNotBefore(DateUtils.addDays(now, -20));
        certificateBuilder.setNotAfter(DateUtils.addYears(now, 20));
        certificateBuilder.setPublicKey(publicKey);
        certificateBuilder.setSerialNumber(serialNumber);
        certificateBuilder.setSignatureAlgorithm("SHA1WithRSAEncryption");
        certificateBuilder.addSubjectKeyIdentifier(true);

        X509Certificate certificate = certificateBuilder.generateCertificate(caPrivateKey, caCertificate);

        assertNotNull(certificate);

        certificates.add(certificate);

        Certificate[] chain = new Certificate[] { certificate, caCertificate, rootCertificate };

        keyStore.setKeyEntry("certificateXSS", privateKey, null, chain);
    }

    /**
     * Generates a certificate without S/MIME extended key usage extension
     * 
     * @throws Exception
     */
    private void generateCertificateNoSMIMEExtKeyUsage() throws Exception {
        X509CertificateBuilder certificateBuilder = securityFactory.createX509CertificateBuilder();

        String encodedPublicKey = "30819f300d06092a864886f70d010101050003818d00308189028181008e"
                + "702f7941ce945a10c965ddd2113331506fb868c59760548bf8cedc35589e"
                + "9233e3552f518ce72e75fd22b01add0662502ade276d07f12cadfaeea440"
                + "edc01b0f7c01babad5ade01a759a908f5c3279c3fd02aae54940798d56a4"
                + "b8d3a8f3472ffa0fbad9a8d1348ec8b24cb0fc3283aac33f9bfd97b0a338" + "75b7fdea432f7b0203010001";

        String encodedPrivateKey = "30820275020100300d06092a864886f70d01010105000482025f3082025b"
                + "020100028181008e702f7941ce945a10c965ddd2113331506fb868c59760"
                + "548bf8cedc35589e9233e3552f518ce72e75fd22b01add0662502ade276d"
                + "07f12cadfaeea440edc01b0f7c01babad5ade01a759a908f5c3279c3fd02"
                + "aae54940798d56a4b8d3a8f3472ffa0fbad9a8d1348ec8b24cb0fc3283aa"
                + "c33f9bfd97b0a33875b7fdea432f7b02030100010281807b8e43100b0e78"
                + "4f7c3a477bd86a051f24e8146e05e05eb65848b69ffc426822e891ad6603"
                + "76975f0d084cdbb821bc14f1f78d8763a3bd0805cf22cd266955f6972ba6"
                + "10280e6751a3219a4f89ef87faab1d4170b5d0af820844782f7317b025d2"
                + "9de7dcd271776d7c45da37ac5c190e9698ad84129f424d1df6bdd14c1027"
                + "59024100ccb868a0fe755d4327c8a02ef0a80306ee6a31726075748d04ef"
                + "713da09050931c0604bf2c93cca29afd65f7a56d5d501e80eac8775c5701"
                + "2a0ed48be3726af5024100b21df7637604312e4c80ebf2b4c04112b22938"
                + "611755f579d205e2c5826b32039d200cd37d1171639ee503748ac963d71c"
                + "f65df92a65bf6965764b7465548aaf0240388d5899e0b11b2a49fb2a04cd"
                + "861c0ff61c6fbc60d911714343c1cc7c66615bc20a0795a802cc2cbf13f0"
                + "ef104bbdd33c19f0c19ff76a317024d8a22c1a976102405ff2627c126ba9"
                + "ae7e098890422bba21ff14d34901d00d1ea53304784e8bbdf252669c6224"
                + "620c0994e35a9c21d2e0545546a5527e33370be85af3c46c7d410302401f"
                + "86906b598370b2fc4bc60be15521decaf16cd81d047242dc0dd316ba2902"
                + "baf93db44acf00d07c7762ccce97de2841fd565a9c8fee6e70da8e2779af" + "248bf1";

        PrivateKey privateKey = decodePrivateKey(encodedPrivateKey);
        PublicKey publicKey = decodePublicKey(encodedPublicKey);

        X500PrincipalBuilder subjectBuilder = new X500PrincipalBuilder();

        String email = "test@example.com";

        subjectBuilder.setCommonName("No S/MIME extended key usage");
        subjectBuilder.setEmail(email);
        subjectBuilder.setCountryCode("NL");
        subjectBuilder.setLocality("Amsterdam");
        subjectBuilder.setState("NH");

        AltNamesBuilder altNamesBuider = new AltNamesBuilder();
        altNamesBuider.setRFC822Names(email);

        X500Principal subject = subjectBuilder.buildPrincipal();
        GeneralNames altNames = altNamesBuider.buildAltNames();

        Set<KeyUsageType> keyUsage = new TreeSet<KeyUsageType>();

        keyUsage.add(KeyUsageType.DIGITALSIGNATURE);
        keyUsage.add(KeyUsageType.KEYENCIPHERMENT);
        keyUsage.add(KeyUsageType.NONREPUDIATION);

        Set<ExtendedKeyUsageType> extendedKeyUsage = new TreeSet<ExtendedKeyUsageType>();

        extendedKeyUsage.add(ExtendedKeyUsageType.CLIENTAUTH);

        BigInteger serialNumber = new BigInteger("115fd035ba042503bcc6ca44680f9f8", 16);

        Date now = DateFormat.getDateTimeInstance(DateFormat.MEDIUM, DateFormat.MEDIUM, Locale.UK)
                .parse("21-November-2007 11:46:35");

        certificateBuilder.setSubject(subject);
        certificateBuilder.setAltNames(altNames, true);
        certificateBuilder.setKeyUsage(keyUsage, true);
        // make extended key usage critical
        certificateBuilder.setExtendedKeyUsage(extendedKeyUsage, true);
        certificateBuilder.setNotBefore(DateUtils.addDays(now, -20));
        certificateBuilder.setNotAfter(DateUtils.addYears(now, 20));
        certificateBuilder.setPublicKey(publicKey);
        certificateBuilder.setSerialNumber(serialNumber);
        certificateBuilder.setSignatureAlgorithm("SHA1WithRSAEncryption");

        X509Certificate certificate = certificateBuilder.generateCertificate(caPrivateKey, caCertificate);

        assertNotNull(certificate);

        certificates.add(certificate);

        Certificate[] chain = new Certificate[] { certificate, caCertificate, rootCertificate };

        keyStore.setKeyEntry("NoSMIMEExtKeyUsage", privateKey, null, chain);
    }

    /**
     * Generates a certificate without S/MIME extended key usage extension and ext key usage non critical
     * 
     * @throws Exception
     */
    private void generateCertificateNoSMIMEExtKeyUsageNonCritical() throws Exception {
        X509CertificateBuilder certificateBuilder = securityFactory.createX509CertificateBuilder();

        String encodedPublicKey = "30819f300d06092a864886f70d010101050003818d0030818902818100b3"
                + "98c84b2a2649ab19bf1c38d057b1f43429291b4f9d6bbc6172da71b1dd82"
                + "a253f31e4e295db6e6025f3bd09adbfd741557198b17e3f8a4ab9e13b617"
                + "b3e560e16f8f8d72fb95ad3a82c2c9e2baf7efa6e93b5a9bd1e6a9d39277"
                + "c0c9fae99ce7b66d1bbf238a4749a45f40ef5ce02106664ecff54cd64d99" + "03f2e8f949d2f70203010001";

        String encodedPrivateKey = "30820275020100300d06092a864886f70d01010105000482025f3082025b"
                + "02010002818100b398c84b2a2649ab19bf1c38d057b1f43429291b4f9d6b"
                + "bc6172da71b1dd82a253f31e4e295db6e6025f3bd09adbfd741557198b17"
                + "e3f8a4ab9e13b617b3e560e16f8f8d72fb95ad3a82c2c9e2baf7efa6e93b"
                + "5a9bd1e6a9d39277c0c9fae99ce7b66d1bbf238a4749a45f40ef5ce02106"
                + "664ecff54cd64d9903f2e8f949d2f7020301000102818041056c66822110"
                + "84c8b27f16369fb946af67c38126c6d88d803e63c5cbde65803da2847349"
                + "d8aaf20523d37507cbe3ac1659cd5ea54c9ce5895896cc533287357b390d"
                + "0390da3b02ddae5dcd13527526664a127a2f3104ced7d6114020dd527d81"
                + "79a07e36705b29fb4256036e4c6912ca769bada9eb6083134c5f99ada34c"
                + "41024100e94021d2682b169f4aef370060793f28dafcbd375b92dc420368"
                + "402469952a9563df82001b910ceb38441e5d57790392aef97bf0e57c0203"
                + "06daa47850e53b97024100c51d0232655f3dd219e690b3cc99c79d0ef6c9"
                + "cfcf315952164ec81428c06d608723c0018d09af36bb64517146bbe4c3bb"
                + "80d362e415fc112157b3afec9a8fa1024012940d1d99367562d2b1230c60"
                + "a2c7a91568341a08ad35e5fc277d9468e47cb3d174a802222ff77b74cbd8"
                + "2f4f1c50708a874c9bef6b652da08a21b78399fe990240757619ef0a35bd"
                + "534c97f7370dffbdd23c2e9888bbc17ea6ca205c5e970244abb71c78b8f3"
                + "e10786a818d9e794ed371fe4c69a315e1633c5c986c7cf5841aac1024013"
                + "f17fd383e24562c322d2ef1780b93a4452c07dcda48db73f0e9aac9d42a5"
                + "ddfa9e1ffdbe4e8ba33891246e3f153f135bbd7da646dc04cb6b7755b92f" + "9dfe6b";

        PrivateKey privateKey = decodePrivateKey(encodedPrivateKey);
        PublicKey publicKey = decodePublicKey(encodedPublicKey);

        X500PrincipalBuilder subjectBuilder = new X500PrincipalBuilder();

        String email = "test@example.com";

        subjectBuilder.setCommonName("No S/MIME extended key usage non critical");
        subjectBuilder.setEmail(email);
        subjectBuilder.setCountryCode("NL");
        subjectBuilder.setLocality("Amsterdam");
        subjectBuilder.setState("NH");

        AltNamesBuilder altNamesBuider = new AltNamesBuilder();
        altNamesBuider.setRFC822Names(email);

        X500Principal subject = subjectBuilder.buildPrincipal();
        GeneralNames altNames = altNamesBuider.buildAltNames();

        Set<KeyUsageType> keyUsage = new TreeSet<KeyUsageType>();

        keyUsage.add(KeyUsageType.DIGITALSIGNATURE);
        keyUsage.add(KeyUsageType.KEYENCIPHERMENT);
        keyUsage.add(KeyUsageType.NONREPUDIATION);

        Set<ExtendedKeyUsageType> extendedKeyUsage = new TreeSet<ExtendedKeyUsageType>();

        extendedKeyUsage.add(ExtendedKeyUsageType.CLIENTAUTH);

        BigInteger serialNumber = new BigInteger("1178c30016df6384363585b394c6ca6", 16);

        Date now = DateFormat.getDateTimeInstance(DateFormat.MEDIUM, DateFormat.MEDIUM, Locale.UK)
                .parse("21-November-2007 11:46:35");

        certificateBuilder.setSubject(subject);
        certificateBuilder.setAltNames(altNames, true);
        certificateBuilder.setKeyUsage(keyUsage, true);
        // make extended key usage critical
        certificateBuilder.setExtendedKeyUsage(extendedKeyUsage, false);
        certificateBuilder.setNotBefore(DateUtils.addDays(now, -20));
        certificateBuilder.setNotAfter(DateUtils.addYears(now, 20));
        certificateBuilder.setPublicKey(publicKey);
        certificateBuilder.setSerialNumber(serialNumber);
        certificateBuilder.setSignatureAlgorithm("SHA1WithRSAEncryption");

        X509Certificate certificate = certificateBuilder.generateCertificate(caPrivateKey, caCertificate);

        assertNotNull(certificate);

        certificates.add(certificate);

        Certificate[] chain = new Certificate[] { certificate, caCertificate, rootCertificate };

        keyStore.setKeyEntry("NoSMIMEExtKeyUsageNonCritical", privateKey, null, chain);
    }

    /**
     * Generates a certificate that is valid after 2027
     * 
     * @throws Exception
     */
    private void generateCertificateNoYetValid() throws Exception {
        X509CertificateBuilder certificateBuilder = securityFactory.createX509CertificateBuilder();

        String encodedPublicKey = "30819f300d06092a864886f70d010101050003818d00308189028181009f"
                + "b353317a507e1ce39272bc304111f8558ee76c16200464a98c6737c74059"
                + "5bfc72f5647799641da2bc7a629c1ac00da10f26da0f8a83c84e09eb68cc"
                + "d666e92f04f953722956c5f0cc2263c1d8c78c792aa91d53ad5df8616372"
                + "5db07065eb043fd4587dafdab1aff5bb21854525b49ece5eda2bb7c37d8b" + "b06c4e559efb230203010001";

        String encodedPrivateKey = "30820277020100300d06092a864886f70d0101010500048202613082025d"
                + "020100028181009fb353317a507e1ce39272bc304111f8558ee76c162004"
                + "64a98c6737c740595bfc72f5647799641da2bc7a629c1ac00da10f26da0f"
                + "8a83c84e09eb68ccd666e92f04f953722956c5f0cc2263c1d8c78c792aa9"
                + "1d53ad5df86163725db07065eb043fd4587dafdab1aff5bb21854525b49e"
                + "ce5eda2bb7c37d8bb06c4e559efb2302030100010281806c96b090ca0c85"
                + "53fb618ee66b2133a8d9f44b63713fdffcda547fb2aba7139bba72286d61"
                + "ed48e7e5c9a6a5fa632e0796660912e8d2547d14a32610a2877e7d28925c"
                + "5f36025ef20c920ea380fe07fc44ffa3648991e511b6185a4105c229cde1"
                + "2be13929826bf4c55600dff4ce9a57df7422d0849f8c99ebd208dff3ce52"
                + "41024100d438b326a633789279d133fe742c91973879d652804ba1bbbd95"
                + "aa72beef2082a109e5ee4426cece04ae0d9091e36e0afbe02489f98d86f5"
                + "b39d4fcaea795491024100c0a5052b52e885e6a5e4444b686f4697def8dc"
                + "6b6913d211c3f38e87de4f7d395adedf4cd4827458947509aacaec6fb643"
                + "c31820bf41cb6b210ba0adac651e73024003a0746f54a7cc87b44d3ef63a"
                + "4608b6ece0282980c7ca1bcb41a388127b43b2f7cd93805ee9cadefa757f"
                + "05d97869890684ee1aed88dda5954c3af0dcd0f601024100be1e9df961bb"
                + "44da9a01ab3cd876692edcc8b18ff785ae1e064ac9f160ff05d0a2d3ad80"
                + "bf81779d2bf64d72170e3c399eaa5d9783e944fe1700c8b45d9cf5ed0241"
                + "00a1152fdcaa1f14bdd0c26c14feeb9e3e3627db371a4bb00afceb8ccebd"
                + "21a6e27f45fce087da5c029e1be352bbdd7ffbec8e511ea254df76a7ff19" + "4e262c16c0";

        PrivateKey privateKey = decodePrivateKey(encodedPrivateKey);
        PublicKey publicKey = decodePublicKey(encodedPublicKey);

        X500PrincipalBuilder subjectBuilder = new X500PrincipalBuilder();

        String email = "test@example.com";

        subjectBuilder.setCommonName("Not yet valid");
        subjectBuilder.setEmail(email);
        subjectBuilder.setCountryCode("NL");
        subjectBuilder.setLocality("Amsterdam");
        subjectBuilder.setState("NH");

        AltNamesBuilder altNamesBuider = new AltNamesBuilder();
        altNamesBuider.setRFC822Names(email);

        X500Principal subject = subjectBuilder.buildPrincipal();
        GeneralNames altNames = altNamesBuider.buildAltNames();

        Set<KeyUsageType> keyUsage = new TreeSet<KeyUsageType>();

        keyUsage.add(KeyUsageType.DIGITALSIGNATURE);
        keyUsage.add(KeyUsageType.KEYENCIPHERMENT);
        keyUsage.add(KeyUsageType.NONREPUDIATION);

        Set<ExtendedKeyUsageType> extendedKeyUsage = new TreeSet<ExtendedKeyUsageType>();

        extendedKeyUsage.add(ExtendedKeyUsageType.CLIENTAUTH);
        extendedKeyUsage.add(ExtendedKeyUsageType.EMAILPROTECTION);

        BigInteger serialNumber = new BigInteger("115fd064f8eac4ed5dd5e8728b36fd6", 16);

        Date now = DateFormat.getDateTimeInstance(DateFormat.MEDIUM, DateFormat.MEDIUM, Locale.UK)
                .parse("21-Nov-2007 11:49:35");

        certificateBuilder.setSubject(subject);
        certificateBuilder.setAltNames(altNames, true);
        certificateBuilder.setKeyUsage(keyUsage, true);
        certificateBuilder.setExtendedKeyUsage(extendedKeyUsage, false);
        certificateBuilder.setNotBefore(DateUtils.addYears(now, 20));
        certificateBuilder.setNotAfter(DateUtils.addYears(now, 30));
        certificateBuilder.setPublicKey(publicKey);
        certificateBuilder.setSerialNumber(serialNumber);
        certificateBuilder.setSignatureAlgorithm("SHA1WithRSAEncryption");

        X509Certificate certificate = certificateBuilder.generateCertificate(caPrivateKey, caCertificate);

        assertNotNull(certificate);

        certificates.add(certificate);

        Certificate[] chain = new Certificate[] { certificate, caCertificate, rootCertificate };

        keyStore.setKeyEntry("NotYetValid", privateKey, null, chain);
    }

    /**
     * Generates a certificate without extended key usage
     * 
     * @throws Exception
     */
    private void generateCertificateNoExtendedKeyUsage() throws Exception {
        X509CertificateBuilder certificateBuilder = securityFactory.createX509CertificateBuilder();

        String encodedPublicKey = "30819f300d06092a864886f70d010101050003818d003081890281810080"
                + "5fea5eb9bb34314acd0569a985b89bbf79caca577bd186edf7d92be0d1a5"
                + "200d8b321ec3c5ea31bf71715c1744658f86ab65c4bf4e311179da255427"
                + "57b88052c4c9f73c7e288e5f2d17bc6624e39f7b53d07b21b7aca38592be"
                + "291510767ef112d10c9cf0bf39d5f6507a604e6fb128a10abb2bbe09a765" + "4001f93dd93f690203010001";

        String encodedPrivateKey = "30820275020100300d06092a864886f70d01010105000482025f3082025b"
                + "02010002818100805fea5eb9bb34314acd0569a985b89bbf79caca577bd1"
                + "86edf7d92be0d1a5200d8b321ec3c5ea31bf71715c1744658f86ab65c4bf"
                + "4e311179da25542757b88052c4c9f73c7e288e5f2d17bc6624e39f7b53d0"
                + "7b21b7aca38592be291510767ef112d10c9cf0bf39d5f6507a604e6fb128"
                + "a10abb2bbe09a7654001f93dd93f690203010001028180456896a584b24c"
                + "f3e1c79c07971aafc7b5ed39d1d11f2718570dcca3c6b853195379512e05"
                + "17bb1a0eb25d62374a49c7223f05952d022fd18d1a7f5852b541118962de"
                + "41d5c15725f6ee7a36936883a24f8eb60b740252897779175b86762f5cca"
                + "37d5f0f2119abf720acebccf2395167bd1d651cb28511e893fec3c9526d9"
                + "21024100d984779af9de3816e02b90fa274af4e8fc6d8ff07d6a514bdd08"
                + "7b1de1ab114a89ee3bd2786b4297a816ff80103da18d7e7f2cb6dc654a9c"
                + "007775855c5cc21502410097161a6840cf62768e6b9756cd71cd7576fcfb"
                + "e078895c7892f2dae70904a104a6923cfe5273bcb1cec76d032bcf2ca700"
                + "c8740fe33ffa5e1970df9741e1e105024049fe6c09863277f6202ff1d387"
                + "0652a5e729062c131dd5a5eefcf194caadbce61461bc6bee96de4264e5dd"
                + "e89c9dba953d90d98f230e3a01338f6fa4fc3479b9024041152564f95e1c"
                + "75239e973fae1a32be41f6726ddc9e9735dd5f3e0abde8bf8fe84d207711"
                + "7f87ae347bd5aac309689bbc0b9d6b66a21db0c156cd0a3438201d024068"
                + "6d5cbd6457d3cb83eaa111a540b5878129d5e6abc3d219eaa0446d9afc54"
                + "3a113148957cc1e6c6da5d1a0ddb18af723f01f30fd0241bfe9541a8f691" + "4895e7";

        PrivateKey privateKey = decodePrivateKey(encodedPrivateKey);
        PublicKey publicKey = decodePublicKey(encodedPublicKey);

        X500PrincipalBuilder subjectBuilder = new X500PrincipalBuilder();

        String email = "test@example.com";

        subjectBuilder.setCommonName("No extended key usage");
        subjectBuilder.setEmail(email);
        subjectBuilder.setCountryCode("NL");
        subjectBuilder.setLocality("Amsterdam");
        subjectBuilder.setState("NH");

        AltNamesBuilder altNamesBuider = new AltNamesBuilder();
        altNamesBuider.setRFC822Names(email);

        X500Principal subject = subjectBuilder.buildPrincipal();
        GeneralNames altNames = altNamesBuider.buildAltNames();

        Set<KeyUsageType> keyUsage = new TreeSet<KeyUsageType>();

        keyUsage.add(KeyUsageType.DIGITALSIGNATURE);
        keyUsage.add(KeyUsageType.KEYENCIPHERMENT);
        keyUsage.add(KeyUsageType.NONREPUDIATION);

        BigInteger serialNumber = new BigInteger("115fd08d3f0e6159746aea96a50c5d6", 16);

        Date now = DateFormat.getDateTimeInstance(DateFormat.MEDIUM, DateFormat.MEDIUM, Locale.UK)
                .parse("21-Nov-2007 11:50:35");

        certificateBuilder.setSubject(subject);
        certificateBuilder.setAltNames(altNames, true);
        certificateBuilder.setKeyUsage(keyUsage, true);
        certificateBuilder.setNotBefore(DateUtils.addDays(now, -20));
        certificateBuilder.setNotAfter(DateUtils.addYears(now, 20));
        certificateBuilder.setPublicKey(publicKey);
        certificateBuilder.setSerialNumber(serialNumber);
        certificateBuilder.setSignatureAlgorithm("SHA1WithRSAEncryption");

        X509Certificate certificate = certificateBuilder.generateCertificate(caPrivateKey, caCertificate);

        assertNotNull(certificate);

        certificates.add(certificate);

        Certificate[] chain = new Certificate[] { certificate, caCertificate, rootCertificate };

        keyStore.setKeyEntry("NoExtendedKeyUsage", privateKey, null, chain);
    }

    /**
     * Generates a certificate without key usage
     * 
     * @throws Exception
     */
    private void generateCertificateNoKeyUsage() throws Exception {
        X509CertificateBuilder certificateBuilder = securityFactory.createX509CertificateBuilder();

        String encodedPublicKey = "30819f300d06092a864886f70d010101050003818d0030818902818100b2"
                + "0e2afe37e1235b93919e2c30207b3c52547a7ca4b5929d3ac63984b5d951"
                + "244d6ee103a1cf5fd1e57f67a4becd0cb1be3c5cfe884130c412c46fdc13"
                + "cb175b51b3d6707130a57063e6e98c92ec5ec274cbb3c53d29be5b02383a"
                + "ab5f26581a84b2a32e20c84a84d182720737ccd53d7b1331b7db0d816e9c" + "b85927158c288f0203010001";

        String encodedPrivateKey = "30820276020100300d06092a864886f70d0101010500048202603082025c"
                + "02010002818100b20e2afe37e1235b93919e2c30207b3c52547a7ca4b592"
                + "9d3ac63984b5d951244d6ee103a1cf5fd1e57f67a4becd0cb1be3c5cfe88"
                + "4130c412c46fdc13cb175b51b3d6707130a57063e6e98c92ec5ec274cbb3"
                + "c53d29be5b02383aab5f26581a84b2a32e20c84a84d182720737ccd53d7b"
                + "1331b7db0d816e9cb85927158c288f020301000102818076054e1a138ff7"
                + "8fcbd0c9b7206f674024923a5e440ed68fc15582eaa45ed799e879864c92"
                + "0492cede000502fe358c2484a41e3fd8b0dd5219de7b06b557f8b242eb9a"
                + "0c7650dc8a9d68b20ab32aca5fbff4a01a15a2a3e90930d4040540e695ef"
                + "90c21fc7383364cb111f509aa559889830a9b3846777a9b8b755152482f8"
                + "81024100e8dfecea5ee39b456a552eed6c51f917c191dda274edbe2ea550"
                + "d1360bd531aed9a5e740ab9468fde289dbdb8d8b2cf57eea3317cf0b0a7f"
                + "89e6b8b17e6d2b7d024100c3bca3e3b3457ac7280902a3d5ab4a2a7f6f34"
                + "6f37e4e9f233d4498f336aea8169c2cccd702880e58432e43bbae9301283"
                + "093519c9a888bf744f3c3fb191a9fb0240361eec919f91e8211ed04342bc"
                + "7ce49627cf7da1e6e8e5dd33606feece9b329bbf4b764e2a52288070a8b7"
                + "66f42357448ac565307056d18ec87ecd87baa926850240130977cf1f9274"
                + "5c86524a05713495a4087ce256a6d306c5ddb099eee98b4e7f83afc4877e"
                + "8f11ea40af4a6f5cc06d427fa81798087af1c1dd280fae0a31269d024100"
                + "98982a55da07b7d2ed807e3f960265180ae755edd5cb8df393c7dfdc70ec"
                + "db9ce973f9aa9f14834c6bf92f9e36de5163b5e27a998a0935645f2f4ec2" + "d3e685c7";

        PrivateKey privateKey = decodePrivateKey(encodedPrivateKey);
        PublicKey publicKey = decodePublicKey(encodedPublicKey);

        X500PrincipalBuilder subjectBuilder = new X500PrincipalBuilder();

        String email = "test@example.com";

        subjectBuilder.setCommonName("No key usage");
        subjectBuilder.setEmail(email);
        subjectBuilder.setCountryCode("NL");
        subjectBuilder.setLocality("Amsterdam");
        subjectBuilder.setState("NH");

        AltNamesBuilder altNamesBuider = new AltNamesBuilder();
        altNamesBuider.setRFC822Names(email);

        X500Principal subject = subjectBuilder.buildPrincipal();
        GeneralNames altNames = altNamesBuider.buildAltNames();

        Set<ExtendedKeyUsageType> extendedKeyUsage = new TreeSet<ExtendedKeyUsageType>();

        extendedKeyUsage.add(ExtendedKeyUsageType.CLIENTAUTH);
        extendedKeyUsage.add(ExtendedKeyUsageType.EMAILPROTECTION);

        BigInteger serialNumber = new BigInteger("115fd0bd417e7a6f347eeacb7ff3f38", 16);

        Date now = DateFormat.getDateTimeInstance(DateFormat.MEDIUM, DateFormat.MEDIUM, Locale.UK)
                .parse("21-Nov-2007 11:51:35");

        certificateBuilder.setSubject(subject);
        certificateBuilder.setAltNames(altNames, true);
        certificateBuilder.setExtendedKeyUsage(extendedKeyUsage, false);
        certificateBuilder.setNotBefore(DateUtils.addDays(now, -20));
        certificateBuilder.setNotAfter(DateUtils.addYears(now, 20));
        certificateBuilder.setPublicKey(publicKey);
        certificateBuilder.setSerialNumber(serialNumber);
        certificateBuilder.setSignatureAlgorithm("SHA1WithRSAEncryption");

        X509Certificate certificate = certificateBuilder.generateCertificate(caPrivateKey, caCertificate);

        assertNotNull(certificate);

        certificates.add(certificate);

        Certificate[] chain = new Certificate[] { certificate, caCertificate, rootCertificate };

        keyStore.setKeyEntry("NoKeyUsage", privateKey, null, chain);
    }

    /**
     * Generates a certificate without a CN
     * 
     * @throws Exception
     */
    private void generateCertificateNoCN() throws Exception {
        X509CertificateBuilder certificateBuilder = securityFactory.createX509CertificateBuilder();

        String encodedPublicKey = "30819f300d06092a864886f70d010101050003818d00308189028181008c"
                + "853445a83b7993183d8ed24a1eb8448bde884755c51341a20168343d2a9b"
                + "ab59477e643a5717e5bbea935dac51caa3a3fbff89059be9d6bf6af8d739"
                + "5bde8c8c45f89aeb4530805387f3402491defcd523031f2ef7085c63db71"
                + "bfe9e25378929f5b3c0b53e0e073e5ed7321de1ed6564e387250cef278dd" + "15a7727824620f0203010001";

        String encodedPrivateKey = "30820275020100300d06092a864886f70d01010105000482025f3082025b"
                + "020100028181008c853445a83b7993183d8ed24a1eb8448bde884755c513"
                + "41a20168343d2a9bab59477e643a5717e5bbea935dac51caa3a3fbff8905"
                + "9be9d6bf6af8d7395bde8c8c45f89aeb4530805387f3402491defcd52303"
                + "1f2ef7085c63db71bfe9e25378929f5b3c0b53e0e073e5ed7321de1ed656"
                + "4e387250cef278dd15a7727824620f02030100010281806efedcde54d7bd"
                + "dd71dd560e479be263cab3d9a3b75d372bb5c334c366b95c4349ff4e17ef"
                + "795218168a612331f55d824b0ac7bb3d21fde0b24cd60873775cdf2db306"
                + "a899f7733d36c11064b76efab7c1b9ab8a897737a5d0b4f05378a033ff71"
                + "a150ed772f1cdbba4cbf8d41025081c960072c07c1f62d7f20a76b6d549f"
                + "61024100cad28338a54224d1a56c32c9f1ad7e0f721e7059dd1bb0310d2b"
                + "04ecc900f57b8f58d773f908a8870ba8676b4363c6087fc44f516d21c9c7"
                + "ea761e07ac77363f024100b15cf740a7162c3bc998fbf57c2d5335e4426d"
                + "5085ed295a432084c1f4311da996a8d40768d3e064e2615e0b2660faf023"
                + "86ed0cbce55a1b4ef0aa6583ed003102402ea29ad3828423ed24892d606b"
                + "b6859ecd919c29bd82694fce044f3c96b726bac36a1d182871ca364b02ec"
                + "cca8111feec25a0416e7edf5f486bfa40605acdf87024064abff0fec8732"
                + "5e51448ba7406fbdae763c9a2dbd86eb14f7cb2a6fa8ba843ab1706cc133"
                + "e827933bc7c6888fa5366a3dd0251738d4f9fb4c28609fb46d3ed1024007"
                + "49ec34b3aa1be30efcc2bc5a18b7ed51ed7b670b9a215c05725ea5dea6da"
                + "6a71aa14e33ab2c8c5d05f4d8e33ed09e83b1df5cdeaf73571f87e67a412" + "864bde";

        PrivateKey privateKey = decodePrivateKey(encodedPrivateKey);
        PublicKey publicKey = decodePublicKey(encodedPublicKey);

        X500PrincipalBuilder subjectBuilder = new X500PrincipalBuilder();

        String email = "test@example.com";

        subjectBuilder.setEmail(email);
        subjectBuilder.setCountryCode("NL");
        subjectBuilder.setLocality("Amsterdam");
        subjectBuilder.setState("NH");

        AltNamesBuilder altNamesBuider = new AltNamesBuilder();
        altNamesBuider.setRFC822Names(email);

        X500Principal subject = subjectBuilder.buildPrincipal();
        GeneralNames altNames = altNamesBuider.buildAltNames();

        Set<KeyUsageType> keyUsage = new TreeSet<KeyUsageType>();

        keyUsage.add(KeyUsageType.DIGITALSIGNATURE);
        keyUsage.add(KeyUsageType.KEYENCIPHERMENT);
        keyUsage.add(KeyUsageType.NONREPUDIATION);

        Set<ExtendedKeyUsageType> extendedKeyUsage = new TreeSet<ExtendedKeyUsageType>();

        extendedKeyUsage.add(ExtendedKeyUsageType.CLIENTAUTH);
        extendedKeyUsage.add(ExtendedKeyUsageType.EMAILPROTECTION);

        BigInteger serialNumber = new BigInteger("115fd0e5ee990d9426c93dea720e970", 16);

        Date now = DateFormat.getDateTimeInstance(DateFormat.MEDIUM, DateFormat.MEDIUM, Locale.UK)
                .parse("21-Nov-2007 11:52:35");

        certificateBuilder.setSubject(subject);
        certificateBuilder.setAltNames(altNames, true);
        certificateBuilder.setKeyUsage(keyUsage, true);
        certificateBuilder.setExtendedKeyUsage(extendedKeyUsage, false);
        certificateBuilder.setNotBefore(DateUtils.addDays(now, -20));
        certificateBuilder.setNotAfter(DateUtils.addYears(now, 20));
        certificateBuilder.setPublicKey(publicKey);
        certificateBuilder.setSerialNumber(serialNumber);
        certificateBuilder.setSignatureAlgorithm("SHA1WithRSAEncryption");

        X509Certificate certificate = certificateBuilder.generateCertificate(caPrivateKey, caCertificate);

        assertNotNull(certificate);

        certificates.add(certificate);

        Certificate[] chain = new Certificate[] { certificate, caCertificate, rootCertificate };

        keyStore.setKeyEntry("NoCN", privateKey, null, chain);
    }

    /**
     * Generates a certificate with multiple email addresses
     * 
     * @throws Exception
     */
    private void generateCertificateMultipleEmail() throws Exception {
        X509CertificateBuilder certificateBuilder = securityFactory.createX509CertificateBuilder();

        String encodedPublicKey = "30819f300d06092a864886f70d010101050003818d00308189028181008e"
                + "1347f6e22318a40d4d8b9a97cdb06355d9a761f35f44b7d3356d4596ddf6"
                + "db2606fc572ed5b9c79fb2f76466f7f9bf2797de2ae1f8d9ea14d9380f2e"
                + "afe2040d6faab65f746d9705f7fab00956b918bc7b0c2e312895b24153b7"
                + "33ffede39bf6dfe0d419b8020c8772f9da1d8d1ca3d2a9da172fafdcfb7b" + "4ecff5048d46c90203010001";

        String encodedPrivateKey = "30820276020100300d06092a864886f70d0101010500048202603082025c"
                + "020100028181008e1347f6e22318a40d4d8b9a97cdb06355d9a761f35f44"
                + "b7d3356d4596ddf6db2606fc572ed5b9c79fb2f76466f7f9bf2797de2ae1"
                + "f8d9ea14d9380f2eafe2040d6faab65f746d9705f7fab00956b918bc7b0c"
                + "2e312895b24153b733ffede39bf6dfe0d419b8020c8772f9da1d8d1ca3d2"
                + "a9da172fafdcfb7b4ecff5048d46c90203010001028180723bc28318f40b"
                + "1decac4af133d9685796717889e33ad86fcd5c89cd882e540b8499dd4ee4"
                + "13685abf67104f24138235564a5f91af3b7d4b1f144064c4af1a53e045f7"
                + "1678bd7af11e33f02dbd846782ff0b8a6f7fea20d6c068b0a79f0c3b136c"
                + "dcd201443ecc7113d8e73e9a4f8faacdd87fd314c42f54c6532ffcceeb2d"
                + "d9024100cd8ffedb65cdfbafc3ffe2ba0743ab4f0ebf5298bddd542be36b"
                + "e9393788fccb1bc8218fe0f81e85c9c2eade11d68ae30284b931cf2654bb"
                + "8ace741dcf67450b024100b0ef76b44180f5d729619cd855e0da81d5129c"
                + "b8866fee97291961f3487a3a8b5d28049cd0b7062590a963420923331ce8"
                + "7f76d49f7e6d02837916dd0878dffb024067979084fa5a02e381efbb4faa"
                + "87849653c54117ae5f12a3077a034f8d5820a52ebbfd85e786c2c3037992"
                + "29156e3c11c8dc200424f39931e5f2c2fb9ee0d91f02410088005906ef3e"
                + "b8391db6c93fc4ab246a1da4c3d0568ddd2055d80be15bb9901ca58b6818"
                + "3d9a21606894bb15fc3e1140cc3985d6a38e232e866e62339e1a83570240"
                + "10b51e80ac96ea754e7232e633daeae50efaf8f0b9f55fcd113226722197"
                + "d9650870c7a245348be5d4f3dd2face76ad2e82f5c6b658c67b4cdfe6d14" + "dbaf86bd";

        PrivateKey privateKey = decodePrivateKey(encodedPrivateKey);
        PublicKey publicKey = decodePublicKey(encodedPublicKey);

        X500PrincipalBuilder subjectBuilder = new X500PrincipalBuilder();

        String email[] = new String[] { "test@example.com", "test2@example.com", "test3@example.com", "invalid" };

        subjectBuilder.setCommonName("multiple email");
        subjectBuilder.setEmail(email);
        subjectBuilder.setCountryCode("NL");
        subjectBuilder.setLocality("Amsterdam");
        subjectBuilder.setState("NH");

        AltNamesBuilder altNamesBuider = new AltNamesBuilder();
        altNamesBuider.setRFC822Names(email);

        X500Principal subject = subjectBuilder.buildPrincipal();
        GeneralNames altNames = altNamesBuider.buildAltNames();

        Set<KeyUsageType> keyUsage = new TreeSet<KeyUsageType>();

        keyUsage.add(KeyUsageType.DIGITALSIGNATURE);
        keyUsage.add(KeyUsageType.KEYENCIPHERMENT);
        keyUsage.add(KeyUsageType.NONREPUDIATION);

        Set<ExtendedKeyUsageType> extendedKeyUsage = new TreeSet<ExtendedKeyUsageType>();

        extendedKeyUsage.add(ExtendedKeyUsageType.CLIENTAUTH);
        extendedKeyUsage.add(ExtendedKeyUsageType.EMAILPROTECTION);

        BigInteger serialNumber = new BigInteger("115fd110a82f742d0ae14a71b651962", 16);

        Date now = DateFormat.getDateTimeInstance(DateFormat.MEDIUM, DateFormat.MEDIUM, Locale.UK)
                .parse("21-Nov-2007 11:52:35");

        certificateBuilder.setSubject(subject);
        certificateBuilder.setAltNames(altNames, true);
        certificateBuilder.setKeyUsage(keyUsage, true);
        certificateBuilder.setExtendedKeyUsage(extendedKeyUsage, false);
        certificateBuilder.setNotBefore(DateUtils.addDays(now, -20));
        certificateBuilder.setNotAfter(DateUtils.addYears(now, 20));
        certificateBuilder.setPublicKey(publicKey);
        certificateBuilder.setSerialNumber(serialNumber);
        certificateBuilder.setSignatureAlgorithm("SHA1WithRSAEncryption");

        X509Certificate certificate = certificateBuilder.generateCertificate(caPrivateKey, caCertificate);

        assertNotNull(certificate);

        certificates.add(certificate);

        Certificate[] chain = new Certificate[] { certificate, caCertificate, rootCertificate };

        keyStore.setKeyEntry("multipleEmail", privateKey, null, chain);
    }

    /**
     * Generates a certificate with MD5 Hash algorithm
     * 
     * @throws Exception
     */
    private void generateCertificateMD5Hash() throws Exception {
        X509CertificateBuilder certificateBuilder = securityFactory.createX509CertificateBuilder();

        String encodedPublicKey = "30819f300d06092a864886f70d010101050003818d003081890281810080"
                + "204142a37fe819010c9c5e021b8df7ee54083c588a04c31ffd714695ce18"
                + "51721b0f00a392643fa91392aa7bcf1426d2e2f724a5d996740d97b8586c"
                + "f59cc7bc8d865bf3957a629c8f36bb9b71017c53e8baf71821cf622ca025"
                + "d3c523c084700a5c1af9b624639c86c556d8038a7afc2235d2f1d0f226c4" + "48a40c2e0327dd0203010001";

        String encodedPrivateKey = "30820275020100300d06092a864886f70d01010105000482025f3082025b"
                + "0201000281810080204142a37fe819010c9c5e021b8df7ee54083c588a04"
                + "c31ffd714695ce1851721b0f00a392643fa91392aa7bcf1426d2e2f724a5"
                + "d996740d97b8586cf59cc7bc8d865bf3957a629c8f36bb9b71017c53e8ba"
                + "f71821cf622ca025d3c523c084700a5c1af9b624639c86c556d8038a7afc"
                + "2235d2f1d0f226c448a40c2e0327dd020301000102818028427a5f2722fc"
                + "da468320eb453c454adf9f960ae8434e25c5fa8c4a82ae04e42ab7a7ea2a"
                + "7bc8765c7962ffa0f1bbc24b47b822d2de61314c481d4be3c8f59f3497f6"
                + "4d6d84e7d61b7858f20e88e803ff924f8d98a311a2f39398b149100a158c"
                + "ac03df61da458599e87da0ca48b749dee040f66c8fe3eda072f44ec4829f"
                + "3d024100e4361bd0489cb47e204af8905d617e1e04e7102fec2c22711b85"
                + "9dbade040aa41f0f2a349b88444da57c6b5a16f198ea9ac70350855eece1"
                + "6eafe7789a2c33730241008fba3f47889514c507b76a289d097a220f07d8"
                + "0dea9fd55191b6519646d11ad6399d97924906768ea19f8262cad28c7a16"
                + "b76d8cdc069b6c639fdce3a027836f0240678ca9b82b8a7757977d8d25ac"
                + "497579578e24c929e7a8c51bd0d80e17794bfec65d123086b6210ffe5be3"
                + "36209d055ec6563109d34a8c3f8a02e50bd320e543024033d5e4049489cf"
                + "d7cf94a2c0cb0223fe2c9593a251401bdb334621dea4e3bd5e0da17c8cd1"
                + "b17708b1d9a9589ff5979c609cfef19258ffacf3b130251819a819024018"
                + "81b9dae35212866780b9ce93e0c10fa40e3679773e3b067d5743bfdb8c74"
                + "ce8d1ed3a0d5312f220f7d0eb44c074c46898acbcfdba15c480385458d90" + "14fd7b";

        PrivateKey privateKey = decodePrivateKey(encodedPrivateKey);
        PublicKey publicKey = decodePublicKey(encodedPublicKey);

        X500PrincipalBuilder subjectBuilder = new X500PrincipalBuilder();

        String email[] = new String[] { "test@example.com" };

        subjectBuilder.setCommonName("md5 Hash");
        subjectBuilder.setEmail(email);
        subjectBuilder.setCountryCode("NL");
        subjectBuilder.setLocality("Amsterdam");
        subjectBuilder.setState("NH");

        AltNamesBuilder altNamesBuider = new AltNamesBuilder();
        altNamesBuider.setRFC822Names(email);

        X500Principal subject = subjectBuilder.buildPrincipal();
        GeneralNames altNames = altNamesBuider.buildAltNames();

        Set<KeyUsageType> keyUsage = new TreeSet<KeyUsageType>();

        keyUsage.add(KeyUsageType.DIGITALSIGNATURE);
        keyUsage.add(KeyUsageType.KEYENCIPHERMENT);
        keyUsage.add(KeyUsageType.NONREPUDIATION);

        Set<ExtendedKeyUsageType> extendedKeyUsage = new TreeSet<ExtendedKeyUsageType>();

        extendedKeyUsage.add(ExtendedKeyUsageType.CLIENTAUTH);
        extendedKeyUsage.add(ExtendedKeyUsageType.EMAILPROTECTION);

        BigInteger serialNumber = new BigInteger("115fd1392a8ff07aa727558fa50b262", 16);

        Date now = DateFormat.getDateTimeInstance(DateFormat.MEDIUM, DateFormat.MEDIUM, Locale.UK)
                .parse("21-Nov-2007 11:54:35");

        certificateBuilder.setSubject(subject);
        certificateBuilder.setAltNames(altNames, true);
        certificateBuilder.setKeyUsage(keyUsage, true);
        certificateBuilder.setExtendedKeyUsage(extendedKeyUsage, false);
        certificateBuilder.setNotBefore(DateUtils.addDays(now, -20));
        certificateBuilder.setNotAfter(DateUtils.addYears(now, 20));
        certificateBuilder.setPublicKey(publicKey);
        certificateBuilder.setSerialNumber(serialNumber);
        certificateBuilder.setSignatureAlgorithm("MD5WithRSAEncryption");

        X509Certificate certificate = certificateBuilder.generateCertificate(caPrivateKey, caCertificate);

        assertNotNull(certificate);

        certificates.add(certificate);

        Certificate[] chain = new Certificate[] { certificate, caCertificate, rootCertificate };

        keyStore.setKeyEntry("md5Hash", privateKey, null, chain);
    }

    /**
     * Generates a certificate with SHA256 Hash algorithm
     * 
     * @throws Exception
     */
    private void generateCertificateSHA256Hash() throws Exception {
        X509CertificateBuilder certificateBuilder = securityFactory.createX509CertificateBuilder();

        String encodedPublicKey = "30819f300d06092a864886f70d010101050003818d00308189028181008b"
                + "08d9d440857d8b6e0adf44301cecacc9e3619e25e3ecb2735a0c25a8d65c"
                + "005d44c92fea1e82693d676c25653d4f4a30702aefde057983ab4fd1d381"
                + "a18938318dcf07f635e68b32b47b5ec8246e783c912e7287c9d2e75c5f01"
                + "24653694c0dcf8b5983bf7659fa2558426f44978db1e5e81a4abae5ea245" + "f915d6ef663af70203010001";

        String encodedPrivateKey = "30820277020100300d06092a864886f70d0101010500048202613082025d"
                + "020100028181008b08d9d440857d8b6e0adf44301cecacc9e3619e25e3ec"
                + "b2735a0c25a8d65c005d44c92fea1e82693d676c25653d4f4a30702aefde"
                + "057983ab4fd1d381a18938318dcf07f635e68b32b47b5ec8246e783c912e"
                + "7287c9d2e75c5f0124653694c0dcf8b5983bf7659fa2558426f44978db1e"
                + "5e81a4abae5ea245f915d6ef663af702030100010281807277ce07ef3b38"
                + "7ac415d56de982d6e507aeda5eff69212666cc3b760204c2685661dc9643"
                + "55ed1ec23c551090c2a2763d5d0c2cc289955aef7f5f0c990caad0c4be38"
                + "ea093a0ff82f987fb85432ff0c97acec554b9ffe6bdccec9b2c30b57e866"
                + "b9f964cd64d007311e2b477f88d15c4fccc57fbd06afdf815624c92ba03d"
                + "a9024100f508e549437f5ec1b2307b6843f692f189feed369389a598172c"
                + "859a768bc5b3e02765b0a8e672e54b1096f526c8df741d12910296be0c16"
                + "e93f7bb77fb13bd502410091419f88e027d1b0f99408eaab6dd26b2bd0a6"
                + "62e47f5d40f20d191dab1864a6bfea4a9c5b1b3f1aea35c4134bdf005cd0"
                + "25d4a0e98299e6aa2be46591607d9b024100f119f8a9f70d4bca612f8d2e"
                + "11b97beac8729b2c194dd62f6995f83bfd2b18b41dfa05f826a8e222b592"
                + "b446b20bf2bac8a46d24d3f859e2ed4cf6c99e8e60a502410085a22ee858"
                + "f8a934bcd7d1403c08a42e0eb83d6afbb6a50f6be05afbed7d5a940239c4"
                + "fc85e0d234abc65d263785e8aa7aa06336cabd696349a969cd7b6a9f0302"
                + "405653037277299bfd0d055bc55b5f8f9892e7254f7ddf09cb0a5a159095"
                + "746a3d914caa2c2a8c24d1ab57c1d065cf9c31ef4820855b2dbfa6f7a91c" + "96b152f9ef";

        PrivateKey privateKey = decodePrivateKey(encodedPrivateKey);
        PublicKey publicKey = decodePublicKey(encodedPublicKey);

        X500PrincipalBuilder subjectBuilder = new X500PrincipalBuilder();

        String email[] = new String[] { "test@example.com" };

        subjectBuilder.setCommonName("SHA256 Hash");
        subjectBuilder.setEmail(email);
        subjectBuilder.setCountryCode("NL");
        subjectBuilder.setLocality("Amsterdam");
        subjectBuilder.setState("NH");

        AltNamesBuilder altNamesBuider = new AltNamesBuilder();
        altNamesBuider.setRFC822Names(email);

        X500Principal subject = subjectBuilder.buildPrincipal();
        GeneralNames altNames = altNamesBuider.buildAltNames();

        Set<KeyUsageType> keyUsage = new TreeSet<KeyUsageType>();

        keyUsage.add(KeyUsageType.DIGITALSIGNATURE);
        keyUsage.add(KeyUsageType.KEYENCIPHERMENT);
        keyUsage.add(KeyUsageType.NONREPUDIATION);

        Set<ExtendedKeyUsageType> extendedKeyUsage = new TreeSet<ExtendedKeyUsageType>();

        extendedKeyUsage.add(ExtendedKeyUsageType.CLIENTAUTH);
        extendedKeyUsage.add(ExtendedKeyUsageType.EMAILPROTECTION);

        BigInteger serialNumber = new BigInteger("115fd16008275f2616b8a235d761fff", 16);

        Date now = DateFormat.getDateTimeInstance(DateFormat.MEDIUM, DateFormat.MEDIUM, Locale.UK)
                .parse("21-Nov-2007 06:38:35");

        certificateBuilder.setSubject(subject);
        certificateBuilder.setAltNames(altNames, true);
        certificateBuilder.setKeyUsage(keyUsage, true);
        certificateBuilder.setExtendedKeyUsage(extendedKeyUsage, false);
        certificateBuilder.setNotBefore(DateUtils.addDays(now, -20));
        certificateBuilder.setNotAfter(DateUtils.addYears(now, 20));
        certificateBuilder.setPublicKey(publicKey);
        certificateBuilder.setSerialNumber(serialNumber);
        certificateBuilder.setSignatureAlgorithm("SHA256WithRSAEncryption");

        X509Certificate certificate = certificateBuilder.generateCertificate(caPrivateKey, caCertificate);

        assertNotNull(certificate);

        certificates.add(certificate);

        Certificate[] chain = new Certificate[] { certificate, caCertificate, rootCertificate };

        keyStore.setKeyEntry("sha256Hash", privateKey, null, chain);
    }

    /**
     * Generates a certificate with RSA 2048 key length
     * 
     * @throws Exception
     */
    private void generateCertificateRSA2048() throws Exception {
        X509CertificateBuilder certificateBuilder = securityFactory.createX509CertificateBuilder();

        String encodedPublicKey = "30820122300d06092a864886f70d01010105000382010f003082010a0282"
                + "010100804e190456423f3253d25f622b11d6601cce51b2793cb752265461"
                + "6e34804282b081cf0b9389a7160649ce2d62a224201027113a74351b9fda"
                + "7a640d96615615e934cea567b1d809180f034660ab1692d2db3a04cbc439"
                + "a20e947bfe5552a1a32152b7b3501c54c7255943102c5712ec0648823b44"
                + "be3a8c85bf550f3fda7edf8adff1505dffe1fdd8e8100f5808e57f349d5b"
                + "cd41d2fc8cbc3e24e29f02468ecdaa152581e55e068e3e2af0ef5c7ad106"
                + "01934a3e698c485971e69a8820ad7a697b1492bd695747a8dedcbfb72a6f"
                + "f04e4adf8c56bdcc0592cd36288cc1daee35950e9e8676c52fe0fbee02d8"
                + "52c09ff906c7296b12aa2bc972240af9f4720f0203010001";

        String encodedPrivateKey = "308204bd020100300d06092a864886f70d0101010500048204a7308204a3"
                + "0201000282010100804e190456423f3253d25f622b11d6601cce51b2793c"
                + "b7522654616e34804282b081cf0b9389a7160649ce2d62a224201027113a"
                + "74351b9fda7a640d96615615e934cea567b1d809180f034660ab1692d2db"
                + "3a04cbc439a20e947bfe5552a1a32152b7b3501c54c7255943102c5712ec"
                + "0648823b44be3a8c85bf550f3fda7edf8adff1505dffe1fdd8e8100f5808"
                + "e57f349d5bcd41d2fc8cbc3e24e29f02468ecdaa152581e55e068e3e2af0"
                + "ef5c7ad10601934a3e698c485971e69a8820ad7a697b1492bd695747a8de"
                + "dcbfb72a6ff04e4adf8c56bdcc0592cd36288cc1daee35950e9e8676c52f"
                + "e0fbee02d852c09ff906c7296b12aa2bc972240af9f4720f020301000102"
                + "820100307fd4fb0bb42cf9543010782639aee453df358896457a326664bd"
                + "13906aef3941893fff6b3cbc5919f56a2743c2708f622bb25a7b34dc0557"
                + "ebadc86910d01ea6319cef6f3c0da29a628a655f032d1c40f237833a9729"
                + "05f626f09bda1acb18c3eee59bb56b902c5b14dbc1d050f5c91c32ea6f86"
                + "f3b5640ae6a13b8b7287446321e3c7c7543ce9bb95a2329be4e09f8ae3db"
                + "9eb6a886168fa91954595332091bb09580dcc83444c02e63a5915d80eaa8"
                + "894159bc0ec787b7cd897ce26014d537ef731d0f7d7726585fb5193b76e4"
                + "5d9c2baf1f8a80ed84cf15c591d0d09122c4377bdde75b7a72b0aaeec170"
                + "a604ffe77491038762c4125083463a11b7802902818100dcd8b76c1d0599"
                + "0e54a22a65fb5cdb41674f6496fa15b3d09d5b32417a5f02c477a0da482c"
                + "ea27fb3a5c11acf9770b83d66b43ba16d92f927ce6a3dab71ade3a918d97"
                + "b951d3b14ea5edeb8786df83ce46e204ece2c06ab445102ba2c74dff607a"
                + "84933e9f54dd987bf306079e337692df4d0d335f97f302c69106577134d9"
                + "030281810094ba67c454dc1b8cbaff49cde17cdc583319572d29b4f284d1"
                + "0b9740cb468678b0fa196626208406181717a4bc9acfaef8627ce086e0bb"
                + "8c95b14e911be6e8c5569a6c8198dcaa88291fc7d7ec560b19258a3d544c"
                + "8a6a81d09454521921c96f5b1f5c9dfc77c53d6ffe17b59fdfed04381233"
                + "27c1bbed740cab748324346705028181009d216097feaa2df52148644c3d"
                + "251b2714bf4b3d945ffe994e6c457c8af9b0b962b842b699a65c9e062edd"
                + "b0a9aa06ba5dc3e1e3344080f5840281d0aaf8e5e6dc0ad749d6ab7cfb0d"
                + "5a137b50fe15049e304ffacf76c234d2f2a76960cee1059f0656d17681e6"
                + "4c88dc278d220551b73c43d1419d213a98ddf8ef7f259fc94b0281805949"
                + "e39c31da06cc2143bc5a56c23042df429a5ca9ca5142bd81b8e794621dbe"
                + "fd78d8a0c3c90799e50290163d88afa07acc1dee69eb278d8a1ced6f1e92"
                + "2d32b400779e02589024b893b4d583b4506b63672fd499330c282d41afb1"
                + "ae16e3a8efcacf3ea5e07dd09998b1413fdf1e9b46d25e55c2f080e907e6"
                + "3347bc079dc502818021c107a9757dc38395f859e7d59ba1ef12c8719e62"
                + "ebbbf9d720bf29db7c48a19c2c63ab283254cd87ced3415381db08ca2714"
                + "0ea7cbdcf47a3bb091eeb1333caefdda0f78d41c073c166b187195fac3cd"
                + "54ca7ffbbc1056fe7ec2654e126ff09e2da201337f1c7733cbd28f8e2804"
                + "c2eb55c4224f84e28875aafab7a827a687";

        PrivateKey privateKey = decodePrivateKey(encodedPrivateKey);
        PublicKey publicKey = decodePublicKey(encodedPublicKey);

        X500PrincipalBuilder subjectBuilder = new X500PrincipalBuilder();

        String email[] = new String[] { "test@example.com" };

        subjectBuilder.setCommonName("RSA 2048");
        subjectBuilder.setEmail(email);
        subjectBuilder.setCountryCode("NL");
        subjectBuilder.setLocality("Amsterdam");
        subjectBuilder.setState("NH");

        AltNamesBuilder altNamesBuider = new AltNamesBuilder();
        altNamesBuider.setRFC822Names(email);

        X500Principal subject = subjectBuilder.buildPrincipal();
        GeneralNames altNames = altNamesBuider.buildAltNames();

        Set<KeyUsageType> keyUsage = new TreeSet<KeyUsageType>();

        keyUsage.add(KeyUsageType.DIGITALSIGNATURE);
        keyUsage.add(KeyUsageType.KEYENCIPHERMENT);
        keyUsage.add(KeyUsageType.NONREPUDIATION);

        Set<ExtendedKeyUsageType> extendedKeyUsage = new TreeSet<ExtendedKeyUsageType>();

        extendedKeyUsage.add(ExtendedKeyUsageType.CLIENTAUTH);
        extendedKeyUsage.add(ExtendedKeyUsageType.EMAILPROTECTION);

        BigInteger serialNumber = new BigInteger("115fd1606444bc50de5464af7d0d468", 16);

        Date now = DateFormat.getDateTimeInstance(DateFormat.MEDIUM, DateFormat.MEDIUM, Locale.UK)
                .parse("21-Nov-2007 06:38:35");

        certificateBuilder.setSubject(subject);
        certificateBuilder.setAltNames(altNames, true);
        certificateBuilder.setKeyUsage(keyUsage, true);
        certificateBuilder.setExtendedKeyUsage(extendedKeyUsage, false);
        certificateBuilder.setNotBefore(DateUtils.addDays(now, -20));
        certificateBuilder.setNotAfter(DateUtils.addYears(now, 20));
        certificateBuilder.setPublicKey(publicKey);
        certificateBuilder.setSerialNumber(serialNumber);
        certificateBuilder.setSignatureAlgorithm("SHA1WithRSAEncryption");

        X509Certificate certificate = certificateBuilder.generateCertificate(caPrivateKey, caCertificate);

        assertNotNull(certificate);

        certificates.add(certificate);

        Certificate[] chain = new Certificate[] { certificate, caCertificate, rootCertificate };

        keyStore.setKeyEntry("rsa2048", privateKey, null, chain);
    }
}