mirror of
https://github.com/trezor/trezor-firmware.git
synced 2024-12-24 15:28:10 +00:00
core: add documentation for SLIP-39 handling in Trezor
This commit is contained in:
parent
81a2476a45
commit
f491239c26
105
docs/core/misc/slip0039.md
Normal file
105
docs/core/misc/slip0039.md
Normal file
@ -0,0 +1,105 @@
|
||||
# Use of SLIP-39 in trezor-core
|
||||
|
||||
[SLIP-39](https://github.com/satoshilabs/slips/blob/master/slip-0039.md) describes a way
|
||||
to securely back up a secret value using Shamir's Secret Sharing scheme.
|
||||
|
||||
The secret value, called a Master Secret (**MS**) in SLIP-39 terminology, is first
|
||||
encrypted by a passphrase, producing an Encrypted Master Secret (**EMS**). The EMS is
|
||||
then split into a number of shares, which are encoded as a set of mnemonic words.
|
||||
Afterwards, it is possible to recombine some or all of the shares to obtain back the
|
||||
EMS, and when the correct passphrase is provided, decrypt the original Master Secret.
|
||||
|
||||
This does not quite match Trezor's use of the "passphrase protection" feature, namely
|
||||
that any passphrase is valid, and using any passphrase will yield a working wallet.
|
||||
|
||||
SLIP-39 enables this usage by specifying that passphrases are not validated in any way.
|
||||
Decrypting an EMS with any passphrase will produce data usable as the Master Secret,
|
||||
regardless of whether it is the original data or not.
|
||||
|
||||
|
||||
## Seed handling in Trezor
|
||||
|
||||
Trezor stores a _mnemonic secret_ in a storage field `_MNEMONIC_SECRET`. This is the
|
||||
input for the root node derivation process: `mnemonic.get_seed(passphrase)` takes the
|
||||
user-provided passphrase as an argument, and derives the appropriate root node from the
|
||||
mnemonic secret.
|
||||
|
||||
With BIP-39, the recovery phrase itself is the mnemonic secret. During device
|
||||
initialization, the raw recovery phrase is given to the user, and also directly stored
|
||||
in the `_MNEMONIC_SECRET` field. Whenever the root node is required, it is derived by
|
||||
applying PBKDF2 to the mnemonic secret plus passphrase.
|
||||
|
||||
For SLIP-39 it is not practical to store the raw data of the recovery shares. During
|
||||
device initialization, a random Encrypted Master Secret is generated and stored as
|
||||
`_MNEMONIC_SECRET`. SLIP-39 encryption parameters (a random identifier and an iteration
|
||||
exponent) are stored alongside the mnemonic secret in their own storage fields. Whenever
|
||||
the root node is required, it is derived by "decrypting" the stored mnemonic secret with
|
||||
the provided passphrase.
|
||||
|
||||
|
||||
## SLIP-39 implementation
|
||||
|
||||
The [reference implementation](https://github.com/trezor/python-shamir-mnemonic) of
|
||||
SLIP-39 provides the following high-level API:
|
||||
|
||||
* `generate_mnemonics(group parameters, master_secret, passphrase)`: Encrypt Master
|
||||
Secret with the provided passphrase, and split into a number of shares defined via
|
||||
the group parameters.
|
||||
Implemented using the following:
|
||||
- `encrypt(master_secret, passphrase, iteration_exponent, identifier)`: Encrypt the
|
||||
Master Secret with the given passphrase and parameters.
|
||||
- **`split_ems(group parameters, identifier, iteration_exponent, encrypted_master_secret)`**:
|
||||
Split the encrypted secret and encode the metadata into a set of shares defined via
|
||||
the group parameters.
|
||||
* `combine_mnemonics(set of shares, passphrase)`: Combine the given set of shares to
|
||||
reconstruct the secret, then decrypt it with the provided passphrase.
|
||||
Implemented using the following:
|
||||
- **`recover_ems(set of shares)`**: Combine the given set of shares to obtain the
|
||||
encrypted master secret, identifier and iteration exponent.
|
||||
- **`decrypt(encrypted_master_secret, passphrase, iteration_exponent, identifier)`**:
|
||||
Decrypt the secret with the given passphrase and parameters, to obtain the original
|
||||
Master Secret.
|
||||
|
||||
Only the functions denoted in **bold** are implemented in trezor-core. Recovery shares
|
||||
are generated with `split_ems` and combined with `recover_ems`. Passphrase decryption is
|
||||
done with `decrypt`. There is never an original "master secret" to be encrypted, so the
|
||||
`encrypt` function is also omitted.
|
||||
|
||||
|
||||
## Step-by-step
|
||||
|
||||
### Device initialization
|
||||
|
||||
This process does not use passphrase.
|
||||
|
||||
1. Generate the required number of random bits (128 or 256), and store as
|
||||
`_MNEMONIC_SECRET`.
|
||||
2. Generate a random identifier and store as `_SLIP39_IDENTIFIER`.
|
||||
3. Store the default iteration exponent `1` as `_SLIP39_ITERATION_EXPONENT`.
|
||||
4. The storage now contains all parameters required for seed derivation.
|
||||
|
||||
### Seed derivation
|
||||
|
||||
This is the only process that uses passphrase.
|
||||
|
||||
1. If passphrase is enabled, prompt user for passphrase. Otherwise use empty string.
|
||||
2. Use `slip39.decrypt(_MNEMONIC_SECRET, passphrase, _SLIP39_ITERATION_EXPONENT, _SLIP39_IDENTIFIER)`
|
||||
to "decrypt" the root node that matches the provided passphrase.
|
||||
|
||||
### Seed backup
|
||||
|
||||
This process does not use passphrase.
|
||||
|
||||
1. Prompt user for group parameters (number of groups, number of shares per group, etc.).
|
||||
2. Use `slip39.split_ems(group parameters, _SLIP39_IDENTIFIER, _SLIP39_ITERATION_EXPONENT, _MNEMONIC_SECRET)` to split the secret into the given number of shares.
|
||||
|
||||
### Seed recovery
|
||||
|
||||
This process does not use passphrase.
|
||||
|
||||
1. Prompt the user to enter enough shares.
|
||||
2. Use `slip39.recover_ems(shares)` to combine the shares and get metadata.
|
||||
3. Store the Encrypted Master Secret as `_MNEMONIC_SECRET`.
|
||||
4. Store the identifier as `_SLIP39_IDENTIFIER`.
|
||||
5. Store the iteration exponent as `_SLIP39_ITERATION_EXPONENT`.
|
||||
6. The storage now contains all parameters required for seed derivation.
|
Loading…
Reference in New Issue
Block a user