gpt4 book ai didi

java - Nodejs 加密 ECDH 公钥十六进制为 X.509

转载 作者:行者123 更新时间:2023-12-02 10:50:19 38 4
gpt4 key购买 nike

我使用 prime256v1 曲线生成 key 对,并使用 nodejs 和默认的 crypto 模块进行签名。

使用加密

let crypto = require('crypto');
let e = crypto.createECDH('prime256v1');
e.generateKeys();
privateKey = e.getPrivateKey();
privateKeyHex = privateKey.toString('hex');
publicKey = e.getPublicKey();
publicKeyHex = publicKey.toString('hex');

我获得了一个类似于下面的十六进制字符串的公钥:

'049a6b0ac242afe41128cf59736412686ca83c9e902ee3fa0f13810b9d59ebfe5e49204427c23b630be12ae33815b0bda6ed8d0603386c6ea5f1906cdb0e731286'

Usign jsrsasign

let jsrsa = require('jsrsasign');
let KEYUTIL = jsrsa.KEYUTIL;
let kp = KEYUTIL.generateKeypair("EC", "prime256v1");
let pkHex = kp.pubKeyObj.pubKeyHex

返回

'04f36e41189420db05dd8a73e3cb310b0c55809190bdedd89bf19769ac8df3cd06c1380f646e9e65e31c24affff79e43516b37e0186c3753cfdfd29894c2becc84'

将 PublicKey Hex 转换为 Java 中的 PublicKey 对象

我想使用这些公钥并将其转换为java中的PublicKey对象。使用 EC KeyFactory,我将十六进制转换为 byte[] 并尝试在 java 中构造需要 X.509 的 PublicKey 对象格式编码。

public PublicKey getPublicKey(byte[] pk) throws NoSuchAlgorithmException, InvalidKeySpecException {
EncodedKeySpec publicKeySpec = new X509EncodedKeySpec(pk);
KeyFactory kf = KeyFactory.getInstance("EC");
PublicKey pub = kf.generatePublic(publicKeySpec);
return pub;
}

要将十六进制字符串转换为 byte[],我使用以下命令:

public byte[] hexStringToByteArray(String hexString) {
byte[] bytes = new byte[hexString.length() / 2];

for(int i = 0; i < hexString.length(); i += 2) {
String sub = hexString.substring(i, i + 2);
Integer intVal = Integer.parseInt(sub, 16);
bytes[i / 2] = intVal.byteValue();
String hex = "".format("0x%x", bytes[i / 2]);
}
return bytes;
}

尝试使用如下测试用例执行相同操作会导致 InvalidKeySpecException:

@Test
public void pkConversionTest() throws NoSuchAlgorithmException, InvalidKeySpecException {
ECDSA.setDebug(true);
byte[] pk = hexStringToByteArray("049a6b0ac242afe41128cf59736412686ca83c9e902ee3fa0f13810b9d59ebfe5e49204427c23b630be12ae33815b0bda6ed8d0603386c6ea5f1906cdb0e731286");
PublicKey pub = ECDSA.getPublicKey(pk);
System.out.println(pub);
}

返回

java.security.spec.InvalidKeySpecException: java.security.InvalidKeyException: IOException: DerInputStream.getLength(): lengthTag=26, too big.

但是,我可以使用 java 生成 KeyPair 并使用通过 nodejs 获得的 publicKey 十六进制来执行签名 verify。从 java 生成的示例公钥十六进制如下所示:

3059301306072a8648ce3d020106082a8648ce3d0301070342000425a321d5a1a74e6c04a6e3cab030401f3dbc04d5242f9bc629175c3d3988799175eb80cd96d7e76ea924630a8d86b93c54dec7cb965b58de31705eb3343846a1

如何将nodejs生成的公钥格式化为X.509格式以便在java端使用?

编辑:

3059301306072a8648ce3d020106082a8648ce3d030107034200 似乎是使用 java 生成的 publicKey 十六进制的常见前缀。由于长度较小,通过将其前缀添加到使用nodejs获得的PublicKey的十六进制值似乎可以解决问题。但有人可以解释为什么吗?

谢谢。

最佳答案

But can someone explain why?

Java 以“X.509”格式对公钥进行编码,或者更准确地说是 X.509/PKIX 定义的 SubjectPublicKeyInfo 结构 (SPKI);请参阅 rfc5280、rfc3279,对于 ECC,请参阅 rfc5480。这就是为什么您传递给 key 工厂的数据位于名为 X509EncodedKeySpec 的类中。此 ASN.1 结构包含一个 AlgorithmIdentifier ,它标识所使用的算法及其参数(对于 ECC 来说是所使用的曲线/组,在您的情况下是标识 prime256 又名 P-256 又名 secp256r1 的 OID)以及一个BIT STRING 类型,包含实际编码的公钥值(对于 ECC 来说是 X9.62 格式的点,它有多种变体;这里使用的是未压缩的;根据 the doc nodejs.crypto 也支持压缩)。

您的“前缀”是 ASN.1 外部序列、算法标识符以及标记长度和 padcount 的 DER 编码,它们开始包含公钥点的位字符串。

基本上是骗人的:
* How can I get a PublicKey object from EC public key bytes?
* Loading raw 64-byte long ECDSA public key in Java (Maarten 的答案实际上就是您所做的)
* How can I generate a valid ECDSA EC key pair? (披露:我的)

仅供引用:实际上 RSA 也会出现同样的问题,并且还有更多问题。与特定于算法的格式相比,通用 PKCS8 格式的私钥也存在类似的问题,但由于公钥通常与其他系统和/或程序交换,而私钥通常不会,因此私钥编码的互操作性不太常见。

关于java - Nodejs 加密 ECDH 公钥十六进制为 X.509,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52232996/

38 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com