我有一个由两个文件(.crt和.key)组成的客户端证书,我希望将其导入到java KeyStore中,然后在SSLContext中使用Apache的HTTPClient发送HTTP请求。然而,我似乎找不到一种方法来以编程的方式做到这一点,我发现的大多数其他问题要么指向外部工具,要么不适合我的情况。
我的证书是用典型的“开始CERTIFICATE”编码的,后面是一个Base64编码的字符串,密钥是“BEGIN RSA PRIVATE KEY”,然后是另一个Base64编码的字符串。
这是我目前得到的:
private static SSLContext createSSLContext(File certFile, File keyFile) throws IOException {
try {
PEMParser pemParser = new PEMParser(new FileReader(keyFile));
JcaPEMKeyConverter converter = new JcaPEMKeyConverter().setProvider(new BouncyCastleProvider());
Object object = pemParser.readObject();
KeyPair kp = converter.getKeyPair((PEMKeyPair) object);
PrivateKey privateKey = kp.getPrivate();
CertificateFactory certFactory = CertificateFactory.getInstance("X.509");
FileInputStream stream = new FileInputStream(certFile);
X509Certificate cert = (X509Certificate) certFactory.generateCertificate(stream);
KeyStore store = KeyStore.getInstance("JKS");
store.load(null);
store.setCertificateEntry("certificate", cert);
store.setKeyEntry("private-key", privateKey, "changeit".toCharArray(), new Certificate[] { cert });
SSLContext sslContext = SSLContexts.custom()
.loadKeyMaterial(store, "changeit".toCharArray())
.build();
return sslContext;
} catch (IOException | NoSuchAlgorithmException | CertificateException | KeyStoreException | KeyManagementException | UnrecoverableKeyException e) {
throw new IOException(e);
}
}
字符串
Stacktrace:
java.io.IOException:java.security.spec.InvalidKeySpecException:java.security.InvalidKeyException:在me.failedshack.ssltest.SSLTest.createSSLContext(SSLTest.java:80)在me.failedshack.ssltest.SSLTest.main(SSLTest.java:31)处的密钥格式无效
原因:java.security.spec.InvalidKeySpecException:java.security.InvalidKeyException:在java.base/sun.security.rsa.RSAKeyFactory.engineGeneratePrivate(RSAKeyFactory.java:216)在java.base/java.security.KeyFactory.generatePrivate(KeyFactory.java:390)在me.failedshack.ssltest.SSLTest.createSSLContext(SSLTest.java:62)处的密钥格式无效...再加一个
原因:java.security.InvalidKeyException:java中密钥格式无效。base/sun.security.pkcs.PKCS8Key.decode(PKCS8Key.java:330)。base/sun.security.pkcs.PKCS8Key.decode(PKCS8Key.java:355)。base/sun.security.rsa.RSAPrivateCrtKeyImpl.(RSAPrivateCrtKeyImpl.java:91)。基地/太阳安全rsa RSA PrivateCrtKeyImpl. java中的newKey(RSAPrivateCrtKeyImpl.java:75)。基地/太阳安全rsa RSAKeyFactory。java中的generatePrivate(RSAKeyFactory.java:315)。基地/太阳安全rsa RSAKeyFactory。engineGeneratePrivate(RSAKeyFactory.java:212)... 3更多
不幸的是,当从文件中生成私钥时,我一直得到InvalidKeyException。
2条答案
按热度按时间efzxgjgh1#
RSA PRIVATE KEY
类型的PEM文件是base64而不是二进制,更重要的是它是PKCS 1格式而不是PKCS 8格式,因此不能作为PKCS8EncodedKeySpec
处理。您的选择包括:
PKCS8EncodedKeySpec
中--但是您说您不需要外部工具,而且将privatekeyPLUS cert(或链)转换为PKCS 12(DER)(它已经是Java密钥库)也很容易,可以避免这个问题PKCS8EncodedKeySpec
中--同上bcpkix
,它可以直接读取和解析 * 所有 * OpenSSL用于私钥的PEM变体,包括解密加密的;但是,如果您还没有使用它,那就是要安装和/或部署额外jar查看以下一个或多个欺骗:
Load certificate to KeyStore (JAVA)(Q使用BouncyCastle构建PKCS 8)
Java: Convert DKIM private key from RSA to DER for JavaMail(我的答案“手工”构造PKCS 8)
How to Load RSA Private Key From File(使用BouncyCastle读取)
Read RSA private key of format PKCS1 in JAVA(使用BouncyCastle读取)
Get a PrivateKey from a RSA .pem file(使用BC解密)
Decrypting an OpenSSL PEM Encoded RSA private key with Java?(手动解密)
maybe PKCS#1 and PKCS#8 format for RSA private key(background)
和Differences between "BEGIN RSA PRIVATE KEY" and "BEGIN PRIVATE KEY"(背景)
nuypyhwy2#
使用这个小型库https://github.com/KarlScheibelhofer/java-crypto-tools/tree/main,您可以轻松地加载这种PEM格式的私钥和证书。用更少的代码
字符串
有关示例和更多详细信息,请参见自述文件。