-
Notifications
You must be signed in to change notification settings - Fork 89
/
keyUtils.py
129 lines (106 loc) · 6.18 KB
/
keyUtils.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
# https://pypi.python.org/pypi/ecdsa/0.10
import ecdsa
import ecdsa.der
import ecdsa.util
import hashlib
import unittest
import random
import re
import struct
import utils
# https://en.bitcoin.it/wiki/Wallet_import_format
def privateKeyToWif(key_hex):
return utils.base58CheckEncode(0x80, key_hex.decode('hex'))
def wifToPrivateKey(s):
b = utils.base58CheckDecode(s)
return b.encode('hex')
# Input is a hex-encoded, DER-encoded signature
# Output is a 64-byte hex-encoded signature
def derSigToHexSig(s):
s, junk = ecdsa.der.remove_sequence(s.decode('hex'))
if junk != '':
print 'JUNK', junk.encode('hex')
assert(junk == '')
x, s = ecdsa.der.remove_integer(s)
y, s = ecdsa.der.remove_integer(s)
return '%064x%064x' % (x, y)
# Input is hex string
def privateKeyToPublicKey(s):
sk = ecdsa.SigningKey.from_string(s.decode('hex'), curve=ecdsa.SECP256k1)
vk = sk.verifying_key
return ('\04' + sk.verifying_key.to_string()).encode('hex')
# Input is hex string
def keyToAddr(s):
return pubKeyToAddr(privateKeyToPublicKey(s))
def pubKeyToAddr(s):
ripemd160 = hashlib.new('ripemd160')
ripemd160.update(hashlib.sha256(s.decode('hex')).digest())
return utils.base58CheckEncode(0, ripemd160.digest())
def addrHashToScriptPubKey(b58str):
assert(len(b58str) == 34)
# 76 A9 14 (20 bytes) 88 AC
return '76a914' + utils.base58CheckDecode(b58str).encode('hex') + '88ac'
class TestKey(unittest.TestCase):
def test_privateKeyToWif(self):
w = privateKeyToWif("0C28FCA386C7A227600B2FE50B7CAE11EC86D3BF1FBE471BE89827E19D72AA1D")
self.assertEqual(w, "5HueCGU8rMjxEXxiPuD5BDku4MkFqeZyd4dZ1jvhTVqvbTLvyTJ")
def test_WifToPrivateKey(self):
k = wifToPrivateKey("5HueCGU8rMjxEXxiPuD5BDku4MkFqeZyd4dZ1jvhTVqvbTLvyTJ")
self.assertEqual(k.upper(), "0C28FCA386C7A227600B2FE50B7CAE11EC86D3BF1FBE471BE89827E19D72AA1D")
def test_keyToAddr(self):
a = keyToAddr("18E14A7B6A307F426A94F8114701E7C8E774E7F9A47E2C2035DB29A206321725")
self.assertEqual(a, "16UwLL9Risc3QfPqBUvKofHmBQ7wMtjvM")
def test_pairs1(self):
#blockchain.info
wallet_addr = "1EyBEhrriJeghX4iqATQEWDq38Ae8ubBJe"
wallet_private = "8tnArBrrp4KHVjv8WA6HiX4ev56WDhqGA16XJCHJzhNH"
wallet_key = utils.base256encode(utils.base58decode(wallet_private)).encode('hex')
self.assertEqual(keyToAddr(wallet_key), wallet_addr)
# can import into multibit
bitcoin_qt = "5Jhw8B9J9QLaMmcBRfz7x8KkD9gwbNoyBMfWyANqiDwm3FFwgGC"
wallet_key = utils.base58CheckDecode(bitcoin_qt).encode('hex')
self.assertEqual(keyToAddr(wallet_key), wallet_addr)
wallet_key = "754580de93eea21579441b58e0c9b09f54f6005fc71135f5cfac027394b22caa"
self.assertEqual(keyToAddr(wallet_key), wallet_addr)
def test_pairs2(self):
#http://gobittest.appspot.com/Address
# Cannot import into multibit
wallet_private = "BB08A897EA1E422F989D36DE8D8186D8406BE25E577FD2A66976BF172325CDC9"
wallet_addr = "1MZ1nxFpvUgaPYYWaLPkLGAtKjRqcCwbGh"
self.assertEqual(keyToAddr(wallet_private), wallet_addr)
def test_pairs3(self):
# Can import into multibit
# http://bitaddress.org
wallet_private = "5J8PhneLEaL9qEPvW5voRgrELeXcmM12B6FbiA9wZAwDMnJMb2L"
wallet_addr = "1Q2SuNLDXDtda7DPnBTocQWtUg1v4xZMrV"
self.assertEqual(keyToAddr(utils.base58CheckDecode(wallet_private).encode('hex')), wallet_addr)
def test_der(self):
self.assertEqual(ecdsa.der.encode_sequence(
ecdsa.der.encode_integer(0x123456),
ecdsa.der.encode_integer(0x89abcd)).encode('hex'),
"300b020312345602040089abcd")
def test_derSigToHexSig(self):
derSig = "304502204c01fee2d724fb2e34930c658f585d49be2f6ac87c126506c0179e6977716093022100faad0afd3ae536cfe11f83afaba9a8914fc0e70d4c6d1495333b2fb3df6e8cae"
self.assertEqual("4c01fee2d724fb2e34930c658f585d49be2f6ac87c126506c0179e6977716093faad0afd3ae536cfe11f83afaba9a8914fc0e70d4c6d1495333b2fb3df6e8cae",
derSigToHexSig(derSig))
txn = ("0100000001a97830933769fe33c6155286ffae34db44c6b8783a2d8ca52ebee6414d399ec300000000" +
"8a47" +
"304402202c2e1a746c556546f2c959e92f2d0bd2678274823cc55e11628284e4a13016f80220797e716835f9dbcddb752cd0115a970a022ea6f2d8edafff6e087f928e41baac01" +
"41" +
"04392b964e911955ed50e4e368a9476bc3f9dcc134280e15636430eb91145dab739f0d68b82cf33003379d885a0b212ac95e9cddfd2d391807934d25995468bc55" +
"ffffffff02015f0000000000001976a914c8e90996c7c6080ee06284600c684ed904d14c5c88ac204e000000000000" +
"1976a914348514b329fda7bd33c7b2336cf7cd1fc9544c0588ac00000000")
myTxn_forSig = ("0100000001a97830933769fe33c6155286ffae34db44c6b8783a2d8ca52ebee6414d399ec300000000" +
"1976a914" + "167c74f7491fe552ce9e1912810a984355b8ee07" + "88ac" +
"ffffffff02015f0000000000001976a914c8e90996c7c6080ee06284600c684ed904d14c5c88ac204e000000000000" +
"1976a914348514b329fda7bd33c7b2336cf7cd1fc9544c0588ac00000000" +
"01000000")
public_key = "04392b964e911955ed50e4e368a9476bc3f9dcc134280e15636430eb91145dab739f0d68b82cf33003379d885a0b212ac95e9cddfd2d391807934d25995468bc55"
hashToSign = hashlib.sha256(hashlib.sha256(myTxn_forSig.decode('hex')).digest()).digest().encode('hex')
sig_der = "304402202c2e1a746c556546f2c959e92f2d0bd2678274823cc55e11628284e4a13016f80220797e716835f9dbcddb752cd0115a970a022ea6f2d8edafff6e087f928e41baac01"[:-2]
sig = derSigToHexSig(sig_der)
vk = ecdsa.VerifyingKey.from_string(public_key[2:].decode('hex'), curve=ecdsa.SECP256k1)
self.assertEquals(vk.verify_digest(sig.decode('hex'), hashToSign.decode('hex')), True)
#OP_DUP OP_HASH160 167c74f7491fe552ce9e1912810a984355b8ee07 OP_EQUALVERIFY OP_CHECKSIG
if __name__ == '__main__':
unittest.main()