I want to use openssl on unixoide systems to verify a transaction. I step on errors, when trying to verify a bitcoin trx’s hash. Here I am working on Mac OSX and OpenSSL (1.0.2a 19 Mar 2015).
I know I can use the QT client, or the several python/php/java solutions, this is not the goal here. I also understand, that bitcoin moves to libsecp256k1… I followed the example from the Pizza trx here:
How does the ECDSA verification algorithm work during transaction?
Verifying does not need the private key, only pubkey, hash and sig. Openssl offers two ways to verify a result:
openssl dgst -sha256 -verify pubkey.pem -signature tmpfile.sig sha256.txt
or
openssl pkeyutl -verify -pubin -inkey pubkey.pem -sigfile tmpfile.sig -in sha256.txt
Tricky part is, how to get from the hex pub key („042e930f39…ebcabb“) to the PEM format, which openssl wants for verification. At the end I added the steps, how I transformed the hex key to PEM.
When I use the bitocin double sha256 of the mentioned Pizza trx (I also tried several others), I get this error:
openssl dgst -sha256 -verify pubkey.pem -signature tmpfile.sig sha256.txt
Error Verifying Data
140735175988048:error:0D0680A8:asn1 encoding routines:ASN1_CHECK_TLEN:wrong tag:tasn_dec.c:1198:
140735175988048:error:0D07803A:asn1 encoding routines:ASN1_ITEM_EX_D2I:nested asn1 error:tasn_dec.c:372:Type=ECDSA_SIG
or with pkeyutl:
openssl pkeyutl -verify -pubin -inkey pubkey.pem -sigfile tmpfile.sig -in sha256.txt
Public Key operation error
140735175988048:error:0D0680A8:asn1 encoding routines:ASN1_CHECK_TLEN:wrong tag:tasn_dec.c:1198:
140735175988048:error:0D07803A:asn1 encoding routines:ASN1_ITEM_EX_D2I:nested asn1 error:tasn_dec.c:372:Type=ECDSA_SIG
When I create my priv and pub keys with openssl, and sign a „demo sha256“ string, I can verify correctly. Only these bitcoin sha256s strings don’t work. I must be missing something…
CREATING the PEM File:
based on several readings here in the stackexchange, I reverse engineered the pem keys from openssl. The pem formatted key wants a PEM_prestring („3056301006072a8648ce3d020106052b8104000a034200“) and the pubkey attached.
$ result=3056301006072a8648ce3d020106052b8104000a034200042e930f39ba62c6534ee98ed20ca98959d34aa9e057cda01cfd422c6bab3667b76426529382c23f42b9b08d7832d4fee1d6b437a8526e59667ce9c4e9dcebcabb
$ result=$( echo $result | sed 's/[[:xdigit:]]\{2\}/\\x&/g' )
$ printf $result > tmpfile
$ hexdump -C tmpfile
00000000 30 56 30 10 06 07 2a 86 48 ce 3d 02 01 06 05 2b |0V0...*.H.=....+|
00000010 81 04 00 0a 03 42 00 04 2e 93 0f 39 ba 62 c6 53 |.....B.....9.b.S|
00000020 4e e9 8e d2 0c a9 89 59 d3 4a a9 e0 57 cd a0 1c |N......Y.J..W...|
00000030 fd 42 2c 6b ab 36 67 b7 64 26 52 93 82 c2 3f 42 |.B,k.6g.d&R...?B|
00000040 b9 b0 8d 78 32 d4 fe e1 d6 b4 37 a8 52 6e 59 66 |...x2.....7.RnYf|
00000050 7c e9 c4 e9 dc eb ca bb ||.......|
This will be base64 encoded, and added some nice surroundings.
$ openssl enc -base64 -in tmpfile -out pubkey.pem
$ cat pubkey.pem
MFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAELpMPObpixlNO6Y7SDKmJWdNKqeBXzaAc
/UIsa6s2Z7dkJlKTgsI/QrmwjXgy1P7h1rQ3qFJuWWZ86cTp3OvKuw==
and we give pubkey.pem some nice surroundings, to make it look like this:
-----BEGIN PUBLIC KEY-----
MFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAELpMPObpixlNO6Y7SDKmJWdNKqeBXzaAc
/UIsa6s2Z7dkJlKTgsI/QrmwjXgy1P7h1rQ3qFJuWWZ86cTp3OvKuw==
-----END PUBLIC KEY-----
and check via asn the structure:
$ openssl asn1parse -in pubkey.pem
0:d=0 hl=2 l= 86 cons: SEQUENCE
2:d=1 hl=2 l= 16 cons: SEQUENCE
4:d=2 hl=2 l= 7 prim: OBJECT :id-ecPublicKey
13:d=2 hl=2 l= 5 prim: OBJECT :secp256k1
20:d=1 hl=2 l= 66 prim: BIT STRING
The files I used:
$ cat pubkey.pem
-----BEGIN PUBLIC KEY-----
MFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAELpMPObpixlNO6Y7SDKmJWdNKqeBXzaAc
/UIsa6s2Z7dkJlKTgsI/QrmwjXgy1P7h1rQ3qFJuWWZ86cTp3OvKuw==
-----END PUBLIC KEY-----
$ cat tmpfile.sig
30450221009908144ca6539e09512b9295c8a27050d478fbb96f8addbc3d075544dc41328702201aa528be2b907d316d2da068dd9eb1e23243d97e444d59290d2fddf25269ee0e
$ cat sha256.txt
692678553d1b85ccf87d4d4443095f276cdf600f2bb7dd44f6effbd7458fd4c2