# 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.