/************************************************************************* * * * 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.PrivateKey; import java.security.UnrecoverableKeyException; import java.security.cert.Certificate; import java.security.cert.CertificateEncodingException; import java.security.cert.CertificateException; import java.security.cert.X509Certificate; import java.util.Enumeration; import org.cesecore.keys.util.KeyTools; import org.cesecore.util.Base64; import org.cesecore.util.CertTools; import org.cesecore.util.CryptoProviderTools; /** * JKStoPEM is used to export PEM files from a single jks 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 common name.pem, common * nameKey.pem and common nameCA.pem derived from the DN in user certificate. * * @version $Id: JKStoPEM.java 22117 2015-10-29 10:53:42Z mikekushner $ */ public class JKStoPEM { String exportpath = "./p12/pem/"; String jksFile; String password; String keypass; KeyStore ks = null; boolean overwrite = false; 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(); JKStoPEM jks = null; try { if (args.length > 4) { boolean overwrite = false; if (args[4].equalsIgnoreCase("true")) { overwrite = true; } jks = new JKStoPEM(args[0], args[1], args[2], args[3], overwrite); } else if (args.length > 3) { jks = new JKStoPEM(args[0], args[1], args[2], args[3]); } else { System.out.println( "Usage: JKStoPEM [overwrite (true/false)(default false)]"); System.exit(0); // NOPMD this is a cli command } jks.createPEM(); } catch (Exception e) { e.printStackTrace(); } } /** * Basic construtor for the JKStoPEM class, set variables for the class. * * @param jksFile jksFile The (path +) name of the input jks file. * @param password password The password for the jks file. * */ public JKStoPEM(String jksFile, String password, String keypass, String outpath) { this.jksFile = jksFile; this.password = password; this.keypass = keypass; exportpath = outpath; } /** * Basic constructor using an in memory KeyStore instead for a file. * * @param keystore the KeyStore to use. * @param password password The password for the jks file. * @param overwrite overwrite If existing files should be overwritten. */ public JKStoPEM(KeyStore keystore, String password, String keypass, String outpath, boolean overwrite) { this.password = password; this.ks = keystore; this.keypass = keypass; exportpath = outpath; this.overwrite = overwrite; } /** * 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; } /** * Constructor for the JKStoPEM class. * * @param jksFile jksFile The (path +) name of the input jks file. * @param password password The password for the jks file. * @param overwrite overwrite If existing files should be overwritten. */ public JKStoPEM(String jksFile, String password, String keypass, String outpath, boolean overwrite) { this.jksFile = jksFile; this.password = password; this.overwrite = overwrite; this.keypass = keypass; exportpath = outpath; } /** * DOCUMENT ME! * * @throws KeyStoreException DOCUMENT ME! * @throws FileNotFoundException DOCUMENT ME! * @throws IOException DOCUMENT ME! * @throws NoSuchAlgorithmException DOCUMENT ME! * @throws CertificateEncodingException DOCUMENT ME! * @throws CertificateException DOCUMENT ME! * @throws UnrecoverableKeyException DOCUMENT ME! */ public void createPEM() throws KeyStoreException, FileNotFoundException, IOException, NoSuchAlgorithmException, CertificateEncodingException, CertificateException, UnrecoverableKeyException { if(this.ks == null){ ks = KeyStore.getInstance("JKS"); InputStream in = new FileInputStream(jksFile); ks.load(in, password.toCharArray()); in.close(); } // Find the key private key entry in the keystore Enumeration 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, keypass.toCharArray())) != null)) { break; } } } byte[] privKeyEncoded = "".getBytes(); if (serverPrivKey != null) { privKeyEncoded = serverPrivKey.getEncoded(); } //Certificate chain[] = ks.getCertificateChain((String) o); Certificate[] chain = KeyTools.getCertChain(ks, (String) o); 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); if (!overwrite) { if (tmpFile.exists()) { System.out.println("File '" + tmpFile + "' already exists, don't overwrite."); return; } } OutputStream out = new FileOutputStream(tmpFile); out.write(beginCertificate); out.write(NL); byte[] userCertB64 = Base64.encode(output); out.write(userCertB64); out.write(NL); out.write(endCertificate); out.close(); tmpFile = new File(path, userFile + "-Key" + filetype); if (!overwrite) { if (tmpFile.exists()) { System.out.println("File '" + tmpFile + "' already exists, don't overwrite."); return; } } out = new FileOutputStream(tmpFile); out.write(beginPrivateKey); out.write(NL); byte[] privKey = Base64.encode(privKeyEncoded); out.write(privKey); out.write(NL); out.write(endPrivateKey); out.close(); tmpFile = new File(path, userFile + "-CA" + filetype); if (!overwrite) { if (tmpFile.exists()) { System.out.println("File '" + tmpFile + "' already exists, don't overwrite."); return; } } if (CertTools.isSelfSigned(userX509Certificate)) { System.out.println( "User certificate is selfsigned, this is a RootCA, no CA certificates written."); } else { out = new FileOutputStream(tmpFile); for (int num = 1; num < chain.length; num++) { X509Certificate tmpX509Cert = (X509Certificate) chain[num]; byte[] tmpOutput = tmpX509Cert.getEncoded(); out.write(beginCertificate); out.write(NL); byte[] tmpCACertB64 = Base64.encode(tmpOutput); out.write(tmpCACertB64); out.write(NL); out.write(endCertificate); out.write(NL); } out.close(); } } // createPEM } // JKStoPEM