Diferencia entre mensaje de firma y transacción de firma

Usando "Firmar mensaje" se puede probar la propiedad de una dirección.
Esto sucede al firmar una cadena legible por humanos usando la clave privada que pertenece a la dirección.
Luego, el propietario proporciona la dirección, el mensaje y la firma, y ​​cualquiera puede verificar que efectivamente posee la clave privada de la dirección.
La firma ECDSA normalmente se proporciona en formato de 65 bytes ( Recovery byte + 32-byte R + 32-byte S) y codificada en base64.

Sin embargo, también existe otro tipo de firma, que se utiliza para "Firmar Transacción" .
Para cada entrada de una transacción, hay algunos datos para firmar. Estos datos son datos binarios, normalmente proporcionados en formato hexadecimal.
La firma correspondiente se proporciona en formato DER de 70, 71 o 72 bytes.

En ambos casos, el mensaje (cadena de mensaje en el primer caso y datos binarios por entrada en el segundo caso) se transforma en una matriz de bytes y la clave privada se usa para generar una firma ECDSA para esa matriz de bytes de mensaje.
El formato de salida es diferente, pero el formato de 65 bytes se puede convertir fácilmente a DER.

En consecuencia, pensé que podría usar "Firmar mensaje" (con una modificación menor, de modo que se necesita una cadena hexadecimal en lugar de una cadena ASCII/UTF-8) para firmar los datos binarios por entrada de una transacción con codificación hexadecimal.
Hice eso, convertí la firma a formato DER e intenté enviar la transacción, pero no funcionó, porque la firma estaba mal.

Entonces mi pregunta es, ¿cuál es la diferencia entre cómo "Firmar mensaje" y "Firmar transacción" generan firmas y por qué no son compatibles?

¿Es la diferencia que para "Firmar mensaje" , primero se crea un resumen, que luego se firma, mientras que para "Firmar transacción" (en el significado escrito anteriormente), la entrada ya es un resumen, por lo que no debe volver a codificarse? ?

¡Gracias!

Respuestas (2)

¿Es la diferencia que para "Firmar mensaje", primero se crea un resumen, que luego se firma, mientras que para "Firmar transacción" (en el significado escrito anteriormente), la entrada ya es un resumen, por lo que no debe volver a codificarse? ?

No. No tiene nada que ver con el hashing. Además, la entrada aún no es un resumen, se debe codificar antes de firmar. Tanto el mensaje como los datos de entrada se codifican dos veces con SHA256.

La diferencia entre la firma de mensajes y la firma de entrada de transacciones es que la firma de mensajes antepone la cadena Bitcoin Signed Message:\n(que \nes un carácter de nueva línea, no literalmente \n) al mensaje antes de que se convierta en hash.

Además, la firma de 65 bytes producida por la firma de mensajes tiene un byte al principio que no forma parte de la firma criptográfica en sí. En cambio, es una identificación de recuperación para que la clave pública correcta pueda recuperarse de la firma durante la verificación del mensaje firmado. En las firmas de transacciones, hay un byte diferente adjunto al final de la firma que es del tipo sighash, por lo general es el byte 0x01.

Gracias, @andrew. Escribes que en la firma de 65 bytes hay un byte de recuperación al final. El byte de recuperación está al principio (como se menciona en mi pregunta anterior). Además, ¿en qué firmas TX hay un byte adicional al final? En formato DER, hay otros bytes específicos de DER, pero no relacionados con signhash. Traté de mantener mi pregunta genérica, pero tal vez debería haber mencionado que la entrada TX que quiero firmar es toSign de BlockCypher . Creo que ya es un resumen, por lo que solo necesita ser firmado.
Mi mal, el byte de recuperación es de hecho al principio. Si decodificas correctamente con DER una firma que colocas en una transacción (o una firma que obtienes de una transacción), encontrarás que hay un byte extra al final. Ese byte corresponde al tipo sighash.
Cabe señalar que la "cadena mágica" antepuesta incluye un byte de codificador de tamaño prefijado, de modo que lee "\x18Bitcoin Signed Message:\n" (Esto es diferente del byte de recuperación en la firma)

@andrew proporcionó información útil de que una gran diferencia entre "Firmar mensaje" y "Firmar transacción" es que "Firmar mensaje" antepone internamente una cadena personalizada al mensaje de texto que se firma.
Además, su respuesta aborda el caso cuando realiza todos los pasos de la creación y firma de TX.

Traté de mantener mi pregunta inicial genérica, pero ahora veo que debería haber mencionado que los datos de TX por entrada que quiero firmar son la matriz toSign de BlockCypher .
En su documentación no está claro de inmediato, pero con un poco de investigación, descubrí que las toSigncadenas hexadecimales proporcionadas ya están codificadas dos veces con SHA256, por lo que, de hecho, solo necesitan estar firmadas.
Probablemente también haya otros sistemas que proporcionen dichos resúmenes para firmar.

Entonces, en resumen, si está utilizando un sistema externo para crear TX, que le proporciona datos para firmar con su clave privada, es posible que esos datos ya estén cifrados. Un buen indicador de dicho resumen es que tiene una longitud de 32 bytes.
Hay varias razones por las que "Firmar mensaje" no funcionará de inmediato para firmar dichos datos de TX:

  • Los datos de TX son datos binarios (generalmente en formato hexadecimal) y "Sign Message" espera cadenas ASCII/UTF-8.
  • "Firmar mensaje" agrega internamente un prefijo personalizado al mensaje que se firma.
  • Los datos de TX ya están cifrados, por lo que no deberían volver a codificarse.
  • El resultado de "Sign Message" es una firma ECDSA de 65 bytes y no está en formato DER (se puede convertir fácilmente).

Sin embargo, la firma real es la misma tanto para "Firmar mensaje" como para "Firmar transacción" .

Con suerte, esto ahorrará algo de tiempo de investigación para otros con un caso de uso similar.