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?
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 Schoolbus
está firmada por la dirección 0xd1ade25ccd3d550a7eb532ac759cac7be09c2719
y la firma resultante es 0x2ac19db245478a06032e69cdbd2b54e648b78431d0a47bd1fbab18f79f820ba407466e37adbe9e84541cab97ab7d290f4a64a5825c876d22109f3bf813254e8601
.
Hasta aquí todo bien. Ahora, lo que me gustaría hacer es verificar usando ecrecover
que la firma sea correcta para la dirección y el dato dados. La cosa es que ecrecover
toma cuatro argumentos: ecrecover(h, v, r, s)
. Aparte de h
ser 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 ecrecover
devuelve 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 0x2ac19db245478a06032e69cdbd2b54e648b78431d0a47bd1fbab18f79f820ba407466e37adbe9e84541cab97ab7d290f4a64a5825c876d22109f3bf813254e8601
o 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?
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.
recovery
propiedad, me temo. Además, solo me aseguro: ¿es necesario el hash para ecrecover
sha256?ecrecover
que no funcionará sin pasar el valor correcto.¿Qué significan exactamente v, r y s?
r
es el R.x
valor del punto de la firma R
.s
es la prueba de la firma paraR.x
v
es un parámetro de recuperación utilizado para facilitar la verificación de la firma.v
no es obligatorio, pero a menudo se incluye. Pero que es v
?
Dado que la firma solo incluye la x
coordenada del punto R
, hay 0, 1, 2, 3 o 4 y
coordenadas 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..3
según las siguientes condiciones:
R.y
par y R.x
menor que el orden de la curva n
:recovery_id := 0
R.y
impar y R.x
menor que el orden de la curva n
:recovery_id := 1
R.y
par y R.x
mayor que el orden de la curva n
:recovery_id := 2
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. v
es simplemente v = recory_id + 27
para Bitcoin. Además de los v
valores de 27..30
que 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 v
de 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 + 27
parte que Bitcoin usó para evitar la protección de reproducción:
v = chain_id * 2 + 35 + recovery_id
En Ethereum, v
refleja 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 v
es 42.
chain_id = (v - 35) / 2
Ahora, podemos comprobar que el v
de 42 solo es válido en la cadena con ID 3 (Ropsten).
Lo que sé es que
ecrecover
devuelve 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 ecrecover
devuelve y address
es 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.
señorchico
arik
señorchico
arik
señorchico
arik
ecrecover
es, 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.arik
web3.toDecimal
yString.prototype.slice
. Estoy probando todas las respuestas en un contrato a medida que vienen.garen vartanian
ecrecover
hace. Compara el hash pasado con el mensaje hash descifrado de la firma para ver si coinciden, luego devuelve la dirección si es verdadera.