¿Por qué la firma siempre tiene 65 (1+32+32) bytes?

Una firma creada por el cliente Bitcoin-Qt siempre se puede decodificar (base64) en una matriz de 65 bytes. Esta matriz parece (según https://github.com/bitcoin/bitcoin/blob/master/src/key.cpp#L217 ) contener un byte de encabezado, una parte R de 32 bytes y una parte S de 32 bytes. .

He extraído algunos pares (R,S) de algunas firmas ECDSA codificadas en formato DER. Descubrí que R y S no tienen necesariamente un tamaño de 32 bytes. A veces pueden tener una longitud de 33 bytes. ¿Alguien podría decirme por qué la firma creada por el cliente Qt es siempre de 65 bytes, o si está bien convertir siempre R y S en una matriz de 32 bytes? Gracias.

Respuestas (1)

Se utilizan dos codificaciones diferentes.

Todo en el protocolo Bitcoin, incluidas las firmas de transacciones y las firmas de alerta , utiliza la codificación DER . Esto da como resultado firmas de 71 bytes (en promedio), ya que hay varios bytes de encabezado y los valores R y S son de longitud variable.

Para las firmas de mensajes , se usa una codificación personalizada que es más compacta (y más reciente) y admite la recuperación de claves públicas (dado un mensaje y una firma, encuentre qué clave pública lo habría creado). El código al que se refiere en la pregunta es para crear tales firmas.

Una firma codificada en DER correcta tiene la siguiente forma:

  • 0x30: un byte de encabezado que indica una estructura compuesta.
  • Un descriptor de longitud de 1 byte para todo lo que sigue.
  • 0x02: un byte de encabezado que indica un número entero.
  • Un descriptor de longitud de 1 byte para el valor R
  • La coordenada R, como un entero big-endian.
  • 0x02: un byte de encabezado que indica un número entero.
  • Un descriptor de longitud de 1 byte para el valor S.
  • La coordenada S, como un entero big-endian.

Donde los 0x00bytes iniciales para R y S no están permitidos, excepto cuando su primer byte estaría arriba 0x7F(en cuyo caso 0x00se requiere un solo al frente). También tenga en cuenta que dentro de las firmas de transacciones, un byte de tipo hash adicional sigue a los datos reales de la firma.

¡Gracias, Pieter! Ahora entiendo por qué podemos ignorar con seguridad el primer byte en los casos de 33 bytes.
¿Por qué no se permiten valores superiores a 0x7F en el primer byte de R o S? ¿Tal vez algo que ver con DER? Las firmas que se están imprimiendo para mí parecen tener el 0x00 delante de la R, S aproximadamente el 50 % del tiempo, de forma inconexa.
@StephenM347 Si el primer byte tiene su bit más alto establecido (> 0x7F), BER (del cual DER es una especialización) dice que debe interpretarse como un número negativo. OpenSSL, sabiendo que las firmas solo contienen números positivos, ignora esto, pero viola la especificación. A partir de la versión 0.8.0, Bitcoin Core requiere un cumplimiento estricto de DER para las firmas, aunque todo lo que acepta OpenSSL es válido en la cadena de bloques por ahora (aunque BIP62 propone convertirlo en una regla de red para requerir un DER estricto).
Muchas gracias. Una especie de deseo de que Satoshi hubiera usado los datos para R y S en la pila en lugar de todo este asunto de DER, ¡pero qué puedes hacer! :)
¿Puede ampliar más el formato personalizado? Estoy tratando de recrear el proceso de firma de QT. Sin embargo, C++ está mucho más allá de mi comprensión.
¿Qué tal en Schnorr Signature, si ambos valores (R, s) están incluidos en el campo de firma?
@CiscoMmu Sí, en las firmas BIP340, los primeros 32 bytes son la coordenada X de R (y la coordenada Y es implícitamente par), y los últimos 32 bytes son s.
gracias Pieter, estuve investigando durante algunos días (me pregunto por qué el valor de Public Nonce no se mencionó en ninguna parte), hasta que descubrí que la firma ECDSA en realidad consta de firma y Public Nonce. Supongo que es lo mismo con SCHNorr. por eso pregunto.