Nodejs Crypto ECDH PublicKey Hex为X.509

问题描述 投票:0回答:1

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

使用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'

使用qazxsw poi

jsrsasign

返回

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

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

我想使用这些publicKeys并将其转换为'04f36e41189420db05dd8a73e3cb310b0c55809190bdedd89bf19769ac8df3cd06c1380f646e9e65e31c24affff79e43516b37e0186c3753cfdfd29894c2becc84' 中的PublicKey对象。使用java KeyFactory,我将十六进制转换为EC并尝试在java中构造byte[]对象,该对象需要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. 生成KeyPair并使用java获得的publicKey十六进制来执行签名nodejs。从java生成的示例publickey十六进制如下所示:

verify

如何格式化以java.5方式使用的X.509格式的nodejs生成的publicKey?

Edit:

3059301306072a8648ce3d020106082a8648ce3d0301070342000425a321d5a1a74e6c04a6e3cab030401f3dbc04d5242f9bc629175c3d3988799175eb80cd96d7e76ea924630a8d86b93c54dec7cb965b58de31705eb3343846a1 似乎是使用3059301306072a8648ce3d020106082a8648ce3d030107034200生成的publicKey hexes的通用前缀。通过javaing这个使用Prefix获得的PublicKey的十六进制值,因为长度较小似乎解决了问题。但有人可以解释为什么吗?

谢谢。

java node.js cryptography ecdsa
1个回答
1
投票

但有人可以解释为什么吗?

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

您的“前缀”是ASN.1外部SEQUENCE,AlgorithmIdentifier的DER编码,以及开始BIT STRING以包含publickey点的标记长度和padcount。

基本上是欺骗: * the doc * How can I get a PublicKey object from EC public key bytes?(Maarten的回答实际上就是你所做的) * Loading raw 64-byte long ECDSA public key in Java(披露:我的)

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

© www.soinside.com 2019 - 2024. All rights reserved.