gpt4 book ai didi

node.js - 使用 Node.js/crypto 生成 ECDSA 签名

转载 作者:搜寻专家 更新时间:2023-10-31 22:22:44 25 4
gpt4 key购买 nike

我有代码使用 jsrsasign 和 JWK 格式的 key 为 ECDSA 签名生成串联 (r-s) 签名:

const sig = new Signature({ alg: 'SHA256withECDSA' });
sig.init(KEYUTIL.getKey(key));
sig.updateHex(dataBuffer.toString('hex'));
const asn1hexSig = sig.sign();
const concatSig = ECDSA.asn1SigToConcatSig(asn1hexSig);
return new Buffer(concatSig, 'hex');

似乎有效。我也有使用 SubtleCrypto 实现相同目的的代码:

importEcdsaKey(key, 'sign') // importKey JWK -> raw
.then((privateKey) => subtle.sign(
{ name: 'ECDSA', hash: {name: 'SHA-256'} },
privateKey,
dataBuffer
))

它们都返回 128 字节的缓冲区;他们交叉验证(即我可以验证 jsrsasign 签名与 SubtleCrypto 反之亦然)。但是,当我在 Node.js crypto 模块中使用 Sign 类时,我似乎得到了一些完全不同的东西。

key = require('jwk-to-pem')(key, {'private': true});
const sign = require('crypto').createSign('sha256');
sign.update(dataBuffer);
return sign.sign(key);

这里我得到一个可变长度的缓冲区,大约 70 个字节;它不会与 jsrsa 进行交叉验证(这避免了提示 r-s 签名的长度无效)。

如何使用 Node crypto 获得由 jsrsasignSubtleCrypto 生成的 r-s 签名?

最佳答案

答案原来是 Node crypto 模块生成 ASN.1/DER 签名,而其他 API,如 jsrsasignSubtleCrypto产生一个“串联”签名。在这两种情况下,签名都是 (r, s) 的串联。不同之处在于 ASN.1 使用最少的字节数加上一些有效载荷长度数据;而 P1363 格式使用两个 32 位十六进制编码整数,必要时用零填充它们。

以下解决方案假定“规范”格式是 SubtleCrypto 使用的串联样式。

const asn1 = require('asn1.js');
const BN = require('bn.js');
const crypto = require('crypto');

const EcdsaDerSig = asn1.define('ECPrivateKey', function() {
return this.seq().obj(
this.key('r').int(),
this.key('s').int()
);
});

function asn1SigSigToConcatSig(asn1SigBuffer) {
const rsSig = EcdsaDerSig.decode(asn1SigBuffer, 'der');
return Buffer.concat([
rsSig.r.toArrayLike(Buffer, 'be', 32),
rsSig.s.toArrayLike(Buffer, 'be', 32)
]);
}

function concatSigToAsn1SigSig(concatSigBuffer) {
const r = new BN(concatSigBuffer.slice(0, 32).toString('hex'), 16, 'be');
const s = new BN(concatSigBuffer.slice(32).toString('hex'), 16, 'be');
return EcdsaDerSig.encode({r, s}, 'der');
}

function ecdsaSign(hashBuffer, key) {
const sign = crypto.createSign('sha256');
sign.update(asBuffer(hashBuffer));
const asn1SigBuffer = sign.sign(key, 'buffer');
return asn1SigSigToConcatSig(asn1SigBuffer);
}

function ecdsaVerify(data, signature, key) {
const verify = crypto.createVerify('SHA256');
verify.update(data);
const asn1sig = concatSigToAsn1Sig(signature);
return verify.verify(key, new Buffer(asn1sig, 'hex'));
}

感谢

关于node.js - 使用 Node.js/crypto 生成 ECDSA 签名,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39499040/

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