【问题标题】:Convert elliptic curve private key to (unencrypted) PKCS#8 format将椭圆曲线私钥转换为(未加密的)PKCS#8 格式
【发布时间】:2021-04-04 14:25:57
【问题描述】:

我正在尝试转换 EC 私钥

-----BEGIN EC PRIVATE KEY-----
MHcCAQEEIE2tzb8O0gBVw2IFOB/B8l1Ztjax3ut4DeNtuC3UMmZ6oAoGCCqGSM49
AwEHoUQDQgAEayT6Tv8zZlpIUOKHEYnmsKZyTaqOHajL0InS4c5tK4fhkHZDSWUa
3tPl1ibIXt0LvaxHk47h0Tc4SGr3Ex8Bhg==
-----END EC PRIVATE KEY----- 

到私钥

 -----BEGIN PRIVATE KEY-----
MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgTa3Nvw7SAFXDYgU4
H8HyXVm2NrHe63gN4224LdQyZnqhRANCAARrJPpO/zNmWkhQ4ocRieawpnJNqo4d
qMvQidLhzm0rh+GQdkNJZRre0+XWJshe3Qu9rEeTjuHRNzhIavcTHwGG
-----END PRIVATE KEY-----

当你像这样执行 openSsl 命令时很容易:

openssl pkcs8 -topk8 -nocrypt -in ec1.pem -out ec2.pem

但我想以 Java 方式执行此操作,但没有找到任何解决方案(从 stackoverflow 尝试了很多)。 所以我现在有以下课程:

        ECNamedCurveParameterSpec ecNamedCurveParameterSpec = ECNamedCurveTable.getParameterSpec("prime256v1");
        KeyPairGenerator keyPair = KeyPairGenerator.getInstance("ECDSA", "BC");

        // Create a secure random number generator using the SHA1PRNG algorithm
        SecureRandom secureRandomGenerator = SecureRandom.getInstance("SHA1PRNG");
        keyPair.initialize(ecNamedCurveParameterSpec, secureRandomGenerator);
    

然后我生成 KeyPair 并在 ECPrivateKey 对象中获取 PrivateKey:

KeyPair pair =keyPair.generateKeyPair();
ECPrivateKey privateKey = (ECPrivateKey) pair.getPrivate();
StringWriter sw = new StringWriter();

        try (JcaPEMWriter jcaPEMWriter = new JcaPEMWriter(sw);) {
            jcaPEMWriter.writeObject(privateKey);
        }

String pemFormat = sw.toString();

这个字符串pemFormat其实就是以BEGIN EC PRIVATE KEY开头的PEM格式

如何将其转换为 BEGIN PRIVATE KEY

如果 openSsl 可以做到,我认为这应该是一种方式。

【问题讨论】:

标签: java openssl cryptography bouncycastle


【解决方案1】:

根本不需要从 SEC1/PEM (-----BEGIN EC PRIVATE KEY-----...) 到 PKCS#8/PEM 格式 (-----BEGIN PRIVATE KEY-----...) 的转换,因为 privateKey.getEncoded() 返回的密钥已经是 PKCS#8 格式。所以它只需要导出为 PEM 例如带有PemWriter:

import org.bouncycastle.util.io.pem.PemWriter;

...

// Your code
Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());
...
ECPrivateKey privateKey = (ECPrivateKey)pair.getPrivate();
System.out.println(privateKey.getFormat()); // PKCS#8

// Export as PKCS#8 PEM encoded key via PemWriter
StringWriter stringWriter = new StringWriter();
try (PemWriter pemWriter = new PemWriter(stringWriter)){
    pemWriter.writeObject((PemObjectGenerator)new PemObject("PRIVATE KEY", privateKey.getEncoded()));
}
String pkcs8PEM = stringWriter.toString();
System.out.println(pkcs8PEM); // -----BEGIN PRIVATE KEY-----MIGTAg...-----END PRIVATE KEY-----

您可以在 ASN.1 解析器中检查格式,例如https://lapo.it/asn1js.


但是,如果您确实在寻找将 SEC1/PEM 密钥显式转换为 PKCS#8/PEM 密钥,则描述了 SEC1/PEM 密钥的导入,例如here。然后可以使用PemWriter 将导入的密钥导出为PKCS#8/PEM 密钥,如上例所示。

【讨论】:

  • 谢谢!!!它真的帮助我处理。我还通过转换回 EC pem 格式和相同的值进行了检查。
  • “(ECPrivateKey)pair.getPrivate()”中pair对象的类型是什么。我正在尝试从字符串中读取我的密钥并返回 PrivateKey 对象。你能分享一下我在上面的sn-p中需要更新什么吗?
  • @dhamu - 请发布一个包含所有需要回答的信息的新问题。如有需要,您可以参考这篇文章。
猜你喜欢
  • 1970-01-01
  • 2023-03-20
  • 1970-01-01
  • 2016-11-01
  • 2016-09-30
  • 2011-02-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多