From 5c62d5efa652e3510e212b11256e2dce0404d026 Mon Sep 17 00:00:00 2001 From: PiRK Date: Wed, 18 Oct 2023 06:54:04 +0200 Subject: [PATCH] [electrum] fix hardware wallet decryption Summary: Wallets are encrypted with a key derived from a password. Hardware wallets use a hex-encoded public key generated by the device on a special derivation path as the password. With the recent refactorings, `Xpub.get_pubkey_from_xpub` now returns bytes, so we need to explicitely convert it to a hex string before passing it to `storage.decrypt`. Note that this was already fixed in `HardwareKeyStore.get_password_for_storage_encryption` which is called when the wallet is first created, so any wallet created by Electrum ABC 5.2.8 will be correctly encrypted. The bug affect the decryption when the user tries to reopen the wallet later. Test Plan: Open an encrypted hardware wallet. Tested with a Ledger Nano S and a Satochip card. Reviewers: #bitcoin_abc, Fabien Reviewed By: #bitcoin_abc, Fabien Differential Revision: https://reviews.bitcoinabc.org/D14645 --- electrumabc/base_wizard.py | 2 +- electrumabc/daemon.py | 2 +- electrumabc/storage.py | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/electrumabc/base_wizard.py b/electrumabc/base_wizard.py index 1e6cce8348a8..1927c35a0196 100644 --- a/electrumabc/base_wizard.py +++ b/electrumabc/base_wizard.py @@ -456,7 +456,7 @@ def on_device(self, name, device_info: DeviceInfo, *, purpose, storage=None): xpub = self.plugin.get_xpub( device_info.device.id_, derivation, "standard", self ) - password = keystore.Xpub.get_pubkey_from_xpub(xpub, ()) + password = keystore.Xpub.get_pubkey_from_xpub(xpub, ()).hex() try: storage.decrypt(password) except util.InvalidPassword: diff --git a/electrumabc/daemon.py b/electrumabc/daemon.py index 858093ff91a8..38e4ea4a2342 100644 --- a/electrumabc/daemon.py +++ b/electrumabc/daemon.py @@ -259,7 +259,7 @@ def run_gui(self, config_options): ) return response - def load_wallet(self, path, password): + def load_wallet(self, path, password: str): path = standardize_path(path) # wizard will be launched if we return if path in self.wallets: diff --git a/electrumabc/storage.py b/electrumabc/storage.py index e400df1c33c9..d296987cf56c 100644 --- a/electrumabc/storage.py +++ b/electrumabc/storage.py @@ -163,7 +163,7 @@ def _init_encryption_version(self): except Exception: return STO_EV_PLAINTEXT - def get_key(self, password): + def get_key(self, password: str) -> bitcoin.ECKey: secret = hashlib.pbkdf2_hmac( "sha512", password.encode("utf-8"), b"", iterations=1024 ) @@ -179,7 +179,7 @@ def _get_encryption_magic(self): else: raise WalletFileException("no encryption magic for version: %s" % v) - def decrypt(self, password): + def decrypt(self, password: str): ec_key = self.get_key(password) if self.raw: enc_magic = self._get_encryption_magic()