Firmar una transacción con openSSL

He leído un poco sobre la firma de una transacción usando openSSL, he intentado implementarlo pero parece que las firmas generadas no son aceptadas. Entonces me pregunto si los siguientes comandos proporcionan una firma válida.

Vamos a crear una clave privada: dd1cd59c4de2fa92e363dac282afe790a5193177d413b38e206b2b86b879ffbfY generar una dirección pública de testnet: mhZQtrhzjqkDmm8yp8jR2D84AagCdL4YzMY enviarle algo de testnet btc:a05f60a9679a1ad0ef57b092006b6c01886291a2ff696f5e2ac107b349594cf6

Crearemos una transacción que envíe el BTC a 2N8hwP1WmJrFF5QWABn38y63uYLhnJYJYTF.

Bien, entonces la transacción sin procesar sin firmar es: 01000000 01 f64c5949b307c12a5e6f69ffa2916288016c6b0092b057efd01a9a67a9605fa0 00000000 19 166749c16df955750990623397be66e965863611 ffffffff 01 70508e0600000000 1976a914a9974100aeee974a20cda9a2f545704a0ab54fdc88ac 00000000 01000000

Hacemos doble hash de la transacción sin procesar: 372f7f092abc73c2bcd357ec2b0dab4a9fdbb956771c676cf92a899feedcda0a. Y cree una clave PEM para openSSL (30740201010420 . private_key . a00706052b8104000aa144034200 . public_key y base64 it): -----BEGIN EC PRIVATE KEY----- MHQCAQEEIN0c1ZxN4vqS42PawoKv55ClGTF31BOzjiBrK4a4ef+/oAcGBSuBBAAK oUQDQgAEnQ9w7thTRcpcHARWO+0ZYIViw31kQGF4WoNujxmRVfKBih4mYfntUB2P kGYRiSCZqd5afqn2Qey03XW7tjwtWg== -----END EC PRIVATE KEY-----

Y luego uso el siguiente comando para crear la firma DER: echo "372f7f092abc73c2bcd357ec2b0dab4a9fdbb956771c676cf92a899feedcda0a" | openssl dgst -sha256 -hex -sign key.pem.

Agregando el byte de longitud y la clave pública, obtenemos el siguiente scriptSig: 46 304402203c8aaa41ae647149f70ce24f73109e99d59d7e54a5d854239943358d581e9f8302206336cb57c00bb78f46c881b3d6bb2ed76dc652eedf36064ae022ea4ae3ba3b100141049d0f70eed85345ca5c1c 04 563bed19608562c37d644061785a836e8f199155f2818a1e2661f9ed501d8f906611892099a9de5a7ea9f641ecb4dd75bbb63c2d5a.

Excelente. Esto nos deja con la siguiente transacción sin procesar: 01000000 01 f64c5949b307c12a5e6f69ffa2916288016c6b0092b057efd01a9a67a9605fa0 00000000 8a 47304402203c8aaa41ae647149f70ce24f73109e99d59d7e54a5d854239943358d581e9f8302206336cb57c00bb78f46c881b3d6bb2ed76dc652eedf36064ae022ea4ae3ba3b100141049d0f70eed85345ca5c1c04563bed19608562c37d644061785a836e8f199155f2818a1e2661f9ed501d8f906611892099a9de5a7ea9f641ecb4dd75bbb63c2d5a ffffffff 01 70508e0600000000 1976a914a9974100aeee974a20cda9a2f545704a0ab54fdc88ac 00000000

Lo cual, lamentablemente, no es una transacción válida (error recibido: PUSH TRANSACTION ERROR: 16: MANDATORY-SCRIPT-VERIFY-FLAG-FAILED (OPCODE MISSING OR NOT UNDERSTOOD)).

Usando una herramienta de transacción, obtengo la siguiente transacción sin procesar (válida), que pude canjear: 01000000 01 f64c5949b307c12a5e6f69ffa2916288016c6b0092b057efd01a9a67a9605fa0 00000000 8a 47304402204cdb6499578276106748c4877bf2a3381ba484fb621ce8d3faa2161254bdeec902205e3536aeaa65f8f0f55b3eb31a9bf8959b70e247c0ebd9da485e586370a25b900141 049d0f70eed85345ca5c1c04563bed19608562c37d644061785a836e8f199155f2818a1e2661f9ed501d8f906611892099a9de5a7ea9f641ecb4dd75bbb63c2d5a ffffffff 01 70508e0600000000 1976a914a9974100aeee974a20cda9a2f545704a0ab54fdc88ac 00000000

Todos los campos son correctos excepto la firma. ¿Por qué el comando de firma openSSL que utilicé era incorrecto?

¿La firma generada es válida? ¿Es válido el comando openSSL? ¿Podemos incluso usar openSSL para firmar una transacción?

Respuestas (1)

Si bien no he verificado la firma, al inspeccionar la codificación, creo que puedo ver qué está mal. Analicemos brevemente el scriptSig y le mostraré:

8a (total number of bytes to follow)
46 (the signature is 0x46 bytes long *THIS IS WHERE THE ISSUE IS*)
30 (compound DER type)
44 (0x44 bytes following)
02 (integer type)
20 (0x20 bytes long)
3c8aaa41ae647149f70ce24f73109e99d59d7e54a5d854239943358d581e9f83 (R value)
02 (integer type)
20 (0x20 bytes long)
6336cb57c00bb78f46c881b3d6bb2ed76dc652eedf36064ae022ea4ae3ba3b10 (S value)
01 (SIGHASH_ALL sighash type)
41 (length of public key is 0x41 bytes)
049d0f70eed85345ca5c1c04563bed19608562c37d644061785a836e8f199155f2818a1e2661f9ed501d8f906611892099a9de5a7ea9f641ecb4dd75bbb63c2d5a (public key)

Ahora he resaltado la longitud de la firma codificada DER como el problema: 46. Esto debería 47ser La razón es que se supone que esa longitud es la longitud de la firma más un byte para el tipo sighash . A diferencia de la firma DER normal producida por OpenSSL, Bitcoin requiere que se agregue el tipo sighash, en este caso 01para SIGHASH_ALL. Puede ver el 01byte presente. Pero no has actualizado la longitud. En la transacción válida debajo de ella, por otro lado, puede ver que la longitud es 47a pesar de que los campos tienen la misma longitud.

Así que intente actualizar el 46 a un 47 y vea si funciona :)

Tienes razón, calculé mal la longitud de la firma (no incluí el 01). Lo cambié e intenté enviarlo, pero aún no se acepta la firma.
¿Qué error tienes ahora? No puedo ayudar sin más información :)
Hola, recibo un error con respecto a las entradas (lo que sugiere un problema con la firma porque cuando intento volver a enviar la misma transacción sin procesar, aparece un error de que la transacción ya se transmitió).
¿Podría ser que lo vea como un gasto doble porque ya creó una transacción válida después? Asegúrese de que la otra transacción no se transmitió y elimínela de su mempool si está allí
Cuando la firma es válida, aparece un error de que la transacción ya se ha transmitido (bien), pero cuando no es válida, aparece un error diferente. Por lo tanto, sé que cuando mi firma aún no es válida. ¿Hay alguna forma de verificar mi firma (utilizando una herramienta en línea o algo así)?
No estoy seguro, no he visto uno antes que yo pueda recordar. Específicamente, ¿qué mensaje de error te da?