繁体   English   中英

Nodejs加密:椭圆曲线签署消息并将公钥导出为文本

[英]Nodejs crypto: Elliptic Curve to sign message and export public key as text

我想使用 Nodejs 加密模块实现以下目标:

  1. 我想用我的私钥在定义的 EC 上签署一条消息,并将签名作为原始缓冲区/十六进制。
  2. 我想将各自的公钥作为原始缓冲区/十六进制。

我可以单独实现这两个目标,但我目前无法同时实现它们,这似乎很奇怪,使用节点加密模块很难实现。

使用以下代码很容易在曲线上生成签名,但我无法设法解码 publicKey:

//Get pub and priv key from curve
const {publicKey, privateKey} = crypto.generateKeyPairSync('ec', {'namedCurve' : 'secp128r1'});
var message = "Hello";
var signer = crypto.createSign('sha256');
signer.update(message);
// Signature as raw hex. That's what I want.
var sigString = signer.sign(privateKey, 'hex'); // Needs a proper KeyObject

使用此代码,可以轻松地从曲线中提取私钥的公钥,但不允许使用curve.getPrivateKey返回的密钥进行签名:

refCurve = crypto.createECDH('secp128r1');
//Public key split into x and y components. That's what I want.
refPubKey = {
 x: '0x' + curve.getPublicKey('hex').slice(2,34),
 y: '0x' + curve.getPublicKey('hex').slice(-32)
}

我不可能同时实现两者。 问题是,曲线 object 只能导出为缓冲区/十六进制,而加密中的所有签名函数只接受正确的密钥对象。 同时,似乎不可能将两者相互转换。 KeyObjects 没有导出到缓冲区的功能,并且无法从从曲线导出的原始键创建 KeyObject。 我错过了什么? 我还尝试使用curve.setPrivateKey(privateKey)在曲线上设置相应的私钥,但即使这样也不起作用。

或者,我也愿意使用另一个节点库,但我发现的那些似乎不支持我想要使用的曲线(SECP128R1)

例如,这就是 python 和 ecdsa 库的简单程度:

sk = SigningKey.generate(curve=SECP128r1, hashfunc=sha256)
vk = sk.verifying_key
message = b"Hello"
m = sha256(message)
//Signature
signature = sk.sign(message)
//Public Key
[vk.to_string()[:16], vk.to_string()[16:]]

感谢您的帮助!

您可以使用export()以 X.509/SPKI 格式和 DER 编码导出公钥。 对于 secp128r1 密钥,最后 32 个字节是 x 和 y 的串联:

const { publicKey, privateKey } = crypto.generateKeyPairSync('ec', { 'namedCurve': 'secp128r1' });
// ...

var key = publicKey.export({ type: 'spki',  format: 'der' });
var rawX = key.subarray(-32, -16);
var rawY = key.subarray(-16);

console.log(key.toString('hex'));  // e.g. 3036301006072a8648ce3d020106052b8104001c03220004d15885cfb3c75417bbeb95625da313dcb4d27ecb6f89923ae539faa7c09b4797
console.log(rawX.toString('hex')); // e.g. d15885cfb3c75417bbeb95625da313dc
console.log(rawY.toString('hex')); // e.g. b4d27ecb6f89923ae539faa7c09b4797

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

请注意,不应使用此曲线,因为它根据NIST的长度。


另一个方便的选项是导出为 JWK,因为这里可以直接提取 x 和 y(Base64url 编码)。 但是这种方式只能导出JWK支持的曲线,secp128r1不是其中之一。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM