forked from LBRYCommunity/lbry-sdk
make decrypt atomic, if it fails the state for all encrypted values in account does not change
This commit is contained in:
parent
0fa9e8d9f5
commit
ad6bd840a9
1 changed files with 24 additions and 32 deletions
|
@ -346,51 +346,43 @@ class BaseAccount:
|
||||||
|
|
||||||
def decrypt(self, password: str) -> bool:
|
def decrypt(self, password: str) -> bool:
|
||||||
assert self.encrypted, "Key is not encrypted."
|
assert self.encrypted, "Key is not encrypted."
|
||||||
success = (
|
|
||||||
self._decrypt_seed(password) and
|
|
||||||
self._decrypt_private_key_string(password)
|
|
||||||
)
|
|
||||||
if success:
|
|
||||||
self.encrypted = False
|
|
||||||
return success
|
|
||||||
|
|
||||||
def _decrypt_private_key_string(self, password: str) -> bool:
|
|
||||||
if not self.private_key_string:
|
|
||||||
return True
|
|
||||||
try:
|
try:
|
||||||
private_key_string, pk_iv = aes_decrypt(password, self.private_key_string)
|
seed = self._decrypt_seed(password)
|
||||||
except ValueError:
|
except ValueError:
|
||||||
# failed to remove padding, password is wrong
|
|
||||||
return False
|
return False
|
||||||
if not private_key_string:
|
|
||||||
self.private_key_string = ""
|
|
||||||
self.private_key = None
|
|
||||||
return True
|
|
||||||
try:
|
try:
|
||||||
self.private_key = from_extended_key_string(
|
private_key = self._decrypt_private_key_string(password)
|
||||||
self.ledger, private_key_string
|
|
||||||
)
|
|
||||||
except (TypeError, ValueError):
|
except (TypeError, ValueError):
|
||||||
return False
|
return False
|
||||||
self.init_vectors['private_key'] = pk_iv
|
self.seed = seed
|
||||||
|
self.private_key = private_key
|
||||||
|
self.private_key_string = ""
|
||||||
self.encrypted = False
|
self.encrypted = False
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def _decrypt_seed(self, password: str) -> bool:
|
def _decrypt_private_key_string(self, password: str) -> Optional[PrivateKey]:
|
||||||
|
if not self.private_key_string:
|
||||||
|
return None
|
||||||
|
private_key_string, self.init_vectors['private_key'] = aes_decrypt(password, self.private_key_string)
|
||||||
|
if not private_key_string:
|
||||||
|
return None
|
||||||
|
return from_extended_key_string(
|
||||||
|
self.ledger, private_key_string
|
||||||
|
)
|
||||||
|
|
||||||
|
def _decrypt_seed(self, password: str) -> str:
|
||||||
if not self.seed:
|
if not self.seed:
|
||||||
return True
|
return ""
|
||||||
try:
|
seed, self.init_vectors['seed'] = aes_decrypt(password, self.seed)
|
||||||
seed, seed_iv = aes_decrypt(password, self.seed)
|
if not seed:
|
||||||
except ValueError: # failed to remove padding, password is wrong
|
return ""
|
||||||
return False
|
|
||||||
try:
|
try:
|
||||||
Mnemonic().mnemonic_decode(seed)
|
Mnemonic().mnemonic_decode(seed)
|
||||||
except IndexError: # failed to decode the seed, this either means it decrypted and is invalid
|
except IndexError:
|
||||||
|
# failed to decode the seed, this either means it decrypted and is invalid
|
||||||
# or that we hit an edge case where an incorrect password gave valid padding
|
# or that we hit an edge case where an incorrect password gave valid padding
|
||||||
return False
|
raise ValueError("Failed to decode seed.")
|
||||||
self.seed = seed
|
return seed
|
||||||
self.init_vectors['seed'] = seed_iv
|
|
||||||
return True
|
|
||||||
|
|
||||||
def encrypt(self, password: str) -> bool:
|
def encrypt(self, password: str) -> bool:
|
||||||
assert not self.encrypted, "Key is already encrypted."
|
assert not self.encrypted, "Key is already encrypted."
|
||||||
|
|
Loading…
Add table
Reference in a new issue