beta01.SimpleRootCA.java Source code

Java tutorial

Introduction

Here is the source code for beta01.SimpleRootCA.java

Source

/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package beta01;

import cwguide.BcCredential;
import cwguide.BcUtils;
import cwguide.SHA1DigestCalculator;
import java.math.BigInteger;
import java.security.SecureRandom;
import java.security.cert.CertPathBuilder;
import java.security.cert.CertStore;
import java.security.cert.PKIXBuilderParameters;
import java.security.cert.PKIXCertPathBuilderResult;
import java.security.cert.TrustAnchor;
import java.security.cert.X509CertSelector;
import java.security.cert.X509Certificate;
import java.util.Collections;
import java.util.Date;
import org.bouncycastle.asn1.x500.X500Name;
import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
import org.bouncycastle.asn1.x509.BasicConstraints;
import org.bouncycastle.asn1.x509.Extension;
import org.bouncycastle.asn1.x509.KeyUsage;
import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo;
import org.bouncycastle.cert.X509CertificateHolder;
import org.bouncycastle.cert.X509ExtensionUtils;
import org.bouncycastle.cert.X509v1CertificateBuilder;
import org.bouncycastle.cert.X509v3CertificateBuilder;
import org.bouncycastle.crypto.AsymmetricCipherKeyPair;
import org.bouncycastle.crypto.AsymmetricCipherKeyPairGenerator;
import org.bouncycastle.crypto.generators.RSAKeyPairGenerator;
import org.bouncycastle.crypto.params.AsymmetricKeyParameter;
import org.bouncycastle.crypto.params.RSAKeyGenerationParameters;
import org.bouncycastle.crypto.util.SubjectPublicKeyInfoFactory;
import org.bouncycastle.operator.ContentSigner;
import org.bouncycastle.operator.DefaultDigestAlgorithmIdentifierFinder;
import org.bouncycastle.operator.DefaultSignatureAlgorithmIdentifierFinder;
import org.bouncycastle.operator.SignatureAlgorithmIdentifierFinder;
import org.bouncycastle.operator.bc.BcRSAContentSignerBuilder;

/**
 *
 * @author Pizaini
 */
public class SimpleRootCA {
    public static final String ROOT_ALIAS = "root";
    public static final String INTERMEDIATE_ALIAS = "intermediate";
    public static final String END_ENTITY_ALIAS = "end";

    private static final int VALIDITY_PERIOD = 7 * 24 * 60 * 60 * 1000; // one week

    public static char[] KEY_PASSWD = "keyPassword".toCharArray();

    private static final SignatureAlgorithmIdentifierFinder algFinder = new DefaultSignatureAlgorithmIdentifierFinder();

    /**
     * Create a KeyStore containing the a private credential with
     * certificate chain and a trust anchor.
     * @return 
     * @throws java.lang.Exception
     */
    public static BcCredential createCredentials() throws Exception {
        BcCredential rootCredential = BcUtils.createRootCredential();
        BcCredential interCredential = BcUtils.createIntermediateCredential(rootCredential.getPrivateKey(),
                rootCredential.getCertificateChain()[0]);
        BcCredential endCredential = BcUtils.createEndEntityCredential(interCredential.getPrivateKey(),
                interCredential.getCertificateChain()[0]);

        return new BcCredential(endCredential.getAlias(), endCredential.getPrivateKey(),
                new X509CertificateHolder[] { endCredential.getCertificateChain()[0],
                        interCredential.getCertificateChain()[0], rootCredential.getCertificateChain()[0] });
    }

    /**
     * Build a sample V1 certificate to use as a CA root certificate
     * @param keyPair
     */
    public static X509CertificateHolder buildRootCert(org.bouncycastle.crypto.AsymmetricCipherKeyPair keyPair)
            throws Exception {
        X509v1CertificateBuilder certBldr = new X509v1CertificateBuilder(new X500Name("CN=Test Root Certificate"),
                BigInteger.valueOf(1), new Date(System.currentTimeMillis()),
                new Date(System.currentTimeMillis() + VALIDITY_PERIOD), new X500Name("CN=Test Root Certificate"),
                SubjectPublicKeyInfoFactory
                        .createSubjectPublicKeyInfo((AsymmetricKeyParameter) keyPair.getPublic()));

        AlgorithmIdentifier sigAlg = algFinder.find("SHA1withRSA");
        AlgorithmIdentifier digAlg = new DefaultDigestAlgorithmIdentifierFinder().find(sigAlg);

        ContentSigner signer = new BcRSAContentSignerBuilder(sigAlg, digAlg)
                .build((AsymmetricKeyParameter) keyPair.getPrivate());

        return certBldr.build(signer);
    }

    /**
     * Build a sample V3 certificate to use as an intermediate CA certificate
     * @param intKey
     * @param caKey
     * @param caCert
     * @return 
     * @throws java.lang.Exception 
     */
    public static X509CertificateHolder buildIntermediateCert(AsymmetricKeyParameter intKey,
            AsymmetricKeyParameter caKey, X509CertificateHolder caCert) throws Exception {
        SubjectPublicKeyInfo intKeyInfo = SubjectPublicKeyInfoFactory.createSubjectPublicKeyInfo(intKey);

        X509v3CertificateBuilder certBldr = new X509v3CertificateBuilder(caCert.getSubject(), BigInteger.valueOf(1),
                new Date(System.currentTimeMillis()), new Date(System.currentTimeMillis() + VALIDITY_PERIOD),
                new X500Name("CN=Test CA Certificate"), intKeyInfo);

        X509ExtensionUtils extUtils = new X509ExtensionUtils(new SHA1DigestCalculator());

        certBldr.addExtension(Extension.authorityKeyIdentifier, false,
                extUtils.createAuthorityKeyIdentifier(caCert))
                .addExtension(Extension.subjectKeyIdentifier, false,
                        extUtils.createSubjectKeyIdentifier(intKeyInfo))
                .addExtension(Extension.basicConstraints, true, new BasicConstraints(0))
                .addExtension(Extension.keyUsage, true,
                        new KeyUsage(KeyUsage.digitalSignature | KeyUsage.keyCertSign | KeyUsage.cRLSign));

        AlgorithmIdentifier sigAlg = algFinder.find("SHA1withRSA");
        AlgorithmIdentifier digAlg = new DefaultDigestAlgorithmIdentifierFinder().find(sigAlg);

        ContentSigner signer = new BcRSAContentSignerBuilder(sigAlg, digAlg).build(caKey);

        return certBldr.build(signer);
    }

    /**
     * Build a sample V3 certificate to use as an end entity certificate
     */
    public static X509CertificateHolder buildEndEntityCert(AsymmetricKeyParameter entityKey,
            AsymmetricKeyParameter caKey, X509CertificateHolder caCert) throws Exception {
        SubjectPublicKeyInfo entityKeyInfo = SubjectPublicKeyInfoFactory.createSubjectPublicKeyInfo(entityKey);

        X509v3CertificateBuilder certBldr = new X509v3CertificateBuilder(caCert.getSubject(), BigInteger.valueOf(1),
                new Date(System.currentTimeMillis()), new Date(System.currentTimeMillis() + VALIDITY_PERIOD),
                new X500Name("CN=Test End Entity Certificate"), entityKeyInfo);

        X509ExtensionUtils extUtils = new X509ExtensionUtils(new SHA1DigestCalculator());

        certBldr.addExtension(Extension.authorityKeyIdentifier, false,
                extUtils.createAuthorityKeyIdentifier(caCert))
                .addExtension(Extension.subjectKeyIdentifier, false,
                        extUtils.createSubjectKeyIdentifier(entityKeyInfo))
                .addExtension(Extension.basicConstraints, true, new BasicConstraints(false))
                .addExtension(Extension.keyUsage, true,
                        new KeyUsage(KeyUsage.digitalSignature | KeyUsage.keyEncipherment));

        AlgorithmIdentifier sigAlg = algFinder.find("SHA1withRSA");
        AlgorithmIdentifier digAlg = new DefaultDigestAlgorithmIdentifierFinder().find(sigAlg);

        ContentSigner signer = new BcRSAContentSignerBuilder(sigAlg, digAlg).build(caKey);

        return certBldr.build(signer);
    }

    /**
     * Create a random 2048 bit RSA key pair
     */
    public static AsymmetricCipherKeyPair generateRSAKeyPair() throws Exception {
        AsymmetricCipherKeyPairGenerator kpGen = new RSAKeyPairGenerator();

        kpGen.init(new RSAKeyGenerationParameters(BigInteger.valueOf(0x11), new SecureRandom(), 2048, 12));

        return kpGen.generateKeyPair();
    }

    /**
     * Create a BcCredential for the root entity.
     */
    public static BcCredential createRootCredential() throws Exception {
        AsymmetricCipherKeyPair rootPair = generateRSAKeyPair();
        X509CertificateHolder rootCert = buildRootCert(rootPair);

        return new BcCredential(ROOT_ALIAS, (AsymmetricKeyParameter) rootPair.getPrivate(), rootCert);
    }

    /**
     * Create a BcCredential for the intermediate entity.
     */
    public static BcCredential createIntermediateCredential(AsymmetricKeyParameter caKey,
            X509CertificateHolder caCert) throws Exception {
        AsymmetricCipherKeyPair interPair = generateRSAKeyPair();
        X509CertificateHolder interCert = buildIntermediateCert((AsymmetricKeyParameter) interPair.getPublic(),
                caKey, caCert);

        return new BcCredential(INTERMEDIATE_ALIAS, (AsymmetricKeyParameter) interPair.getPrivate(), interCert);
    }

    /**
     * Create a BcCredential for the end entity.
     */
    public static BcCredential createEndEntityCredential(AsymmetricKeyParameter caKey, X509CertificateHolder caCert)
            throws Exception {
        AsymmetricCipherKeyPair endPair = generateRSAKeyPair();
        X509CertificateHolder endCert = buildEndEntityCert((AsymmetricKeyParameter) endPair.getPublic(), caKey,
                caCert);

        return new BcCredential(END_ENTITY_ALIAS, (AsymmetricKeyParameter) endPair.getPrivate(), endCert);
    }

    /**
     * Build a path using the given root as the trust anchor, and the passed
     * in end constraints and certificate store.
     * <p>
     * Note: the path is built with revocation checking turned off.
     * @param rootCert
     * @param endConstraints
     * @param certsAndCRLs
     * @return 
     * @throws java.lang.Exception 
     */
    public static PKIXCertPathBuilderResult buildPath(X509Certificate rootCert, X509CertSelector endConstraints,
            CertStore certsAndCRLs) throws Exception {
        CertPathBuilder builder = CertPathBuilder.getInstance("PKIX", "BC");
        PKIXBuilderParameters buildParams = new PKIXBuilderParameters(
                Collections.singleton(new TrustAnchor(rootCert, null)), endConstraints);

        buildParams.addCertStore(certsAndCRLs);
        buildParams.setRevocationEnabled(false);

        return (PKIXCertPathBuilderResult) builder.build(buildParams);
    }

}