@@ -104,11 +104,41 @@ class Helper:
104
104
@staticmethod
105
105
def pinToAesKey (pin , salt = "" , iterations = 2048 , hashfn = sha256 , phase1_key_length = 16 , phase2_key_length = 32 ):
106
106
# use pbkdf2 magic
107
- # ( password, keylen, salt = "", itercount = 1024, hashfn = sha256 )
108
107
ret = pbkdf2 .pbkdf2 (pin , phase1_key_length , salt , int (iterations / 2 ), hashfn )
109
108
ret = pbkdf2 .pbkdf2 (hexlify (ret ), phase2_key_length , salt , int (iterations / 2 ), hashfn )
110
109
return hexlify (ret ) # the encryption key
111
110
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
+
112
142
@staticmethod
113
143
def extractKey (encrypted_data , enc_key_hex ):
114
144
# encryption key is in hex
@@ -304,15 +334,13 @@ def create_and_sign_transaction(self, prepare_data, keys = []):
304
334
cur_key = PrivateKey (secret_exponent = int (cur_key_hex ,16 ))
305
335
self .private_keys [cur_key .get_public_key ().to_hex (compressed = True )] = cur_key
306
336
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 :
308
338
raise BlockIoUnknownError ("No PIN provided to decrypt signer private key." )
309
339
310
- if self .encryption_key is None and 'user_key' in prepare_data ['data' ]:
311
- self .encryption_key = self .Helper .pinToAesKey (self .pin )
312
-
313
340
# 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 )
316
344
317
345
if (key .pubkey_hex ().decode ('utf-8' ) != prepare_data ['data' ]['user_key' ]['public_key' ]):
318
346
raise Exception ("Expected pubkey=" ,prepare_data ['data' ]['user_key' ]['public_key' ],"but got pubkey=" ,key .pubkey_hex (),". Invalid PIN provided." )
0 commit comments