2
1
I am trying to learn bitcoin blockchain programming. I am trying to verify signature in Transaction with txid: 4269fdc239d027922dcec96f1ae283dbaff10e2d1bd49605661d091e79714956
I am getting BadSignatureError
Raw Transaction
./bitcoin-cli getrawtransaction 4269fdc239d027922dcec96f1ae283dbaff10e2d1bd49605661d091e79714956
01000000017f950ab790838e0c05e79856d25d586823fe139e1807405a3f207ff33f9b7663010000006b483045022100d8629403cd3b49950da9293653c6279149c029e6b7b15371342d0d2ce286c8f2022078787985a644e94fd9246f6c25733336c94af5f00d9d34a07dc2f9e0987ef990012102b726d7eae11a6d5cf3b2362e773e116a6140347dcee1b2943f4a2897351e5d90ffffffff021bf03c000000000017a91469f3757380a56820abc7052867216599e575cddd8777c1ca1c000000001976a914d5f950abe0b559b2b7a7ab3d18a507ea1c3e4ac688ac00000000
Decode Raw Transaction
./core/bitcoin-0.16.0/bin/bitcoin-cli decoderawtransaction 01000000017f950ab790838e0c05e79856d25d586823fe139e1807405a3f207ff33f9b7663010000006b483045022100d8629403cd3b49950da9293653c6279149c029e6b7b15371342d0d2ce286c8f2022078787985a644e94fd9246f6c25733336c94af5f00d9d34a07dc2f9e0987ef990012102b726d7eae11a6d5cf3b2362e773e116a6140347dcee1b2943f4a2897351e5d90ffffffff021bf03c000000000017a91469f3757380a56820abc7052867216599e575cddd8777c1ca1c000000001976a914d5f950abe0b559b2b7a7ab3d18a507ea1c3e4ac688ac00000000
{
"txid": "4269fdc239d027922dcec96f1ae283dbaff10e2d1bd49605661d091e79714956",
"hash": "4269fdc239d027922dcec96f1ae283dbaff10e2d1bd49605661d091e79714956",
"version": 1,
"size": 224,
"vsize": 224,
"locktime": 0,
"vin": [
{
"txid": "63769b3ff37f203f5a4007189e13fe2368585dd25698e7050c8e8390b70a957f",
"vout": 1,
"scriptSig": {
"asm": "3045022100d8629403cd3b49950da9293653c6279149c029e6b7b15371342d0d2ce286c8f2022078787985a644e94fd9246f6c25733336c94af5f00d9d34a07dc2f9e0987ef990[ALL] 02b726d7eae11a6d5cf3b2362e773e116a6140347dcee1b2943f4a2897351e5d90",
"hex": "483045022100d8629403cd3b49950da9293653c6279149c029e6b7b15371342d0d2ce286c8f2022078787985a644e94fd9246f6c25733336c94af5f00d9d34a07dc2f9e0987ef990012102b726d7eae11a6d5cf3b2362e773e116a6140347dcee1b2943f4a2897351e5d90"
},
"sequence": 4294967295
}
],
"vout": [
{
"value": 0.03993627,
"n": 0,
"scriptPubKey": {
"asm": "OP_HASH160 69f3757380a56820abc7052867216599e575cddd OP_EQUAL",
"hex": "a91469f3757380a56820abc7052867216599e575cddd87",
"reqSigs": 1,
"type": "scripthash",
"addresses": [
"3BMEXVvXXRFh2eJ9Eji115xfqJjWmLTCf8"
]
}
},
{
"value": 4.83049847,
"n": 1,
"scriptPubKey": {
"asm": "OP_DUP OP_HASH160 d5f950abe0b559b2b7a7ab3d18a507ea1c3e4ac6 OP_EQUALVERIFY OP_CHECKSIG",
"hex": "76a914d5f950abe0b559b2b7a7ab3d18a507ea1c3e4ac688ac",
"reqSigs": 1,
"type": "pubkeyhash",
"addresses": [
"1LWPbaYN2jqhv9oZvYHxYKXuaiR1qJn52i"
]
}
}
]
}
Here "asm" contains Signation and Public Key
"vin": [
{
"txid": "63769b3ff37f203f5a4007189e13fe2368585dd25698e7050c8e8390b70a957f",
"vout": 1,
"scriptSig": {
"asm": "3045022100d8629403cd3b49950da9293653c6279149c029e6b7b15371342d0d2ce286c8f2022078787985a644e94fd9246f6c25733336c94af5f00d9d34a07dc2f9e0987ef990[ALL] 02b726d7eae11a6d5cf3b2362e773e116a6140347dcee1b2943f4a2897351e5d90",
"hex": "483045022100d8629403cd3b49950da9293653c6279149c029e6b7b15371342d0d2ce286c8f2022078787985a644e94fd9246f6c25733336c94af5f00d9d34a07dc2f9e0987ef990012102b726d7eae11a6d5cf3b2362e773e116a6140347dcee1b2943f4a2897351e5d90"
},
"sequence": 4294967295
}
],
To obtain Signature
3045022100d8629403cd3b49950da9293653c6279149c029e6b7b15371342d0d2ce286c8f2022078787985a644e94fd9246f6c25733336c94af5f00d9d34a07dc2f9e0987ef990
=>
0x30 DER
0x45 Length
0x02 Type Integer
0x21 Length of R
0x00d8629403cd3b49950da9293653c6279149c029e6b7b15371342d0d2ce286c8f2 (R)
0x02 Type Integer
0x20 Length of S
0x78787985a644e94fd9246f6c25733336c94af5f00d9d34a07dc2f9e0987ef990 (S)
Removing 00 from R
Signature = R + S = d8629403cd3b49950da9293653c6279149c029e6b7b15371342d0d2ce286c8f278787985a644e94fd9246f6c25733336c94af5f00d9d34a07dc2f9e0987ef990
Compressed Public Key 02b726d7eae11a6d5cf3b2362e773e116a6140347dcee1b2943f4a2897351e5d90
Uncompressing Public Key Code
def getFullPubKeyFromCompressed(x_str: str):
prefix = x_str[0:2]
print("prefix = %s" % (prefix))
x_str = x_str[2:]
x = int(x_str, 16)
print("x = %x" % (x))
p = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F
y_squared = (x**3 + 7) % p
y = modular_sqrt(y_squared, p)
y_str = "%x" % y
print("y_str = %s" % (y_str))
y_is_even = (int(y_str[-1], 16) % 2 == 0)
if prefix == "02" and y_is_even == False or prefix == "03" and y_is_even == True:
y = p - y
y_str = "%x" % y
print("y = %s" % (y_str))
return "04" + x_str + y_str
prefix = pubkey[0:2]
if prefix == "02" or prefix == "03":
pubkey = getFullPubKeyFromCompressed(pubkey)[2:]
elif prefix == "04":
pubkey = pubkey[2:]
print("full public key = %s" % pubkey)
Output:
x = b726d7eae11a6d5cf3b2362e773e116a6140347dcee1b2943f4a2897351e5d90
y_str = cacc567dc3036f2fceb1b6f16676285b153821eb79825dae124b17b9e29479cb
y = 3533a9823cfc90d0314e490e9989d7a4eac7de14867da251edb4e8451d6b8264
full public key = b726d7eae11a6d5cf3b2362e773e116a6140347dcee1b2943f4a2897351e5d903533a9823cfc90d0314e490e9989d7a4eac7de14867da251edb4e8451d6b8264
Transaction single time SHA256 hashing as this will be done again signature verification Code
hashval = binascii.hexlify(hashlib.sha256(bytes.fromhex(raw_txn)).digest())
txn_sha256 = bytes.decode(hashval)
print("txn_sha256 = %s" % (txn_sha256))
Output
txn_sha256 = fb0c792bfba8139654cffd2818bdd56f3541d11fb43ea46f646c3477de3d2e40
We have all three information to verify signature now
txn_sha256 = fb0c792bfba8139654cffd2818bdd56f3541d11fb43ea46f646c3477de3d2e40
pubkey = b726d7eae11a6d5cf3b2362e773e116a6140347dcee1b2943f4a2897351e5d903533a9823cfc90d0314e490e9989d7a4eac7de14867da251edb4e8451d6b8264
sig = d8629403cd3b49950da9293653c6279149c029e6b7b15371342d0d2ce286c8f278787985a644e94fd9246f6c25733336c94af5f00d9d34a07dc2f9e0987ef990
I execute check signature program
sig_b = bytes.fromhex(sig)
txn_sha256_b = bytes.fromhex(txn_sha256)
vk = ecdsa.VerifyingKey.from_string(bytes.fromhex(pubkey),curve=ecdsa.SECP256k1)
if vk.verify(sig_b, txn_sha256_b, hashlib.sha256) == True: # True
print("Signature is Valid")
else:
print("Signature is not Valid")
But I get BadSignatureError
Traceback (most recent call last):
File "bitcoin_localapis.py", line 294, in <module>
sigcheck(sig, pubkey, raw_txn)
File "bitcoin_localapis.py", line 202, in sigcheck
if vk.verify(sig_b, txn_sha256_b, hashlib.sha256) == True: # True
File "/home/vizeet/anaconda3/lib/python3.6/site-packages/ecdsa/keys.py", line 101, in verify
return self.verify_digest(signature, digest, sigdecode)
File "/home/vizeet/anaconda3/lib/python3.6/site-packages/ecdsa/keys.py", line 113, in verify_digest
raise BadSignatureError
ecdsa.keys.BadSignatureError
Please help me solve this issue.
I am not familiar with python, but have a short observation/question. I tried to do like here: https://bitcoin.stackexchange.com/questions/46455/verifying-a-bitcoin-trx-on-the-unix-cmd-line-with-openssl, and it failed with the given values. What is the unsigned raw tx you have?
– pebwindkraft – 2018-03-20T13:01:51.417Raw Transaction in HEX: 01000000017f950ab790838e0c05e79856d25d586823fe139e1807405a3f207ff33f9b7663010000006b483045022100d8629403cd3b49950da9293653c6279149c029e6b7b15371342d0d2ce286c8f2022078787985a644e94fd9246f6c25733336c94af5f00d9d34a07dc2f9e0987ef990012102b726d7eae11a6d5cf3b2362e773e116a6140347dcee1b2943f4a2897351e5d90ffffffff021bf03c000000000017a91469f3757380a56820abc7052867216599e575cddd8777c1ca1c000000001976a914d5f950abe0b559b2b7a7ab3d18a507ea1c3e4ac688ac00000000 – Vizeet Srivastava – 2018-03-20T13:53:22.573
If this is what you used to sign, then this will be wrong. This tx includes the signatures already, but you would need the signature removed, length adapted, etc ... see @amaclin's answer here: https://bitcoin.stackexchange.com/questions/32305/how-does-the-ecdsa-verification-algorithm-work-during-transaction/32308#32308
– pebwindkraft – 2018-03-20T15:35:00.757I tried to do the same, whereas the pizza example works, it doesn't match with your data. Is the pubkey the correct one? Do you have the privkey/pubkey in hex format? Or is it someone else's tx? (don't publish the priv key here!) – pebwindkraft – 2018-03-20T15:51:34.907
It worked for me after removing input script from raw transaction and replacing it with1976a914d5f950abe0b559b2b7a7ab3d18a507ea1c3e4ac688ac
and adding 01000000 at the end – Vizeet Srivastava – 2018-03-20T17:03:17.973
1976a914d5f950abe0b559b2b7a7ab3d18a507ea1c3e4ac688ac is : OP_DUP OP_HASH160 <Hash160(PublicKey)> OP_EQUALVERIFY OP_CHECKSIG PublicKey (02b726d7eae11a6d5cf3b2362e773e116a6140347dcee1b2943f4a2897351e5d90) -> Address (1LWPbaYN2jqhv9oZvYHxYKXuaiR1qJn52i) -> Hash160 d5f950abe0b559b2b7a7ab3d18a507ea1c3e4ac6 – Vizeet Srivastava – 2018-03-20T17:10:57.900
Code to convert PublicKey to Address: def sha256d(bstr): return hashlib.sha256(hashlib.sha256(bstr).digest()).digest()
def convertPKHToAddress(prefix, addr): data = prefix + addr return base58.b58encode(data + sha256d(data)[:4])
def pubkeyToAddress(pubkey_hex): pubkey = bytearray.fromhex(pubkey_hex) round1 = hashlib.sha256(pubkey).digest() h = hashlib.new('ripemd160') h.update(round1) pubkey_hash = h.digest() return convertPKHToAddress(b'\x00', pubkey_hash) – Vizeet Srivastava – 2018-03-20T17:11:24.890
Address to Hash160 I just used https://blockchain.info/address/1LWPbaYN2jqhv9oZvYHxYKXuaiR1qJn52i
– Vizeet Srivastava – 2018-03-20T17:11:30.910This is not my transaction. I just randomly used a transaction from a block. – Vizeet Srivastava – 2018-03-20T17:13:45.000
So great! Kudos! For future readers who might fall on the same issue, would you mind to collect this into a summary below into the answer section, showing what you have done? Eventually the question can then be accepted as well. – pebwindkraft – 2018-03-20T17:48:17.377
I'll add an answer to this. Thanks for help.. :) – Vizeet Srivastava – 2018-03-21T01:12:26.200