У меня есть некоторый код ниже, который будет использоваться для проверки подлинности сообщения с использованием JavaScript. Генерация пары ключей с использованием эллиптической кривой secp256k1 довольно проста, однако я не понимаю, почему моя реализация подписи не работает (почему сообщение не проверяется успешно). Вот мой код:
https://pastebin.com/k1WT6apV
/**
* 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
Что не так с моей реализацией? Я что-то пропустил? Я сделал что-то не так?
EDIT:
После некоторой ревизии я придумал следующее:
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;
}
Однако проверить подпись по-прежнему не удается. Надеюсь, это немного прояснит ситуацию.