bitcoin2johnhashscript
bitcoin2johnhashscript
/usr/bin/env python
2
3# jackjack's pywallet.py
4# https://github.com/jackjack-jj/pywallet
5# forked from Joric's pywallet.py
6
7missing_dep = []
8
9try:
10 from bsddb.db import *
11except:
12 from bsddb3.db import *
13 # missing_dep.append('bsddb')
14
15import os, sys, time
16pyw_filename = sys.argv[0].split('/')[len(sys.argv[0].split('/')) - 1]
17pyw_path = os.getcwd()
18
19try:
20 import json
21except:
22 try:
23 import simplejson as json
24 except:
25 sys.stdout.write("json or simplejson package is needed")
26
27import logging
28import struct
29import traceback
30import types
31import string
32import hashlib
33import random
34import math
35import binascii
36
37max_version = 81000
38addrtype = 0
39json_db = {}
40private_keys = []
41private_hex_keys = []
42passphrase = ""
43global_merging_message = ["", ""]
44
45wallet_dir = ""
46wallet_name = ""
47
48ko = 1e3
49kio = 1024
50Mo = 1e6
51Mio = 1024 ** 2
52Go = 1e9
53Gio = 1024 ** 3
54To = 1e12
55Tio = 1024 ** 4
56
57prekeys = [binascii.unhexlify("308201130201010420"),
binascii.unhexlify("308201120201010420")]
58postkeys = [binascii.unhexlify("a081a530"), binascii.unhexlify("81a530")]
59
60def hash_160(public_key):
61 md = hashlib.new('ripemd160')
62 md.update(hashlib.sha256(public_key).digest())
63 return md.digest()
64
65def public_key_to_bc_address(public_key):
66 h160 = hash_160(public_key)
67 return hash_160_to_bc_address(h160)
68
69def hash_160_to_bc_address(h160):
70 vh160 = chr(addrtype) + h160
71 h = Hash(vh160)
72 addr = vh160 + h[0:4]
73 return b58encode(addr)
74
75def bc_address_to_hash_160(addr):
76 bytes = b58decode(addr, 25)
77 return bytes[1:21]
78
79__b58chars = '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz'
80__b58base = len(__b58chars)
81
82def b58encode(v):
83 """ encode v, which is a string of bytes, to base58.
84 """
85
86 long_value = 0
87 for (i, c) in enumerate(v[::-1]):
88 long_value += (256 ** i) * ord(c)
89
90 result = ''
91 while long_value >= __b58base:
92 div, mod = divmod(long_value, __b58base)
93 result = __b58chars[mod] + result
94 long_value = div
95 result = __b58chars[long_value] + result
96
97 # Bitcoin does a little leading-zero-compression:
98 # leading 0-bytes in the input become leading-1s
99 nPad = 0
100 for c in v:
101 if c == '\0': nPad += 1
102 else: break
103
104 return (__b58chars[0] * nPad) + result
105
106def b58decode(v, length):
107 """ decode v into a string of len bytes
108 """
109 long_value = 0
110 for (i, c) in enumerate(v[::-1]):
111 long_value += __b58chars.find(c) * (__b58base ** i)
112
113 result = ''
114 while long_value >= 256:
115 div, mod = divmod(long_value, 256)
116 result = chr(mod) + result
117 long_value = div
118 result = chr(long_value) + result
119
120 nPad = 0
121 for c in v:
122 if c == __b58chars[0]: nPad += 1
123 else: break
124
125 result = chr(0) * nPad + result
126 if length is not None and len(result) != length:
127 return None
128
129 return result
130
131# end of bitcointools base58 implementation
132
133def Hash(data):
134 return hashlib.sha256(hashlib.sha256(data).digest()).digest()
135
136# bitcointools wallet.dat handling code
137
138def create_env(db_dir):
139 db_env = DBEnv(0)
140 r = db_env.open(db_dir, (DB_CREATE | DB_INIT_LOCK | DB_INIT_LOG |
DB_INIT_MPOOL | DB_INIT_TXN | DB_THREAD | DB_RECOVER))
141 return db_env
142
143def parse_CAddress(vds):
144 d = {'ip':'0.0.0.0', 'port':0, 'nTime': 0}
145 try:
146 d['nVersion'] = vds.read_int32()
147 d['nTime'] = vds.read_uint32()
148 d['nServices'] = vds.read_uint64()
149 d['pchReserved'] = vds.read_bytes(12)
150 d['ip'] = socket.inet_ntoa(vds.read_bytes(4))
151 d['port'] = vds.read_uint16()
152 except:
153 pass
154 return d
155
156def deserialize_CAddress(d):
157 return d['ip'] + ":" + str(d['port'])
158
159def parse_BlockLocator(vds):
160 d = { 'hashes' : [] }
161 nHashes = vds.read_compact_size()
162 for i in xrange(nHashes):
163 d['hashes'].append(vds.read_bytes(32))
164 return d
165
166def deserialize_BlockLocator(d):
167 result = "Block Locator top: " + d['hashes'][0][::-1].encode('hex_codec')
168 return result
169
170def parse_setting(setting, vds):
171 if setting[0] == "f": # flag (boolean) settings
172 return str(vds.read_boolean())
173 elif setting[0:4] == "addr": # CAddress
174 d = parse_CAddress(vds)
175 return deserialize_CAddress(d)
176 elif setting == "nTransactionFee":
177 return vds.read_int64()
178 elif setting == "nLimitProcessors":
179 return vds.read_int32()
180 return 'unknown setting'
181
182class SerializationError(Exception):
183 """ Thrown when there's a problem deserializing or serializing """
184
185def ts():
186 return int(time.mktime(datetime.now().timetuple()))
187
188def check_postkeys(key, postkeys):
189 for i in postkeys:
190 if key[:len(i)] == i:
191 return True
192 return False
193
194def one_element_in(a, string):
195 for i in a:
196 if i in string:
197 return True
198 return False
199
200def first_read(device, size, prekeys, inc=10000):
201 t0 = ts() - 1
202 try:
203 fd = os.open (device, os.O_RDONLY)
204 except:
205 sys.stdout.write("Can't open %s, check the path or try as root"
% device)
206 exit(0)
207 prekey = prekeys[0]
208 data = ""
209 i = 0
210 data = os.read (fd, i)
211 before_contained_key = False
212 contains_key = False
213 ranges = []
214
215 while i < int(size):
216 if i % (10 * Mio) > 0 and i % (10 * Mio) <= inc:
217 sys.stdout.write("\n%.2f/%.2f Go" % (i / 1e9, size /
1e9))
218 t = ts()
219 speed = i / (t - t0)
220 ETAts = size / speed + t0
221 d = datetime.fromtimestamp(ETAts)
222 sys.stdout.write(d.strftime(" ETA: %H:%M:%S"))
223
224 try:
225 data = os.read (fd, inc)
226 except Exception as exc:
227 os.lseek(fd, inc, os.SEEK_CUR)
228 sys.stdout.write(str(exc))
229 i += inc
230 continue
231
232 contains_key = one_element_in(prekeys, data)
233
234 if not before_contained_key and contains_key:
235 ranges.append(i)
236
237 if before_contained_key and not contains_key:
238 ranges.append(i)
239
240 before_contained_key = contains_key
241
242 i += inc
243
244 os.close (fd)
245 return ranges
246
247def shrink_intervals(device, ranges, prekeys, inc=1000):
248 prekey = prekeys[0]
249 nranges = []
250 fd = os.open (device, os.O_RDONLY)
251 for j in range(len(ranges) / 2):
252 before_contained_key = False
253 contains_key = False
254 bi = ranges[2 * j]
255 bf = ranges[2 * j + 1]
256
257 mini_blocks = []
258 k = bi
259 while k <= bf + len(prekey) + 1:
260 mini_blocks.append(k)
261 k += inc
262 mini_blocks.append(k)
263
264 for k in range(len(mini_blocks) / 2):
265 mini_blocks[2 * k] -= len(prekey) + 1
266 mini_blocks[2 * k + 1] += len(prekey) + 1
267
268
269 bi = mini_blocks[2 * k]
270 bf = mini_blocks[2 * k + 1]
271
272 os.lseek(fd, bi, 0)
273
274 data = os.read(fd, bf - bi + 1)
275 contains_key = one_element_in(prekeys, data)
276
277 if not before_contained_key and contains_key:
278 nranges.append(bi)
279
280 if before_contained_key and not contains_key:
281 nranges.append(bi + len(prekey) + 1 +
len(prekey) + 1)
282
283 before_contained_key = contains_key
284
285 os.close (fd)
286
287 return nranges
288
289def find_offsets(device, ranges, prekeys):
290 prekey = prekeys[0]
291 list_offsets = []
292 to_read = 0
293 fd = os.open (device, os.O_RDONLY)
294 for i in range(len(ranges) / 2):
295 bi = ranges[2 * i] - len(prekey) - 1
296 os.lseek(fd, bi, 0)
297 bf = ranges[2 * i + 1] + len(prekey) + 1
298 to_read += bf - bi + 1
299 buf = ""
300 for j in range(len(prekey)):
301 buf += "\x00"
302 curs = bi
303
304 while curs <= bf:
305 data = os.read(fd, 1)
306 buf = buf[1:] + data
307 if buf in prekeys:
308 list_offsets.append(curs)
309 curs += 1
310
311 os.close (fd)
312
313 return [to_read, list_offsets]
314
315def read_keys(device, list_offsets):
316 found_hexkeys = []
317 fd = os.open (device, os.O_RDONLY)
318 for offset in list_offsets:
319 os.lseek(fd, offset + 1, 0)
320 data = os.read(fd, 40)
321 hexkey = data[1:33].encode('hex')
322 after_key = data[33:39].encode('hex')
323 if hexkey not in found_hexkeys and
check_postkeys(after_key.decode('hex'), postkeys):
324 found_hexkeys.append(hexkey)
325
326 os.close (fd)
327
328 return found_hexkeys
329
330
331def md5_2(a):
332 return hashlib.md5(a).digest()
333
334def md5_file(nf):
335 fichier = file(nf, 'r').read()
336 return md5_2(fichier)
337
338
339class KEY:
340
341 def __init__ (self):
342 self.prikey = None
343 self.pubkey = None
344
345 def generate (self, secret=None):
346 if secret:
347 exp = int ('0x' + secret.encode ('hex'), 16)
348 self.prikey =
ecdsa.SigningKey.from_secret_exponent (exp, curve=secp256k1)
349 else:
350 self.prikey = ecdsa.SigningKey.generate
(curve=secp256k1)
351 self.pubkey = self.prikey.get_verifying_key()
352 return self.prikey.to_der()
353
354 def set_privkey (self, key):
355 if len(key) == 279:
356 seq1, rest = der.remove_sequence (key)
357 integer, rest = der.remove_integer (seq1)
358 octet_str, rest = der.remove_octet_string (rest)
359 tag1, cons1, rest, = der.remove_constructed
(rest)
360 tag2, cons2, rest, = der.remove_constructed
(rest)
361 point_str, rest = der.remove_bitstring (cons2)
362 self.prikey =
ecdsa.SigningKey.from_string(octet_str, curve=secp256k1)
363 else:
364 self.prikey = ecdsa.SigningKey.from_der (key)
365
366 def set_pubkey (self, key):
367 key = key[1:]
368 self.pubkey = ecdsa.VerifyingKey.from_string (key,
curve=secp256k1)
369
370 def get_privkey (self):
371 _p = self.prikey.curve.curve.p ()
372 _r = self.prikey.curve.generator.order ()
373 _Gx = self.prikey.curve.generator.x ()
374 _Gy = self.prikey.curve.generator.y ()
375 encoded_oid2 = der.encode_oid (*(1, 2, 840, 10045, 1, 1))
376 encoded_gxgy = "\x04" + ("%64x" % _Gx).decode('hex') + ("%64x"
% _Gy).decode('hex')
377 param_sequence = der.encode_sequence (
378 ecdsa.der.encode_integer(1),
379 der.encode_sequence (
380 encoded_oid2,
381 der.encode_integer (_p),
382 ),
383 der.encode_sequence (
384 der.encode_octet_string("\x00"),
385 der.encode_octet_string("\x07"),
386 ),
387 der.encode_octet_string (encoded_gxgy),
388 der.encode_integer (_r),
389 der.encode_integer (1),
390 );
391 encoded_vk = "\x00\x04" + self.pubkey.to_string ()
392 return der.encode_sequence (
393 der.encode_integer (1),
394 der.encode_octet_string (self.prikey.to_string
()),
395 der.encode_constructed (0, param_sequence),
396 der.encode_constructed (1, der.encode_bitstring
(encoded_vk)),
397 )
398
399 def get_pubkey (self):
400 return "\x04" + self.pubkey.to_string()
401
402 def sign (self, hash):
403 sig = self.prikey.sign_digest (hash,
sigencode=ecdsa.util.sigencode_der)
404 return sig.encode('hex')
405
406 def verify (self, hash, sig):
407 return self.pubkey.verify_digest (sig, hash,
sigdecode=ecdsa.util.sigdecode_der)
408
409def bool_to_int(b):
410 if b:
411 return 1
412 return 0
413
414class BCDataStream(object):
415 def __init__(self):
416 self.input = None
417 self.read_cursor = 0
418
419 def clear(self):
420 self.input = None
421 self.read_cursor = 0
422
423 def write(self, bytes): # Initialize with string of bytes
424 if self.input is None:
425 self.input = bytes
426 else:
427 self.input += bytes
428
429 def map_file(self, file, start): # Initialize with bytes from file
430 self.input = mmap.mmap(file.fileno(), 0,
access=mmap.ACCESS_READ)
431 self.read_cursor = start
432 def seek_file(self, position):
433 self.read_cursor = position
434 def close_file(self):
435 self.input.close()
436
437 def read_string(self):
438 # Strings are encoded depending on length:
439 # 0 to 252 : 1-byte-length followed by bytes (if any)
440 # 253 to 65,535 : byte'253' 2-byte-length followed by bytes
441 # 65,536 to 4,294,967,295 : byte '254' 4-byte-length followed by
bytes
442 # ... and the Bitcoin client is coded to understand:
443 # greater than 4,294,967,295 : byte '255' 8-byte-length followed
by bytes of string
444 # ... but I don't think it actually handles any strings that
big.
445 if self.input is None:
446 raise SerializationError("call write(bytes) before
trying to deserialize")
447
448 try:
449 length = self.read_compact_size()
450 except IndexError:
451 raise SerializationError("attempt to read past end of
buffer")
452
453 return self.read_bytes(length)
454
455 def write_string(self, string):
456 # Length-encoded as with read-string
457 self.write_compact_size(len(string))
458 self.write(string)
459
460 def read_bytes(self, length):
461 try:
462 result = self.input[self.read_cursor:self.read_cursor +
length]
463 self.read_cursor += length
464 return result
465 except IndexError:
466 raise SerializationError("attempt to read past end of
buffer")
467
468 return ''
469
470 def read_boolean(self): return self.read_bytes(1)[0] != chr(0)
471 def read_int16(self): return self._read_num('<h')
472 def read_uint16(self): return self._read_num('<H')
473 def read_int32(self): return self._read_num('<i')
474 def read_uint32(self): return self._read_num('<I')
475 def read_int64(self): return self._read_num('<q')
476 def read_uint64(self): return self._read_num('<Q')
477
478 def write_boolean(self, val): return self.write(chr(bool_to_int(val)))
479 def write_int16(self, val): return self._write_num('<h', val)
480 def write_uint16(self, val): return self._write_num('<H', val)
481 def write_int32(self, val): return self._write_num('<i', val)
482 def write_uint32(self, val): return self._write_num('<I', val)
483 def write_int64(self, val): return self._write_num('<q', val)
484 def write_uint64(self, val): return self._write_num('<Q', val)
485
486 def read_compact_size(self):
487 size = self.input[self.read_cursor]
488 if isinstance(size, str):
489 size = ord(self.input[self.read_cursor])
490 self.read_cursor += 1
491 if size == 253:
492 size = self._read_num('<H')
493 elif size == 254:
494 size = self._read_num('<I')
495 elif size == 255:
496 size = self._read_num('<Q')
497 return size
498
499 def write_compact_size(self, size):
500 if size < 0:
501 raise SerializationError("attempt to write size < 0")
502 elif size < 253:
503 self.write(chr(size))
504 elif size < 2 ** 16:
505 self.write('\xfd')
506 self._write_num('<H', size)
507 elif size < 2 ** 32:
508 self.write('\xfe')
509 self._write_num('<I', size)
510 elif size < 2 ** 64:
511 self.write('\xff')
512 self._write_num('<Q', size)
513
514 def _read_num(self, format):
515 (i,) = struct.unpack_from(format, self.input, self.read_cursor)
516 self.read_cursor += struct.calcsize(format)
517 return i
518
519 def _write_num(self, format, num):
520 s = struct.pack(format, num)
521 self.write(s)
522
523def open_wallet(walletfile, writable=False):
524 db = DB()
525 DB_TYPEOPEN = DB_RDONLY
526 flags = DB_THREAD | DB_TYPEOPEN
527 try:
528 r = db.open(walletfile, "main", DB_BTREE, flags)
529 except DBError:
530 r = True
531
532 if r is not None:
533 logging.error("Couldn't open wallet.dat/main. Try quitting
Bitcoin and running this again.")
534 sys.exit(1)
535
536 return db
537
538def inversetxid(txid):
539 if len(txid) is not 64:
540 sys.stdout.write("Bad txid")
541 return "CORRUPTEDTXID:" + txid
542 new_txid = ""
543 for i in range(32):
544 new_txid += txid[62 - 2 * i];
545 new_txid += txid[62 - 2 * i + 1];
546 return new_txid
547
548def parse_wallet(db, item_callback):
549 kds = BCDataStream()
550 vds = BCDataStream()
551
552
553 def parse_TxIn(vds):
554 d = {}
555 d['prevout_hash'] = vds.read_bytes(32).encode('hex')
556 d['prevout_n'] = vds.read_uint32()
557 d['scriptSig'] =
vds.read_bytes(vds.read_compact_size()).encode('hex')
558 d['sequence'] = vds.read_uint32()
559 return d
560
561
562 def parse_TxOut(vds):
563 d = {}
564 d['value'] = vds.read_int64() / 1e8
565 d['scriptPubKey'] =
vds.read_bytes(vds.read_compact_size()).encode('hex')
566 return d
567
568
569 for (key, value) in db.items():
570 d = { }
571
572 kds.clear(); kds.write(key)
573 vds.clear(); vds.write(value)
574
575 type = kds.read_string()
576
577 d["__key__"] = key
578 d["__value__"] = value
579 d["__type__"] = type
580
581 try:
582 if type == "tx":
583 d["tx_id"] =
inversetxid(kds.read_bytes(32).encode('hex_codec'))
584 start = vds.read_cursor
585 d['version'] = vds.read_int32()
586 n_vin = vds.read_compact_size()
587 d['txIn'] = []
588 for i in xrange(n_vin):
589 d['txIn'].append(parse_TxIn(vds))
590 n_vout = vds.read_compact_size()
591 d['txOut'] = []
592 for i in xrange(n_vout):
593 d['txOut'].append(parse_TxOut(vds))
594 d['lockTime'] = vds.read_uint32()
595 d['tx'] =
vds.input[start:vds.read_cursor].encode('hex_codec')
596 d['txv'] = value.encode('hex_codec')
597 d['txk'] = key.encode('hex_codec')
598 elif type == "name":
599 d['hash'] = kds.read_string()
600 d['name'] = vds.read_string()
601 elif type == "version":
602 d['version'] = vds.read_uint32()
603 elif type == "minversion":
604 d['minversion'] = vds.read_uint32()
605 elif type == "setting":
606 d['setting'] = kds.read_string()
607 d['value'] = parse_setting(d['setting'], vds)
608 elif type == "key":
609 d['public_key'] =
kds.read_bytes(kds.read_compact_size())
610 d['private_key'] =
vds.read_bytes(vds.read_compact_size())
611 elif type == "wkey":
612 d['public_key'] =
kds.read_bytes(kds.read_compact_size())
613 d['private_key'] =
vds.read_bytes(vds.read_compact_size())
614 d['created'] = vds.read_int64()
615 d['expires'] = vds.read_int64()
616 d['comment'] = vds.read_string()
617 elif type == "defaultkey":
618 d['key'] =
vds.read_bytes(vds.read_compact_size())
619 elif type == "pool":
620 d['n'] = kds.read_int64()
621 d['nVersion'] = vds.read_int32()
622 d['nTime'] = vds.read_int64()
623 d['public_key'] =
vds.read_bytes(vds.read_compact_size())
624 elif type == "acc":
625 d['account'] = kds.read_string()
626 d['nVersion'] = vds.read_int32()
627 d['public_key'] =
vds.read_bytes(vds.read_compact_size())
628 elif type == "acentry":
629 d['account'] = kds.read_string()
630 d['n'] = kds.read_uint64()
631 d['nVersion'] = vds.read_int32()
632 d['nCreditDebit'] = vds.read_int64()
633 d['nTime'] = vds.read_int64()
634 d['otherAccount'] = vds.read_string()
635 d['comment'] = vds.read_string()
636 elif type == "bestblock":
637 d['nVersion'] = vds.read_int32()
638 d.update(parse_BlockLocator(vds))
639 elif type == "ckey":
640 d['public_key'] =
kds.read_bytes(kds.read_compact_size())
641 d['encrypted_private_key'] =
vds.read_bytes(vds.read_compact_size())
642 elif type == "mkey":
643 d['nID'] = kds.read_uint32()
644 d['encrypted_key'] = vds.read_string()
645 d['salt'] = vds.read_string()
646 d['nDerivationMethod'] = vds.read_uint32()
647 d['nDerivationIterations'] = vds.read_uint32()
648 d['otherParams'] = vds.read_string()
649
650 item_callback(type, d)
651
652 except Exception:
653 traceback.print_exc()
654 sys.stdout.write("ERROR parsing wallet.dat, type %s" %
type)
655 sys.stdout.write("key data: %s" % key)
656 sys.stdout.write("key data in hex: %s" %
key.encode('hex_codec'))
657 sys.stdout.write("value data in hex: %s" %
value.encode('hex_codec'))
658 sys.exit(1)
659
660
661# end of bitcointools wallet.dat handling code
662
663# wallet.dat reader / writer
664
665def read_wallet(json_db, walletfile, print_wallet, print_wallet_transactions,
transaction_filter, include_balance, vers= -1, FillPool=False):
666 global passphrase
667 crypted = False
668
669 private_keys = []
670 private_hex_keys = []
671
672 if vers > -1:
673 global addrtype
674 oldaddrtype = addrtype
675 addrtype = vers
676
677 db = open_wallet(walletfile, writable=FillPool)
678
679 json_db['keys'] = []
680 json_db['pool'] = []
681 json_db['tx'] = []
682 json_db['names'] = {}
683 json_db['ckey'] = []
684 json_db['mkey'] = {}
685
686 def item_callback(type, d):
687 if type == "tx":
688 json_db['tx'].append({"tx_id" : d['tx_id'], "txin" :
d['txIn'], "txout" : d['txOut'], "tx_v" : d['txv'], "tx_k" : d['txk']})
689
690 elif type == "name":
691 json_db['names'][d['hash']] = d['name']
692
693 elif type == "version":
694 json_db['version'] = d['version']
695
696 elif type == "minversion":
697 json_db['minversion'] = d['minversion']
698
699 elif type == "setting":
700 if not json_db.has_key('settings'): json_db['settings']
= {}
701 json_db["settings"][d['setting']] = d['value']
702
703 elif type == "defaultkey":
704 json_db['defaultkey'] =
public_key_to_bc_address(d['key'])
705
706 elif type == "key":
707 addr = public_key_to_bc_address(d['public_key'])
708 compressed = d['public_key'][0] != '\04'
709 sec = SecretToASecret(PrivKeyToSecret(d['private_key']),
compressed)
710 hexsec = ASecretToSecret(sec).encode('hex')
711 private_keys.append(sec)
712 json_db['keys'].append({'addr' : addr, 'sec' : sec,
'hexsec' : hexsec, 'secret' : hexsec, 'pubkey':d['public_key'].encode('hex'),
'compressed':compressed, 'private':d['private_key'].encode('hex')})
713
714 elif type == "wkey":
715 if not json_db.has_key('wkey'): json_db['wkey'] = []
716 json_db['wkey']['created'] = d['created']
717
718 elif type == "pool":
719 """ d['n'] = kds.read_int64()
720 d['nVersion'] = vds.read_int32()
721 d['nTime'] = vds.read_int64()
722 d['public_key'] =
vds.read_bytes(vds.read_compact_size())"""
723 try:
724 json_db['pool'].append({'n': d['n'], 'addr':
public_key_to_bc_address(d['public_key']), 'addr2':
public_key_to_bc_address(d['public_key'].decode('hex')), 'addr3':
public_key_to_bc_address(d['public_key'].encode('hex')), 'nTime' : d['nTime'],
'nVersion' : d['nVersion'], 'public_key_hex' : d['public_key'] })
725 except:
726 json_db['pool'].append({'n': d['n'], 'addr':
public_key_to_bc_address(d['public_key']), 'nTime' : d['nTime'], 'nVersion' :
d['nVersion'], 'public_key_hex' : d['public_key'].encode('hex') })
727
728 elif type == "acc":
729 json_db['acc'] = d['account']
730 sys.stdout.write("Account %s (current key: %s)" %
(d['account'], public_key_to_bc_address(d['public_key'])))
731
732 elif type == "acentry":
733 json_db['acentry'] = (d['account'], d['nCreditDebit'],
d['otherAccount'], time.ctime(d['nTime']), d['n'], d['comment'])
734
735 elif type == "bestblock":
736 json_db['bestblock'] = d['hashes'][0][::-
1].encode('hex_codec')
737
738 elif type == "ckey":
739 crypted = True
740 compressed = d['public_key'][0] != '\04'
741 json_db['keys'].append({ 'pubkey':
d['public_key'].encode('hex'), 'addr': public_key_to_bc_address(d['public_key']),
'encrypted_privkey': d['encrypted_private_key'].encode('hex_codec'),
'compressed':compressed})
742
743 elif type == "mkey":
744 json_db['mkey']['nID'] = d['nID']
745 json_db['mkey']['encrypted_key'] =
d['encrypted_key'].encode('hex_codec')
746 json_db['mkey']['salt'] = d['salt'].encode('hex_codec')
747 json_db['mkey']['nDerivationMethod'] =
d['nDerivationMethod']
748 json_db['mkey']['nDerivationIterations'] =
d['nDerivationIterations']
749 json_db['mkey']['otherParams'] = d['otherParams']
750
751 if passphrase:
752 res = crypter.SetKeyFromPassphrase(passphrase,
d['salt'], d['nDerivationIterations'], d['nDerivationMethod'])
753 if res == 0:
754 logging.error("Unsupported derivation
method")
755 sys.exit(1)
756 masterkey = crypter.Decrypt(d['encrypted_key'])
757 crypter.SetKey(masterkey)
758
759 else:
760 json_db[type] = 'unsupported'
761
762 parse_wallet(db, item_callback)
763
764
765 nkeys = len(json_db['keys'])
766 i = 0
767 for k in json_db['keys']:
768 i += 1
769 addr = k['addr']
770 if addr in json_db['names'].keys():
771 k["label"] = json_db['names'][addr]
772 k["reserve"] = 0
773
774 db.close()
775
776 crypted = 'salt' in json_db['mkey']
777
778 if not crypted:
779 sys.stdout.write("%s : this wallet is not encrypted!" %
walletfile)
780 return -1
781
782 for k in json_db['keys']:
783 if k['compressed'] and 'secret' in k:
784 k['secret'] += "01"
785
786 if vers > -1:
787 addrtype = oldaddrtype
788
789 return {'crypted':crypted}
790
791
792from optparse import OptionParser
793
794if __name__ == '__main__':
795
796 parser = OptionParser(usage="%prog [bitcoin wallet files]")
797
798 (options, args) = parser.parse_args()
799
800 if len(args) < 1:
801 print >> sys.stderr, "Usage: %s [bitcon wallet files]" % sys.argv[0]
802 sys.exit(-1)
803
804 for i in range(0, len(args)):
805 filename = args[i]
806 if read_wallet(json_db, filename, True, True, "", False) == -1:
807 continue
808
809 cry_master = json_db['mkey']['encrypted_key'].decode('hex')
810 cry_salt = json_db['mkey']['salt'].decode('hex')
811 cry_rounds = json_db['mkey']['nDerivationIterations']
812 cry_method = json_db['mkey']['nDerivationMethod']
813
814 crypted = 'salt' in json_db['mkey']
815
816 if not crypted:
817 print >> sys.stderr, "%s : this wallet is not encrypted" %
os.path.basename(filename)
818 continue
819
820 for k in json_db['keys']:
821 pass # dirty hack but it works!
822
823 ckey = k['encrypted_privkey']
824 public_key = k['pubkey']
825 cry_master = json_db['mkey']['encrypted_key']
826 cry_salt = json_db['mkey']['salt']
827
828 sys.stdout.write("$bitcoin$%s$%s$%s$%s$%s$%s$%s$%s$%s\n" %
829 (len(cry_master), cry_master, len(cry_salt),
830 cry_salt, cry_rounds, len(ckey), ckey, len(public_key),
831 public_key))
832
833
834
835
836