1

I've read a bit about signing a transaction using openSSL, I've tried implementing it but it seems like the signatures generated are not accepted. So I'm wondering if the following commands provide a valid signature.

Let's create a private key: dd1cd59c4de2fa92e363dac282afe790a5193177d413b38e206b2b86b879ffbf And generate a testnet public address: mhZQtrhzjqkDmm8yp8jR2D84AagCdL4YzM And send some testnet btc to it: a05f60a9679a1ad0ef57b092006b6c01886291a2ff696f5e2ac107b349594cf6

We will create a transaction that sends the BTC to 2N8hwP1WmJrFF5QWABn38y63uYLhnJYJYTF.

Okay, so the unsigned raw transaction is: 01000000 01 f64c5949b307c12a5e6f69ffa2916288016c6b0092b057efd01a9a67a9605fa0 00000000 19 166749c16df955750990623397be66e965863611 ffffffff 01 70508e0600000000 1976a914a9974100aeee974a20cda9a2f545704a0ab54fdc88ac 00000000 01000000

We double hash the raw transaction: 372f7f092abc73c2bcd357ec2b0dab4a9fdbb956771c676cf92a899feedcda0a. And create a PEM key for openSSL (30740201010420 . private_key . a00706052b8104000aa144034200 . public_key and base64 it): -----BEGIN EC PRIVATE KEY----- MHQCAQEEIN0c1ZxN4vqS42PawoKv55ClGTF31BOzjiBrK4a4ef+/oAcGBSuBBAAK oUQDQgAEnQ9w7thTRcpcHARWO+0ZYIViw31kQGF4WoNujxmRVfKBih4mYfntUB2P kGYRiSCZqd5afqn2Qey03XW7tjwtWg== -----END EC PRIVATE KEY-----

And then I use the following command to create the DER sig: echo "372f7f092abc73c2bcd357ec2b0dab4a9fdbb956771c676cf92a899feedcda0a" | openssl dgst -sha256 -hex -sign key.pem.

Adding the length byte and public key, we end up with the following scriptSig: 46 304402203c8aaa41ae647149f70ce24f73109e99d59d7e54a5d854239943358d581e9f8302206336cb57c00bb78f46c881b3d6bb2ed76dc652eedf36064ae022ea4ae3ba3b100141049d0f70eed85345ca5c1c 04 563bed19608562c37d644061785a836e8f199155f2818a1e2661f9ed501d8f906611892099a9de5a7ea9f641ecb4dd75bbb63c2d5a.

Great. This leaves us with the following raw transaction: 01000000 01 f64c5949b307c12a5e6f69ffa2916288016c6b0092b057efd01a9a67a9605fa0 00000000 8a 47304402203c8aaa41ae647149f70ce24f73109e99d59d7e54a5d854239943358d581e9f8302206336cb57c00bb78f46c881b3d6bb2ed76dc652eedf36064ae022ea4ae3ba3b100141049d0f70eed85345ca5c1c04563bed19608562c37d644061785a836e8f199155f2818a1e2661f9ed501d8f906611892099a9de5a7ea9f641ecb4dd75bbb63c2d5a ffffffff 01 70508e0600000000 1976a914a9974100aeee974a20cda9a2f545704a0ab54fdc88ac 00000000

Which is unfortunately not a valid transaction (error received: PUSH TRANSACTION ERROR: 16: MANDATORY-SCRIPT-VERIFY-FLAG-FAILED (OPCODE MISSING OR NOT UNDERSTOOD)).

Using a transaction tool, I get the following (valid) raw transaction, which I was able to redeem: 01000000 01 f64c5949b307c12a5e6f69ffa2916288016c6b0092b057efd01a9a67a9605fa0 00000000 8a 47304402204cdb6499578276106748c4877bf2a3381ba484fb621ce8d3faa2161254bdeec902205e3536aeaa65f8f0f55b3eb31a9bf8959b70e247c0ebd9da485e586370a25b900141 049d0f70eed85345ca5c1c04563bed19608562c37d644061785a836e8f199155f2818a1e2661f9ed501d8f906611892099a9de5a7ea9f641ecb4dd75bbb63c2d5a ffffffff 01 70508e0600000000 1976a914a9974100aeee974a20cda9a2f545704a0ab54fdc88ac 00000000

All the fields are correct besides the signature. How come the openSSL signing command I used was incorrect?

Is the signature generated valid? Is the openSSL command valid? Can we even use openSSL to sign a transaction?

1

While I haven't verified the signature, upon inspection of the encoding I think I can see what is wrong. Let's break down the scriptSig briefly and I'll show you:

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)

Now I've highlighted the length of the DER encoded signature as the issue - 46. This should be 47. The reason is that that length is actually supposed to be the length of the signature plus one byte for the sighash type. Unlike normal DER signature produced by OpenSSL, Bitcoin requires the sighash type to be appended, in this case 01 for SIGHASH_ALL. You can see the 01 byte present. But you haven't updated the length. In the valid transaction below it, on the other hand, you can see the length is 47 despite the fields being the same length.

So try updating the 46 to a 47 and see if it works :)

  • You're correct I did miscalculate the signature length (didn't include the 01). I changed it and try to submit it, but the signature is still not accepted. – user2298995 Jan 3 '18 at 12:05
  • What error do you have now? I cannot help without more info :) – MeshCollider Jan 3 '18 at 12:10
  • Hi, I'm getting an error regarding the inputs (which suggest an issue with the signature because when I try to re-submit the same raw transaction, I get an error that the transaction was already broadcasted). – user2298995 Jan 3 '18 at 14:51
  • It could be that it views it as a double spend because you already created a valid transaction afterwards? Make sure the other transaction wasn't broadcast and remove it from your mempool if it is there – MeshCollider Jan 3 '18 at 19:39
  • When the signature is valid, I get an error that the transaction has already been broadcasted (good), but when it's invalid I get a different error. Therefore I know that when my signature is still invalid. Is there a way to verify my signature (using an online tool or something)? – user2298995 Jan 4 '18 at 7:44

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.