Open SomberNight opened 4 years ago
Note: if we make an incompatible change to the storage file format, we should also change the KDF to something stronger. Maybe scrypt (and introduce a random salt at the same time).
somewhat related: https://github.com/spesmilo/electrum/issues/5561
@ln2max take a look
See my comment here: https://github.com/spesmilo/electrum/issues/4823#issuecomment-919348130
To allow password-encryption for hardware wallets (#5561), we need to have multiple ways to decrypt the same wallet. We can encrypt the wallet with a random "master key", and add several fields, each containing master key, encrypted with a different passwords. This also allows us to change the password without rewriting the entire file.
Regarding #5993, I am not sure why the derivation path should be part of the header. Since the derivation path depends on the hardware wallet, I believe it should be defined in the corresponding plugin.
Since the master key we are encrypting is random, no rainbow table can be built. Thus, I believe a salt is unnecessary.
The header would consist of:
Note: I think we can drop ECIES, and simply use symmetric encryption. Forward secrecy is not really useful here, because what we need to protect is the wallet file content, which contains seed/privkeys.
On Thu, Sep 30, 2021 at 06:53:08AM -0700, ThomasV wrote:
The header would consist of:
- Magic: b"Electrum"
- Version (1 byte)
If I understand you correctly, the idea is to use the version number to provide for future changes to the header format, rather than trying to design a modular header format now?
If I understand you correctly, the idea is to use the version number to provide for future changes to the header format, rather than trying to design a modular header format now?
yes
Regarding #5993, I am not sure why the derivation path should be part of the header. Since the derivation path depends on the hardware wallet, I believe it should be defined in the corresponding plugin.
Currently all hardware devices use the same hardcoded bip32 path (m/4541509h/1112098098h
) for deriving a pubkey used as encryption password.
The discussion in the linked thread was about the bitbox02 restricting get xpub requests to certain specific paths, so we had not been able to request the pubkey for the hardcoded path (m/4541509h/1112098098h
) -- the resolution there was the bitbox02 adding an exception in the firmware for just this specific path we wanted. So atm all hardware wallets behave the same.
The current approach allows for encrypting a wallet file with a Trezor and decrypting it with a Ledger (although functionality is limited in that case, e.g. the wallet itself will not be able to sign). So even if you lose your device but have a different one (initialised with the same seed) you can easily decrypt the wallet file and recover your labels (for instance). Similar to it being encrypted with a user-password: just because you lost your device, if you have your secrets, ideally you should be able to recover information from the file.
I don't like the approach of plugins customising this derivation path directly and then not exposing what path they use outside of the plugin itself. Imagine the wizard pairs with a hw device and tries to decrypt a wallet file, deriving the password from a key along a bip32 path that is simply hardcoded in the plugin code - i.e. specific to that manufacturer and plugin. Critically, this would mean we might not be able to delete/remove a plugin - otherwise some existing wallet files could not be decrypted anymore. It is fine not being able to use a wallet file after the corresponding plugin has been deleted, but the file should be decryptable if possible, so watch-only information is still available (e.g. labels can be recovered).
This, along with the bitbox02 originally not supporting our hardcoded path, is the reason I had suggested that we could put the derivation path into the file header. That would mean different hww plugins/manufacturers can use different paths, which would then be encoded in a generic hww-agnostic way in the file header, making the file itself decryptable in a hww-agnostic way.
On Mon, Oct 04, 2021 at 08:15:19AM -0700, ghost43 wrote:
This, along with the bitbox02 originally not supporting our hardcoded path, is the reason I had suggested that we could put the derivation path into the file header. That would mean different hww plugins/manufacturers can use different paths, which would then be encoded in a generic hww-agnostic way in the file header, making the file itself decryptable in a hww-agnostic way.
This makes sense. Unfortunately I don't see any good way to put a variable-length string into a binary header. The JSON-based approach would be much better for that kind of thing.
note: we should also add a header to unencrypted files. Even if only to contain a magic prefix. This would finally solve https://github.com/spesmilo/electrum/issues/6349#issuecomment-754158457 - those old software should not be able to open new wallet files as they just corrupt them.
Currently, encrypted wallet files don't really have a header. The file contents are: https://github.com/spesmilo/electrum/blob/ce81957d25e66296c0baaf48683adcc623a3dae4/electrum/ecc.py#L503-L506 So it's just a 4 byte magic, and data needed for the decryption itself.
The magic itself is used to distinguish between two wallet types.
BIE1
wallets are encrypted with a user provided password ("userpw"), andBIE2
wallets are encrypted with a pubkey used as password that comes from a hardware wallet (along a hardcoded bip32 derivation path) ("xpubpw"). https://github.com/spesmilo/electrum/blob/ce81957d25e66296c0baaf48683adcc623a3dae4/electrum/storage.py#L171-L176It would be useful to have a proper header. For example, the header could include