-
Notifications
You must be signed in to change notification settings - Fork 25
/
keyfmt.py
80 lines (70 loc) · 3.41 KB
/
keyfmt.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
#!/usr/bin/env python
#
# Read a private key from stdin and output formatted data values.
# Input one key per line either hex (64 chars) or WIF key (51 base 58 chars).
#
# The format argument can contain variables:
#
# %h = HEX privkey
# %w = WIF privkey
# %p = public key
# %a = address
#
# eg. "Address: %a\nPrivkey: %w" outputs a format like the vanitygen program
# "a:%w" outputs a format good for importing to Electrum
#
# This generates a new key for importing to Electrum:
#
# hexdump -v -e '/1 "%02X"' -n 32 /dev/urandom | keyfmt "%a:%w"
#
import sys, binascii, hashlib
if len(sys.argv) < 2:
print "Usage: %s <format string>\n\nRead a hex private key from stdin and output formatted data.\n" % sys.argv[0]
print "These variables are supported:\n%h = HEX privkey\n%w = WIF privkey\n%p = public key\n%a = address\n"
print "eg. 'Address: %a\\nPrivkey: %w' outputs a format like the vanitygen program\n"
sys.exit(1)
alphabet="123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz"
advanced = any(v in sys.argv[1] for v in ['%p', '%a'])
def b58encode(num, pad=''):
out = ''
while num >= 58:
num,m = divmod(num, 58)
out = alphabet[m] + out
return pad + alphabet[num] + out
def b58hex(s58):
num = 0L
for (i, c) in enumerate(s58[::-1]):
num += alphabet.find(c) * (58**i)
return hex(num)[4:-9].upper()
if advanced:
import ecdsa
# secp256k1, http://www.oid-info.com/get/1.3.132.0.10
_p = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2FL
_r = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141L
_b = 0x0000000000000000000000000000000000000000000000000000000000000007L
_a = 0x0000000000000000000000000000000000000000000000000000000000000000L
_Gx = 0x79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798L
_Gy = 0x483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8L
curve_secp256k1 = ecdsa.ellipticcurve.CurveFp( _p, _a, _b )
generator_secp256k1 = ecdsa.ellipticcurve.Point( curve_secp256k1, _Gx, _Gy, _r )
oid_secp256k1 = (1,3,132,0,10)
SECP256k1 = ecdsa.curves.Curve("SECP256k1", curve_secp256k1, generator_secp256k1, oid_secp256k1 )
for line in sys.stdin:
line = line.replace(' ', '')
line = b58hex(line[:51]) if line[0] == '5' and len(line) < 64 else line[:64]
chksum = binascii.hexlify(hashlib.sha256(hashlib.sha256(binascii.unhexlify('80'+line)).digest()).digest()[:4])
privkey = long('80'+line+chksum, 16)
if advanced:
pubkey = chr(4) + ecdsa.SigningKey.from_secret_exponent(long(line, 16), curve=SECP256k1 ).get_verifying_key().to_string()
pad = ""
rmd = hashlib.new('ripemd160')
rmd.update(hashlib.sha256(pubkey).digest())
an = chr(0) + rmd.digest()
for c in an:
if c == '\0': pad += '1'
else: break
addr = long(binascii.hexlify(an + hashlib.sha256(hashlib.sha256(an).digest()).digest()[0:4]), 16)
out = sys.argv[1].replace('%h', line).replace('%w', b58encode(privkey))
if advanced:
out = out.replace('%p', binascii.hexlify(pubkey).upper()).replace('%a', b58encode(addr, pad))
print out.decode('string-escape')