Java tutorial
//$Header: /cvsroot/mec-as2/b47/de/mendelson/util/security/PEMKeys2PKCS12.java,v 1.1 2015/01/06 11:07:56 heller Exp $ package de.mendelson.util.security; import java.io.ByteArrayInputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.FileReader; import java.io.InputStream; import java.io.InputStreamReader; import java.io.OutputStream; import java.io.Reader; import java.security.KeyPair; import java.security.KeyStore; import java.security.PrivateKey; import java.security.Security; import java.security.cert.CertificateFactory; import java.security.cert.X509Certificate; import java.util.logging.Logger; import org.bouncycastle.asn1.pkcs.PrivateKeyInfo; import org.bouncycastle.jce.provider.BouncyCastleProvider; import org.bouncycastle.openssl.PEMDecryptorProvider; import org.bouncycastle.openssl.PEMEncryptedKeyPair; import org.bouncycastle.openssl.PEMKeyPair; import org.bouncycastle.openssl.PEMParser; import org.bouncycastle.openssl.PasswordFinder; import org.bouncycastle.openssl.jcajce.JcaPEMKeyConverter; import org.bouncycastle.openssl.jcajce.JcePEMDecryptorProviderBuilder; /* * Copyright (C) mendelson-e-commerce GmbH Berlin Germany * * This software is subject to the license agreement set forth in the license. * Please read and agree to all terms before using this software. * Other product and brand names are trademarks of their respective owners. */ /** * This class allows to import keys that exist in PEM encoding (human readable * format), e.g. created by openssl, into a PKCS#12 keystore. Please remember * that this class does only work with the bountycastle provider as Suns JDK has * no idea of how to handle PKCS#12 keystores. To give you an idea of how the * PEM encoded key looks like, this is a part of a key -----BEGIN RSA PRIVATE * KEY----- Proc-Type: 4,ENCRYPTED DEK-Info: DES-EDE3-CBC,6FAA019A9B61FB51 * * ky5DLG4z7r2op5W/DhPTBg34RdG0eDSKUP4nRNxtHfGYQBMDQwKSYGIu0tztnwij * akh3DSRi+r6oZYc7oowjxFUsubZ7JMz6SYgRiDpgN3aVt4SGqqGdFuphuvVsHNhx -----END RSA * PRIVATE KEY----- * * @author S.Heller * @version $Revision: 1.1 $ */ public class PEMKeys2PKCS12 implements PasswordFinder { private Logger logger = Logger.getAnonymousLogger(); private char[] keypass = null; /** * Keystore to use, if this is not set a new one will be created */ private KeyStore keystore = null; /** * Creates a new instance of PEMUtil * * @param logger Logger to log the information to */ public PEMKeys2PKCS12(Logger logger) { this.logger = logger; //forget it to work without BC at this point, the SUN JCE provider //could not handle pcks12 Security.addProvider(new BouncyCastleProvider()); } /** * @param pemReader Reader that accesses the RSA key in PEM format * @param keypass Passphrase for the keys stored in the PEM file * @param certificateStream Stream that accesses the certificate for the * keys * @param alias Alias to use in the new keystore * */ public void importKey(Reader pemReader, char[] keypass, InputStream certificateStream, String alias) throws Exception { this.keypass = keypass; PEMParser pemParser = new PEMParser(pemReader); Object readObject = pemParser.readObject(); PEMDecryptorProvider decryptorProvider = new JcePEMDecryptorProviderBuilder().build(keypass); JcaPEMKeyConverter converter = new JcaPEMKeyConverter().setProvider("BC"); PrivateKey privateKey = null; if (readObject instanceof PEMEncryptedKeyPair) { //Encrypted key - use provided password KeyPair keyPair = converter .getKeyPair(((PEMEncryptedKeyPair) readObject).decryptKeyPair(decryptorProvider)); privateKey = keyPair.getPrivate(); } else if (readObject instanceof PrivateKeyInfo) { //PKCS#8 format, the object will be an instanceof PrivateKeyInfo privateKey = converter.getPrivateKey((PrivateKeyInfo) readObject); } else { //Unencrypted key - no password needed KeyPair keyPair = converter.getKeyPair((PEMKeyPair) readObject); privateKey = keyPair.getPrivate(); } X509Certificate cert = this.readCertificate(certificateStream); KeyStore store = this.keystore; if (store == null) { store = this.generateKeyStore(); } //PKCS12 keys dont have a password store.setKeyEntry(alias, privateKey, "dummy".toCharArray(), new X509Certificate[] { cert }); } /** * @param pemKeyFile File that contains the RSA key in PEM format * @param keypass Passphrase for the keys stored in the PEM file * @param certificateFile File that hold the certificate for the keys * @param alias Alias to use in the new keystore * */ public void importKey(File pemKeyFile, char[] keypass, File certificateFile, String alias) throws Exception { FileReader fileReader = new FileReader(pemKeyFile); InputStream certStream = new FileInputStream(certificateFile); this.importKey(fileReader, keypass, certStream, alias); fileReader.close(); certStream.close(); } /** * @param pemData array that contains the RSA key in PEM format * @param keypass Passphrase for the keys stored in the PEM file * @param certificateData array that holds the certificate for the keys * @param alias Alias to use in the new keystore * */ public void importKey(byte[] pemData, char[] keypass, byte[] certificateData, String alias) throws Exception { Reader reader = new InputStreamReader(new ByteArrayInputStream(pemData)); ByteArrayInputStream certStream = new ByteArrayInputStream(certificateData); this.importKey(reader, keypass, certStream, alias); reader.close(); certStream.close(); } /** * Loads ore creates a keystore to import the keys to */ private KeyStore generateKeyStore() throws Exception { //do not remove the BC paramter, SUN cannot handle the format proper KeyStore generatedKeystore = KeyStore.getInstance("PKCS12", "BC"); generatedKeystore.load(null, null); return (generatedKeystore); } /** * Sets an already existing keystore to this class. Without an existing * keystore a new one is created */ public void setTargetKeyStore(KeyStore keystore, char[] keystorePass) { this.keystore = keystore; } /** * Saves the passed keystore * * @param keystorePass Password for the keystore * @param filename Filename where to save the keystore to */ public void saveKeyStore(KeyStore keystore, char[] keystorePass, File file) throws Exception { OutputStream out = new FileOutputStream(file); keystore.store(out, keystorePass); out.close(); } /** * Reads the certificate from the certificate input stream and returns the * certificate itself */ private X509Certificate readCertificate(InputStream certificateStream) throws Exception { X509Certificate cert = null; CertificateFactory factory = CertificateFactory.getInstance("X.509"); cert = (X509Certificate) factory.generateCertificate(certificateStream); return (cert); } /** * makes this a PasswordFinder */ @Override public char[] getPassword() { return this.keypass; } }