mmgen-pywallet 52 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718
  1. #!/usr/bin/env python
  2. #
  3. # mmgen = Multi-Mode GENerator, command-line Bitcoin cold storage solution
  4. # Copyright (C) 2013 by philemon <mmgen-py@yandex.com>
  5. #
  6. # This program is free software: you can redistribute it and/or modify
  7. # it under the terms of the GNU General Public License as published by
  8. # the Free Software Foundation, either version 3 of the License, or
  9. # (at your option) any later version.
  10. #
  11. # This program is distributed in the hope that it will be useful,
  12. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. # GNU General Public License for more details.
  15. #
  16. # You should have received a copy of the GNU General Public License
  17. # along with this program. If not, see <http://www.gnu.org/licenses/>.
  18. """
  19. mmgen-pywallet: Dump contents of a bitcoind wallet to file
  20. """
  21. # Changes by Philemon:
  22. # password entry at prompt
  23. # dump keys, addresses or keys for specified addresses (output in flat list)
  24. # PyWallet 1.2.1 (Public Domain)
  25. # http://github.com/joric/pywallet
  26. # Most of the actual PyWallet code placed in the public domain.
  27. # PyWallet includes portions of free software, listed below.
  28. # BitcoinTools (wallet.dat handling code, MIT License)
  29. # https://github.com/gavinandresen/bitcointools
  30. # Copyright (c) 2010 Gavin Andresen
  31. # python-ecdsa (EC_KEY implementation, MIT License)
  32. # http://github.com/warner/python-ecdsa
  33. # "python-ecdsa" Copyright (c) 2010 Brian Warner
  34. # Portions written in 2005 by Peter Pearson and placed in the public domain.
  35. # SlowAES (aes.py code, Apache 2 License)
  36. # http://code.google.com/p/slowaes/
  37. # Copyright (c) 2008, Josh Davis (http://www.josh-davis.org),
  38. # Alex Martelli (http://www.aleax.it)
  39. # Ported from C code written by Laurent Haan (http://www.progressive-coding.com)
  40. from mmgen.Opts import *
  41. from mmgen.utils import msg
  42. from bsddb.db import *
  43. import os, sys, time
  44. import json
  45. import logging
  46. import struct
  47. import StringIO
  48. import traceback
  49. import socket
  50. import types
  51. import string
  52. import exceptions
  53. import hashlib
  54. import random
  55. import math
  56. max_version = 60000
  57. addrtype = 0
  58. json_db = {}
  59. private_keys = []
  60. password = None
  61. prog_name = sys.argv[0].split("/")[-1]
  62. help_data = {
  63. 'prog_name': prog_name,
  64. 'desc': "Dump contents of a bitcoind wallet to file",
  65. 'usage': "[opts] <bitcoind wallet file>",
  66. 'options': """
  67. -h, --help Print this help message
  68. -d, --outdir d Specify an alternate directory 'd' for output
  69. -j, --json Dump wallet in json format
  70. -k, --keys Dump all private keys (flat list)
  71. -a, --addrs Dump all addresses (flat list)
  72. -K, --keysforaddrs f Dump private keys for addresses listed in file 'f'
  73. -q, --quiet Suppress warnings; overwrite files without asking
  74. -S, --stdout Dump to stdout rather than file
  75. """
  76. }
  77. short_opts = "hd:jkaK:qS"
  78. long_opts = "help","outdir=","json","keys","addrs","keysforaddrs=","quiet","stdout"
  79. opts,cmd_args = process_opts(sys.argv,help_data,short_opts,long_opts)
  80. from mmgen.utils import check_infile,check_opts
  81. if len(cmd_args) == 1:
  82. check_infile(cmd_args[0])
  83. else:
  84. usage(help_data)
  85. check_opts(opts,('outdir',))
  86. if ('json' not in opts and 'keys' not in opts
  87. and 'addrs' not in opts and 'keysforaddrs' not in opts):
  88. usage(help_data)
  89. # from the SlowAES project, http://code.google.com/p/slowaes (aes.py)
  90. def append_PKCS7_padding(s):
  91. """return s padded to a multiple of 16-bytes by PKCS7 padding"""
  92. numpads = 16 - (len(s)%16)
  93. return s + numpads*chr(numpads)
  94. def strip_PKCS7_padding(s):
  95. """return s stripped of PKCS7 padding"""
  96. if len(s)%16 or not s:
  97. raise ValueError("String of len %d can't be PCKS7-padded" % len(s))
  98. numpads = ord(s[-1])
  99. if numpads > 16:
  100. raise ValueError("String ending with %r can't be PCKS7-padded" % s[-1])
  101. return s[:-numpads]
  102. class AES(object):
  103. # valid key sizes
  104. keySize = dict(SIZE_128=16, SIZE_192=24, SIZE_256=32)
  105. # Rijndael S-box
  106. sbox = [0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67,
  107. 0x2b, 0xfe, 0xd7, 0xab, 0x76, 0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59,
  108. 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0, 0xb7,
  109. 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1,
  110. 0x71, 0xd8, 0x31, 0x15, 0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05,
  111. 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75, 0x09, 0x83,
  112. 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29,
  113. 0xe3, 0x2f, 0x84, 0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b,
  114. 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf, 0xd0, 0xef, 0xaa,
  115. 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c,
  116. 0x9f, 0xa8, 0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc,
  117. 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2, 0xcd, 0x0c, 0x13, 0xec,
  118. 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19,
  119. 0x73, 0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee,
  120. 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb, 0xe0, 0x32, 0x3a, 0x0a, 0x49,
  121. 0x06, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79,
  122. 0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4,
  123. 0xea, 0x65, 0x7a, 0xae, 0x08, 0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6,
  124. 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a, 0x70,
  125. 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9,
  126. 0x86, 0xc1, 0x1d, 0x9e, 0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e,
  127. 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf, 0x8c, 0xa1,
  128. 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0,
  129. 0x54, 0xbb, 0x16]
  130. # Rijndael Inverted S-box
  131. rsbox = [0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38, 0xbf, 0x40, 0xa3,
  132. 0x9e, 0x81, 0xf3, 0xd7, 0xfb , 0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f,
  133. 0xff, 0x87, 0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb , 0x54,
  134. 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d, 0xee, 0x4c, 0x95, 0x0b,
  135. 0x42, 0xfa, 0xc3, 0x4e , 0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24,
  136. 0xb2, 0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25 , 0x72, 0xf8,
  137. 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16, 0xd4, 0xa4, 0x5c, 0xcc, 0x5d,
  138. 0x65, 0xb6, 0x92 , 0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda,
  139. 0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84 , 0x90, 0xd8, 0xab,
  140. 0x00, 0x8c, 0xbc, 0xd3, 0x0a, 0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3,
  141. 0x45, 0x06 , 0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02, 0xc1,
  142. 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b , 0x3a, 0x91, 0x11, 0x41,
  143. 0x4f, 0x67, 0xdc, 0xea, 0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6,
  144. 0x73 , 0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85, 0xe2, 0xf9,
  145. 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e , 0x47, 0xf1, 0x1a, 0x71, 0x1d,
  146. 0x29, 0xc5, 0x89, 0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b ,
  147. 0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20, 0x9a, 0xdb, 0xc0,
  148. 0xfe, 0x78, 0xcd, 0x5a, 0xf4 , 0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07,
  149. 0xc7, 0x31, 0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f , 0x60,
  150. 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d, 0x2d, 0xe5, 0x7a, 0x9f,
  151. 0x93, 0xc9, 0x9c, 0xef , 0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5,
  152. 0xb0, 0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61 , 0x17, 0x2b,
  153. 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26, 0xe1, 0x69, 0x14, 0x63, 0x55,
  154. 0x21, 0x0c, 0x7d]
  155. def getSBoxValue(self,num):
  156. """Retrieves a given S-Box Value"""
  157. return self.sbox[num]
  158. def getSBoxInvert(self,num):
  159. """Retrieves a given Inverted S-Box Value"""
  160. return self.rsbox[num]
  161. def rotate(self, word):
  162. """ Rijndael's key schedule rotate operation.
  163. Rotate a word eight bits to the left: eg, rotate(1d2c3a4f) == 2c3a4f1d
  164. Word is an char list of size 4 (32 bits overall).
  165. """
  166. return word[1:] + word[:1]
  167. # Rijndael Rcon
  168. Rcon = [0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36,
  169. 0x6c, 0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97,
  170. 0x35, 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91, 0x39, 0x72,
  171. 0xe4, 0xd3, 0xbd, 0x61, 0xc2, 0x9f, 0x25, 0x4a, 0x94, 0x33, 0x66,
  172. 0xcc, 0x83, 0x1d, 0x3a, 0x74, 0xe8, 0xcb, 0x8d, 0x01, 0x02, 0x04,
  173. 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d,
  174. 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3,
  175. 0x7d, 0xfa, 0xef, 0xc5, 0x91, 0x39, 0x72, 0xe4, 0xd3, 0xbd, 0x61,
  176. 0xc2, 0x9f, 0x25, 0x4a, 0x94, 0x33, 0x66, 0xcc, 0x83, 0x1d, 0x3a,
  177. 0x74, 0xe8, 0xcb, 0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40,
  178. 0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc,
  179. 0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5,
  180. 0x91, 0x39, 0x72, 0xe4, 0xd3, 0xbd, 0x61, 0xc2, 0x9f, 0x25, 0x4a,
  181. 0x94, 0x33, 0x66, 0xcc, 0x83, 0x1d, 0x3a, 0x74, 0xe8, 0xcb, 0x8d,
  182. 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c,
  183. 0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35,
  184. 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91, 0x39, 0x72, 0xe4,
  185. 0xd3, 0xbd, 0x61, 0xc2, 0x9f, 0x25, 0x4a, 0x94, 0x33, 0x66, 0xcc,
  186. 0x83, 0x1d, 0x3a, 0x74, 0xe8, 0xcb, 0x8d, 0x01, 0x02, 0x04, 0x08,
  187. 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a,
  188. 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d,
  189. 0xfa, 0xef, 0xc5, 0x91, 0x39, 0x72, 0xe4, 0xd3, 0xbd, 0x61, 0xc2,
  190. 0x9f, 0x25, 0x4a, 0x94, 0x33, 0x66, 0xcc, 0x83, 0x1d, 0x3a, 0x74,
  191. 0xe8, 0xcb ]
  192. def getRconValue(self, num):
  193. """Retrieves a given Rcon Value"""
  194. return self.Rcon[num]
  195. def core(self, word, iteration):
  196. """Key schedule core."""
  197. # rotate the 32-bit word 8 bits to the left
  198. word = self.rotate(word)
  199. # apply S-Box substitution on all 4 parts of the 32-bit word
  200. for i in range(4):
  201. word[i] = self.getSBoxValue(word[i])
  202. # XOR the output of the rcon operation with i to the first part
  203. # (leftmost) only
  204. word[0] = word[0] ^ self.getRconValue(iteration)
  205. return word
  206. def expandKey(self, key, size, expandedKeySize):
  207. """Rijndael's key expansion.
  208. Expands an 128,192,256 key into an 176,208,240 bytes key
  209. expandedKey is a char list of large enough size,
  210. key is the non-expanded key.
  211. """
  212. # current expanded keySize, in bytes
  213. currentSize = 0
  214. rconIteration = 1
  215. expandedKey = [0] * expandedKeySize
  216. # set the 16, 24, 32 bytes of the expanded key to the input key
  217. for j in range(size):
  218. expandedKey[j] = key[j]
  219. currentSize += size
  220. while currentSize < expandedKeySize:
  221. # assign the previous 4 bytes to the temporary value t
  222. t = expandedKey[currentSize-4:currentSize]
  223. # every 16,24,32 bytes we apply the core schedule to t
  224. # and increment rconIteration afterwards
  225. if currentSize % size == 0:
  226. t = self.core(t, rconIteration)
  227. rconIteration += 1
  228. # For 256-bit keys, we add an extra sbox to the calculation
  229. if size == self.keySize["SIZE_256"] and ((currentSize % size) == 16):
  230. for l in range(4): t[l] = self.getSBoxValue(t[l])
  231. # We XOR t with the four-byte block 16,24,32 bytes before the new
  232. # expanded key. This becomes the next four bytes in the expanded
  233. # key.
  234. for m in range(4):
  235. expandedKey[currentSize] = expandedKey[currentSize - size] ^ \
  236. t[m]
  237. currentSize += 1
  238. return expandedKey
  239. def addRoundKey(self, state, roundKey):
  240. """Adds (XORs) the round key to the state."""
  241. for i in range(16):
  242. state[i] ^= roundKey[i]
  243. return state
  244. def createRoundKey(self, expandedKey, roundKeyPointer):
  245. """Create a round key.
  246. Creates a round key from the given expanded key and the
  247. position within the expanded key.
  248. """
  249. roundKey = [0] * 16
  250. for i in range(4):
  251. for j in range(4):
  252. roundKey[j*4+i] = expandedKey[roundKeyPointer + i*4 + j]
  253. return roundKey
  254. def galois_multiplication(self, a, b):
  255. """Galois multiplication of 8 bit characters a and b."""
  256. p = 0
  257. for counter in range(8):
  258. if b & 1: p ^= a
  259. hi_bit_set = a & 0x80
  260. a <<= 1
  261. # keep a 8 bit
  262. a &= 0xFF
  263. if hi_bit_set:
  264. a ^= 0x1b
  265. b >>= 1
  266. return p
  267. #
  268. # substitute all the values from the state with the value in the SBox
  269. # using the state value as index for the SBox
  270. #
  271. def subBytes(self, state, isInv):
  272. if isInv: getter = self.getSBoxInvert
  273. else: getter = self.getSBoxValue
  274. for i in range(16): state[i] = getter(state[i])
  275. return state
  276. # iterate over the 4 rows and call shiftRow() with that row
  277. def shiftRows(self, state, isInv):
  278. for i in range(4):
  279. state = self.shiftRow(state, i*4, i, isInv)
  280. return state
  281. # each iteration shifts the row to the left by 1
  282. def shiftRow(self, state, statePointer, nbr, isInv):
  283. for i in range(nbr):
  284. if isInv:
  285. state[statePointer:statePointer+4] = \
  286. state[statePointer+3:statePointer+4] + \
  287. state[statePointer:statePointer+3]
  288. else:
  289. state[statePointer:statePointer+4] = \
  290. state[statePointer+1:statePointer+4] + \
  291. state[statePointer:statePointer+1]
  292. return state
  293. # galois multiplication of the 4x4 matrix
  294. def mixColumns(self, state, isInv):
  295. # iterate over the 4 columns
  296. for i in range(4):
  297. # construct one column by slicing over the 4 rows
  298. column = state[i:i+16:4]
  299. # apply the mixColumn on one column
  300. column = self.mixColumn(column, isInv)
  301. # put the values back into the state
  302. state[i:i+16:4] = column
  303. return state
  304. # galois multiplication of 1 column of the 4x4 matrix
  305. def mixColumn(self, column, isInv):
  306. if isInv: mult = [14, 9, 13, 11]
  307. else: mult = [2, 1, 1, 3]
  308. cpy = list(column)
  309. g = self.galois_multiplication
  310. column[0] = g(cpy[0], mult[0]) ^ g(cpy[3], mult[1]) ^ \
  311. g(cpy[2], mult[2]) ^ g(cpy[1], mult[3])
  312. column[1] = g(cpy[1], mult[0]) ^ g(cpy[0], mult[1]) ^ \
  313. g(cpy[3], mult[2]) ^ g(cpy[2], mult[3])
  314. column[2] = g(cpy[2], mult[0]) ^ g(cpy[1], mult[1]) ^ \
  315. g(cpy[0], mult[2]) ^ g(cpy[3], mult[3])
  316. column[3] = g(cpy[3], mult[0]) ^ g(cpy[2], mult[1]) ^ \
  317. g(cpy[1], mult[2]) ^ g(cpy[0], mult[3])
  318. return column
  319. # applies the 4 operations of the forward round in sequence
  320. def aes_round(self, state, roundKey):
  321. state = self.subBytes(state, False)
  322. state = self.shiftRows(state, False)
  323. state = self.mixColumns(state, False)
  324. state = self.addRoundKey(state, roundKey)
  325. return state
  326. # applies the 4 operations of the inverse round in sequence
  327. def aes_invRound(self, state, roundKey):
  328. state = self.shiftRows(state, True)
  329. state = self.subBytes(state, True)
  330. state = self.addRoundKey(state, roundKey)
  331. state = self.mixColumns(state, True)
  332. return state
  333. # Perform the initial operations, the standard round, and the final
  334. # operations of the forward aes, creating a round key for each round
  335. def aes_main(self, state, expandedKey, nbrRounds):
  336. state = self.addRoundKey(state, self.createRoundKey(expandedKey, 0))
  337. i = 1
  338. while i < nbrRounds:
  339. state = self.aes_round(state, self.createRoundKey(expandedKey, 16*i))
  340. i += 1
  341. state = self.subBytes(state, False)
  342. state = self.shiftRows(state, False)
  343. state = self.addRoundKey(state, self.createRoundKey(expandedKey, 16*nbrRounds))
  344. return state
  345. # Perform the initial operations, the standard round, and the final
  346. # operations of the inverse aes, creating a round key for each round
  347. def aes_invMain(self, state, expandedKey, nbrRounds):
  348. state = self.addRoundKey(state, self.createRoundKey(expandedKey, 16*nbrRounds))
  349. i = nbrRounds - 1
  350. while i > 0:
  351. state = self.aes_invRound(state, self.createRoundKey(expandedKey, 16*i))
  352. i -= 1
  353. state = self.shiftRows(state, True)
  354. state = self.subBytes(state, True)
  355. state = self.addRoundKey(state, self.createRoundKey(expandedKey, 0))
  356. return state
  357. # encrypts a 128 bit input block against the given key of size specified
  358. def encrypt(self, iput, key, size):
  359. output = [0] * 16
  360. # the number of rounds
  361. nbrRounds = 0
  362. # the 128 bit block to encode
  363. block = [0] * 16
  364. # set the number of rounds
  365. if size == self.keySize["SIZE_128"]: nbrRounds = 10
  366. elif size == self.keySize["SIZE_192"]: nbrRounds = 12
  367. elif size == self.keySize["SIZE_256"]: nbrRounds = 14
  368. else: return None
  369. # the expanded keySize
  370. expandedKeySize = 16*(nbrRounds+1)
  371. # Set the block values, for the block:
  372. # a0,0 a0,1 a0,2 a0,3
  373. # a1,0 a1,1 a1,2 a1,3
  374. # a2,0 a2,1 a2,2 a2,3
  375. # a3,0 a3,1 a3,2 a3,3
  376. # the mapping order is a0,0 a1,0 a2,0 a3,0 a0,1 a1,1 ... a2,3 a3,3
  377. #
  378. # iterate over the columns
  379. for i in range(4):
  380. # iterate over the rows
  381. for j in range(4):
  382. block[(i+(j*4))] = iput[(i*4)+j]
  383. # expand the key into an 176, 208, 240 bytes key
  384. # the expanded key
  385. expandedKey = self.expandKey(key, size, expandedKeySize)
  386. # encrypt the block using the expandedKey
  387. block = self.aes_main(block, expandedKey, nbrRounds)
  388. # unmap the block again into the output
  389. for k in range(4):
  390. # iterate over the rows
  391. for l in range(4):
  392. output[(k*4)+l] = block[(k+(l*4))]
  393. return output
  394. # decrypts a 128 bit input block against the given key of size specified
  395. def decrypt(self, iput, key, size):
  396. output = [0] * 16
  397. # the number of rounds
  398. nbrRounds = 0
  399. # the 128 bit block to decode
  400. block = [0] * 16
  401. # set the number of rounds
  402. if size == self.keySize["SIZE_128"]: nbrRounds = 10
  403. elif size == self.keySize["SIZE_192"]: nbrRounds = 12
  404. elif size == self.keySize["SIZE_256"]: nbrRounds = 14
  405. else: return None
  406. # the expanded keySize
  407. expandedKeySize = 16*(nbrRounds+1)
  408. # Set the block values, for the block:
  409. # a0,0 a0,1 a0,2 a0,3
  410. # a1,0 a1,1 a1,2 a1,3
  411. # a2,0 a2,1 a2,2 a2,3
  412. # a3,0 a3,1 a3,2 a3,3
  413. # the mapping order is a0,0 a1,0 a2,0 a3,0 a0,1 a1,1 ... a2,3 a3,3
  414. # iterate over the columns
  415. for i in range(4):
  416. # iterate over the rows
  417. for j in range(4):
  418. block[(i+(j*4))] = iput[(i*4)+j]
  419. # expand the key into an 176, 208, 240 bytes key
  420. expandedKey = self.expandKey(key, size, expandedKeySize)
  421. # decrypt the block using the expandedKey
  422. block = self.aes_invMain(block, expandedKey, nbrRounds)
  423. # unmap the block again into the output
  424. for k in range(4):
  425. # iterate over the rows
  426. for l in range(4):
  427. output[(k*4)+l] = block[(k+(l*4))]
  428. return output
  429. class AESModeOfOperation(object):
  430. aes = AES()
  431. # structure of supported modes of operation
  432. modeOfOperation = dict(OFB=0, CFB=1, CBC=2)
  433. # converts a 16 character string into a number array
  434. def convertString(self, string, start, end, mode):
  435. if end - start > 16: end = start + 16
  436. if mode == self.modeOfOperation["CBC"]: ar = [0] * 16
  437. else: ar = []
  438. i = start
  439. j = 0
  440. while len(ar) < end - start:
  441. ar.append(0)
  442. while i < end:
  443. ar[j] = ord(string[i])
  444. j += 1
  445. i += 1
  446. return ar
  447. # Mode of Operation Encryption
  448. # stringIn - Input String
  449. # mode - mode of type modeOfOperation
  450. # hexKey - a hex key of the bit length size
  451. # size - the bit length of the key
  452. # hexIV - the 128 bit hex Initilization Vector
  453. def encrypt(self, stringIn, mode, key, size, IV):
  454. if len(key) % size:
  455. return None
  456. if len(IV) % 16:
  457. return None
  458. # the AES input/output
  459. plaintext = []
  460. iput = [0] * 16
  461. output = []
  462. ciphertext = [0] * 16
  463. # the output cipher string
  464. cipherOut = []
  465. # char firstRound
  466. firstRound = True
  467. if stringIn != None:
  468. for j in range(int(math.ceil(float(len(stringIn))/16))):
  469. start = j*16
  470. end = j*16+16
  471. if end > len(stringIn):
  472. end = len(stringIn)
  473. plaintext = self.convertString(stringIn, start, end, mode)
  474. # print 'PT@%s:%s' % (j, plaintext)
  475. if mode == self.modeOfOperation["CFB"]:
  476. if firstRound:
  477. output = self.aes.encrypt(IV, key, size)
  478. firstRound = False
  479. else:
  480. output = self.aes.encrypt(iput, key, size)
  481. for i in range(16):
  482. if len(plaintext)-1 < i:
  483. ciphertext[i] = 0 ^ output[i]
  484. elif len(output)-1 < i:
  485. ciphertext[i] = plaintext[i] ^ 0
  486. elif len(plaintext)-1 < i and len(output) < i:
  487. ciphertext[i] = 0 ^ 0
  488. else:
  489. ciphertext[i] = plaintext[i] ^ output[i]
  490. for k in range(end-start):
  491. cipherOut.append(ciphertext[k])
  492. iput = ciphertext
  493. elif mode == self.modeOfOperation["OFB"]:
  494. if firstRound:
  495. output = self.aes.encrypt(IV, key, size)
  496. firstRound = False
  497. else:
  498. output = self.aes.encrypt(iput, key, size)
  499. for i in range(16):
  500. if len(plaintext)-1 < i:
  501. ciphertext[i] = 0 ^ output[i]
  502. elif len(output)-1 < i:
  503. ciphertext[i] = plaintext[i] ^ 0
  504. elif len(plaintext)-1 < i and len(output) < i:
  505. ciphertext[i] = 0 ^ 0
  506. else:
  507. ciphertext[i] = plaintext[i] ^ output[i]
  508. for k in range(end-start):
  509. cipherOut.append(ciphertext[k])
  510. iput = output
  511. elif mode == self.modeOfOperation["CBC"]:
  512. for i in range(16):
  513. if firstRound:
  514. iput[i] = plaintext[i] ^ IV[i]
  515. else:
  516. iput[i] = plaintext[i] ^ ciphertext[i]
  517. # print 'IP@%s:%s' % (j, iput)
  518. firstRound = False
  519. ciphertext = self.aes.encrypt(iput, key, size)
  520. # always 16 bytes because of the padding for CBC
  521. for k in range(16):
  522. cipherOut.append(ciphertext[k])
  523. return mode, len(stringIn), cipherOut
  524. # Mode of Operation Decryption
  525. # cipherIn - Encrypted String
  526. # originalsize - The unencrypted string length - required for CBC
  527. # mode - mode of type modeOfOperation
  528. # key - a number array of the bit length size
  529. # size - the bit length of the key
  530. # IV - the 128 bit number array Initilization Vector
  531. def decrypt(self, cipherIn, originalsize, mode, key, size, IV):
  532. # cipherIn = unescCtrlChars(cipherIn)
  533. if len(key) % size:
  534. return None
  535. if len(IV) % 16:
  536. return None
  537. # the AES input/output
  538. ciphertext = []
  539. iput = []
  540. output = []
  541. plaintext = [0] * 16
  542. # the output plain text string
  543. stringOut = ''
  544. # char firstRound
  545. firstRound = True
  546. if cipherIn != None:
  547. for j in range(int(math.ceil(float(len(cipherIn))/16))):
  548. start = j*16
  549. end = j*16+16
  550. if j*16+16 > len(cipherIn):
  551. end = len(cipherIn)
  552. ciphertext = cipherIn[start:end]
  553. if mode == self.modeOfOperation["CFB"]:
  554. if firstRound:
  555. output = self.aes.encrypt(IV, key, size)
  556. firstRound = False
  557. else:
  558. output = self.aes.encrypt(iput, key, size)
  559. for i in range(16):
  560. if len(output)-1 < i:
  561. plaintext[i] = 0 ^ ciphertext[i]
  562. elif len(ciphertext)-1 < i:
  563. plaintext[i] = output[i] ^ 0
  564. elif len(output)-1 < i and len(ciphertext) < i:
  565. plaintext[i] = 0 ^ 0
  566. else:
  567. plaintext[i] = output[i] ^ ciphertext[i]
  568. for k in range(end-start):
  569. stringOut += chr(plaintext[k])
  570. iput = ciphertext
  571. elif mode == self.modeOfOperation["OFB"]:
  572. if firstRound:
  573. output = self.aes.encrypt(IV, key, size)
  574. firstRound = False
  575. else:
  576. output = self.aes.encrypt(iput, key, size)
  577. for i in range(16):
  578. if len(output)-1 < i:
  579. plaintext[i] = 0 ^ ciphertext[i]
  580. elif len(ciphertext)-1 < i:
  581. plaintext[i] = output[i] ^ 0
  582. elif len(output)-1 < i and len(ciphertext) < i:
  583. plaintext[i] = 0 ^ 0
  584. else:
  585. plaintext[i] = output[i] ^ ciphertext[i]
  586. for k in range(end-start):
  587. stringOut += chr(plaintext[k])
  588. iput = output
  589. elif mode == self.modeOfOperation["CBC"]:
  590. output = self.aes.decrypt(ciphertext, key, size)
  591. for i in range(16):
  592. if firstRound:
  593. plaintext[i] = IV[i] ^ output[i]
  594. else:
  595. plaintext[i] = iput[i] ^ output[i]
  596. firstRound = False
  597. if originalsize is not None and originalsize < end:
  598. for k in range(originalsize-start):
  599. stringOut += chr(plaintext[k])
  600. else:
  601. for k in range(end-start):
  602. stringOut += chr(plaintext[k])
  603. iput = ciphertext
  604. return stringOut
  605. # end of aes.py code
  606. # pywallet crypter implementation
  607. crypter = None
  608. try:
  609. from Crypto.Cipher import AES
  610. crypter = 'pycrypto'
  611. except:
  612. pass
  613. class Crypter_pycrypto( object ):
  614. def SetKeyFromPassphrase(self, vKeyData, vSalt, nDerivIterations, nDerivationMethod):
  615. if nDerivationMethod != 0:
  616. return 0
  617. data = vKeyData + vSalt
  618. for i in xrange(nDerivIterations):
  619. data = hashlib.sha512(data).digest()
  620. self.SetKey(data[0:32])
  621. self.SetIV(data[32:32+16])
  622. return len(data)
  623. def SetKey(self, key):
  624. self.chKey = key
  625. def SetIV(self, iv):
  626. self.chIV = iv[0:16]
  627. def Encrypt(self, data):
  628. return AES.new(self.chKey,AES.MODE_CBC,self.chIV).encrypt(data)[0:32]
  629. def Decrypt(self, data):
  630. return AES.new(self.chKey,AES.MODE_CBC,self.chIV).decrypt(data)[0:32]
  631. try:
  632. if not crypter:
  633. import ctypes
  634. import ctypes.util
  635. ssl = ctypes.cdll.LoadLibrary (ctypes.util.find_library ('ssl') or 'libeay32')
  636. crypter = 'ssl'
  637. except:
  638. pass
  639. class Crypter_ssl(object):
  640. def __init__(self):
  641. self.chKey = ctypes.create_string_buffer (32)
  642. self.chIV = ctypes.create_string_buffer (16)
  643. def SetKeyFromPassphrase(self, vKeyData, vSalt, nDerivIterations, nDerivationMethod):
  644. if nDerivationMethod != 0:
  645. return 0
  646. strKeyData = ctypes.create_string_buffer (vKeyData)
  647. chSalt = ctypes.create_string_buffer (vSalt)
  648. return ssl.EVP_BytesToKey(ssl.EVP_aes_256_cbc(), ssl.EVP_sha512(), chSalt, strKeyData,
  649. len(vKeyData), nDerivIterations, ctypes.byref(self.chKey), ctypes.byref(self.chIV))
  650. def SetKey(self, key):
  651. self.chKey = ctypes.create_string_buffer(key)
  652. def SetIV(self, iv):
  653. self.chIV = ctypes.create_string_buffer(iv)
  654. def Encrypt(self, data):
  655. buf = ctypes.create_string_buffer(len(data) + 16)
  656. written = ctypes.c_int(0)
  657. final = ctypes.c_int(0)
  658. ctx = ssl.EVP_CIPHER_CTX_new()
  659. ssl.EVP_CIPHER_CTX_init(ctx)
  660. ssl.EVP_EncryptInit_ex(ctx, ssl.EVP_aes_256_cbc(), None, self.chKey, self.chIV)
  661. ssl.EVP_EncryptUpdate(ctx, buf, ctypes.byref(written), data, len(data))
  662. output = buf.raw[:written.value]
  663. ssl.EVP_EncryptFinal_ex(ctx, buf, ctypes.byref(final))
  664. output += buf.raw[:final.value]
  665. return output
  666. def Decrypt(self, data):
  667. buf = ctypes.create_string_buffer(len(data) + 16)
  668. written = ctypes.c_int(0)
  669. final = ctypes.c_int(0)
  670. ctx = ssl.EVP_CIPHER_CTX_new()
  671. ssl.EVP_CIPHER_CTX_init(ctx)
  672. ssl.EVP_DecryptInit_ex(ctx, ssl.EVP_aes_256_cbc(), None, self.chKey, self.chIV)
  673. ssl.EVP_DecryptUpdate(ctx, buf, ctypes.byref(written), data, len(data))
  674. output = buf.raw[:written.value]
  675. ssl.EVP_DecryptFinal_ex(ctx, buf, ctypes.byref(final))
  676. output += buf.raw[:final.value]
  677. return output
  678. class Crypter_pure(object):
  679. def __init__(self):
  680. self.m = AESModeOfOperation()
  681. self.cbc = self.m.modeOfOperation["CBC"]
  682. self.sz = self.m.aes.keySize["SIZE_256"]
  683. def SetKeyFromPassphrase(self, vKeyData, vSalt, nDerivIterations, nDerivationMethod):
  684. if nDerivationMethod != 0:
  685. return 0
  686. data = vKeyData + vSalt
  687. for i in xrange(nDerivIterations):
  688. data = hashlib.sha512(data).digest()
  689. self.SetKey(data[0:32])
  690. self.SetIV(data[32:32+16])
  691. return len(data)
  692. def SetKey(self, key):
  693. self.chKey = [ord(i) for i in key]
  694. def SetIV(self, iv):
  695. self.chIV = [ord(i) for i in iv]
  696. def Encrypt(self, data):
  697. mode, size, cypher = self.m.encrypt(data, self.cbc, self.chKey, self.sz, self.chIV)
  698. return ''.join(map(chr, cypher))
  699. def Decrypt(self, data):
  700. chData = [ord(i) for i in data]
  701. return self.m.decrypt(chData, self.sz, self.cbc, self.chKey, self.sz, self.chIV)
  702. # secp256k1
  703. _p = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2FL
  704. _r = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141L
  705. _b = 0x0000000000000000000000000000000000000000000000000000000000000007L
  706. _a = 0x0000000000000000000000000000000000000000000000000000000000000000L
  707. _Gx = 0x79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798L
  708. _Gy = 0x483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8L
  709. # python-ecdsa code (EC_KEY implementation)
  710. class CurveFp( object ):
  711. def __init__( self, p, a, b ):
  712. self.__p = p
  713. self.__a = a
  714. self.__b = b
  715. def p( self ):
  716. return self.__p
  717. def a( self ):
  718. return self.__a
  719. def b( self ):
  720. return self.__b
  721. def contains_point( self, x, y ):
  722. return ( y * y - ( x * x * x + self.__a * x + self.__b ) ) % self.__p == 0
  723. class Point( object ):
  724. def __init__( self, curve, x, y, order = None ):
  725. self.__curve = curve
  726. self.__x = x
  727. self.__y = y
  728. self.__order = order
  729. if self.__curve: assert self.__curve.contains_point( x, y )
  730. if order: assert self * order == INFINITY
  731. def __add__( self, other ):
  732. if other == INFINITY: return self
  733. if self == INFINITY: return other
  734. assert self.__curve == other.__curve
  735. if self.__x == other.__x:
  736. if ( self.__y + other.__y ) % self.__curve.p() == 0:
  737. return INFINITY
  738. else:
  739. return self.double()
  740. p = self.__curve.p()
  741. l = ( ( other.__y - self.__y ) * \
  742. inverse_mod( other.__x - self.__x, p ) ) % p
  743. x3 = ( l * l - self.__x - other.__x ) % p
  744. y3 = ( l * ( self.__x - x3 ) - self.__y ) % p
  745. return Point( self.__curve, x3, y3 )
  746. def __mul__( self, other ):
  747. def leftmost_bit( x ):
  748. assert x > 0
  749. result = 1L
  750. while result <= x: result = 2 * result
  751. return result / 2
  752. e = other
  753. if self.__order: e = e % self.__order
  754. if e == 0: return INFINITY
  755. if self == INFINITY: return INFINITY
  756. assert e > 0
  757. e3 = 3 * e
  758. negative_self = Point( self.__curve, self.__x, -self.__y, self.__order )
  759. i = leftmost_bit( e3 ) / 2
  760. result = self
  761. while i > 1:
  762. result = result.double()
  763. if ( e3 & i ) != 0 and ( e & i ) == 0: result = result + self
  764. if ( e3 & i ) == 0 and ( e & i ) != 0: result = result + negative_self
  765. i = i / 2
  766. return result
  767. def __rmul__( self, other ):
  768. return self * other
  769. def __str__( self ):
  770. if self == INFINITY: return "infinity"
  771. return "(%d,%d)" % ( self.__x, self.__y )
  772. def double( self ):
  773. if self == INFINITY:
  774. return INFINITY
  775. p = self.__curve.p()
  776. a = self.__curve.a()
  777. l = ( ( 3 * self.__x * self.__x + a ) * \
  778. inverse_mod( 2 * self.__y, p ) ) % p
  779. x3 = ( l * l - 2 * self.__x ) % p
  780. y3 = ( l * ( self.__x - x3 ) - self.__y ) % p
  781. return Point( self.__curve, x3, y3 )
  782. def x( self ):
  783. return self.__x
  784. def y( self ):
  785. return self.__y
  786. def curve( self ):
  787. return self.__curve
  788. def order( self ):
  789. return self.__order
  790. INFINITY = Point( None, None, None )
  791. def inverse_mod( a, m ):
  792. if a < 0 or m <= a: a = a % m
  793. c, d = a, m
  794. uc, vc, ud, vd = 1, 0, 0, 1
  795. while c != 0:
  796. q, c, d = divmod( d, c ) + ( c, )
  797. uc, vc, ud, vd = ud - q*uc, vd - q*vc, uc, vc
  798. assert d == 1
  799. if ud > 0: return ud
  800. else: return ud + m
  801. class Signature( object ):
  802. def __init__( self, r, s ):
  803. self.r = r
  804. self.s = s
  805. class Public_key( object ):
  806. def __init__( self, generator, point ):
  807. self.curve = generator.curve()
  808. self.generator = generator
  809. self.point = point
  810. n = generator.order()
  811. if not n:
  812. raise RuntimeError, "Generator point must have order."
  813. if not n * point == INFINITY:
  814. raise RuntimeError, "Generator point order is bad."
  815. if point.x() < 0 or n <= point.x() or point.y() < 0 or n <= point.y():
  816. raise RuntimeError, "Generator point has x or y out of range."
  817. def verifies( self, hash, signature ):
  818. G = self.generator
  819. n = G.order()
  820. r = signature.r
  821. s = signature.s
  822. if r < 1 or r > n-1: return False
  823. if s < 1 or s > n-1: return False
  824. c = inverse_mod( s, n )
  825. u1 = ( hash * c ) % n
  826. u2 = ( r * c ) % n
  827. xy = u1 * G + u2 * self.point
  828. v = xy.x() % n
  829. return v == r
  830. class Private_key( object ):
  831. def __init__( self, public_key, secret_multiplier ):
  832. self.public_key = public_key
  833. self.secret_multiplier = secret_multiplier
  834. def der( self ):
  835. hex_der_key = '06052b8104000a30740201010420' + \
  836. '%064x' % self.secret_multiplier + \
  837. 'a00706052b8104000aa14403420004' + \
  838. '%064x' % self.public_key.point.x() + \
  839. '%064x' % self.public_key.point.y()
  840. return hex_der_key.decode('hex')
  841. def sign( self, hash, random_k ):
  842. G = self.public_key.generator
  843. n = G.order()
  844. k = random_k % n
  845. p1 = k * G
  846. r = p1.x()
  847. if r == 0: raise RuntimeError, "amazingly unlucky random number r"
  848. s = ( inverse_mod( k, n ) * \
  849. ( hash + ( self.secret_multiplier * r ) % n ) ) % n
  850. if s == 0: raise RuntimeError, "amazingly unlucky random number s"
  851. return Signature( r, s )
  852. class EC_KEY(object):
  853. def __init__( self, secret ):
  854. curve = CurveFp( _p, _a, _b )
  855. generator = Point( curve, _Gx, _Gy, _r )
  856. self.pubkey = Public_key( generator, generator * secret )
  857. self.privkey = Private_key( self.pubkey, secret )
  858. self.secret = secret
  859. # end of python-ecdsa code
  860. # pywallet openssl private key implementation
  861. def i2d_ECPrivateKey(pkey, compressed=False):
  862. if compressed:
  863. key = '3081d30201010420' + \
  864. '%064x' % pkey.secret + \
  865. 'a081a53081a2020101302c06072a8648ce3d0101022100' + \
  866. '%064x' % _p + \
  867. '3006040100040107042102' + \
  868. '%064x' % _Gx + \
  869. '022100' + \
  870. '%064x' % _r + \
  871. '020101a124032200'
  872. else:
  873. key = '308201130201010420' + \
  874. '%064x' % pkey.secret + \
  875. 'a081a53081a2020101302c06072a8648ce3d0101022100' + \
  876. '%064x' % _p + \
  877. '3006040100040107044104' + \
  878. '%064x' % _Gx + \
  879. '%064x' % _Gy + \
  880. '022100' + \
  881. '%064x' % _r + \
  882. '020101a144034200'
  883. return key.decode('hex') + i2o_ECPublicKey(pkey, compressed)
  884. def i2o_ECPublicKey(pkey, compressed=False):
  885. # public keys are 65 bytes long (520 bits)
  886. # 0x04 + 32-byte X-coordinate + 32-byte Y-coordinate
  887. # 0x00 = point at infinity, 0x02 and 0x03 = compressed, 0x04 = uncompressed
  888. # compressed keys: <sign> <x> where <sign> is 0x02 if y is even and 0x03 if y is odd
  889. if compressed:
  890. if pkey.pubkey.point.y() & 1:
  891. key = '03' + '%064x' % pkey.pubkey.point.x()
  892. else:
  893. key = '02' + '%064x' % pkey.pubkey.point.x()
  894. else:
  895. key = '04' + \
  896. '%064x' % pkey.pubkey.point.x() + \
  897. '%064x' % pkey.pubkey.point.y()
  898. return key.decode('hex')
  899. # bitcointools hashes and base58 implementation
  900. def hash_160(public_key):
  901. md = hashlib.new('ripemd160')
  902. md.update(hashlib.sha256(public_key).digest())
  903. return md.digest()
  904. def public_key_to_bc_address(public_key):
  905. h160 = hash_160(public_key)
  906. return hash_160_to_bc_address(h160)
  907. def hash_160_to_bc_address(h160):
  908. vh160 = chr(addrtype) + h160
  909. h = Hash(vh160)
  910. addr = vh160 + h[0:4]
  911. return b58encode(addr)
  912. def bc_address_to_hash_160(addr):
  913. bytes = b58decode(addr, 25)
  914. return bytes[1:21]
  915. __b58chars = '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz'
  916. __b58base = len(__b58chars)
  917. def b58encode(v):
  918. """ encode v, which is a string of bytes, to base58.
  919. """
  920. long_value = 0L
  921. for (i, c) in enumerate(v[::-1]):
  922. long_value += (256**i) * ord(c)
  923. result = ''
  924. while long_value >= __b58base:
  925. div, mod = divmod(long_value, __b58base)
  926. result = __b58chars[mod] + result
  927. long_value = div
  928. result = __b58chars[long_value] + result
  929. # Bitcoin does a little leading-zero-compression:
  930. # leading 0-bytes in the input become leading-1s
  931. nPad = 0
  932. for c in v:
  933. if c == '\0': nPad += 1
  934. else: break
  935. return (__b58chars[0]*nPad) + result
  936. def b58decode(v, length):
  937. """ decode v into a string of len bytes
  938. """
  939. long_value = 0L
  940. for (i, c) in enumerate(v[::-1]):
  941. long_value += __b58chars.find(c) * (__b58base**i)
  942. result = ''
  943. while long_value >= 256:
  944. div, mod = divmod(long_value, 256)
  945. result = chr(mod) + result
  946. long_value = div
  947. result = chr(long_value) + result
  948. nPad = 0
  949. for c in v:
  950. if c == __b58chars[0]: nPad += 1
  951. else: break
  952. result = chr(0)*nPad + result
  953. if length is not None and len(result) != length:
  954. return None
  955. return result
  956. # end of bitcointools base58 implementation
  957. # address handling code
  958. def Hash(data):
  959. return hashlib.sha256(hashlib.sha256(data).digest()).digest()
  960. def EncodeBase58Check(secret):
  961. hash = Hash(secret)
  962. return b58encode(secret + hash[0:4])
  963. def DecodeBase58Check(sec):
  964. vchRet = b58decode(sec, None)
  965. secret = vchRet[0:-4]
  966. csum = vchRet[-4:]
  967. hash = Hash(secret)
  968. cs32 = hash[0:4]
  969. if cs32 != csum:
  970. return None
  971. else:
  972. return secret
  973. def PrivKeyToSecret(privkey):
  974. if len(privkey) == 279:
  975. return privkey[9:9+32]
  976. else:
  977. return privkey[8:8+32]
  978. def SecretToASecret(secret, compressed=False):
  979. vchIn = chr((addrtype+128)&255) + secret
  980. if compressed: vchIn += '\01'
  981. return EncodeBase58Check(vchIn)
  982. def ASecretToSecret(sec):
  983. vch = DecodeBase58Check(sec)
  984. if vch and vch[0] == chr((addrtype+128)&255):
  985. return vch[1:]
  986. else:
  987. return False
  988. def regenerate_key(sec):
  989. b = ASecretToSecret(sec)
  990. if not b:
  991. return False
  992. b = b[0:32]
  993. secret = int('0x' + b.encode('hex'), 16)
  994. return EC_KEY(secret)
  995. def GetPubKey(pkey, compressed=False):
  996. return i2o_ECPublicKey(pkey, compressed)
  997. def GetPrivKey(pkey, compressed=False):
  998. return i2d_ECPrivateKey(pkey, compressed)
  999. def GetSecret(pkey):
  1000. return ('%064x' % pkey.secret).decode('hex')
  1001. def is_compressed(sec):
  1002. b = ASecretToSecret(sec)
  1003. return len(b) == 33
  1004. # bitcointools wallet.dat handling code
  1005. def create_env(db_dir):
  1006. db_env = DBEnv(0)
  1007. r = db_env.open(db_dir, (DB_CREATE|DB_INIT_LOCK|DB_INIT_LOG|DB_INIT_MPOOL|DB_INIT_TXN|DB_THREAD|DB_RECOVER))
  1008. return db_env
  1009. def parse_CAddress(vds):
  1010. d = {'ip':'0.0.0.0','port':0,'nTime': 0}
  1011. try:
  1012. d['nVersion'] = vds.read_int32()
  1013. d['nTime'] = vds.read_uint32()
  1014. d['nServices'] = vds.read_uint64()
  1015. d['pchReserved'] = vds.read_bytes(12)
  1016. d['ip'] = socket.inet_ntoa(vds.read_bytes(4))
  1017. d['port'] = vds.read_uint16()
  1018. except:
  1019. pass
  1020. return d
  1021. def deserialize_CAddress(d):
  1022. return d['ip']+":"+str(d['port'])
  1023. def parse_BlockLocator(vds):
  1024. d = { 'hashes' : [] }
  1025. nHashes = vds.read_compact_size()
  1026. for i in xrange(nHashes):
  1027. d['hashes'].append(vds.read_bytes(32))
  1028. return d
  1029. def deserialize_BlockLocator(d):
  1030. result = "Block Locator top: "+d['hashes'][0][::-1].encode('hex_codec')
  1031. return result
  1032. def parse_setting(setting, vds):
  1033. if setting[0] == "f": # flag (boolean) settings
  1034. return str(vds.read_boolean())
  1035. elif setting[0:4] == "addr": # CAddress
  1036. d = parse_CAddress(vds)
  1037. return deserialize_CAddress(d)
  1038. elif setting == "nTransactionFee":
  1039. return vds.read_int64()
  1040. elif setting == "nLimitProcessors":
  1041. return vds.read_int32()
  1042. return 'unknown setting'
  1043. class SerializationError(Exception):
  1044. """ Thrown when there's a problem deserializing or serializing """
  1045. class BCDataStream(object):
  1046. def __init__(self):
  1047. self.input = None
  1048. self.read_cursor = 0
  1049. def clear(self):
  1050. self.input = None
  1051. self.read_cursor = 0
  1052. def write(self, bytes): # Initialize with string of bytes
  1053. if self.input is None:
  1054. self.input = bytes
  1055. else:
  1056. self.input += bytes
  1057. def map_file(self, file, start): # Initialize with bytes from file
  1058. self.input = mmap.mmap(file.fileno(), 0, access=mmap.ACCESS_READ)
  1059. self.read_cursor = start
  1060. def seek_file(self, position):
  1061. self.read_cursor = position
  1062. def close_file(self):
  1063. self.input.close()
  1064. def read_string(self):
  1065. # Strings are encoded depending on length:
  1066. # 0 to 252 : 1-byte-length followed by bytes (if any)
  1067. # 253 to 65,535 : byte'253' 2-byte-length followed by bytes
  1068. # 65,536 to 4,294,967,295 : byte '254' 4-byte-length followed by bytes
  1069. # ... and the Bitcoin client is coded to understand:
  1070. # greater than 4,294,967,295 : byte '255' 8-byte-length followed by bytes of string
  1071. # ... but I don't think it actually handles any strings that big.
  1072. if self.input is None:
  1073. raise SerializationError("call write(bytes) before trying to deserialize")
  1074. try:
  1075. length = self.read_compact_size()
  1076. except IndexError:
  1077. raise SerializationError("attempt to read past end of buffer")
  1078. return self.read_bytes(length)
  1079. def write_string(self, string):
  1080. # Length-encoded as with read-string
  1081. self.write_compact_size(len(string))
  1082. self.write(string)
  1083. def read_bytes(self, length):
  1084. try:
  1085. result = self.input[self.read_cursor:self.read_cursor+length]
  1086. self.read_cursor += length
  1087. return result
  1088. except IndexError:
  1089. raise SerializationError("attempt to read past end of buffer")
  1090. return ''
  1091. def read_boolean(self): return self.read_bytes(1)[0] != chr(0)
  1092. def read_int16(self): return self._read_num('<h')
  1093. def read_uint16(self): return self._read_num('<H')
  1094. def read_int32(self): return self._read_num('<i')
  1095. def read_uint32(self): return self._read_num('<I')
  1096. def read_int64(self): return self._read_num('<q')
  1097. def read_uint64(self): return self._read_num('<Q')
  1098. def write_boolean(self, val): return self.write(chr(1) if val else chr(0))
  1099. def write_int16(self, val): return self._write_num('<h', val)
  1100. def write_uint16(self, val): return self._write_num('<H', val)
  1101. def write_int32(self, val): return self._write_num('<i', val)
  1102. def write_uint32(self, val): return self._write_num('<I', val)
  1103. def write_int64(self, val): return self._write_num('<q', val)
  1104. def write_uint64(self, val): return self._write_num('<Q', val)
  1105. def read_compact_size(self):
  1106. size = ord(self.input[self.read_cursor])
  1107. self.read_cursor += 1
  1108. if size == 253:
  1109. size = self._read_num('<H')
  1110. elif size == 254:
  1111. size = self._read_num('<I')
  1112. elif size == 255:
  1113. size = self._read_num('<Q')
  1114. return size
  1115. def write_compact_size(self, size):
  1116. if size < 0:
  1117. raise SerializationError("attempt to write size < 0")
  1118. elif size < 253:
  1119. self.write(chr(size))
  1120. elif size < 2**16:
  1121. self.write('\xfd')
  1122. self._write_num('<H', size)
  1123. elif size < 2**32:
  1124. self.write('\xfe')
  1125. self._write_num('<I', size)
  1126. elif size < 2**64:
  1127. self.write('\xff')
  1128. self._write_num('<Q', size)
  1129. def _read_num(self, format):
  1130. (i,) = struct.unpack_from(format, self.input, self.read_cursor)
  1131. self.read_cursor += struct.calcsize(format)
  1132. return i
  1133. def _write_num(self, format, num):
  1134. s = struct.pack(format, num)
  1135. self.write(s)
  1136. def open_wallet(db_env, db_file="wallet.dat", writable=False):
  1137. db = DB(db_env)
  1138. flags = DB_THREAD | (DB_CREATE if writable else DB_RDONLY)
  1139. try:
  1140. r = db.open(db_file, "main", DB_BTREE, flags)
  1141. except DBError:
  1142. r = True
  1143. if r is not None:
  1144. logging.error("Couldn't open " + db_file + "/main. Try quitting Bitcoin and running this again.")
  1145. sys.exit(1)
  1146. return db
  1147. def parse_wallet(db, item_callback):
  1148. kds = BCDataStream()
  1149. vds = BCDataStream()
  1150. for (key, value) in db.items():
  1151. d = { }
  1152. kds.clear(); kds.write(key)
  1153. vds.clear(); vds.write(value)
  1154. type = kds.read_string()
  1155. d["__key__"] = key
  1156. d["__value__"] = value
  1157. d["__type__"] = type
  1158. try:
  1159. if type == "tx":
  1160. d["tx_id"] = kds.read_bytes(32)
  1161. elif type == "name":
  1162. d['hash'] = kds.read_string()
  1163. d['name'] = vds.read_string()
  1164. elif type == "version":
  1165. d['version'] = vds.read_uint32()
  1166. elif type == "minversion":
  1167. d['minversion'] = vds.read_uint32()
  1168. elif type == "setting":
  1169. d['setting'] = kds.read_string()
  1170. d['value'] = parse_setting(d['setting'], vds)
  1171. elif type == "key":
  1172. d['public_key'] = kds.read_bytes(kds.read_compact_size())
  1173. d['private_key'] = vds.read_bytes(vds.read_compact_size())
  1174. elif type == "wkey":
  1175. d['public_key'] = kds.read_bytes(kds.read_compact_size())
  1176. d['private_key'] = vds.read_bytes(vds.read_compact_size())
  1177. d['created'] = vds.read_int64()
  1178. d['expires'] = vds.read_int64()
  1179. d['comment'] = vds.read_string()
  1180. elif type == "ckey":
  1181. d['public_key'] = kds.read_bytes(kds.read_compact_size())
  1182. d['crypted_key'] = vds.read_bytes(vds.read_compact_size())
  1183. elif type == "mkey":
  1184. d['nID'] = kds.read_int32()
  1185. d['crypted_key'] = vds.read_bytes(vds.read_compact_size())
  1186. d['salt'] = vds.read_bytes(vds.read_compact_size())
  1187. d['nDerivationMethod'] = vds.read_int32()
  1188. d['nDeriveIterations'] = vds.read_int32()
  1189. d['vchOtherDerivationParameters'] = vds.read_bytes(vds.read_compact_size())
  1190. elif type == "defaultkey":
  1191. d['key'] = vds.read_bytes(vds.read_compact_size())
  1192. elif type == "pool":
  1193. d['n'] = kds.read_int64()
  1194. d['nVersion'] = vds.read_int32()
  1195. d['nTime'] = vds.read_int64()
  1196. d['public_key'] = vds.read_bytes(vds.read_compact_size())
  1197. elif type == "acc":
  1198. d['account'] = kds.read_string()
  1199. d['nVersion'] = vds.read_int32()
  1200. d['public_key'] = vds.read_bytes(vds.read_compact_size())
  1201. elif type == "acentry":
  1202. d['account'] = kds.read_string()
  1203. d['n'] = kds.read_uint64()
  1204. d['nVersion'] = vds.read_int32()
  1205. d['nCreditDebit'] = vds.read_int64()
  1206. d['nTime'] = vds.read_int64()
  1207. d['otherAccount'] = vds.read_string()
  1208. d['comment'] = vds.read_string()
  1209. elif type == "bestblock":
  1210. d['nVersion'] = vds.read_int32()
  1211. d.update(parse_BlockLocator(vds))
  1212. item_callback(type, d)
  1213. except Exception, e:
  1214. traceback.print_exc()
  1215. print("ERROR parsing wallet.dat, type %s" % type)
  1216. print("key data in hex: %s"%key.encode('hex_codec'))
  1217. print("value data in hex: %s"%value.encode('hex_codec'))
  1218. sys.exit(1)
  1219. def update_wallet(db, type, data):
  1220. """Write a single item to the wallet.
  1221. db must be open with writable=True.
  1222. type and data are the type code and data dictionary as parse_wallet would
  1223. give to item_callback.
  1224. data's __key__, __value__ and __type__ are ignored; only the primary data
  1225. fields are used.
  1226. """
  1227. d = data
  1228. kds = BCDataStream()
  1229. vds = BCDataStream()
  1230. # Write the type code to the key
  1231. kds.write_string(type)
  1232. vds.write("") # Ensure there is something
  1233. try:
  1234. if type == "tx":
  1235. raise NotImplementedError("Writing items of type 'tx'")
  1236. kds.write(d['tx_id'])
  1237. elif type == "name":
  1238. kds.write_string(d['hash'])
  1239. vds.write_string(d['name'])
  1240. elif type == "version":
  1241. vds.write_uint32(d['version'])
  1242. elif type == "minversion":
  1243. vds.write_uint32(d['minversion'])
  1244. elif type == "setting":
  1245. raise NotImplementedError("Writing items of type 'setting'")
  1246. kds.write_string(d['setting'])
  1247. #d['value'] = parse_setting(d['setting'], vds)
  1248. elif type == "key":
  1249. kds.write_string(d['public_key'])
  1250. vds.write_string(d['private_key'])
  1251. elif type == "wkey":
  1252. kds.write_string(d['public_key'])
  1253. vds.write_string(d['private_key'])
  1254. vds.write_int64(d['created'])
  1255. vds.write_int64(d['expires'])
  1256. vds.write_string(d['comment'])
  1257. elif type == "ckey":
  1258. kds.write_string(d['public_key'])
  1259. vds.write_string(d['crypted_key'])
  1260. elif type == "defaultkey":
  1261. vds.write_string(d['key'])
  1262. elif type == "pool":
  1263. kds.write_int64(d['n'])
  1264. vds.write_int32(d['nVersion'])
  1265. vds.write_int64(d['nTime'])
  1266. vds.write_string(d['public_key'])
  1267. elif type == "acc":
  1268. kds.write_string(d['account'])
  1269. vds.write_int32(d['nVersion'])
  1270. vds.write_string(d['public_key'])
  1271. elif type == "acentry":
  1272. kds.write_string(d['account'])
  1273. kds.write_uint64(d['n'])
  1274. vds.write_int32(d['nVersion'])
  1275. vds.write_int64(d['nCreditDebit'])
  1276. vds.write_int64(d['nTime'])
  1277. vds.write_string(d['otherAccount'])
  1278. vds.write_string(d['comment'])
  1279. elif type == "bestblock":
  1280. vds.write_int32(d['nVersion'])
  1281. vds.write_compact_size(len(d['hashes']))
  1282. for h in d['hashes']:
  1283. vds.write(h)
  1284. else:
  1285. print "Unknown key type: "+type
  1286. # Write the key/value pair to the database
  1287. db.put(kds.input, vds.input)
  1288. except Exception, e:
  1289. print("ERROR writing to wallet.dat, type %s"%type)
  1290. print("data dictionary: %r"%data)
  1291. traceback.print_exc()
  1292. # def rewrite_wallet(db_env, destFileName, pre_put_callback=None):
  1293. # db = open_wallet(db_env)
  1294. #
  1295. # db_out = DB(db_env)
  1296. # try:
  1297. # r = db_out.open(destFileName, "main", DB_BTREE, DB_CREATE)
  1298. # except DBError:
  1299. # r = True
  1300. #
  1301. # if r is not None:
  1302. # logging.error("Couldn't open %s."%destFileName)
  1303. # sys.exit(1)
  1304. #
  1305. # def item_callback(type, d):
  1306. # if (pre_put_callback is None or pre_put_callback(type, d)):
  1307. # db_out.put(d["__key__"], d["__value__"])
  1308. #
  1309. # parse_wallet(db, item_callback)
  1310. # db_out.close()
  1311. # db.close()
  1312. #
  1313. # end of bitcointools wallet.dat handling code
  1314. # wallet.dat reader / writer
  1315. def read_wallet(json_db, db_env, db_file, print_wallet, print_wallet_transactions, transaction_filter):
  1316. db = open_wallet(db_env, db_file)
  1317. json_db['keys'] = []
  1318. json_db['pool'] = []
  1319. json_db['names'] = {}
  1320. def item_callback(type, d):
  1321. global password
  1322. if type == "name":
  1323. json_db['names'][d['hash']] = d['name']
  1324. elif type == "version":
  1325. json_db['version'] = d['version']
  1326. elif type == "minversion":
  1327. json_db['minversion'] = d['minversion']
  1328. elif type == "setting":
  1329. if not json_db.has_key('settings'): json_db['settings'] = {}
  1330. json_db["settings"][d['setting']] = d['value']
  1331. elif type == "defaultkey":
  1332. json_db['defaultkey'] = public_key_to_bc_address(d['key'])
  1333. elif type == "key":
  1334. addr = public_key_to_bc_address(d['public_key'])
  1335. compressed = d['public_key'][0] != '\04'
  1336. sec = SecretToASecret(PrivKeyToSecret(d['private_key']), compressed)
  1337. private_keys.append(sec)
  1338. json_db['keys'].append({'addr' : addr, 'sec' : sec})
  1339. # json_db['keys'].append({'addr' : addr, 'sec' : sec,
  1340. # 'secret':PrivKeyToSecret(d['private_key']).encode('hex'),
  1341. # 'pubkey':d['public_key'].encode('hex'),
  1342. # 'privkey':d['private_key'].encode('hex')})
  1343. elif type == "wkey":
  1344. if not json_db.has_key('wkey'): json_db['wkey'] = []
  1345. json_db['wkey']['created'] = d['created']
  1346. elif type == "ckey":
  1347. addr = public_key_to_bc_address(d['public_key'])
  1348. ckey = d['crypted_key']
  1349. pubkey = d['public_key']
  1350. json_db['keys'].append( {'addr' : addr, 'ckey': ckey.encode('hex'), 'pubkey': pubkey.encode('hex') })
  1351. elif type == "mkey":
  1352. mkey = {}
  1353. mkey['nID'] = d['nID']
  1354. mkey['crypted_key'] = d['crypted_key'].encode('hex')
  1355. mkey['salt'] = d['salt'].encode('hex')
  1356. mkey['nDeriveIterations'] = d['nDeriveIterations']
  1357. mkey['nDerivationMethod'] = d['nDerivationMethod']
  1358. mkey['vchOtherDerivationParameters'] = d['vchOtherDerivationParameters'].encode('hex')
  1359. json_db['mkey'] = mkey
  1360. if password == None and \
  1361. ('json' in opts or 'keysforaddrs' in opts or 'keys' in opts):
  1362. from mmgen.utils import my_getpass
  1363. password = my_getpass("Enter password: ")
  1364. if password != None:
  1365. global crypter
  1366. if crypter == 'pycrypto':
  1367. crypter = Crypter_pycrypto()
  1368. elif crypter == 'ssl':
  1369. crypter = Crypter_ssl()
  1370. else:
  1371. crypter = Crypter_pure()
  1372. logging.warning("pycrypto or libssl not found, decryption may be slow")
  1373. res = crypter.SetKeyFromPassphrase(password, d['salt'], d['nDeriveIterations'], d['nDerivationMethod'])
  1374. if res == 0:
  1375. logging.error("Unsupported derivation method")
  1376. sys.exit(1)
  1377. masterkey = crypter.Decrypt(d['crypted_key'])
  1378. crypter.SetKey(masterkey)
  1379. elif type == "pool":
  1380. json_db['pool'].append( {'n': d['n'], 'addr': public_key_to_bc_address(d['public_key']), 'nTime' : d['nTime'] } )
  1381. elif type == "acc":
  1382. json_db['acc'] = d['account']
  1383. # msg("Account %s (current key: %s)"%(d['account'], public_key_to_bc_address(d['public_key'])))
  1384. elif type == "acentry":
  1385. json_db['acentry'] = (d['account'], d['nCreditDebit'], d['otherAccount'], time.ctime(d['nTime']), d['n'], d['comment'])
  1386. elif type == "bestblock":
  1387. json_db['bestblock'] = d['hashes'][0][::-1].encode('hex_codec')
  1388. else:
  1389. json_db[type] = 'unsupported'
  1390. parse_wallet(db, item_callback)
  1391. db.close()
  1392. for k in json_db['keys']:
  1393. addr = k['addr']
  1394. if addr in json_db['names'].keys():
  1395. k["label"] = json_db['names'][addr]
  1396. else:
  1397. k["reserve"] = 1
  1398. if 'mkey' in json_db.keys() and password != None:
  1399. check = True
  1400. for k in json_db['keys']:
  1401. ckey = k['ckey'].decode('hex')
  1402. public_key = k['pubkey'].decode('hex')
  1403. crypter.SetIV(Hash(public_key))
  1404. secret = crypter.Decrypt(ckey)
  1405. compressed = public_key[0] != '\04'
  1406. if check:
  1407. check = False
  1408. pkey = EC_KEY(int('0x' + secret.encode('hex'), 16))
  1409. if public_key != GetPubKey(pkey, compressed):
  1410. logging.error("wrong password")
  1411. sys.exit(1)
  1412. sec = SecretToASecret(secret, compressed)
  1413. k['sec'] = sec
  1414. k['secret'] = secret.encode('hex')
  1415. del(k['ckey'])
  1416. del(k['secret'])
  1417. del(k['pubkey'])
  1418. private_keys.append(sec)
  1419. del(json_db['pool'])
  1420. del(json_db['names'])
  1421. def parse_wallet_file_arg(path):
  1422. s = path.rfind("/")
  1423. if path[0] == '/':
  1424. if s == 0: return "/", path
  1425. else: return path[0:s], path[s+1:]
  1426. else:
  1427. curdir = os.path.abspath(".")
  1428. if s == -1: return curdir,path
  1429. else: return curdir + "/" + path[0:s], path[s+1:]
  1430. # main()
  1431. db_dir,db_file = parse_wallet_file_arg(cmd_args[0])
  1432. # print "[%s] [%s]" % (db_dir,db_file)
  1433. db_env = create_env(db_dir)
  1434. read_wallet(json_db, db_env, db_file, True, True, "")
  1435. if json_db.get('minversion') > max_version:
  1436. print "Version mismatch (must be <= %d)" % max_version
  1437. exit(1)
  1438. wallet_addrs = [i['addr'] for i in json_db['keys']]
  1439. data,ext,what = [],"",""
  1440. if 'json' in opts:
  1441. data = [ json.dumps(json_db, sort_keys=True, indent=4) ]
  1442. ext,what = "json","json dump"
  1443. elif 'keys' in opts:
  1444. for i in json_db['keys']: data.append(i['sec'])
  1445. ext,what = "keys","private keys"
  1446. elif 'addrs' in opts:
  1447. for i in json_db['keys']: data.append(i['addr'])
  1448. ext,what = "addrs","addresses"
  1449. elif 'keysforaddrs' in opts:
  1450. from mmgen.utils import get_lines_from_file
  1451. usr_addrs = get_lines_from_file(opts['keysforaddrs'],"addresses")
  1452. for addr in usr_addrs:
  1453. try:
  1454. idx = wallet_addrs.index(addr)
  1455. data.append(json_db['keys'][idx]['sec'])
  1456. except:
  1457. msg("WARNING: Address '%s' not found" % addr)
  1458. ext,what = "keys","private keys"
  1459. len_arg = "%s" % len(wallet_addrs) \
  1460. if len(data) == len(wallet_addrs) or ext == "json" \
  1461. else "%s:%s" % (len(data),len(wallet_addrs))
  1462. from mmgen.utils import make_chksum_8,write_walletdat_dump_to_file,write_to_stdout
  1463. wallet_id = make_chksum_8(str(sorted(wallet_addrs)))
  1464. data = "\n".join(data) + "\n"
  1465. # Output data
  1466. if 'stdout' in opts:
  1467. if 'addrs' in opts or 'quiet' in opts: confirm = False
  1468. else: confirm = True
  1469. write_to_stdout(data,"secret keys",confirm)
  1470. elif not sys.stdout.isatty():
  1471. write_to_stdout(data,"secret keys",confirm=False)
  1472. else:
  1473. write_walletdat_dump_to_file(wallet_id, data, len_arg, ext, what, opts)