我有代码使用jsrsasign
为ECDSA签名生成串联(r-s)签名和JWK格式的密钥:
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');
似乎有效。我也有使用SubuleCrypto
来实现相同目标的代码:
importEcdsaKey(key, 'sign') // importKey JWK -> raw
.then((privateKey) => subtle.sign(
{ name: 'ECDSA', hash: {name: 'SHA-256'} },
privateKey,
dataBuffer
))
这两者都返回128字节的缓冲区;并且它们可以交叉验证(例如,我可以用< code>SubtleCrypto验证< code > JSR sign 签名,反之亦然)。然而,当我在Node.js crypto
模块中使用< code>Sign类时,我似乎得到了完全不同的东西。
key = require('jwk-to-pem')(key, {'private': true});
const sign = require('crypto').createSign('sha256');
sign.update(dataBuffer);
return sign.sign(key);
在这里,我得到了一个可变长度的缓冲区,大约70字节;它不会与 jsrsa 交叉验证(jsrsa
抱怨 r-s 签名的长度无效)。
如何使用 Node 加密
获取由 jsrsasign
和 SubtleCrypto
生成的 r-s 签名?
答案是Nodecrypto
模块生成ASN.1/DER签名,而其他API(如jsrsasign
和SubtleCrypto
)生成“连接”签名。在这两种情况下,签名都是(r, s)
的连接。区别在于ASN.1使用最小字节数以及一些有效负载长度html" target="_blank">数据来执行此操作;而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'));
}
多亏了你,我才明白
下面是Java代码: 然后使用C代码来验证签名 我在想我需要将我的签名编码为hexa,但它并没有解决我的问题。我已经使用crypto编写了一个c版本的符号方法,并且已经验证过了。所以为什么当我使用java代码时,签名没有得到验证。谢谢
问题内容: 我用nodejs crypto创建了一个私钥,并想用该密钥签名文件。我的代码如下: 但是我得到了错误: 我知道它与密钥格式有关,但我不知道该如何解决。有人可以帮忙吗? 更新:我编辑了privateKey以适合pem格式: 现在我遇到了另一个错误: 问题答案: 用于签署数据的密钥必须是有效的PEM编码的私钥。DH 函数不以这种格式返回密钥,而是返回裸机专用密钥数据。 您的选择包括: 通过
我试图用ECDSA和secp256r1曲线(P256)和SHA256算法来生成签名。我也在使用弹力城堡图书馆。下面的代码,
我正在使用secp256r1曲线和使用BouncyCastle的SHA256算法实现ECDSA签名生成。 对于某些输入,签名长度为127个字符。我感觉开头的“0”被删除了,因为签名被存储到ECDSASigner类中的BigInteger datatype中。 我使用确定性方法添加了rfc6979 ECDSA签名中的示例 唯一的区别是r值中的零。因为签名的长度只有127。 如果我的推论是正确的,请让
我在nodejs中有一个非常小的代码,我在其中签名一个字符串,然后尝试使用openssl生成的节点密码和密钥对来验证它。无论我尝试什么,结果总是“错误”,签名无法验证。 生成公钥/私钥对: 生成的密钥是(我不在乎是否公开): 然后,这是我的节点代码: 我尝试使用不同的算法和编码。我已经读了带有"fs"的PEM文件,也没有运气。我错过了什么?顺便说一句,这些键使用npm URSA模块完美工作,所以我
我已经在Java中生成了一个ECDSA签名,我希望从中获得R和S值,以便获得COSE编码的签名。根据我的理解,我生成的签名是DER编码的(默认情况下使用bouncyCastle)。当我使用P-256曲线(SHA256withECDSA)时,我正确地检索了R和S值。 当我使用其他曲线(P-521、P-384)时,从一种编码到另一种编码的签名解析有一些问题。