//$Header: /cvsroot-fuse/mec-as2/39/mendelson/util/security/PEMKeys2PKCS12.java,v 1.1 2012/04/18 14:10:45 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.Security; import java.security.cert.CertificateFactory; import java.security.cert.X509Certificate; import java.util.logging.Logger; import org.bouncycastle.jce.provider.BouncyCastleProvider; import org.bouncycastle.openssl.PEMReader; import org.bouncycastle.openssl.PasswordFinder; /* * 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; PEMReader reader = new PEMReader(pemReader, this); Object readObject = reader.readObject(); KeyPair pair = null; if (readObject instanceof KeyPair) { pair = (KeyPair)readObject; } else { this.logger.severe("--SORRY, no key pair found!.--"); return; } X509Certificate cert = this.readCertificate( certificateStream ); KeyStore store = this.keystore; if( store == null ) store = this.generateKeyStore(); //PKCS12 keys dont have a password store.setKeyEntry( alias, pair.getPrivate(), "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; } }