@@ -104,11 +104,41 @@ class Helper:
104104 @staticmethod
105105 def pinToAesKey (pin , salt = "" , iterations = 2048 , hashfn = sha256 , phase1_key_length = 16 , phase2_key_length = 32 ):
106106 # use pbkdf2 magic
107- # ( password, keylen, salt = "", itercount = 1024, hashfn = sha256 )
108107 ret = pbkdf2 .pbkdf2 (pin , phase1_key_length , salt , int (iterations / 2 ), hashfn )
109108 ret = pbkdf2 .pbkdf2 (hexlify (ret ), phase2_key_length , salt , int (iterations / 2 ), hashfn )
110109 return hexlify (ret ) # the encryption key
111110
111+ @staticmethod
112+ def dynamicExtractKey (user_key , pin ):
113+ # uses the algorithm specified in the user_key object
114+ # if no algorithm specified, uses the following default (legacy)
115+
116+ algorithm = {
117+ "pbkdf2_salt" : "" ,
118+ "pbkdf2_iterations" : 2048 ,
119+ "pbkdf2_hash_function" : "SHA256" ,
120+ "pbkdf2_phase1_key_length" : 16 ,
121+ "pbkdf2_phase2_key_length" : 32 ,
122+ "aes_iv" : None ,
123+ "aes_cipher" : "AES-256-ECB" ,
124+ "aes_auth_tag" : None ,
125+ "aes_auth_data" : None
126+ }
127+
128+ if 'algorithm' in user_key :
129+ algorithm = user_key ['algorithm' ]
130+
131+ if algorithm ['pbkdf2_hash_function' ] != "SHA256" :
132+ raise Exception ("Unknown hash function specified. Are you using current version of this library?" )
133+
134+ aes_key = BlockIo .Helper .pinToAesKey (pin , algorithm ['pbkdf2_salt' ], algorithm ['pbkdf2_iterations' ],
135+ sha256 , algorithm ['pbkdf2_phase1_key_length' ], algorithm ['pbkdf2_phase2_key_length' ])
136+
137+ decrypted = BlockIo .Helper .decrypt (user_key ['encrypted_passphrase' ], aes_key ,
138+ algorithm ['aes_iv' ], algorithm ['aes_cipher' ], algorithm ['aes_auth_tag' ])
139+
140+ return BlockIo .Key .from_passphrase (unhexlify (decrypted ))
141+
112142 @staticmethod
113143 def extractKey (encrypted_data , enc_key_hex ):
114144 # encryption key is in hex
@@ -304,15 +334,13 @@ def create_and_sign_transaction(self, prepare_data, keys = []):
304334 cur_key = PrivateKey (secret_exponent = int (cur_key_hex ,16 ))
305335 self .private_keys [cur_key .get_public_key ().to_hex (compressed = True )] = cur_key
306336
307- if self .encryption_key is None and self . pin is None and 'user_key' in prepare_data ['data' ]:
337+ if self .pin is None and 'user_key' in prepare_data ['data' ] and prepare_data [ 'data' ][ 'user_key' ][ 'public_key' ] not in self . private_keys :
308338 raise BlockIoUnknownError ("No PIN provided to decrypt signer private key." )
309339
310- if self .encryption_key is None and 'user_key' in prepare_data ['data' ]:
311- self .encryption_key = self .Helper .pinToAesKey (self .pin )
312-
313340 # decrypt the signer private key if we can
314- if self .encryption_key is not None and 'user_key' in prepare_data ['data' ]:
315- key = self .Helper .extractKey (prepare_data ['data' ]['user_key' ]['encrypted_passphrase' ], self .encryption_key )
341+ if self .pin is not None and 'user_key' in prepare_data ['data' ] and prepare_data ['data' ]['user_key' ]['public_key' ] not in self .private_keys :
342+
343+ key = self .Helper .dynamicExtractKey (prepare_data ['data' ]['user_key' ], self .pin )
316344
317345 if (key .pubkey_hex ().decode ('utf-8' ) != prepare_data ['data' ]['user_key' ]['public_key' ]):
318346 raise Exception ("Expected pubkey=" ,prepare_data ['data' ]['user_key' ]['public_key' ],"but got pubkey=" ,key .pubkey_hex (),". Invalid PIN provided." )
0 commit comments