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

时间:2019-05-03 20:24:36

标签: javascript signature javacard ecdsa

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

我的applet( 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上用相同的密钥签名相同的消息,则验证成功。

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

1 个答案:

答案 0 :(得分:0)

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