Javascript(椭圆)上的 ECDSA 签名验证失败 [关闭]

Posted

技术标签:

【中文标题】Javascript(椭圆)上的 ECDSA 签名验证失败 [关闭]【英文标题】:ECDSA Signature Verification Failed on Javascript(Elliptic) [closed] 【发布时间】:2019-05-03 20:24:35 【问题描述】:

我在验证 javacard 上的 ECDSA 签名时遇到问题。我正在尝试验证 javascript(Elliptic) 中的签名,但验证总是失败。

我的小程序(javacard)看起来像:

//initialization
ecdsa = Signature.getInstance(Signature.ALG_ECDSA_SHA_256, false);
eccKey=SecP256k1.newKeyPair(); //in SecP256k1 the p,a,b,g,r,k are set
eccKey.genKeyPair();

//singing method
ecdsa.init(eccKey.getPrivate(), Signature.MODE_SIGN);

//Generates the signature of all input data.
short lenTmp = ecdsa.sign(buffer, ISO7816.OFFSET_CDATA, (short)1, buffer, 
(short)0);
//I tried also to sigh precomputed hash - same result
/*short lenTmp = ecdsa.signPreComputedHash(buffer, ISO7816.OFFSET_CDATA, 
len, buffer, (short)0); */

apdu.setOutgoingAndSend((short)0, lenTmp);

我得到了一个私钥 (e.g. : 3E05E289911E66A8153EE9C15A0AFC109C49207DB9DC4656CC4D092323EA65BC)

当我签署消息(e.g : 0x01)

我得到了 DER 格式的签名: 304402205F376BB2B2D48BBB0275099C3B9591F18ECA424DD953EB27FDE37BA819B98F980220539A85B91491E977F6B31B5A76BEF6805BBC3B6481A51C23B9E7C6F39FB70569

在javacard上也验证成功.. 但是当我尝试在nodejs上验证它时,它总是失败。 我的代码如下:

let elliptic = require('elliptic');
let ec = new elliptic.ec('secp256k1');
let keyPair = ec.keyFromPrivate("3E05E289911E66A8153EE9C15A0AFC109C49207DB9DC4656CC4D092323EA65BC");
let privKey = keyPair.getPrivate("hex");
let pubKey = keyPair.getPublic();
let signature = "304402205F376BB2B2D48BBB0275099C3B9591F18ECA424DD953EB27FDE37BA819B98F980220539A85B91491E977F6B31B5A76BEF6805BBC3B6481A51C23B9E7C6F39FB70569";
let msg = 0x01;
let validSig = ec.verify(msg, signature, pubKey);
console.log("Signature valid?", validSig);//returns always false

另外,如果我在nodejs上用相同的key对相同的消息进行签名,则验证成功。

此外,我注意到javacard中的签名总是不同的,而椭圆上的签名总是相同的,也许它总是选择相同的随机k。

【问题讨论】:

我认为错误在SecP256k1.newKeyPair(),请包括它... 投票关闭此问题,因为缺少所需的信息,恕我直言,无法回答该问题。 【参考方案1】:

这很可能是由于 java/go/python/etc 中的标准 ecdsa 库导致的。生成签名 der 编码,其中 javascript 库只是连接签名的 R 和 S 值。这是我在自己的库HERE 中处理此问题的方法。抱歉,示例是 golang 到 typescript,但希望您可以将其反向工程为 java/javascript。 Node.js 中的事件存在此问题。这是一个 LINK 的讨论,最终帮助我弄清楚如何在我自己的工作中打破实现之间的差距。

【讨论】:

我也在 javascript 上做了一个签名(使用相同的私钥和消息),结果也是 DER 格式(不仅 r 和 s 连接),但我总是得到相同的签名:@987654323 @ 嗯...我记得在尝试使用 elliptic 库时遇到了同样的问题。最终我确实解决了这个问题。相反,我决定简单地依赖浏览器内置的 crypto.subtle 库。抱歉,帮不上这个忙。不过一般来说,签名应该总是不同的,因为它里面有一个随机因素。因此,如果它始终是相同的值,则肯定存在问题。如果您最终切换到subtle.crypto,请随时向我提出更多问题。我对它的规范做了很多工作,并且很好地理解了它。

以上是关于Javascript(椭圆)上的 ECDSA 签名验证失败 [关闭]的主要内容,如果未能解决你的问题,请参考以下文章

如何字符串化椭圆签名 ECDSA

Java - 使用 ECDSA(椭圆曲线)创建 XML 数字签名

椭圆曲线数字签名算法(ECDSA)

ECDSA数字签名算法

golang 椭圆曲线加密使用ecdsa

公钥生成和签名计算的椭圆曲线应该相同吗?