Importing PEM certificate into Java KeyStore programmatically
我有一个客户端证书,由两个文件(.CRT和.Key)组成,我希望将其导入到Java密钥存储库中,然后在SSLVIEW中使用Apache的HTTPclient发送HTTP请求。然而,我似乎找不到一种程序化的方法来实现这一点,我发现的大多数其他问题要么指向外部工具,要么不适合我的情况。
我的证书用典型的"begin certificate"编码,后跟base64编码的字符串,密钥用"begin rsa private key"编码,然后是另一个base64编码的字符串。
这就是我到目前为止所得到的:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | 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: invalid key format
at me.failedshack.ssltest.SSLTest.createSSLContext(SSLTest.java:80)
at me.failedshack.ssltest.SSLTest.main(SSLTest.java:31)Caused by: java.security.spec.InvalidKeySpecException: java.security.InvalidKeyException: invalid key format
at java.base/sun.security.rsa.RSAKeyFactory.engineGeneratePrivate(RSAKeyFactory.java:216)
at java.base/java.security.KeyFactory.generatePrivate(KeyFactory.java:390)
at me.failedshack.ssltest.SSLTest.createSSLContext(SSLTest.java:62)
... 1 moreCaused by: java.security.InvalidKeyException: invalid key format
at java.base/sun.security.pkcs.PKCS8Key.decode(PKCS8Key.java:330)
at java.base/sun.security.pkcs.PKCS8Key.decode(PKCS8Key.java:355)
at java.base/sun.security.rsa.RSAPrivateCrtKeyImpl.(RSAPrivateCrtKeyImpl.java:91)
at java.base/sun.security.rsa.RSAPrivateCrtKeyImpl.newKey(RSAPrivateCrtKeyImpl.java:75)
at java.base/sun.security.rsa.RSAKeyFactory.generatePrivate(RSAKeyFactory.java:315)
at java.base/sun.security.rsa.RSAKeyFactory.engineGeneratePrivate(RSAKeyFactory.java:212)
... 3 more
遗憾的是,在从文件生成私钥时,我一直得到一个InvalidKeyException。
您的选择是:
将PKCS1 PEM格式转换为PKCS8(未加密)PEM格式;读取并删除头和尾部行,并将Base64解码为二进制,并将其放在EDCOX1×1中,但您不需要外部工具,而且将私有密钥+证书(或链)转换为已经是Java密钥存储和AV的PKCS12(DER)也同样容易。回避这个问题
将pkcs1 pem格式转换为pkcs8(未加密)der格式,您只需将其作为二进制文件读取并放入
PKCS8EncodedKeySpec --同上如果pkcs1 pem是未加密的,则按照上述方法将其读取并解码为pkcs1 der,然后手动构造pkcs8(未加密)编码,并使用它
如果pkcs1 pem是加密的,您可以检测到它的主体除了base64之外还包含两个822样式的头行,那么您必须复制openssl的"遗留"密钥文件解密,再构造pkcs8(未加密)编码。
如果您可以使用bouncycastle,特别是
bcpkix ,它可以直接读取和解析openssl用于私钥的所有PEM变量,包括解密加密的PEM变量;但是,如果您还没有使用它,这是安装和/或部署的额外jar
请参阅以下一个或多个副本:向KeyStore(Java)加载证书(Q使用PojCyCARS构建PKCS8)Java:将DKIM私钥从RSA转换为DER,用于JavaMail(我的答案用手构造PKCS8)如何从文件加载RSA私钥(使用BouncyCastle读取)读取Java中的pkCS1格式的RSA私钥(使用PosiCyCar读取)从rsa.pem文件获取私钥(使用bc解密)用Java解密OpenSSL PEM编码的RSA私钥?(手动解密)可能是RSA私钥的pkcs_1和pkcs_8格式(背景)"begin rsa private key"和"begin private key"的区别(背景)