Javascript上的ECDSA签名验证失败(椭圆)

Javascript上的ECDSA签名验证失败(椭圆),javascript,signature,javacard,ecdsa,Javascript,Signature,Javacard,Ecdsa,我对验证javacard上的ECDSA签名有问题。我试图用Javascript(椭圆)验证签名,但验证总是失败 我的小程序(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()

我对验证javacard上的ECDSA签名有问题。我试图用Javascript(椭圆)验证签名,但验证总是失败

我的小程序(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);
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
我有私钥
(例如:3E05E289911E66A8153EE9C15A0AFC109C49207DB9DC4656CC4D09223EA65BC)

当我在邮件上签名时
(例如:0x01)

我以DER格式获得签名:
304402205F376BB2B2D48BBB0275099C3B9591F18ECA424DD953EB27FDE37BA819B980F220539A85B91491E977F6B31B5A76BF6805B3B6481A51C23B9E7C6F39FB70569

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

//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);
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上使用相同的密钥对相同的消息进行签名,则验证成功


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

这很可能是由于java/go/python/etc中的标准ecdsa库生成签名der编码,因为javascript库只是将签名的R和S值串联在一起。以下是我在自己的图书馆如何处理这个问题。抱歉,这个例子是golang到typescript,但希望您可以将其反向工程到java/javascript。Node.js中的事件此问题存在。下面是一个讨论的总结,它最终帮助我找出了如何在我自己的工作中打破实现之间的差距。

我还在javascript上做了一个签名(使用相同的私钥和消息),结果也是DER格式的(不仅仅是r和s连接),但我总是得到相同的签名:
304402206D55364F9EFF56DCFF626467920EA8C2FED4653009CDE369546CC98DA3B2BE00220086ABCC4A127C5AC1DC5D7C4DA51FCA96A75E70CDEEB6BC746010345A691BEB
Hmmm。。。我记得当我尝试使用
椭圆
库时也遇到了同样的问题。最终我解决了这个问题。相反,我决定简单地依赖浏览器内置的
crypto.minute
库。对不起,我帮不上忙。但一般来说,签名应该总是不同的,因为其中有一个随机因素。因此,如果它总是相同的值,那么肯定存在一个问题。如果你最后换成了
微妙的.crypto
,请随时向我询问更多问题。我对它的规范做了大量的工作,并且非常了解它。我假设错误在
SecP256k1.newKeyPair()
,请包括它…投票结束这个问题,因为缺少所需的信息,这使我无法回答这个问题。