将PEM格式的私钥转换

11

我已经用Java代码创建了一个自签名的证书,并将其添加到KeyStore中。现在我想将创建的私钥和证书以PEM格式导出到文件中。是否可以在没有任何第三方库的情况下实现这一点?以下是我用于创建自签名证书的代码。

  public void createSelfSignedSSLCertificate() {
    try {            
        final CertAndKeyGen keypair = new CertAndKeyGen("RSA", "SHA1WithRSA", null);
        final X500Name x500Name =
            new X500Name(commonName, organizationalUnit, organization, city, state, country);
        keypair.generate(keysize);
        final PrivateKey privKey = keypair.getPrivateKey();
        final X509Certificate[] chain = new X509Certificate[1];
        chain[0] = keypair.getSelfCertificate(x500Name, new Date(), validity * 24 * 60 * 60);
        final String alias = JettySSLConfiguration.SSL_CERTIFICATE_ALIAS;
        keyStore.setKeyEntry(alias, privKey, keyStorePassword.toCharArray(), chain);
    } catch (final Exception e) {
       // Handle Exception
    }       
}

有没有建议如何将密钥和证书以PEM格式导出到文件中的?非常感谢。


1
实际上,并不存在单一的“PEM”格式。有各种不同的加密结构,当它们被base64编码并用-----BEGIN <xyz>-----END <xyz>包围时,就被描述为“PEM格式”。您需要明确指出您想要哪一个。 - President James K. Polk
1
不要使用一些内部的 sun.* 包,它们并不是 J2SE API 的一部分,你应该考虑使用第三方库。 - Bruno
3个回答

11

您可以使用Certificate.getEncoded()Key.getEncoded()来获取DER格式,然后手动进行Base64编码,并添加头和尾部信息,例如使用DatatypeConverter.printBase64Binary()或其他方式。类似于以下内容:

certpem = "-----BEGIN CERTIFICATE-----\n" +
          DatatypeConverter.printBase64Binary(chain[0].getEncoded())) +
          "\n-----END CERTIFICATE-----\n";
keypem  = "-----BEGIN RSA PRIVATE KEY-----\n" +
          DatatypeConverter.printBase64Binary(privKey.getEncoded())) +
          "\n-----END RSA PRIVATE KEY-----\n";

3
[Private]Key.getEncoded() 返回的编码一直是 PKCS8,正如文档所述。PKCS8 的正确 PEM 类型一直都是 PRIVATE KEY 而不是 RSA PRIVATE KEY(例如 Anup 最近的 A 中)。虽然 RFC7468 在此之后两年才正式规范化了这一点,但它已经存在了。 - dave_thompson_085

5

感谢Daniel Roethlisberger的回复。 我从您的回复中得到了巨大的帮助。

以下是Java实现:

String encodedString = "-----BEGIN PRIVATE KEY-----\n";
            encodedString = encodedString+Base64.getEncoder().encodeToString(Enrollment2.getKey().getEncoded())+"\n";
            encodedString = encodedString+"-----END PRIVATE KEY-----\n";

2
在 Android 上,您可以使用以下 Kotlin 扩展函数:
import android.util.Base64
import java.security.PublicKey

fun PublicKey.toPemString(): String {
    val publicKeyBase64: String = Base64.encodeToString(this.encoded, Base64.NO_WRAP)
    return publicKeyBase64.chunked(64).joinToString(
        separator = "\n",
        prefix = "-----BEGIN PUBLIC KEY-----\n",
        postfix = "\n-----END PUBLIC KEY-----\n"
    )
}

你好,能为私钥提供解决方案吗?谢谢。 - famfamfam

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