org.ejbca.util.keystore.P12toPEM.java Source code

Java tutorial

Introduction

Here is the source code for org.ejbca.util.keystore.P12toPEM.java

Source

/*************************************************************************
 *                                                                       *
 *  EJBCA Community: The OpenSource Certificate Authority                *
 *                                                                       *
 *  This software 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 2.1 of the License, or any later version.                    *
 *                                                                       *
 *  See terms of license at gnu.org.                                     *
 *                                                                       *
 *************************************************************************/

package org.ejbca.util.keystore;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.PrivateKey;
import java.security.UnrecoverableKeyException;
import java.security.cert.Certificate;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.Enumeration;

import org.apache.log4j.Logger;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.cesecore.keys.util.KeyTools;
import org.cesecore.util.Base64;
import org.cesecore.util.CertTools;
import org.cesecore.util.CryptoProviderTools;

/**
 * P12toPEM is used to export PEM files from a single p12 file. The class exports the user
 * certificate, user private key in seperated files and the chain of sub ca and ca certifikate in
 * a third file. The PEM files will have the names <i>common name</i>.pem, <i>common
 * name</i>Key.pem and <i>common name</i>CA.pem derived from the DN in user certificate.
 *
 * @version $Id$
 */
public class P12toPEM {
    private static Logger log = Logger.getLogger(P12toPEM.class);
    String exportpath = "./p12/pem/";
    String p12File;
    String password;
    KeyStore ks = null;

    byte[] beginCertificate = "-----BEGIN CERTIFICATE-----".getBytes();
    byte[] endCertificate = "-----END CERTIFICATE-----".getBytes();
    byte[] beginPrivateKey = "-----BEGIN PRIVATE KEY-----".getBytes();
    byte[] endPrivateKey = "-----END PRIVATE KEY-----".getBytes();
    byte[] NL = "\n".getBytes();

    /**
     * DOCUMENT ME!
     *
     * @param args DOCUMENT ME!
     */
    public static void main(String[] args) {
        // Bouncy Castle security provider
        CryptoProviderTools.installBCProvider();

        P12toPEM p12 = null;

        try {
            if (args.length > 1) {
                p12 = new P12toPEM(args[0], args[1]);
            } else {
                System.out.println("Usage: P12toPEM <p12file> <p12password>");
                System.exit(0); // NOPMD this is a cli command
            }

            p12.createPEM();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * Basic construtor for the P12toPEM class, set variables for the class.
     *
     * @param p12File p12File The (path +) name of the input p12 file.
     * @param password password The password for the p12 file.
     * 
     */
    public P12toPEM(String p12File, String password) {
        this.p12File = p12File;
        this.password = password;
    }

    /**
     * Basic constructor using a in memory KeyStore instead for a file.
     *
     * @param keystore the KeyStore to use.
     * @param password password The password for the p12 file.
     */
    public P12toPEM(KeyStore keystore, String password) {
        this.password = password;
        this.ks = keystore;
    }

    /**
     * Sets the directory where PEM-files wil be stores
     *
     * @param path path where PEM-files will be stores
     */
    public void setExportPath(String path) {
        exportpath = path;
    }

    /**
     * Converts a P12 into a PEM
     *
     * @return the created PEM file, null if file wasn't found and no other exception was thrown. 
     *
     * @throws FileNotFoundException if the P12 file supplied to this class in its constructor was not found.
     * @throws CertificateException if the p12 couldn't be loaded
     * @throws NoSuchAlgorithmException if the algorithm used to build the P12 couldn't be found
     * @throws KeyStoreException if the keystore has not been initialised. 
     * @throws UnrecoverableKeyException if the password was incorrect 
     */
    public File createPEM() throws FileNotFoundException, NoSuchAlgorithmException, CertificateException,
            KeyStoreException, UnrecoverableKeyException {
        if (this.ks == null) {
            try {
                ks = KeyStore.getInstance("PKCS12", BouncyCastleProvider.PROVIDER_NAME);
            } catch (NoSuchProviderException e) {
                throw new IllegalStateException("BouncyCastle provider not found.", e);
            }
            InputStream in = new FileInputStream(p12File);
            try {
                try {
                    ks.load(in, password.toCharArray());
                } finally {
                    in.close();
                }
            } catch (IOException e) {
                throw new IllegalStateException("Unexpected IOException was thrown", e);
            }
        }
        // Fid the key private key entry in the keystore
        Enumeration<String> e = ks.aliases();
        Object o = null;
        PrivateKey serverPrivKey = null;

        while (e.hasMoreElements()) {
            o = e.nextElement();

            if (o instanceof String) {
                if ((ks.isKeyEntry((String) o))
                        && ((serverPrivKey = (PrivateKey) ks.getKey((String) o, password.toCharArray())) != null)) {
                    if (log.isDebugEnabled()) {
                        log.debug("Aliases " + o + " is KeyEntry.");
                    }
                    break;
                }
            }
        }
        if (log.isDebugEnabled()) {
            log.debug((("Private key encode: " + serverPrivKey) == null) ? null : serverPrivKey.getFormat());
        }
        byte[] privKeyEncoded = "".getBytes();
        if (serverPrivKey != null) {
            privKeyEncoded = serverPrivKey.getEncoded();
        }
        Certificate[] chain = KeyTools.getCertChain(ks, (String) o);
        if (log.isDebugEnabled()) {
            log.debug("Loaded certificate chain with length " + chain.length + " from keystore.");
        }
        X509Certificate userX509Certificate = (X509Certificate) chain[0];

        byte[] output = userX509Certificate.getEncoded();
        String sn = CertTools.getSubjectDN(userX509Certificate);
        String userFile = CertTools.getPartFromDN(sn, "CN");
        String filetype = ".pem";

        File path = new File(exportpath);
        path.mkdir();

        File tmpFile = new File(path, userFile + filetype);

        OutputStream out = new FileOutputStream(tmpFile);
        try {
            try {
                out.write(beginCertificate);
                out.write(NL);
                byte[] userCertB64 = Base64.encode(output);
                out.write(userCertB64);
                out.write(NL);
                out.write(endCertificate);
            } finally {
                out.close();
            }
        } catch (IOException e1) {
            throw new IllegalStateException("Unexpected IOException was thrown", e1);
        }

        tmpFile = new File(path, userFile + "-Key" + filetype);

        out = new FileOutputStream(tmpFile);
        try {
            try {
                out.write(beginPrivateKey);
                out.write(NL);
                byte[] privKey = Base64.encode(privKeyEncoded);
                out.write(privKey);
                out.write(NL);
                out.write(endPrivateKey);
            } finally {
                out.close();
            }
        } catch (IOException e1) {
            throw new IllegalStateException("Unexpected IOException was thrown", e1);
        }

        tmpFile = new File(path, userFile + "-CA" + filetype);

        if (CertTools.isSelfSigned(userX509Certificate)) {
            log.info("User certificate is selfsigned, this is a RootCA, no CA certificates written.");
        } else {
            out = new FileOutputStream(tmpFile);
            try {
                for (int num = 1; num < chain.length; num++) {
                    X509Certificate tmpX509Cert = (X509Certificate) chain[num];
                    byte[] tmpOutput = tmpX509Cert.getEncoded();
                    try {
                        out.write(beginCertificate);
                        out.write(NL);

                        byte[] tmpCACertB64 = Base64.encode(tmpOutput);

                        out.write(tmpCACertB64);
                        out.write(NL);
                        out.write(endCertificate);
                        out.write(NL);
                    } catch (IOException e1) {
                        throw new IllegalStateException("Unexpected IOException was thrown", e1);
                    }
                }

            } finally {
                try {
                    out.close();
                } catch (IOException e1) {
                    throw new IllegalStateException("Unexpected IOException was thrown", e1);
                }
            }
        }
        return tmpFile;
    }
}