blob: 73a6d944d83335ba7655ab17db3f7e7cf6a0af52 [file] [log] [blame]
package org.apache.synapse.securevault.keystore;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.synapse.securevault.IKeyStoreLoader;
import org.apache.synapse.securevault.SecureVaultException;
import java.io.*;
import java.security.*;
import java.security.cert.Certificate;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
/**
* Constructs a KeyStore instance of type JKS from a pkcs8 private key and certificate.
*/
public class PKCS8KeyStoreLoader implements IKeyStoreLoader {
private static Log log = LogFactory.getLog(PKCS8KeyStoreLoader.class);
private String pkPath;
private String certPath;
private String keyPassword;
private String entryAlias;
private static final String HEADER = "-----BEGIN PRIVATE KEY-----\n";
private static final String FOOTER = "-----END PRIVATE KEY-----";
/**
* constructs an instance of KeyStoreLoader
*
* @param pkcs8PrivateKeyPath - path to a private key file. Key must be in PKCS8 format,
* PEM encoded and unencrypted.
* @param certFilePath - path to certificate file. File must be PEM encoded.
* @param keyPass - password to secure the private key within the keystore.
* This will be required later to retrieve the private key
* back from the keystore.
* @param entryAlias - alias for the given entry within the keystore.
*/
public PKCS8KeyStoreLoader(String pkcs8PrivateKeyPath, String certFilePath,
String keyPass,
String entryAlias) {
pkPath = pkcs8PrivateKeyPath;
certPath = certFilePath;
keyPassword = keyPass;
this.entryAlias = entryAlias;
}
/**
* Returns a JKS keyStore from the given private key, certificate path, key password and alias.
*/
public KeyStore getKeyStore() {
File file = new File(pkPath);
if (!file.exists()) {
if (log.isDebugEnabled()) {
log.debug("There is no private key in the given path : " + pkPath);
}
return null;
}
File certFile = new File(certPath);
if (!certFile.exists()) {
if (log.isDebugEnabled()) {
log.debug("There is no certificate in the given path : " + certPath);
}
return null;
}
try {
if (log.isDebugEnabled()) {
log.debug("Reading a private key(unencrypted) from given path : " + pkPath);
}
FileInputStream fileInputStream = new FileInputStream(file);
BufferedInputStream bufferedInputStream = new BufferedInputStream(fileInputStream);
ByteArrayOutputStream outStream = new ByteArrayOutputStream();
byte[] buffer = new byte[1024];
int length;
try {
while ((length = bufferedInputStream.read(buffer)) != -1) {
outStream.write(buffer, 0, length);
}
} catch (IOException e) {
handleException("IOError reading from file : " + pkPath, e);
} finally {
try {
bufferedInputStream.close();
fileInputStream.close();
outStream.close();
} catch (IOException ignored) {
}
}
if (log.isDebugEnabled()) {
log.debug("Creating a private key in PKCS8Encoded using given" +
" (unencrypted) RSA private key ");
}
PrivateKey key = createPrivateKey(outStream.toByteArray());
if (log.isDebugEnabled()) {
log.debug("Generating a X509 certificate form given certificate file");
}
FileInputStream certInputStream = new FileInputStream(certFile);
BufferedInputStream certBufferedInputStream = new BufferedInputStream(certInputStream);
CertificateFactory certFactory = CertificateFactory.getInstance("X509");
Certificate cert = certFactory.generateCertificate(certBufferedInputStream);
certBufferedInputStream.close();
certInputStream.close();
if (log.isDebugEnabled()) {
log.debug("Creating a KeyStore instance of type JKS from a" +
" PKCS8 private key and X509 certificate");
}
KeyStore newKeyStore = KeyStore.getInstance("JKS");
newKeyStore.load(null, null);
newKeyStore.setCertificateEntry("server Cert", cert);
Certificate[] certChain = new Certificate[1];
certChain[0] = cert;
newKeyStore.setKeyEntry(entryAlias, key, keyPassword.toCharArray(), certChain);
return newKeyStore;
} catch (FileNotFoundException e) {
handleException("IOError", e);
} catch (IOException e) {
handleException("IOError", e);
} catch (NoSuchAlgorithmException e) {
handleException("Error creating KeyStore", e);
} catch (KeyStoreException e) {
handleException("Error creating KeyStore", e);
} catch (CertificateException e) {
handleException("Error creating KeyStore", e);
}
return null;
}
/**
* Takes the (unencrypted) RSA private key in pkcs8 format, and creates a private key out of it
*
* @param keyBytes Byte Array of the private key
* @return PKCS8Encoded PrivateKey
*/
private PrivateKey createPrivateKey(byte[] keyBytes) {
int dataStart = HEADER.length();
int dataEnd = keyBytes.length - FOOTER.length() - 1;
int dataLength = dataEnd - dataStart;
byte[] keyContent = new byte[dataLength];
System.arraycopy(keyBytes, dataStart, keyContent, 0, dataLength);
PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(
new Base64().decode(keyContent));
try {
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
return keyFactory.generatePrivate(pkcs8EncodedKeySpec);
} catch (NoSuchAlgorithmException e) {
handleException("Error getting a KeyFactory instance", e);
} catch (InvalidKeySpecException e) {
handleException("Error generating a private key", e);
}
return null;
}
private void handleException(String msg, Exception e) {
log.error(msg, e);
throw new SecureVaultException(msg, e);
}
}