如何在Java中使用由openssl生成的.key和.crt文件?

19

我需要在Java中使用非对称加密。我使用openssl生成带有自定义密码的.key和.crt文件,详情请参考http://www.imacat.idv.tw/tech/sslcerts.html
如何使用这些.key和.crt文件从Java中提取公钥和私钥?

4个回答

27

你的.key.crt文件可能是PEM格式的。要检查这一点,请使用文本编辑器打开它们并检查内容是否类似于------BEGIN CERTIFICATE------(或 "begin RSA private key" ...)。这通常是OpenSSL使用的默认格式,除非您明确指定了DER格式。

虽然可能不是必需的(请参见下文),但如果您的证书采用DER格式(二进制格式),您可以使用以下命令将其转换为PEM格式:

openssl x509 -inform DER -in cert.crt -outform PEM -out cert.pem

(如果需要,可以检查有关使用私钥进行类似操作的帮助,具体请参考openssl rsa。)

随后您将获得两个选项:

  • 构建PKCS#12文件

openssl pkcs12 -export -in myhost.crt -inkey myhost.key -out myhost.p12
你可以将其直接用作Java中的“PKCS12”类型密钥库。大多数Java应用程序应该允许您在文件位置之外指定密钥库类型。对于默认的系统属性,可以使用javax.net.ssl.keyStoreType来完成此操作(但您使用的应用程序可能未使用此选项)。否则,如果需要显式加载它,请使用以下代码:
KeyStore ks = KeyStore.getInstance("PKCS12");
FileInputStream fis =
    new FileInputStream("/path/to/myhost.p12");
ks.load(fis, "password".toCharArray()); // There are other ways to read the password.
fis.close();

然后,您应该能够遍历KeyStorealiases()并使用getCertificate(然后对于公钥使用getPublicKey())和getKey()

 FileReader fr = ... // Create a FileReader for myhost.crt
 PEMReader pemReader = new PEMReader(fr);
 X509Certificate cert = (X509Certificate)pemReader.readObject();
 PublicKey pk = cert.getPublicKey();
 // Close reader...
对于私钥,如果它有密码保护,您需要实现一个PasswordFinder(请参见PEMReader doc中的链接)来构建 PEMReader 。 (您需要将 readObject()的结果强制转换为 Key PrivateKey 。)

如何使用ks获取私钥? - Sajad Bahmani
使用getKey()。当使用PKCS#12格式时,密钥的密码与存储本身的密码相同。 - Bruno
2
@AndrewBacker,刚想起来BouncyCastle的PEMReader并不总是必要的,这取决于你需要读取什么。如果只是为了证书,可以尝试使用CertificateFactory(JSSE的一部分)。请参见此处的示例和此处的注意事项(该评论可能会有用)。 - Bruno
@AndrewBacker,你不必猜测,只需阅读文档就可以了;-) - Bruno
@Bruno 确实是这样。现在我知道它是正确的,以及它的作用,我可以理解那份文档。但是我自己永远不会找到它 :D 所以再次感谢... 顺便说一下...他们写的那些 "use generateCertificates when you want to parse a collection of possibly unrelated certificates" 的东西真是糟糕,但我只有一个 .crt 文件,不是无关的集合?一个文件算不算集合?那是一个带有2个证书的 .pem 文件吗?嗯...我知道你是安全专家,所以这一切都很明显。但我敢打赌,这并不是从文档中读出来的! - Andrew
显示剩余2条评论

5
这段代码可以实现您想要的功能(使用上面建议的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();
}

1

请看org.bouncycastle.crypto.generators.OpenSSLPBEParametersGenerator。


1
据我所知,OpenSSL以所谓的PEM格式保存文件。您需要将其转换为Java密钥存储(JKS)格式,然后使用该格式(它是Java本地格式)来提取文件。请使用this Google query进行转换,它会给出相当不错的结果。
将JKS文件加载到java.security.KeyStore类中。然后使用getCertificate和getKey方法获取所需信息。

1
@SjB 请查看这些文件 - 如果它们是带有“----- BEGIN ... -----”头和相应的尾部的文本,则为PEM格式。 - Eugene Mayevski 'Callback

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接