Java 使用或不使用OpenSSL将SSL.pem转换为.p12
我获得需要转换为Java 使用或不使用OpenSSL将SSL.pem转换为.p12,java,openssl,pem,pkcs#12,Java,Openssl,Pem,Pkcs#12,我获得需要转换为.p12文件的外部.pem文件-我在过程中添加用户名和密码。(我需要这样做才能利用第三方API。) 使用openssl,命令是 openssl pkcs12 -export -in xxxx.pem -inkey xxxx.pem -out xxx.p12 -passout pas:newpassword -name "newname" 我可以在终端会话中运行它,它工作得非常好 然而,我需要经常这样做,并且已经编写了一个Java类来处理这个和更多的问题(我的应用程序主要是带有T
.p12
文件的外部.pem
文件-我在过程中添加用户名和密码。(我需要这样做才能利用第三方API。)
使用openssl
,命令是
openssl pkcs12 -export -in xxxx.pem -inkey xxxx.pem -out xxx.p12 -passout pas:newpassword -name "newname"
我可以在终端会话中运行它,它工作得非常好
然而,我需要经常这样做,并且已经编写了一个Java类来处理这个和更多的问题(我的应用程序主要是带有Tomcat和Apache的.jsp
)。当我尝试使用Runtime.exec
从Java运行相同的命令时,会出现可怕的“无法写入“随机状态”错误()
我假设区别在于,当我从Java运行时,用户不是“root”
那么,有没有更好的方法使用Java库将pem转换为.p12,而不是执行命令行程序(即openssl)
否则,我想我需要在我的服务器上进行一些配置。我在服务器上的任何位置都找不到任何.md
文件。唯一的openssl.cnf
文件位于一个奇怪的目录中(/etc/pki/tls
)。我需要在其他地方创建一个新的openssl.cnf
文件吗 在Java中,请使用,但要注意,学习曲线陡峭,文档稀少。我强烈建议您查看作为源代码发行版的一部分提供的示例
从PemReader开始。这应该可以完成您想要做的事情(如上所述使用BouncyCastle PemReader)——获取PEM编码的私钥+证书,并输出PKCS#12文件。使用与用于保护私钥的PKCS12相同的密码
public static byte[] pemToPKCS12(final String keyFile, final String cerFile, final String password) throws Exception {
// Get the private key
FileReader reader = new FileReader(keyFile);
PEMReader pem = new PEMReader(reader, new PasswordFinder() {
@Override public char[] getPassword() {
return password.toCharArray();
}
});
PrivateKey key = ((KeyPair)pem.readObject()).getPrivate();
pem.close();
reader.close();
// Get the certificate
reader = new FileReader(cerFile);
pem = new PEMReader(reader);
X509Certificate cert = (X509Certificate)pem.readObject();
pem.close();
reader.close();
// Put them into a PKCS12 keystore and write it to a byte[]
ByteArrayOutputStream bos = new ByteArrayOutputStream();
KeyStore ks = KeyStore.getInstance("PKCS12");
ks.load(null);
ks.setKeyEntry("alias", (Key)key, password.toCharArray(), new java.security.cert.Certificate[]{cert});
ks.store(bos, password.toCharArray());
bos.close();
return bos.toByteArray();
}
根据@MugglesMerriweather的回答,v1.51的更新版本如下:
public static byte[] convertPEMToPKCS12(final String keyFile, final String cerFile,
final String password)
throws IOException, CertificateException, KeyStoreException, NoSuchAlgorithmException
{
// Get the private key
FileReader reader = new FileReader(keyFile);
PEMParser pem = new PEMParser(reader);
PEMKeyPair pemKeyPair = ((PEMKeyPair)pem.readObject());
JcaPEMKeyConverter jcaPEMKeyConverter = new JcaPEMKeyConverter().setProvider("SC");
KeyPair keyPair = jcaPEMKeyConverter.getKeyPair(pemKeyPair);
PrivateKey key = keyPair.getPrivate();
pem.close();
reader.close();
// Get the certificate
reader = new FileReader(cerFile);
pem = new PEMParser(reader);
X509CertificateHolder certHolder = (X509CertificateHolder) pem.readObject();
java.security.cert.Certificate X509Certificate =
new JcaX509CertificateConverter().setProvider("SC")
.getCertificate(certHolder);
pem.close();
reader.close();
// Put them into a PKCS12 keystore and write it to a byte[]
ByteArrayOutputStream bos = new ByteArrayOutputStream();
KeyStore ks = KeyStore.getInstance("PKCS12");
ks.load(null);
ks.setKeyEntry("alias", (Key) key, password.toCharArray(),
new java.security.cert.Certificate[]{X509Certificate});
ks.store(bos, password.toCharArray());
bos.close();
return bos.toByteArray();
}
基于这些答案,我创建了一个Java7类,它处理创建有效SSLContext的所有操作。它还创建了必要的链。TODO:如有必要,请联系Trustmanager
public final class SSL_Context {
private static SSL_Context instance = new SSL_Context();
public static SSL_Context getInstance() {
return instance;
}
private SSLContext sslContext = null;
private SSL_Context() {
try {
sslContext = generateSSLContext();
}
catch (Exception e)
{
ErrorLogger.logException(e);
}
}
final private void dumpKeyStore(KeyStore keyStore)
{
try {
// List the aliases
Enumeration aliases = keyStore.aliases();
for (; aliases.hasMoreElements(); ) {
String alias = (String) aliases.nextElement();
// Does alias refer to a private key?
boolean a = keyStore.isKeyEntry(alias);
// Does alias refer to a trusted certificate?
boolean b = keyStore.isCertificateEntry(alias);
ErrorLogger.log(alias + " " + a + " " + b, 2);
}
} catch (Exception e) {
ErrorLogger.logException(e);
}
}
final private KeyStore convertPEMToPKCS12(final String keyAndPubFile, final String chainFile, final String password) {
try {
Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());
PrivateKey key;
Certificate pubCert;
try (FileReader reader = new FileReader(keyAndPubFile);
PEMParser pem = new PEMParser(reader)) {
PEMKeyPair pemKeyPair = ((PEMKeyPair) pem.readObject());
JcaPEMKeyConverter jcaPEMKeyConverter = new JcaPEMKeyConverter().setProvider("BC");
KeyPair keyPair = jcaPEMKeyConverter.getKeyPair(pemKeyPair);
key = keyPair.getPrivate();
X509CertificateHolder certHolder = (X509CertificateHolder) pem.readObject();
pubCert = new JcaX509CertificateConverter().setProvider("BC").getCertificate(certHolder);
}
// Get the certificates
try (FileReader reader = new FileReader(chainFile);
PEMParser pem = new PEMParser(reader)) {
//load all certs
LinkedList<Certificate> certsll = new LinkedList<>();
X509CertificateHolder certHolder = (X509CertificateHolder) pem.readObject();
do {
Certificate X509Certificate = new JcaX509CertificateConverter().setProvider("BC").getCertificate(certHolder);
certsll.add(X509Certificate);
}
while ((certHolder = (X509CertificateHolder) pem.readObject()) != null);
Certificate[] chain = new Certificate[certsll.size()+1];
chain[0] = pubCert;
KeyStore ks = KeyStore.getInstance("PKCS12");
ks.load(null);
int i = 1;
for (Certificate cert : certsll) {
ks.setCertificateEntry("chain" + i, cert);
chain[i] = ks.getCertificate("chain" + i);
i++;
}
ks.setKeyEntry("cert", key, password.toCharArray(), chain);
return ks;
}
}
catch (Exception e)
{
ErrorLogger.logException(e);
}
return null;
}
final private SSLContext generateSSLContext()
{
String keyStorePassword = "";
try {
KeyStore keyStore = convertPEMToPKCS12("ssl/keyandcert.pem", "ssl/ca_bundle.crt", keyStorePassword);
SSLContext sslContext = SSLContext.getInstance("TLSv1");
KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
keyManagerFactory.init(keyStore, keyStorePassword.toCharArray());
sslContext.init(keyManagerFactory.getKeyManagers(), null, new SecureRandom());
return sslContext;
} catch (Exception e) {
ErrorLogger.logException(e);
}
return null;
}
final public SSLContext getContext() {
return sslContext;
}
final public static void main(String args[])
{
getInstance().getContext();
}
}
公共最终类SSL\u上下文{
私有静态SSL_上下文实例=新SSL_上下文();
公共静态SSL_上下文getInstance(){
返回实例;
}
私有SSLContext SSLContext=null;
私有SSL_上下文(){
试一试{
sslContext=生成sslContext();
}
捕获(例外e)
{
ErrorLogger.logException(e);
}
}
最终私有无效转储密钥库(密钥库密钥库)
{
试一试{
//列出别名
枚举别名=keyStore.alias();
对于(;alias.hasMoreElements();){
字符串别名=(字符串)别名。nextElement();
//别名是否引用私钥?
布尔值a=keyStore.isKeyEntry(别名);
//别名是否引用受信任的证书?
布尔b=密钥库.isCertificateEntry(别名);
ErrorLogger.log(别名+“”+a+“”+b,2);
}
}捕获(例外e){
ErrorLogger.logException(e);
}
}
最终私有密钥库转换PEMTOPKCS12(最终字符串键和PubFile、最终字符串链文件、最终字符串密码){
试一试{
addProvider(新org.bouncycastle.jce.provider.BouncyCastleProvider());
私钥;
公共证书;
try(FileReader=newfilereader(keyAndPubFile);
PEMParser pem=新PEMParser(读取器)){
PEMKeyPair PEMKeyPair=((PEMKeyPair)pem.readObject());
JcaPEMKeyConverter JcaPEMKeyConverter=新的JcaPEMKeyConverter().setProvider(“BC”);
KeyPair KeyPair=jcaPEMKeyConverter.getKeyPair(pemKeyPair);
key=keyPair.getPrivate();
X509CertificateHolder证书持有者=(X509CertificateHolder)pem.readObject();
pubCert=new JcaX509CertificateConverter().setProvider(“BC”).getCertificate(证书持有者);
}
//拿到证书
try(FileReader=newfilereader(chainFile);
PEMParser pem=新PEMParser(读取器)){
//加载所有证书
LinkedList certsll=新建LinkedList();
X509CertificateHolder证书持有者=(X509CertificateHolder)pem.readObject();
做{
Certificate X509Certificate=new JcaX509CertificateConverter().setProvider(“BC”).getCertificate(certHolder);
证书添加(X509证书);
}
而((certHolder=(X509CertificateHolder)pem.readObject())!=null);
证书[]链=新证书[certsll.size()+1];
链[0]=pubCert;
KeyStore ks=KeyStore.getInstance(“PKCS12”);
ks.load(空);
int i=1;
适用于(证书:certsll){
ks.setCertificateEntry(“链”+i,证书);
链[i]=ks.getCertificate(“链”+i);
i++;
}
ks.setKeyEntry(“cert”,key,password.tocharray(),chain);
返回ks;
}
}
捕获(例外e)
{
ErrorLogger.logException(e);
}
返回null;
}
最终私有SSLContext generateSSLContext()
{
字符串keystrepassword=“”;
试一试{
KeyStore KeyStore=convertPEMToPKCS12(“ssl/keyandcert.pem”、“ssl/ca_bundle.crt”、keyStorePassword);
SSLContext SSLContext=SSLContext.getInstance(“TLSv1”);
KeyManagerFactory KeyManagerFactory=KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
init(keyStore,keyStorePassword.toCharArray());
sslContext.init(keyManagerFactory.getKeyManagers(),null,new SecureRandom());
返回sslContext;
}捕获(例外e){
ErrorLogger.logException(e);
}
返回null;
}
最终公共SSLContext getContext(){
返回sslContext;
}
最终公共静态void main(字符串参数[])
{
getInstance().getContext();
}
}
此解决方案是对@sascha arthur's的改编,以适应:
- 把手
- 优雅地处理使用公钥的场景
String alias="myalias"; char[] password = "mypassword".toCharArray(); // Private Key PEMParser pem = new PEMParser(new FileReader(keyFile)); Object parsedObject = pem.readObject(); PrivateKeyInfo privateKeyInfo = parsedObject instanceof PEMKeyPair ? ((PEMKeyPair)parsedObject).getPrivateKeyInfo() : (PrivateKeyInfo)parsedObject; PKCS8EncodedKeySpec privateKeySpec = new PKCS8EncodedKeySpec(privateKeyInfo.getEncoded()); KeyFactory factory = KeyFactory.getInstance("RSA"); PrivateKey key = factory.generatePrivate(privateKeySpec); List<X509Certificate> certs = new ArrayList<>(); X509CertificateHolder certHolder = (X509CertificateHolder)pem.readObject(); if(certHolder != null) { certs.add(new JcaX509CertificateConverter().setProvider("BC").getCertificate(certHolder)); } // Certificate pem = new PEMParser(new FileReader(certFile)); while((certHolder = (X509CertificateHolder)pem.readObject()) != null) { certs.add(new JcaX509CertificateConverter().setProvider("BC").getCertificate(certHolder)); } // Keystore KeyStore ks = KeyStore.getInstance("PKCS12"); ks.load(null); for (int i = 0; i < certs.size(); i++) { ks.setCertificateEntry(alias + "_" + i, certs.get(i)); } KeyStore keyStore = KeyStore.getInstance("PKCS12"); keyStore.load(null); keyStore.setKeyEntry(alias, key, password, certs.toArray(new X509Certificate[certs.size()]));