【问题标题】:JAVA 11 - elliptic curve private key - Caused by: java.security.InvalidKeyException: IOException : version mismatch: (supported: 00, parsed: 01JAVA 11 - 椭圆曲线私钥 - 引起:java.security.InvalidKeyException:IOException:版本不匹配:(支持:00,解析:01
【发布时间】:2022-01-08 15:32:55
【问题描述】:

请教关于用Java获取椭圆曲线私钥的小问题。

我在终端中运行这个命令:

openssl ecparam -name secp256k1 -genkey -noout -out ec-secp256k1-dummy-priv-key.pem

此命令运行良好,生成文件正常,我什至可以cat 文件,我可以看到:

-----BEGIN EC PRIVATE KEY-----
MHQCAQEEIDHE7OA9hgIYW427NieIsXz/qAipMVhqVUIwVcEIWwuAoAcGBSuBBAAK
oUQDQgAEcMu2KlVzJLKQ9XfoWvF0jZ+JwbPeUekHqTYVTFK9ISoKLgBN9abxIxyc
JumqIshcc74GUVtm/sJJoiPJNdEPEQ==
-----END EC PRIVATE KEY-----

(请注意这里写的是 BEGIN EC PRIVATE KEY 而不是 BEGIN PRIVATE KEY)

现在,我使用\n 和空格等,基本上将键的“内部”配置为单行字符串。

String s = "MHQCAQEEIDHE7OA9hgIYW427NieIsXz/qAipMVhqVUIwVcEIWwuAoAcGBSuBBAAKoUQDQgAEcMu2KlVzJLKQ9XfoWvF0jZ+JwbPeUekHqTYVTFK9ISoKLgBN9abxIxycJumqIshcc74GUVtm/sJJoiPJNdEPEQ==";

(如果这一步有错请告诉我)

我尝试了什么:然后我使用这段代码来获取私钥

String s = "MHQCAQEEIDHE7OA9hgIYW427NieIsXz/qAipMVhqVUIwVcEIWwuAoAcGBSuBBAAKoUQDQgAEcMu2KlVzJLKQ9XfoWvF0jZ+JwbPeUekHqTYVTFK9ISoKLgBN9abxIxycJumqIshcc74GUVtm/sJJoiPJNdEPEQ==";

        byte[] keyData = Base64.getDecoder().decode(s);
        EncodedKeySpec privKeySpec = new PKCS8EncodedKeySpec(keyData);
        KeyFactory kf = KeyFactory.getInstance("EC");
        PrivateKey privKey = kf.generatePrivate(privKeySpec);

不幸的是,它产生了这个错误

SEVERE: null
java.security.spec.InvalidKeySpecException: java.security.InvalidKeyException: IOException : version mismatch: (supported:     00, parsed:     01

Caused by: java.security.InvalidKeyException: IOException : version mismatch: (supported:     00, parsed:     01
    at java.base/sun.security.pkcs.PKCS8Key.decode(PKCS8Key.java:350)
    at java.base/sun.security.pkcs.PKCS8Key.decode(PKCS8Key.java:355)

我有点难以理解这个问题,以及如何解决这个问题。

如果可能的话,我想避免回到充气城堡,避免改变生成密钥的方式,避免再次将密钥转换为另一种格式。

请问我做错了什么,请问解决这个问题的正确方法是什么?

谢谢

【问题讨论】:

  • 虽然我同意将答案转换为 pkcs8 是最好的方法,但您可以通过在解码后的(二进制) SEC1 格式使其成为 PKCS8 格式,按照stackoverflow.com/questions/41927859/… 中所示的行,但这种情况是 secp384r1,您需要为 secp256k1 使用不同的实际前缀。

标签: java elliptic-curve ecdsa


【解决方案1】:

据我所知PKCS8EncodedKeySpec Javadocs,构造函数的输入必须是 PKCS8 编码的私钥。但是,openssl ecparam command 显然不会生成 PKCS8 格式的密钥。如果我正确理解文档,您需要将私钥转换为 PKCS8,如下所示:

openssl pkcs8 -topk8 -nocrypt -in ec-secp256k1-dummy-priv-key.pem -out p8file.pem

然后您可以去除换行符和 BEGIN/END 标记并将其输入 PKCS8EncodedKeySpec。

【讨论】:

  • 通过上述转换的快速测试。
  • 确实,今天学到了关于命令的新知识。这是正确的答案。点赞 + 接受,非常感谢,美好的一天
  • Nit:dePEMify 删除 BEGIN/END 行和换行符并解码 base64(OP 做了)。另一种转换是openssl pkey -in legacy.pem -out pkcs8.pem,或者您可以使用openssl genpkey 而不是openssl ecparam -genkey 进行生成。
  • 又学到了新东西,非常感谢!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2022-01-09
  • 1970-01-01
  • 2020-03-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-08-31
相关资源
最近更新 更多