org.pepstock.jem.node.security.keystore.SelfSignedCertificate.java Source code

Java tutorial

Introduction

Here is the source code for org.pepstock.jem.node.security.keystore.SelfSignedCertificate.java

Source

/**
JEM, the BEE - Job Entry Manager, the Batch Execution Environment
Copyright (C) 2012-2015   Andrea "Stock" Stocchero
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 3 of the License, or
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, see <http://www.gnu.org/licenses/>.
*/
package org.pepstock.jem.node.security.keystore;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.math.BigInteger;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.SecureRandom;
import java.security.Security;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.Date;
import java.util.UUID;

import javax.security.auth.x500.X500Principal;

import org.bouncycastle.cert.X509v3CertificateBuilder;
import org.bouncycastle.cert.jcajce.JcaX509CertificateConverter;
import org.bouncycastle.cert.jcajce.JcaX509v3CertificateBuilder;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.operator.ContentSigner;
import org.bouncycastle.operator.OperatorCreationException;
import org.bouncycastle.operator.jcajce.JcaContentSignerBuilder;
import org.pepstock.jem.util.TimeUtils;

/**
 * Generate X.509 certificates programmatically leveraging on Bouncycastle lightweight API.
 * <br>
 * list of DN attributes:<br>
 * CN: CommonName<br>
 * OU: OrganizationalUnit<br>
 * O: Organization<br>
 * L: Locality<br>
 * S: StateOrProvinceName<br>
 * C: CountryName<br>
 * 
 * @author Andrea "Stock" Stocchero
 * @version 2.2
 *
 */

final class SelfSignedCertificate {

    // alias for keystore
    private static final String CERTIFICATE_ALIAS = "JEM-HTTP";
    // uses RSA
    private static final String CERTIFICATE_ALGORITHM = "RSA";
    // DN for certificate
    private static final String CERTIFICATE_DN = "CN=jem, O=pepstock, L=verona, S=vr, C=it";
    // uses 1024 bit
    private static final int CERTIFICATE_BITS = 1024;

    // random password 
    static final String CERTIFICATE_PASSWORD = UUID.randomUUID().toString();

    static {
        // adds the Bouncy castle provider to java security
        Security.addProvider(new BouncyCastleProvider());
    }

    /**
     * To avoid any instantiation
     */
    private SelfSignedCertificate() {
    }

    /**
     * Returns X.509 certificates programmatically leveraging on Bouncycastle lightweight API
     * @return certificate in byte array format
     * @throws KeyStoreException if any error occurs
     * @throws NoSuchAlgorithmException if any error occurs
     * @throws CertificateException if any error occurs
     * @throws IOException if any error occurs
     * @throws OperatorCreationException if any error occurs
     */
    static ByteArrayInputStream getCertificate() throws NoSuchAlgorithmException, OperatorCreationException,
            CertificateException, KeyStoreException, IOException {
        // creates a key pair generator
        KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(CERTIFICATE_ALGORITHM);
        keyPairGenerator.initialize(CERTIFICATE_BITS, new SecureRandom());
        // creates a couple of keys
        KeyPair keyPair = keyPairGenerator.generateKeyPair();

        // GENERATE THE X509 CERTIFICATE
        X500Principal principal = new X500Principal(CERTIFICATE_DN);
        // sets times of certificate
        // starting from now
        long now = System.currentTimeMillis();
        Date notBefore = new Date(now - TimeUtils.DAY);
        Date notAfter = new Date(now + 10 * TimeUtils.DAY * 365);
        BigInteger serial = BigInteger.valueOf(now);

        // creaets a builder
        X509v3CertificateBuilder certGen = new JcaX509v3CertificateBuilder(principal, serial, notBefore, notAfter,
                principal, keyPair.getPublic());
        // creates the content signed by private key
        ContentSigner sigGen = new JcaContentSignerBuilder("SHA256WithRSAEncryption").setProvider("BC")
                .build(keyPair.getPrivate());
        // build certificate and convert in JCA
        X509Certificate cert = new JcaX509CertificateConverter().setProvider("BC")
                .getCertificate(certGen.build(sigGen));
        return createKeyStore(cert, keyPair.getPrivate());
    }

    /**
     * Creates a key store to save the certificate and then to use
     * @param cert certificate to add to key store 
     * @param key private key
     * @return a array of bytes of key store
     * @throws KeyStoreException if any error occurs
     * @throws NoSuchAlgorithmException if any error occurs
     * @throws CertificateException if any error occurs
     * @throws IOException if any error occurs
     */
    private static ByteArrayInputStream createKeyStore(X509Certificate cert, PrivateKey key)
            throws KeyStoreException, NoSuchAlgorithmException, CertificateException, IOException {
        KeyStore keyStore = KeyStore.getInstance("JKS");
        // creates an empty keystore
        keyStore.load(null, null);
        // adds certificate
        keyStore.setKeyEntry(CERTIFICATE_ALIAS, key, CERTIFICATE_PASSWORD.toCharArray(),
                new java.security.cert.Certificate[] { cert });
        // stores the key store in bytes
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        keyStore.store(baos, CERTIFICATE_PASSWORD.toCharArray());
        return new ByteArrayInputStream(baos.toByteArray());
    }
}