Ethereum ecrecover verificación de firma y encriptación

La cuestión de firmar y verificar firmas con Solidity se ha planteado en estas preguntas, las cuales he tratado de estudiar:

¿Cómo puedo firmar un dato con la clave privada de una dirección de Ethereum?

¿Cómo puedo verificar una firma criptográfica que fue producida por un par de claves de direcciones de Ethereum?

Sin embargo, todavía hay piezas de información que parece que me faltan.

En primer lugar, me gustaría comenzar con la pregunta sobre la firma. En el ejemplo, la cadena Schoolbusestá firmada por la dirección 0xd1ade25ccd3d550a7eb532ac759cac7be09c2719y la firma resultante es 0x2ac19db245478a06032e69cdbd2b54e648b78431d0a47bd1fbab18f79f820ba407466e37adbe9e84541cab97ab7d290f4a64a5825c876d22109f3bf813254e8601.

Hasta aquí todo bien. Ahora, lo que me gustaría hacer es verificar usando ecrecoverque la firma sea correcta para la dirección y el dato dados. La cosa es que ecrecovertoma cuatro argumentos: ecrecover(h, v, r, s). Aparte de hser el hash, y de {v, r, s}alguna manera comprender la firma, ¿qué significan exactamente v, r y s? ¿Y cómo obtengo todos los valores necesarios de la cadena única 0x2ac19db245478a06032e69cdbd2b54e648b78431d0a47bd1fbab18f79f820ba407466e37adbe9e84541cab97ab7d290f4a64a5825c876d22109f3bf813254e8601?

Lo que sé es que ecrecoverdevuelve una dirección y verificar una firma es esencialmente una cuestión de comparar la dirección resultante con la esperada. Sin embargo, todo el procedimiento parece innecesariamente complicado.

Aparte de esto, también me preguntaba cómo podría producir una firma, ya sea como esta 0x2ac19db245478a06032e69cdbd2b54e648b78431d0a47bd1fbab18f79f820ba407466e37adbe9e84541cab97ab7d290f4a64a5825c876d22109f3bf813254e8601o un conjunto de {h, v, r, s}usar Solidity solo, sin el desvío RPC-JSON como es el caso en la pregunta, ¿siempre que sepa una clave privada?

Visite ethereum.stackexchange.com/questions/1777/… Aquí también enumero el procedimiento para extraer r, v y s de la cadena de firma. Acepto que este procedimiento es demasiado complicado y expresé este problema aquí: github.com/ethereum/EIPs/issues/79
Me temo que la pregunta en cuestión no está en Solidity. Lo que estoy tratando de lograr tiene que ser ejecutado dentro de un contrato.
¿Puede explicar un poco por qué querría firmar algo dentro de un contrato? Como se ha mencionado, esto expondrá la clave privada del firmante a todos.
Simplemente quiero verificar una firma en el formato especificado anteriormente dentro de un contrato. La parte de firma sería solo para pruebas unitarias.
El procedimiento de verificación se realiza en un contrato de solidez en la pregunta que vinculé a
La llamada a ecrecoveres, sí. Pero no tengo un entorno de ejecución en JavaScript que lo rodee que pueda preparar la cadena de firma en los componentes separados antes de introducirlo en un contrato de Solidity. El contrato en sí tiene que ser capaz de manejar la cadena de firma sin procesar.
En principio, posiblemente solo esté buscando los equivalentes de Solidez de web3.toDecimaly String.prototype.slice. Estoy probando todas las respuestas en un contrato a medida que vienen.
@arik "verificar una firma es esencialmente una cuestión de comparar la dirección resultante con la esperada" no es lo que ecrecoverhace. Compara el hash pasado con el mensaje hash descifrado de la firma para ver si coinciden, luego devuelve la dirección si es verdadera.

Respuestas (2)

v, r y s son parámetros que se pueden analizar a partir de la firma. Aquí hay un buen ejemplo de la biblioteca utils de ethereumjs:

  var sig = secp256k1.sign(msgHash, privateKey)
  var ret = {}
  ret.r = sig.signature.slice(0, 32)
  ret.s = sig.signature.slice(32, 64)
  ret.v = sig.recovery + 27

Tenga en cuenta cómo puede analizar cada valor de una firma determinada.

Aunque puede firmar dos mensajes diferentes con la misma clave privada, el proceso de firma (internamente) genera un valor nonce aleatorio (k) que se usa como parte del cálculo y debe ser diferente para cada firma generada.

r y s junto con la clave pública asociada ayudan a validar si la firma es legítima.

Nota: no soy criptógrafo. Esto es lo que he desenterrado tratando de responder las mismas preguntas que tienes. Sugeriría mirar algunos de los recursos en línea para curvas elípticas.

Aside from this, I was also wondering how I could produce a signature, either like this 0x2ac19db245478a06032e69cdbd2b54e648b78431d0a47bd1fbab18f79f820ba407466e37adbe9e84541cab97ab7d290f4a64a5825c876d22109f3bf813254e8601 or a set of {h, v, r, s} using Solidity alone, without the RPC-JSON detour as is the case in the question – siempre que sepa una clave privada?

El problema que tendría al generar una firma desde Solidity es que tendría que exponer la clave privada. Alternativamente, podría generar una firma fuera del proceso de transacción normal de Ethereum utilizando una de las muchas bibliotecas de curvas elípticas y enviar esa firma resultante a un contrato.

¡Gracias por la respuesta! Ahora, si solo tengo la cadena de firma, ¿cómo obtengo el objeto de firma? La cadena de firma en sí no contiene una recoverypropiedad, me temo. Además, solo me aseguro: ¿es necesario el hash para ecrecoversha256?
¿Hay alguna forma de volver a calcular v? Me temo ecrecoverque no funcionará sin pasar el valor correcto.
IIUC cuando una firma está codificada en DER, solo almacena los puntos r y s, y descarta "v". Cuando quiero proporcionar un valor "v", simplemente pruebo ambos. Entonces, donde pubkey_decompressed es la clave pública que creó la dirección ethereum: v_but_not_really, r, s = bitcoin.der_decode_sig(sig) for possible_v en [27, 28]: possible_pub = bitcoin.encode_pubkey(bitcoin.ecdsa_raw_recover(msg_hash, (possible_v, r , s)), 'hex') si pubkey_descomprimido == posible_pub: devuelve posible_v
En la cadena que se devuelve cuando se usa eth.sign, se incluye v. Los dos últimos caracteres hexadecimales representan v. Más sobre esto aquí: ethereum.stackexchange.com/questions/1777/…
para llevar a cabo este proceso de firma, ¿qué cliente o qué entorno necesito? " var sig = secp256k1.sign(msgHash, privateKey) var ret = {} ret.r = sig.signature.slice(0, 32) ret.s = sig.signature.slice(32, 64) ret.v = sig .recuperación + 27"

¿Qué significan exactamente v, r y s?

  • res el R.xvalor del punto de la firma R.
  • ses la prueba de la firma paraR.x
  • ves un parámetro de recuperación utilizado para facilitar la verificación de la firma.

vno es obligatorio, pero a menudo se incluye. Pero que es v?

Dado que la firma solo incluye la xcoordenada del punto R, hay 0, 1, 2, 3 o 4 ycoordenadas coincidentes sobre la curva elíptica Secp256k1. Estos cuatro candidatos potenciales están codificados en algo llamado recovery_id.

Un ID de recuperación puede tener los valores 0..3según las siguientes condiciones:

  • Es R.ypar y R.xmenor que el orden de la curva n:recovery_id := 0
  • Es R.y impar y R.xmenor que el orden de la curva n:recovery_id := 1
  • Es R.ypar y R.x mayor que el orden de la curva n:recovery_id := 2
  • Es R.y impar y R.x más que el orden de la curva n:recovery_id := 3

Ahora sabemos cómo llegar al ID de recuperación. ves simplemente v = recory_id + 27para Bitcoin. Además de los vvalores de 27..30que solo reflejan el ID de recuperación, también existe la noción de recuperar claves públicas comprimidas, usando el mismo ID de recuperación pero vde v = recovery_id + 31.

Pero no estamos hablando de Bitcoin, por lo que, por último, pero no menos importante, desea ver EIP-155 porque ya no usamos la + 27parte que Bitcoin usó para evitar la protección de reproducción:

v = chain_id * 2 + 35 + recovery_id

En Ethereum, vrefleja la cadena para la protección de reproducción y la identificación para la recuperación de la firma.

¿Y cómo obtengo todos los valores necesarios de la cadena única 0x2ac19db245478a06032e69cdbd2b54e648b78431d0a47bd1fbab18f79f820ba407466e37adbe9e84541cab97ab7d290f4a64a5825c876d22109f3bf813254e8601?

Esto es solo una cadena concatenada de "#{v}#{r}#{s}"with:

  • v = 0x2a
  • r = 0xc19db245478a06032e69cdbd2b54e648b78431d0a47bd1fbab18f79f820ba407
  • s = 0x466e37adbe9e84541cab97ab7d290f4a64a5825c876d22109f3bf813254e8601

El ves 42.

chain_id = (v - 35) / 2

Ahora, podemos comprobar que el vde 42 solo es válido en la cadena con ID 3 (Ropsten).

Lo que sé es que ecrecoverdevuelve una dirección y verificar una firma es esencialmente una cuestión de comparar la dirección resultante con la esperada. Sin embargo, todo el procedimiento parece innecesariamente complicado.

Sé que esto no es una pregunta, pero así es literalmente cómo funciona la criptografía de curva elíptica: son solo operaciones matemáticas con varios puntos en una curva.

Una dirección es solo una versión con un formato bonito de la clave pública; la clave pública es solo un punto en la curva elíptica Secp256k1.

Una firma es sólo otro punto. Y si haces magia de clave pública y magia de firma, al final de este proceso matemático pesado tienes dos puntos (claves públicas) y si son coincidencias exactas, la firma puede considerarse verificada .

Eso ecrecoverdevuelve y addresses solo para su conveniencia: puede comparar directamente si la dirección de la firma coincide con la dirección del firmante, y eso es mucho más fácil de hacer en Solidity en lugar de tratar con claves públicas sin comprimir.

Espero que esto arroje algo de luz sobre esta pregunta.