me.it_result.ca.bouncycastle.BouncyCABase.java Source code

Java tutorial

Introduction

Here is the source code for me.it_result.ca.bouncycastle.BouncyCABase.java

Source

/**
 * Copyright 2010 Roman Kisilenko
 *
 * This program is free software: you can redistribute it and/or modify it 
 * under the terms of the GNU Lesser General Public License as published by the
 * Free Software Foundation, either version 3 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 Lesser General Public License 
 * for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
package me.it_result.ca.bouncycastle;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.math.BigInteger;
import java.security.InvalidKeyException;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.PublicKey;
import java.security.Security;
import java.security.SignatureException;
import java.security.cert.CertificateEncodingException;
import java.security.cert.CertificateException;
import java.security.cert.CertificateParsingException;
import java.util.Calendar;
import java.util.Date;

import me.it_result.ca.CAException;
import me.it_result.ca.db.Database;

import org.bouncycastle.asn1.x509.BasicConstraints;
import org.bouncycastle.asn1.x509.X509Extensions;
import org.bouncycastle.jce.X509KeyUsage;
import org.bouncycastle.jce.X509Principal;
import org.bouncycastle.x509.X509V3CertificateGenerator;
import org.bouncycastle.x509.extension.AuthorityKeyIdentifierStructure;
import org.bouncycastle.x509.extension.SubjectKeyIdentifierStructure;

/**
 * @author roman
 *
 */
public abstract class BouncyCABase {

    static final String CA_ALIAS = BouncyCABase.class.getName() + ".ca";;
    static final String KEYSTORE_PROPERTY = BouncyCABase.class.getName() + ".keystore";

    protected Database database;
    protected String keyAlgorithm;
    protected int keyBits;
    protected String keystorePassword;
    protected String signatureAlgorithm;
    protected ProfileRegistry profiles;

    protected X509V3CertificateGenerator certGen = new X509V3CertificateGenerator();

    static {
        Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());
    }

    public BouncyCABase(Database database, String keyAlgorithm, int keyBits, String keystorePassword,
            String signatureAlgorithm, ProfileRegistry profiles) {
        super();
        this.database = database;
        this.keyAlgorithm = keyAlgorithm;
        this.keyBits = keyBits;
        this.keystorePassword = keystorePassword;
        this.signatureAlgorithm = signatureAlgorithm;
        this.profiles = profiles;
    }

    protected void saveKeystore(KeyStore keyStore) throws Exception {
        ByteArrayOutputStream os = new ByteArrayOutputStream();
        keyStore.store(os, keystorePassword.toCharArray());
        byte[] data = os.toByteArray();
        database.writeBytes(CA_ALIAS, KEYSTORE_PROPERTY, data);
    }

    protected KeyPair generateKeyPair() throws NoSuchAlgorithmException {
        KeyPairGenerator keyGen = KeyPairGenerator.getInstance(keyAlgorithm);
        keyGen.initialize(keyBits);
        return keyGen.generateKeyPair();
    }

    protected X509V3CertificateGenerator assembleCertificate(PublicKey publicKey, PublicKey caPublicKey,
            String subjectDN, String issuerDN, BigInteger serialNumber, boolean ca, int validityDays)
            throws CertificateParsingException, InvalidKeyException, CertificateEncodingException,
            IllegalStateException, NoSuchAlgorithmException, SignatureException, FileNotFoundException {
        certGen.setIssuerDN(new X509Principal(issuerDN));
        certGen.setNotBefore(new Date());
        Calendar cal = Calendar.getInstance();
        cal.setTimeInMillis(System.currentTimeMillis());
        cal.add(Calendar.DAY_OF_MONTH, validityDays);
        certGen.setNotAfter(cal.getTime());
        certGen.setPublicKey(publicKey);
        certGen.setSerialNumber(serialNumber);
        certGen.setSignatureAlgorithm(signatureAlgorithm);
        certGen.setSubjectDN(new X509Principal(subjectDN));
        X509KeyUsage keyUsage;
        if (ca)
            keyUsage = new X509KeyUsage(X509KeyUsage.cRLSign | X509KeyUsage.keyCertSign);
        else
            keyUsage = new X509KeyUsage(X509KeyUsage.keyEncipherment | X509KeyUsage.digitalSignature);
        certGen.addExtension(X509Extensions.KeyUsage, true, keyUsage.getDEREncoded());
        BasicConstraints basicConstraints = new BasicConstraints(ca);
        certGen.addExtension(X509Extensions.BasicConstraints, true, basicConstraints.getDEREncoded());
        SubjectKeyIdentifierStructure subjectKeyId = new SubjectKeyIdentifierStructure(publicKey);
        certGen.addExtension(X509Extensions.SubjectKeyIdentifier, false, subjectKeyId.getDEREncoded());
        AuthorityKeyIdentifierStructure authorityKeyId = new AuthorityKeyIdentifierStructure(caPublicKey);
        certGen.addExtension(X509Extensions.AuthorityKeyIdentifier, false, authorityKeyId.getDEREncoded());
        return certGen;
    }

    protected KeyStore loadKeystore()
            throws NoSuchAlgorithmException, CertificateException, IOException, KeyStoreException {
        KeyStore keyStore = KeyStore.getInstance("JKS");
        InputStream is = null;
        try {
            byte[] data = database.readBytes(CA_ALIAS, KEYSTORE_PROPERTY);
            if (data != null)
                is = new ByteArrayInputStream(data);
            keyStore.load(is, keystorePassword.toCharArray());
        } catch (Exception e) {
            keyStore.load(null, keystorePassword.toCharArray());
        } finally {
            try {
                is.close();
            } catch (Exception e) {
            }
        }
        return keyStore;
    }

    public synchronized void destroy() throws CAException {
        try {
            database.destroy();
        } catch (Exception e) {
            throw new CAException(e);
        }
    }

}