[Ethereum] How to verify a secp256r1 signature using solidity

cryptographyecdsaprotocolsignaturesolidity

Sorry if you find these questions are basic, but I am new to encryption. As far as I know, Solidity have ecrecover function for this purpose, but it use secp256k1 signature. which I am intend to use secp256r1. I used the following steps in this gist to get r,s, an v values.

Then I applied all secp256r1 verification from WIKIpedia as follow

 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

Hint: ecadd is adding point function I wrote. ecmul is a multiplication function, isPoint: check if the point is in the curve or not.

My questions are,

1- do I wrote the five steps of the equation correctly; I am not of the 4th and 5th steps. You can check the code of the verification function for further details.

2- if I want to check the verification. I should send a message and a signature. do I need to return more than True/False for verification.

// 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

}

Best Answer

This is an imporant question, since all of the other world (mobile, smartcards, HSM's etc) uses secp256r1.

There's an article at http://blog.enuma.io/update/2016/11/01/a-tale-of-two-curves-hardware-signing-for-ethereum.html

but unfortunately the codes actually implementing the functionality have disappeared. Planning to reverse engineer this from the bytecode, but it might take some time...

Related Topic