导入PEM证书导入Java密钥存储库编程(Importing PEM certificate int

2019-11-05 00:41发布

我有两个文件(.CRT和.KEY),我希望导入到Java密钥存储到随后的SSLContext用于发送与Apache的HTTP的HTTPClient组成请求客户端证书。 不过,我似乎无法找到一个方法来编程方式做到这一点,大多数其他问题我发现无论是点到外部工具或者是不适合我的情况。

我的证书与典型的编码“BEGIN CERTIFICATE”后跟一个64位编码,并与“BEGIN RSA私钥”,然后又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);
    }
}

堆栈跟踪:

产生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.base / java.security在java.base / sun.security.rsa.RSAKeyFactory.engineGeneratePrivate(RSAKeyFactory.java:216)无效的密钥格式:java.security.spec.InvalidKeySpecException:java.security.InvalidKeyException所致。 KeyFactory.generatePrivate(KeyFactory.java:390)在me.failedshack.ssltest.SSLTest.createSSLContext(SSLTest.java:62)... 1更多

java.security.InvalidKeyException:通过引起无效的密钥格式在java.base / sun.security.pkcs.PKCS8Key.decode(PKCS8Key.java:330)在java.base / sun.security.pkcs.PKCS8Key.decode(PKCS8Key。的java:355)在java.base / sun.security.rsa.RSAPrivateCrtKeyImpl(RSAPrivateCrtKeyImpl.java:91)在java.base / sun.security.rsa.RSAPrivateCrtKeyImpl.newKey(RSAPrivateCrtKeyImpl.java:75)在java.base / sun.security.rsa.RSAKeyFactory.generatePrivate(RSAKeyFactory.java:315)在java.base / sun.security.rsa.RSAKeyFactory.engineGeneratePrivate(RSAKeyFactory.java:212)... 3个

可悲的是我一直生成该文件中的私钥时得到一个InvalidKeyException异常。

Answer 1:

类型的PEM文件RSA PRIVATE KEY是BASE64不是二进制并且更重要的是在PKCS1格式NOT PKCS8,因此不能被处理为一个PKCS8EncodedKeySpec

你的选择是:

  • 转换PKCS1 PEM格式PKCS8(未加密)的PEM格式; 读取和删除的头部和尾部线条和解码以base64二进制也放到了PKCS8EncodedKeySpec -但你说你不希望外部工具,再加上它只是简单的专用密钥PLUS证书(或链)转换成PKCS12(DER)这已经是一个Java密钥库和回避的问题

  • 在PKCS1 PEM格式转换为PKCS8(未加密)DER格式,你可以理解为二进制和投入PKCS8EncodedKeySpec -同上

  • 如果PKCS1 PEM未加密,读出和如上述解码它PKCS1 DER然后手动构造PKCS8(未加密)编码,并使用该

  • 如果PKCS1 PEM是加密的,你可以发现,因为它的身体除了包含以base64 2 822风格的标题行,你要复制的OpenSSL的“传统”密钥文件解密,PLUS构建PKCS8(未加密)编码

  • 如果可以使用BouncyCastle的具体bcpkix ,它可以直接读取和解析所有的变体PEM使用OpenSSL,以便privatekeys,包括解密加密那些; 但是,如果你不是已经在使用它,这是一个额外的JAR安装和/或部署

看到这些受骗者的一个或多个:
负载证书密钥库(JAVA) (Q构建使用BouncyCastle的PKCS8)
Java的:从转换DKIM RSA私钥为DER用来为JavaMail (我的回答构建PKCS8“手”)
如何加载RSA私钥从文件 (使用BouncyCastle的读取)
阅读JAVA格式PKCS1的RSA私钥 (使用BouncyCastle的读取)
获得从RSA的.pem文件中的专用密钥 (解密使用BC)
解密与Java的OpenSSL的PEM编码RSA私钥? (手动解密)
也许PKCS#1和PKCS#8格式的RSA私钥 (背景)
和之间的“BEGIN RSA私有密钥”和“BEGIN专用密钥”的差异 (背景)



文章来源: Importing PEM certificate into Java KeyStore programmatically