我下面有一些代码,这些代码将用于使用JavaScript验证邮件的真实性。使用椭圆曲线secp256k1生成密钥对非常简单,但是我无法理解为什么我的签名实现不起作用(为什么消息未成功验证)。这是我的代码:
/**
* Signature Generation
*/
var g = bigInt('55066263022277343669578718895168534326250603453777594175500187360389116729240');
var n = bigInt('115792089237316195423570985008687907852837564279074904382605163141518161494337');
var p = bigInt('115792089237316195423570985008687907853269984665640564039457584007908834671663');
var k = bigInt.randBetween("1", n.subtract(1));
var r = bigInt("0");
var s = bigInt("0");
var privateKey = bigInt('5943918703142138746985297990399309008462887494775678462183405629775262082646');
var publicKey = bigInt(privateKey.multiply(g)).mod(p);
while(s.equals("0")){
while(r.equals("0")){
k = bigInt.randBetween("1", n.subtract(1));
while(bigInt(k).isPrime() == false){
k = bigInt.randBetween("1", n.subtract(1));
}
var xCoord = bigInt(k.multiply(g)).mod(p);
r = xCoord.mod(n);
}
var kInverse = k.modInv(n);
var hashedMessage = bigInt(sha1('hello'),16);
s = bigInt(kInverse*(hashedMessage.add(privateKey.multiply(r)))).mod(n)
}
var signatureParams = {
"publicKey": publicKey.toString(),
"r": r.toString(),
"sign": s.toString()
}
/**
* Signature Verification
*/
var sInverse = bigInt(signatureParams.sign).modInv(n);
var publicKey = bigInt(signatureParams.publicKey);
var w = sInverse.mod(n);
var hashedMessage = bigInt(sha1('hello'),16);
var u1 = bigInt(hashedMessage.multiply(w)).mod(n);
var u2 = bigInt(bigInt(r).multiply(w)).mod(n);
var P = bigInt(u1.multiply(g)).add(u2.multiply(publicKey));
P == r
可以使用浏览器控制台轻松对其进行测试。 我使用了以下指南中的信息汇总:
https://www.maximintegrated.com/en/app-notes/index.mvp/id/5767
http://www.cs.miami.edu/home/burt/learning/Csc609.142/ecdsa-cert.pdf
https://pdfs.semanticscholar.org/c06a/d6512775be1076e4abd43e3f2928729da776.pdf
我的实现有什么问题?我想念什么吗?我做错什么了吗?
编辑:
进行一些修改后,我想到了以下内容:
var g = bigInt('55066263022277343669578718895168534326250603453777594175500187360389116729240');
var n = bigInt('115792089237316195423570985008687907852837564279074904382605163141518161494337');
var p = bigInt('115792089237316195423570985008687907853269984665640564039457584007908834671663');
var privateKey = bigInt('90436540941140970165633788406609967146985661161263948799654498545867952662296');
var publicKey = bigInt(privateKey.multiply(g)).mod(p);
var generateSignature = function(hashedMessage){
hashedMessage = bigInt(hashedMessage,16);
var k = bigInt.randBetween("1", n.subtract(1));
var r = bigInt("0");
var s = bigInt("0");
while(s.equals("0")){
r = bigInt("0");
while(r.equals("0")){
k = bigInt.randBetween("1", n.subtract(1));
r = bigInt(bigInt(k.multiply(g)).mod(p)).mod(n);
}
var kInverse = k.modInv(n);
var pr = privateKey.multiply(r);
hashedMessage = hashedMessage.add(pr);
kInverse = kInverse.multiply(hashedMessage);
s = kInverse.mod(n);
}
return [r.toString(),s.toString()];
}
var validateSignature = function(hashedMessage, signature){
hashedMessage = bigInt(hashedMessage,16);
var r = bigInt(signature[0]);
var s = bigInt(signature[1]);
var w = s.modInv(n);
var u1 = bigInt(hashedMessage.multiply(w)).mod(n);
var u2 = bigInt(r.multiply(w)).mod(n);
var u1g = u1.multiply(g);
var u2pu = u2.multiply(publicKey);
var xCoord =u1g.add(u2pu);
var v = xCoord.mod(n);
if(v.equals(r))
return true;
return false;
}
但是,它仍然无法验证签名。希望它能使它更清晰。
答案 0 :(得分:0)
问题的一部分是g实际上不是数字,而是一个点
这是您所写内容的粗略翻译:
g = 55066263022277343669578718895168534326250603453777594175500187360389116729240
privateKey = 90436540941140970165633788406609967146985661161263948799654498545867952662296
k = <random number>
r = k*g%p%n
e = sha(m)
ki = k^-1%n
pr = privateKey*r
ki*e
s = ki%n
我对此做了一个实现,但是在过去的几周中,是这样的:
g = {
x: 55066263022277343669578718895168534326250603453777594175500187360389116729240,
y: 32670510020758816978083085130507043184471273380659243275938904335757337482424
}
k = <random number>
r = <random number>
e = sha(m)
privateKey = 90436540941140970165633788406609967146985661161263948799654498545867952662296
r = g * k
s = ((privateKey * r.x + e) * (k^-1%n)) % n
r = r.x
它可以帮助您了解点乘法的工作原理,请查看以下链接: https://github.com/Azero123/simple-js-ec-math
https://www.npmjs.com/package/simple-js-ec-math
https://eng.paxos.com/blockchain-101-foundational-math
也许还可以看看我的simple-js-ecdsa实现
请注意,您可能不应该使用sha1,因为它被认为是“官方不安全的”,并且有一些使用它的碰撞公式。也许尝试sha2或sha3