将椭圆曲线私钥转换为(未加密的)PKCS#8格式

4

我正在尝试转换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对象中获取了私钥:

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程序中创建和读取PKCS #8格式的私钥。 - Reinier Torenbeek
1个回答

4
将SEC1/PEM格式(-----BEGIN EC PRIVATE KEY-----...)转换为PKCS#8/PEM格式(-----BEGIN PRIVATE KEY-----...)根本不需要,因为privateKey.getEncoded()返回的密钥已经是PKCS#8格式。所以只需要使用PemWriter将其导出为PEM格式即可。
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密钥来实现,例如在此处中描述。然后,可以使用PemWriter将导入的密钥导出为PKCS#8 / PEM密钥,就像上面的示例一样。

谢谢!这真的帮助我处理了。我还通过转换回EC pem格式并检查了相同的值。 - master17
"(ECPrivateKey)pair.getPrivate()"中的pair对象是什么类型?我正在尝试从字符串中读取我的密钥并返回PrivateKey对象。你能分享一下我需要更新上面代码段中的内容吗? - dhamu
@dhamu - 请发布一个新问题,包含回答所需的所有信息。如果需要,您可以引用此帖子。 - Topaco

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