Wie kann ich eine secp256r1-Signatur mit Solidity überprüfen?

Es tut mir leid, wenn Sie diese Fragen für grundlegend halten, aber ich bin neu in der Verschlüsselung. Soweit ich weiß, hat Solidity eine ecrecoverFunktion für diesen Zweck, verwendet jedoch eine secp256k1Signatur. die ich verwenden möchte secp256r1. Ich habe die folgenden Schritte in diesem Kern verwendet , um zu erhaltenr,s, an v values.

Dann habe ich die gesamte secp256r1-Überprüfung von WIKIpedia wie folgt angewendet

 1. getting r,s, and v values. 
 2. verify that r, s are integers in [1,n-1].
 3. calculate the hashing of the message.
 4. calculate w = s^-1 mod n
 5. calculate the curve point (x1,y1) = u1 x G + u2 x Q

Hinweis: ecadd fügt eine Punktfunktion hinzu, die ich geschrieben habe. ecmul ist eine Multiplikationsfunktion, isPoint: prüft, ob der Punkt in der Kurve liegt oder nicht.

Meine Fragen sind,

1- Habe ich die fünf Schritte der Gleichung richtig geschrieben? Ich bin nicht von der 4. und 5. Stufe. Sie können den Code der Verifizierungsfunktion für weitere Details überprüfen.

2- wenn ich die Verifizierung überprüfen möchte. Ich sollte eine Nachricht und eine Unterschrift senden. muss ich mehr als True/False zur Überprüfung zurückgeben.

// testing signature function
// getting r, s, and v values from signature.
// steps would be as follows
// 1. getting r,s, and v values.
function ectest(bytes32 hash, bytes sig) returns (bool) {
    bytes32 r;
    bytes32 s;
    uint8 v;

    if (sig.length != 65)
      return (false, 0);

    // The signature format is a compact form of:
    //   {bytes32 r}{bytes32 s}{uint8 v}
    // Compact means, uint8 is not padded to 32 bytes.
assembly {
    r := mload(add(sig, 32))
    s := mload(add(sig, 64))

    // Here we are loading the last 32 bytes. We exploit the fact that
    // 'mload' will pad with zeroes if we overread.
    // There is no 'mload8' to do this, but that would be nicer.
    v := byte(0, mload(add(sig, 96)))

    // Alternative solution:
    // 'byte' is not working due to the Solidity parser, so lets
    // use the second best option, 'and'
    // v := and(mload(add(sig, 65)), 255)
}

// albeit non-transactional signatures are not specified by the YP, one would expect it
// to match the YP range of [27, 28]

if (v < 27)
  v += 27;

if (v != 27 && v != 28)
    return (false, 0);

// 2. verify that r, s are integers in [1,n-1] using isPoint function
if(isPoint(r,s) == false)
{
  return (false, 0);
}


//3. calculate the hashing of the message
e = sha3(msg);

//4. let v be the leftmost bits of msg
// calculate above in the assembly code
// v



      //5. calculate w = s^-1 mod n
      w  = invmod(s,n);
      // u1 = v * w mod n
      u1 = (v * w) % n ;
      // u2 = r * w mod n
      u2 = (r * w) % n;

      //6. calculate the curve point (x1,y1) = u1 x G + u2 x Q
      (x3,y3)=  ecmul(gx,gy,u1);
      (x4,y4)= ecmul(gx,gy,u2);

      (x1,y1) = ecadd(x3,y3,x4,y4);
      //7. check the validation
      if (r == x1)
      {
        return (true);
      }
    }// end function

}

Ich bin enttäuscht, dass niemand auf seine Frage eingeht. Die Leute nahmen an, dass er nach secp256k1 fragte.
Ah. Entschuldigung, nachdem ich den vorherigen Kommentar gelesen habe, sehe ich, dass er die secp256r1-Kurve haben möchte.

Antworten (4)

Dies ist eine wichtige Frage, da die ganze andere Welt (Handys, Smartcards, HSMs usw.) secp256r1 verwendet.

Es gibt einen Artikel unter http://blog.enuma.io/update/2016/11/01/a-tale-of-two-curves-hardware-signing-for-ethereum.html

aber leider sind die Codes, die die Funktionalität tatsächlich implementieren, verschwunden. Ich plane, dies aus dem Bytecode zurückzuentwickeln, aber es kann einige Zeit dauern ...

Es gibt eine reine Solidity-Implementierung von SECP256R1 / P256 / PRIME256V1 unter https://github.com/tdrerup/elliptic-curve-solidity .

Der Hauptnachteil ist wahrscheinlich, dass die Überprüfung einer nicht-nativen Signatur in Solidity ziemlich teuer ist. Das Repo enthält einige Trüffeltests, die hilfreich sein sollten, um die Formatierung der Variablen zu verstehen.

Seien Sie vorsichtig, wenn Sie die Sign-Funktion von web3js verwenden, da sie vor dem Signieren einige seltsame Präfixe vornimmt.

Ich habe ein Tutorial zum Signieren und Verifizieren von Daten mit solidity und web3js erstellt .

1) Die ecrecoverFunktion ist in Solidity integriert, sodass Sie all diese Schritte nicht benötigen.

2) Es hängt wirklich davon ab, was Sie damit machen. Denken Sie daran, wenn Sie eine Nachricht signieren (z. B. eth_personalSign), dass der signierten Nachricht ein Nachrichtenpräfix vorangestellt ist, die Zeichenfolge „\x19Ethereum Signed Message:\n“, gefolgt von der Länge der Nachricht.

Die Verwendung ecrecoverist anfangs etwas kompliziert, aber sobald Sie es beherrschen, steht Ihnen eine erstaunliche Welt voller Möglichkeiten zur Verfügung.


Beispiel Soliditätsvertrag:

contract Foobar {
    function checkSignature(bytes32 digest, uint8 v, bytes32 r, byres32 s) constant returns (address signer) {
        return ecrecover(digest, v, r, s);
    }
}

Beispiel-JavaScript:

var ethers = require('ethers');

var privateKey = "0x0123456789012345678901234567890123456789012345678901234567890123";
var signingKey = new ethers.SigningKey(privateKey);
// SigningKey {
//    privateKey: '0x0123456789012345678901234567890123456789012345678901234567890123',
//    publicKey: '0x026655feed4d214c261e0a6b554395596f1f1476a77d999560e5a8df9b8a1a3515',
//    address: '0x14791697260E4c9A71f18484C9f997B308e59325',
// }

// The id function computes the keccak256 of a utf-8 string
var digest = ethers.utils.id("Hello World);
// '0x592fa743889fc7f92ac2a37bb1f5ba1daf2a5c84741ca0e0061d243a2e6707ba'

var sig = signingKey.signMessage(digest);
// { 
//    recoveryParam: 0,
//    r: '0x79f56f3422dc67f57b2aeeb0b20295a99ec90420b203177f83d419c98beda7fe',
//    s: '0x1a9d05433883bdc7e6d882740f4ea7921ef458a61b2cfe6197c2bb1bc47236fd'
// }

var contract = new ethers.Contract( ... )

// The v needs 27 added to it; this is legacy from a Bitcoin standard
var req = contract.checkSig(digest, sig.recoveryParam + 27, sig.r, sig.s);

// Call the Solidity function
req.then(function(signer) {
    console.log(signer);
    // "0x14791697260E4c9A71f18484C9f997B308e59325"
});

Beispiel aus der realen Welt:

Hier ist eine schnelle Sticker-Registrierung, die ich für die Firefly-Sticker-Werbekampagne erstellt habe. Jeder Aufkleber wird prozedural generiert und ist einzigartig und hatte auf der Rückseite einen privaten Schlüssel, der zum Einlösen des Aufklebers verwendet werden konnte. Aber der private Schlüssel hat kein Geld. Stattdessen verwendet ein Benutzer sein eigenes Geld, um das Gas zu bezahlen, um eine Nachricht zu senden, die mit dem privaten Schlüssel des Aufklebers signiert ist. Der Vertrag verifiziert, dass der Aufkleber gültig ist, indem ecrecoverder Aufkleber in einem Merkle-Baum nachgeschlagen wird, und der Aufkleber wird dann an den Benutzer übertragen.

https://etherscan.io/address/0xb90e64082d00437e65a76d4c8187596bc213480a#code

ecrecovererwartet Ed25519Unterschriften, glaube ich