3535 bip32_private_key , bip32_derivation , BIP32_PRIME ,
3636 is_xpub , is_xprv )
3737from .ecc import string_to_number , number_to_string
38- from .crypto import pw_decode , pw_encode , sha256d
38+ from .crypto import ( pw_decode , pw_encode , sha256d , PW_HASH_VERSION_LATEST )
3939from .util import (PrintError , InvalidPassword , hfu , WalletFileException ,
4040 BitcoinException , bh2u , bfh , print_error , inv_dict )
4141from .mnemonic import Mnemonic , load_wordlist
@@ -92,8 +92,9 @@ def ready_to_sign(self):
9292
9393class Software_KeyStore (KeyStore ):
9494
95- def __init__ (self ):
95+ def __init__ (self , d ):
9696 KeyStore .__init__ (self )
97+ self .pw_hash_version = d .get ('pw_hash_version' , 1 )
9798
9899 def may_have_password (self ):
99100 return not self .is_watching_only ()
@@ -122,14 +123,20 @@ def sign_transaction(self, tx, password):
122123 if keypairs :
123124 tx .sign (keypairs )
124125
126+ def update_password (self , old_password , new_password ):
127+ raise NotImplementedError () # implemented by subclasses
128+
129+ def check_password (self , password ):
130+ raise NotImplementedError () # implemented by subclasses
131+
125132
126133class Imported_KeyStore (Software_KeyStore ):
127134 # keystore for imported private keys
128135
129136 type = 'imported'
130137
131138 def __init__ (self , d ):
132- Software_KeyStore .__init__ (self )
139+ Software_KeyStore .__init__ (self , d )
133140 self .keypairs = d .get ('keypairs' , {})
134141
135142 def is_deterministic (self ):
@@ -142,6 +149,7 @@ def dump(self):
142149 return {
143150 'type' : self .type ,
144151 'keypairs' : self .keypairs ,
152+ 'pw_hash_version' : self .pw_hash_version ,
145153 }
146154
147155 def can_import (self ):
@@ -161,14 +169,14 @@ def import_privkey(self, sec, password):
161169 # there will only be one pubkey-privkey pair for it in self.keypairs,
162170 # and the privkey will encode a txin_type but that txin_type cannot be trusted.
163171 # Removing keys complicates this further.
164- self .keypairs [pubkey ] = pw_encode (serialized_privkey , password )
172+ self .keypairs [pubkey ] = pw_encode (serialized_privkey , password , version = self . pw_hash_version )
165173 return txin_type , pubkey
166174
167175 def delete_imported_key (self , key ):
168176 self .keypairs .pop (key )
169177
170178 def get_private_key (self , pubkey , password ):
171- sec = pw_decode (self .keypairs [pubkey ], password )
179+ sec = pw_decode (self .keypairs [pubkey ], password , version = self . pw_hash_version )
172180 txin_type , privkey , compressed = deserialize_privkey (sec )
173181 # this checks the password
174182 if pubkey != ecc .ECPrivkey (privkey ).get_public_key_hex (compressed = compressed ):
@@ -189,29 +197,32 @@ def update_password(self, old_password, new_password):
189197 if new_password == '' :
190198 new_password = None
191199 for k , v in self .keypairs .items ():
192- b = pw_decode (v , old_password )
193- c = pw_encode (b , new_password )
200+ b = pw_decode (v , old_password , version = self . pw_hash_version )
201+ c = pw_encode (b , new_password , version = PW_HASH_VERSION_LATEST )
194202 self .keypairs [k ] = c
203+ self .pw_hash_version = PW_HASH_VERSION_LATEST
195204
196205
197206
198207class Deterministic_KeyStore (Software_KeyStore ):
199208
200209 def __init__ (self , d ):
201- Software_KeyStore .__init__ (self )
210+ Software_KeyStore .__init__ (self , d )
202211 self .seed = d .get ('seed' , '' )
203212 self .passphrase = d .get ('passphrase' , '' )
204213
205214 def is_deterministic (self ):
206215 return True
207216
208217 def dump (self ):
209- d = {}
218+ d = {
219+ 'type' : self .type ,
220+ 'pw_hash_version' : self .pw_hash_version ,
221+ }
210222 if self .seed :
211223 d ['seed' ] = self .seed
212224 if self .passphrase :
213225 d ['passphrase' ] = self .passphrase
214- d ['type' ] = self .type
215226 return d
216227
217228 def has_seed (self ):
@@ -226,10 +237,13 @@ def add_seed(self, seed):
226237 self .seed = self .format_seed (seed )
227238
228239 def get_seed (self , password ):
229- return pw_decode (self .seed , password )
240+ return pw_decode (self .seed , password , version = self . pw_hash_version )
230241
231242 def get_passphrase (self , password ):
232- return pw_decode (self .passphrase , password ) if self .passphrase else ''
243+ if self .passphrase :
244+ return pw_decode (self .passphrase , password , version = self .pw_hash_version )
245+ else :
246+ return ''
233247
234248
235249class Xpub :
@@ -312,10 +326,10 @@ def dump(self):
312326 return d
313327
314328 def get_master_private_key (self , password ):
315- return pw_decode (self .xprv , password )
329+ return pw_decode (self .xprv , password , version = self . pw_hash_version )
316330
317331 def check_password (self , password ):
318- xprv = pw_decode (self .xprv , password )
332+ xprv = pw_decode (self .xprv , password , version = self . pw_hash_version )
319333 if deserialize_xprv (xprv )[4 ] != deserialize_xpub (self .xpub )[4 ]:
320334 raise InvalidPassword ()
321335
@@ -325,13 +339,14 @@ def update_password(self, old_password, new_password):
325339 new_password = None
326340 if self .has_seed ():
327341 decoded = self .get_seed (old_password )
328- self .seed = pw_encode (decoded , new_password )
342+ self .seed = pw_encode (decoded , new_password , version = PW_HASH_VERSION_LATEST )
329343 if self .passphrase :
330344 decoded = self .get_passphrase (old_password )
331- self .passphrase = pw_encode (decoded , new_password )
345+ self .passphrase = pw_encode (decoded , new_password , version = PW_HASH_VERSION_LATEST )
332346 if self .xprv is not None :
333- b = pw_decode (self .xprv , old_password )
334- self .xprv = pw_encode (b , new_password )
347+ b = pw_decode (self .xprv , old_password , version = self .pw_hash_version )
348+ self .xprv = pw_encode (b , new_password , version = PW_HASH_VERSION_LATEST )
349+ self .pw_hash_version = PW_HASH_VERSION_LATEST
335350
336351 def is_watching_only (self ):
337352 return self .xprv is None
@@ -362,7 +377,7 @@ def __init__(self, d):
362377 self .mpk = d .get ('mpk' )
363378
364379 def get_hex_seed (self , password ):
365- return pw_decode (self .seed , password ).encode ('utf8' )
380+ return pw_decode (self .seed , password , version = self . pw_hash_version ).encode ('utf8' )
366381
367382 def dump (self ):
368383 d = Deterministic_KeyStore .dump (self )
@@ -484,8 +499,9 @@ def update_password(self, old_password, new_password):
484499 if new_password == '' :
485500 new_password = None
486501 if self .has_seed ():
487- decoded = pw_decode (self .seed , old_password )
488- self .seed = pw_encode (decoded , new_password )
502+ decoded = pw_decode (self .seed , old_password , version = self .pw_hash_version )
503+ self .seed = pw_encode (decoded , new_password , version = PW_HASH_VERSION_LATEST )
504+ self .pw_hash_version = PW_HASH_VERSION_LATEST
489505
490506
491507
0 commit comments