Pet*_*olm 7 cryptography node.js ecdsa
我有使用jsrsasignJKK格式的密钥为ECDSA签名生成连接(rs)签名的代码:
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');
Run Code Online (Sandbox Code Playgroud)
似乎工作.我也有SubtleCrypto用于实现同样的事情的代码:
importEcdsaKey(key, 'sign') // importKey JWK -> raw
.then((privateKey) => subtle.sign(
{ name: 'ECDSA', hash: {name: 'SHA-256'} },
privateKey,
dataBuffer
))
Run Code Online (Sandbox Code Playgroud)
这两个都返回128字节的缓冲区; 并且他们交叉验证(即我可以验证jsrsasign签名,SubtleCrypto反之亦然).但是,当我Sign在Node.js crypto模块中使用该类时,我似乎得到了一些完全不同的东西.
key = require('jwk-to-pem')(key, {'private': true});
const sign = require('crypto').createSign('sha256');
sign.update(dataBuffer);
return sign.sign(key);
Run Code Online (Sandbox Code Playgroud)
这里我得到一个可变长度的缓冲区,大约70个字节; 它没有交叉验证jsrsa(抱怨rs签名的长度无效).
我怎样才能得到一个RS签名,通过所产生jsrsasign和SubtleCrypto使用节点crypto?
Pet*_*olm 12
答案结果是Node crypto模块生成ASN.1/DER签名,而其他API喜欢jsrsasign并SubtleCrypto生成"连接"签名.在这两种情况下,签名都是串联的(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'));
}
Run Code Online (Sandbox Code Playgroud)
想出来,谢谢你
| 归档时间: |
|
| 查看次数: |
5383 次 |
| 最近记录: |