¿Cómo puedo verificar una firma secp256r1 usando solidez?

Lo siento si encuentra que estas preguntas son básicas, pero soy nuevo en el cifrado. Hasta donde yo sé, Solidity tiene una ecrecoverfunción para este propósito, pero usa secp256k1firma. que tengo la intención de usar secp256r1. Utilicé los siguientes pasos en esta esencia para obtenerr,s, an v values.

Luego apliqué toda la verificación secp256r1 de WIKIpedia de la siguiente manera

 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

Sugerencia: ecadd está agregando la función de punto que escribí. ecmul es una función de multiplicación, isPoint: verifica si el punto está en la curva o no.

Mis preguntas son,

1- ¿Escribí correctamente los cinco pasos de la ecuación? No soy de los pasos 4 y 5. Puede consultar el código de la función de verificación para obtener más detalles.

2- si quiero comprobar la verificación. Debería enviar un mensaje y una firma. ¿Necesito devolver más de Verdadero/Falso para la verificación?

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

}

Me decepciona que nadie responda a su pregunta. La gente asumió que estaba preguntando por secp256k1.
ah Lo siento, después de leer el comentario anterior, veo que quiere la curva secp256r1.

Respuestas (4)

Esta es una pregunta importante, ya que todo el resto del mundo (móviles, tarjetas inteligentes, HSM, etc.) usa secp256r1.

Hay un artículo en http://blog.enuma.io/update/2016/11/01/a-tale-of-two-curves-hardware-signing-for-ethereum.html

pero desafortunadamente los códigos que realmente implementan la funcionalidad han desaparecido. Planeando aplicar ingeniería inversa a esto desde el código de bytes, pero podría llevar algo de tiempo...

Hay una implementación de solidez pura de SECP256R1/P256/PRIME256V1 en https://github.com/tdrerup/elliptic-curve-solidity .

El principal inconveniente es probablemente que verificar una firma no nativa en Solidity es bastante costoso. El repositorio incluye algunas pruebas de trufa que deberían ser útiles para comprender el formato de las variables.

Tenga cuidado cuando use la función de firma de web3js porque hace algunos prefijos extraños antes de firmar.

Hice un tutorial sobre cómo firmar y verificar datos con solidity y web3js .

1) La ecrecoverfunción está integrada en la solidez, por lo que no necesita todos esos pasos.

2) Realmente depende de lo que estés haciendo con él. Tenga en cuenta que si está firmando un mensaje (es decir, eth_personalSign), hay un prefijo de mensaje antepuesto al mensaje firmado, la cadena "\x19Ethereum Signed Message:\n" seguido de la longitud del mensaje.

Su uso ecrecoveres un poco complicado al principio, pero una vez que lo dominas, un asombroso mundo de posibilidades está al alcance de tu mano.


Ejemplo de Contrato de Solidez:

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

JavaScript de ejemplo:

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"
});

Ejemplo del mundo real:

Aquí hay un registro rápido de calcomanías que creé para la campaña promocional de calcomanías Firefly. Cada calcomanía se genera de manera procesal y es única, y tenía una clave privada en la parte posterior, que podía usarse para canjear la calcomanía. Pero la clave privada no tiene fondos. En cambio, un usuario usa sus propios fondos para pagar la gasolina y enviar un mensaje firmado con la clave privada de la etiqueta. El contrato verifica que la etiqueta es válida usando ecrecovery buscando la etiqueta en un árbol merkle y luego la etiqueta se transfiere al usuario.

https://etherscan.io/address/0xb90e64082d00437e65a76d4c8187596bc213480a#código

ecrecoverespera Ed25519firmas creo