【问题标题】:Convert private key in PEM format转换 PEM 格式的私钥
【发布时间】:2013-01-20 15:09:03
【问题描述】:

我用 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 格式文件的建议都会非常有帮助。

【问题讨论】:

  • 确实没有单一的“PEM”格式。有各种不同的加密结构,当 base64 编码并用-----BEGIN <xyz>-----END <xyz> 包围时,被描述为“PEM 格式”。您需要具体说明您想要哪一个。
  • 不要使用一些不属于 J2SE API 的内部 sun.* 包,而应该考虑使用第 3 方库。

标签: java ssl openssl ssl-certificate x509certificate


【解决方案1】:

您使用 Certificate.getEncoded()Key.getEncoded() 获取 DER 并手动执行 base 64 编码和页眉/页脚,例如使用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";

【讨论】:

  • [Private]Key.getEncoded() 返回的编码是并且一直是,如文档所述,PKCS8,PKCS8 的正确 PEM 类型是并且是 PRIVATE KEY(如在 Anup 的最新 A 中)不是 RSA PRIVATE KEY。这是在 RFC7468 中正式化的,尽管那是在 A 之后 2 年。
【解决方案2】:

感谢 Daniel Roethlisberger 的回复。 你的回复给了我很大的帮助..

Java实现如下

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

【讨论】:

    【解决方案3】:

    在 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"
        )
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2023-02-07
      • 2019-06-21
      • 2011-02-26
      • 2012-01-07
      • 2020-01-28
      • 2017-06-13
      • 1970-01-01
      相关资源
      最近更新 更多