net.solarnetwork.node.setup.test.PKITestUtils.java Source code

Java tutorial

Introduction

Here is the source code for net.solarnetwork.node.setup.test.PKITestUtils.java

Source

/* ==================================================================
 * PKITestHelper.java - 18/07/2016 3:52:59 PM
 * 
 * Copyright 2007-2016 SolarNetwork.net Dev Team
 * 
 * This program is free software; you can redistribute it and/or 
 * modify it under the terms of the GNU General Public License as 
 * published by the Free Software Foundation; either version 2 of 
 * the License, or (at your option) any later version.
 * 
 * This program 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 
 * General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License 
 * along with this program; if not, write to the Free Software 
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 
 * 02111-1307 USA
 * ==================================================================
 */

package net.solarnetwork.node.setup.test;

import java.io.IOException;
import java.io.StringWriter;
import java.math.BigInteger;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.SignatureException;
import java.security.cert.CertPath;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.concurrent.atomic.AtomicLong;
import org.bouncycastle.asn1.x500.X500Name;
import org.bouncycastle.asn1.x509.AuthorityKeyIdentifier;
import org.bouncycastle.asn1.x509.BasicConstraints;
import org.bouncycastle.asn1.x509.GeneralName;
import org.bouncycastle.asn1.x509.GeneralNames;
import org.bouncycastle.asn1.x509.SubjectKeyIdentifier;
import org.bouncycastle.asn1.x509.X509Extension;
import org.bouncycastle.cert.X509CertificateHolder;
import org.bouncycastle.cert.X509v3CertificateBuilder;
import org.bouncycastle.cert.jcajce.JcaX500NameUtil;
import org.bouncycastle.cert.jcajce.JcaX509CertificateConverter;
import org.bouncycastle.cert.jcajce.JcaX509ExtensionUtils;
import org.bouncycastle.cert.jcajce.JcaX509v3CertificateBuilder;
import org.bouncycastle.jce.X509KeyUsage;
import org.bouncycastle.operator.ContentSigner;
import org.bouncycastle.operator.OperatorCreationException;
import org.bouncycastle.operator.jcajce.JcaContentSignerBuilder;
import org.bouncycastle.pkcs.PKCS10CertificationRequest;
import org.bouncycastle.util.io.pem.PemObject;
import org.bouncycastle.util.io.pem.PemWriter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import net.solarnetwork.support.CertificateException;

/**
 * Helper class for PKI related tasks within tests.
 * 
 * @author matt
 * @version 1.0
 */
public class PKITestUtils {

    private static final Logger LOG = LoggerFactory.getLogger(PKITestUtils.class);

    public static String getPKCS7Encoding(X509Certificate[] chain)
            throws IOException, java.security.cert.CertificateException {
        CertificateFactory cf = CertificateFactory.getInstance("X.509");
        List<X509Certificate> chainList = Arrays.asList(chain);
        LOG.debug("Cert chain:\n{}", chainList);
        CertPath path = cf.generateCertPath(chainList);
        StringWriter out = new StringWriter();
        PemWriter writer = new PemWriter(out);
        PemObject pemObj = new PemObject("CERTIFICATE CHAIN", path.getEncoded("PKCS7"));
        writer.writeObject(pemObj);
        writer.flush();
        writer.close();
        out.close();
        String result = out.toString();
        LOG.debug("Generated cert chain:\n{}", result);
        return result;

    }

    private static final AtomicLong serialCounter = new AtomicLong(0);

    public static BigInteger getNextSerialNumber() {
        return new BigInteger(Long.valueOf(serialCounter.incrementAndGet()).toString());
    }

    public static X509Certificate generateNewCACert(PublicKey publicKey, String subject, X509Certificate issuer,
            PrivateKey issuerKey, String caDN) throws Exception {
        final X500Name issuerDn = (issuer == null ? new X500Name(subject) : JcaX500NameUtil.getSubject(issuer));
        final X500Name subjectDn = new X500Name(subject);
        final BigInteger serial = getNextSerialNumber();
        final Date notBefore = new Date();
        final Date notAfter = new Date(System.currentTimeMillis() + 1000L * 60L * 60L);
        JcaX509v3CertificateBuilder builder = new JcaX509v3CertificateBuilder(issuerDn, serial, notBefore, notAfter,
                subjectDn, publicKey);

        // add "CA" extension
        BasicConstraints basicConstraints;
        if (issuer == null) {
            basicConstraints = new BasicConstraints(true);
        } else {
            int issuerPathLength = issuer.getBasicConstraints();
            basicConstraints = new BasicConstraints(issuerPathLength - 1);
        }
        builder.addExtension(X509Extension.basicConstraints, true, basicConstraints);

        // add subjectKeyIdentifier
        JcaX509ExtensionUtils utils = new JcaX509ExtensionUtils();
        SubjectKeyIdentifier ski = utils.createSubjectKeyIdentifier(publicKey);
        builder.addExtension(X509Extension.subjectKeyIdentifier, false, ski);

        // add authorityKeyIdentifier
        GeneralNames issuerName = new GeneralNames(new GeneralName(GeneralName.directoryName, caDN));
        AuthorityKeyIdentifier aki = utils.createAuthorityKeyIdentifier(publicKey);
        aki = new AuthorityKeyIdentifier(aki.getKeyIdentifier(), issuerName, serial);
        builder.addExtension(X509Extension.authorityKeyIdentifier, false, aki);

        // add keyUsage
        X509KeyUsage keyUsage = new X509KeyUsage(X509KeyUsage.cRLSign | X509KeyUsage.digitalSignature
                | X509KeyUsage.keyCertSign | X509KeyUsage.nonRepudiation);
        builder.addExtension(X509Extension.keyUsage, true, keyUsage);

        JcaContentSignerBuilder signerBuilder = new JcaContentSignerBuilder("SHA256WithRSA");
        ContentSigner signer = signerBuilder.build(issuerKey);

        X509CertificateHolder holder = builder.build(signer);
        JcaX509CertificateConverter converter = new JcaX509CertificateConverter();
        return converter.getCertificate(holder);
    }

    public static X509Certificate sign(PKCS10CertificationRequest csr, X509Certificate issuer,
            PrivateKey issuerPrivateKey)
            throws InvalidKeyException, NoSuchAlgorithmException, NoSuchProviderException, SignatureException,
            IOException, OperatorCreationException, CertificateException, java.security.cert.CertificateException {

        final BigInteger serial = getNextSerialNumber();
        final Date notBefore = new Date();
        final Date notAfter = new Date(System.currentTimeMillis() + 24L * 60L * 60L * 1000L);

        X500Name issuerName = JcaX500NameUtil.getSubject(issuer);
        X509v3CertificateBuilder myCertificateGenerator = new X509v3CertificateBuilder(issuerName, serial,
                notBefore, notAfter, csr.getSubject(), csr.getSubjectPublicKeyInfo());

        JcaContentSignerBuilder signerBuilder = new JcaContentSignerBuilder("SHA256WithRSA");
        ContentSigner signer = signerBuilder.build(issuerPrivateKey);
        X509CertificateHolder holder = myCertificateGenerator.build(signer);

        JcaX509CertificateConverter converter = new JcaX509CertificateConverter();
        return converter.getCertificate(holder);
    }

}