ECDSA: (v, r, s), ¿qué es v?

La firma determinista de un Tx con RFC6979 devuelve v, r, s, donde ry sson los 2 valores utilizados en las firmas ECDSA estándar. v = 27 + (y % 2), entonces 27 + la paridad de r, como indica pybitcointools .

Entonces, para pares , robtenemos v = 27impares r.v = 28

¿Qué importancia tiene el valor de v(27 o 28)? ¿Por qué es necesario tener un vvalor? Además, ¿por qué es 27?

Parece ser una especie de byte de versión, similar al byte de versión utilizado en la codificación de direcciones. No estoy seguro del significado de 27/28.
Tu enlace a github está roto; Lo arreglaría, pero aparentemente necesito cambiar al menos 6 caracteres para que sea una edición válida.
@DavidGrayson Enlace arreglado. Tal vez Peter Wuille pueda comentar, ya que creo que he leído que 27 se eligió arbitrariamente porque estaba "a medio camino" entre las opciones de bytes de la versión usada, aunque no puedo encontrar esa fuente para mí.
Eso es correcto. Fue una elección arbitraria para un número en ese momento, porque necesitábamos un byte para transmitir información de recuperación de clave pública. Intentaré escribir una respuesta completa más tarde.

Respuestas (4)

Esto no tiene nada que ver con RFC6979, sino con la firma ECDSA y la recuperación de clave pública.

La (r, s) es la salida normal de una firma ECDSA, donde r se calcula como la coordenada X de un punto R, módulo el orden de la curva n.

En Bitcoin, para las firmas de mensajes, usamos un truco llamado recuperación de clave pública. El hecho es que si tiene el punto R completo (no solo su coordenada X) y s, y un mensaje, puede calcular para qué clave pública sería una firma válida. Lo que esto permite es 'verificar' un mensaje con una dirección, sin necesidad de conocer la clave completa (simplemente recuperamos la clave pública en la firma y luego procesamos la clave recuperada y la comparamos con la dirección).

Sin embargo, esto significa que necesitamos las coordenadas R completas. Puede haber hasta 4 puntos diferentes con un "módulo n de coordenadas X" dado. (2 porque cada coordenada X tiene dos coordenadas Y posibles, y 2 porque r+n aún puede ser una coordenada X válida). A ese número entre 0 y 3 lo llamamos ID de recuperación o recid. Por lo tanto, devolvemos un byte adicional, que también funciona como un byte de encabezado, usando 27+recid (para claves públicas recuperadas sin comprimir) o 31+recid (para claves públicas recuperadas comprimidas).

Estrictamente hablando, el recid no es necesario, ya que podemos recorrer todos los pares de coordenadas posibles y verificar si alguno de ellos coincide con la firma. El recid simplemente acelera esta verificación.

En general, si h es el cofactor, el número máximo de puntos diferentes con el "módulo n de coordenadas X" dado será 2 (h + 1). En el caso de secp256k1, que tiene el cofactor 1, obtenemos 2(1+1) = 4.

¿Puedes vincular al código que implementa esto? Voy a empezar a aprender C++ usando funciones como esta que entiendo
El código de firma está en libsecp256k1, que también tiene un código de verificación, pero que no se usa actualmente. Para la verificación, hay un código C en Bitcoin Core (consulte pubkey.cpp) que realiza una serie de llamadas OpenSSL para realizar la mayor parte del trabajo. No estoy seguro de que leer código C criptográfico sea la mejor manera de aprender C++ :)
Es más una forma de aprender cosas que ya entiendo bastante bien y que me interesan. Aprendí Python de esa manera y el objetivo final es conocer el software central también.
@PeterWuille There can be up to 4 different points with a given "X coordinate modulo n". (2 because each X coordinate has two possible Y coordinates, and 2 because r+n may still be a valid X coordinate).Entiendo lo primero (2 valores y para cada x, debido a la simetría)... Pero, ¿cómo funciona lo último? es decir r+n may still be a valid X coordinate??
Las coordenadas X e Y son números módulo p, el tamaño del campo, que es alrededor de 2^256 - 2^32 para secp256k1. Sin embargo, el valor r y s en la firma son módulo n, el orden del grupo, que es alrededor de 2^256 - 2^128. Cuando Rx está entre n y p, r se reduce a Rx-n. Por lo tanto, si tiene un valor r por debajo de 2^128-2^32, puede haber 2 valores Rx válidos correspondientes.
@PieterWuille: ¿es esto específico para secp2561k, o se puede generalizar para todas las firmas de curvas elípticas? Además, ¿cómo se relaciona con esta respuesta en crypto SE - crypto.stackexchange.com/questions/18105/… ?
ECDSA siempre es compatible con la clave pública, independientemente de la curva. Para curvas con cofactor > 1 es un poco más complicado. Esa respuesta vinculada explica el procedimiento.
¿Cuál, por favor, de las 4 posibles salidas (27..30) corresponde a cuál de los posibles resultados? Por ejemplo: 0 = positivo Y y X1? donde esta documentado esto?
@Sentinel Puede obtener información completa sobre el método de recuperación aquí: secg.org/sec1-v2.pdf
27 = menor X par Y. 28 = menor X impar Y. 29 = mayor X par Y. 30 = mayor X impar Y. Tenga en cuenta que 29 y 30 son extremadamente raros y, en la práctica, solo se verán en ejemplos generados específicamente. Solo hay dos posibles valores de X si r está entre 1 y (p mod n), lo que tiene una probabilidad de aproximadamente 0,000000000000000000000000000000000000373 % de que suceda aleatoriamente.
@Souza / Pieter - Gracias. Ya había logrado descubrir la respuesta a eso, ¡me tomó una eternidad! De hecho, encontré ese ASN.1 en sec1-v2.pdf después de una enorme cantidad de excavación. Cuando lo encontré, pensé que había encontrado oro. El problema es que la documentación de Ethereum (estoy implementando un cliente ligero de Ethereum) no incluye información detallada del protocolo, y las implementaciones oficiales tienden a depender de bibliotecas que van donde Bitcoin ya pisó, por lo que detalles como el parámetro 'v' se pierden/se entierran en un código muy, muy oscuro.
@Sentinel mi lucha es la misma. Estoy trabajando sobre el protocolo de Ethereum y dicen poco o nada sobre esto. Y tienes razón, ambos usan libsecp256k1.
@Souza - de acuerdo. es una lucha Estoy tratando de contactar a la fundación Ethereum para reunir documentación de protocolo accesible y obtener fondos para hacerlo. Estoy armando un cliente ligero usando extensiones reactivas y .NET, donde trato todos los mensajes de protocolo como flujos que fluyen a través de adaptadores de capa de pila, y trato de aislar el protocolo de nivel superior de las diferencias de nivel inferior (discv4 vs v5, etc. por ejemplo) . Para cuando termine, debería ser capaz de escribir un libro sobre ello.

No creo que la v que describe sea parte de RFC6979 porque no puedo encontrarla en ese documento. Esta v es parte de la ecdsa_raw_signfunción de signo sin formato en pybitcointools, que llama a deterministic_generate_k, que es una implementación de RFC6979.

RFC6979 solo lo ayuda a generar un valor k determinista para firmar. No te ayuda a generar r y s . Para generar r y s , solo usa el algoritmo ECDSA normal; no tiene que consultar RFC6979 después de haberlo usado para generar k . RFC6979 genera k , que es una entrada al algoritmo de firma que puede generar r y s .

Correcto, pero ¿ vaparece en todas las implementaciones? Pybitcointools no es la única implementación que lo usa, creo.
La única otra implementación que he visto es libsecp256k1 , que no devuelve un número av. Esa biblioteca proporciona una función llamada secp256k1_nonce_function_rfc6979cuya única salida es un búfer de datos de 32 bytes.
secp256k1_ecdsa_sign_compact (API antigua) o secp256k1_pubkey_serialize_compact (API nueva) devuelven el ID de recuperación (el valor v, pero sin el término constante 27). Mira mi respuesta.
Sí, vtiene que ver con la firma, no con RFC6979.
@DavidGrayson sí, he modificado el título :)

Como ya se describe en todas las demás respuestas: vse requiere recuperar la clave pública correcta para una firma porque a veces (incluso con baja probabilidad) hay más de una clave pública válida para ser recuperada por una firma.

Aquí hay una hoja de trucos:

  • 27clave pública sin comprimir, paridad y 0, magnitud xinferior al orden de la curva
  • 28clave pública sin comprimir, paridad y 1, magnitud xinferior al orden de la curva
  • 29clave pública sin comprimir, paridad y 0, magnitud x mayor que el orden de la curva
  • 30clave pública sin comprimir, paridad y 1, magnitud x mayor que el orden de la curva
  • 31 clave pública comprimida0 , paridad y , magnitud xinferior al orden de la curva
  • 32 clave pública comprimida1 , paridad y , magnitud xinferior al orden de la curva
  • 33 clave pública comprimida0 , paridad y , magnitud x mayor que el orden de la curva
  • 34 clave pública comprimida1 , paridad y , magnitud x mayor que el orden de la curva

Para cualquiera v >= 35que pueda estar tratando con firmas de Ethereum según EIP-155 :

v = recovery_id + CHAIN_ID * 2 + 35

ves necesario para recuperar la clave pública. Como resultado de recuperar la clave pública de la firma ECDSA, se pueden devolver 0, 1 o 2 puntos. Para indicar estrictamente qué punto corresponde a la clave pública "original", se utiliza un byte adicional