New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
lnrpc+walletunlocker: extend wallet creation to allow user generated entropy + entropy restore (cipherseed) #719
Conversation
Also looking for feedback w.r.t to the wording displayed on |
lnd.go
Outdated
case initMsg := <-pwService.InitMsgs: | ||
password := initMsg.Passphrase | ||
|
||
// We'll now check to see fit eh user provided any entropy |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
*if the
Will also add an initial e2e integration test to start to exercise the basics of on-chain funds recovery. |
|
The BIP 39 passphrase is a great security option for people who store their mnemonic word seed on physical media (e.g. paper or metal) and the passphrase in their brain. |
lnd.go
Outdated
// mnemonic to the HD seed. | ||
// | ||
// TODO(roasbeef): don't use passphrase? | ||
pass := string(password) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It is kind of confusing to conflate the wallet encrypting password
here with the BIP 39 passphrase. Seems like this needs to be an explicit passphrase, ideally supplied just after the 24-word mnemonic.
Thanks for the feedback concerning the usage of the wallet passphrase. Upon further deliberation, I've concluded that we should actually ditch BIP 39 all together. BIP 39 lacks two important features that are necessary in a modern seed/mneonnic format:
The versioning system is required so we can bind the key derivation schema to the version of the seed, allowing future wallet types to properly detect any mismatched between the default key derivation schema of the software and the seed the software has been presented. A wallet birthday is required so we can properly handle imports of seed format without relying on a 3rd party API service to locate the earliest/oldest instances of address usage. |
And then... there was three. |
Well, the thing is BIP 39 is just flat out lacking. Our needs are very specific, as we'll be using this to deterministically derive all keys we ever use within a channel. This isn't covered under BIP 44, or any of the existing BIPs that govern key derivation. We'll likely document this and put it forth as a standard once it has been implemented (for LN key derivation for channels, including the Even the electrum seed doesn't have a birthday. For wallets that rely on a 3rd party service API to query when the address was first used, this isn't an issue. However, in our case for BIP 39 is rather dated at this point, and should be replaced IMO. |
Here's my proposal for a new seed format/mapping Alright, so I've thought of a new seed format/mapping that meets all the desired traits above, and also has some cool properties of it's on. The tentative name is
The above allows us to ensure the seed description is kept it tact, authenticates the original seed description, and also allows optional usage of a password to enable the mnemonic being kept in plain site. We can modify the level of redundancy we add to tune the number of resulting words, and also the security level of the corresponding MAC construction. A cool trait of this scheme is that the mnemonic is actually encoding a ciphertext of the initial seed description. By mapping this description through an arbitrary length block cipher, we extract a permuted set of bytes that leaks no information concerning the birthday or version. As the |
Building off of the above, we'll need a way to deterministically derive each of the keys we use within a transaction. There are
Using the seed derived from the above Combined with the seed format above, this is a complete suite for recovery of on-chain funds, as well as keys used in any particular channel, given a static description of the channel. |
I agree. But... obligatory: https://xkcd.com/927/ But yeah if we want to do it this way, I HIGHLY suggest making a BOLT so that at LEAST we will have some portability between LND based, CLightning based, and Eclair based client apps. Some concerns:
|
Up to them if they want to support it. I'd favor going ahead with an implementation now, in order for us to have a scheme set for recoverability by
Do we really need more than 255 versions? It must be fixed length as we need to tune the redundancy for our security level.
With 16 bytes, our redundancy is now 12 bytes. We can shift in either direction to achieve diff security levels. We may bump this to 2 bytes, but in any case it needs to be fixed length.
No need to commit to the bday. We're creating an authenticated cipher, it basically rolls a MAC check all into one upon decryption. No need to stretch anything either, as we already use
This format doesn't define a pre-defined word list at all. We're using the mnemonic to encode a cipher-text, not the entropy directly. An explicit checksum isn't necessary as if words are transposed, or a mistake is made in the mnemonic mapping, then you'll get a decryption failure, rather than mapping to some possibly empty wallet.
Yes, this will be the role of the static channel descriptions. The descriptions themselves could also be encrypted with the same (optional) password and format as the seed description. |
Wallet recovery: can I make a suggestion that something other than a password field be used as this doesn't echo back any characters/words to the user. This is fine if copy-pasting the 24 words to the prompt, but problematic if typing word by word from a printed store such as paper or cryptosteel record. In secure environments where the clipboard is disabled due to fears of clipboard hijacking, copy-paste is also not an option. The seed gets echoed to tty during generation, so I don't see a major problem in seeing the words when inputting them back for wallet recovery. They won't be stored in the shell history either as the shell records the initial command, not the interaction with it, unless some sort of recording setup. Dealing with 24 words and spaces, without any visual feedback on where possible input errors might be, is a bit worrying from a user experience perspective. This issue is addressed on mobile phones where characters are briefly seen before being obscured, and with normal GUI apps the entire seed phrase is visible. A password type field is not used in other situations, or provides some sort of input-error-catching during entry. |
I don't see the point in adding another password in the mix. The channel.db can not be used with any other wallet (/entropy/BIP32masterkey/whatever/) so why even bother encrypting it with anything other than the BIP32 master key or a specific path derived from it? (optional) password unlocks the wallet seed, which derives the channel.db key, which decrypts channel.db... makes sense. As for the encoding, I am indifferent. But I assume it will be much longer than 33 bytes... so while 24 words might be fine... 5000 words would give you carpal tunnel syndrome 🤣 at that point, people will save it to txt files anyways, so an encrypted blob file should be fine. |
I'm currently feeling fairly positive about the combination of (variable length ciphertext, AE mode instead of (checksum or yucky block size + padding) for validity check, ciphertext as encoding, birthday, version). (Yeah of course no one wants to xkcd themself. But meh. This is not a tight consensus kind of problem. The word list could even remain the same. Sometimes conforming is actually a bad thing, see e.g. the rationale behind BIP49, although I get why people don't agree). To achieve the crypto properties, I'm wondering about the choice of AEZ, although it does give you what you need, it does seem rather new/unsupported. Does OCB not fit the bill (with AES say)? AFAICT the patent thing shouldn't be an issue. |
Yeah the drawbacks of AEZ are: it's newer and not super straight forward to implement (though we do have an impl we can use. On the otherhand, it may very well end up wining the CAESAR competition, and it likely to be adopted by Tor to thwart known tagging attacks.
Hmm, possibly. I don't think it can be used in the same manner (enciphering/deciperhing) which allows use adopt what's the equivalent of an 8-byte MAC (or even tune it as we wish). Also, it seems there'e a set of restricted "free" patents for usage of OCB. However I'm a bit reluctant to use any patented software within the project... |
So from the AEZ paper, I think I know what you're referring to when you say "can't be used in .. same ..encipher/decipher", but I don't think there's a significant difference here (there would be for modes like CBC of course): The ciphertext is equal in length to the plaintext for any length, while the tag for authentication (~=MAC) is allowed to be of variable size such as 64 bit (so same as your case), with its length being a security tradeoff. There's no reason to also include the nonce in the ciphertext as it doesn't have to be secret or random (so can just be a counter). So you just have ciphertext||tag But yeah patents; it seems like it's not a problem, but who wants to even think about it. Looked again at GCM, it seems, unless I'm missing something, that you get basically exactly the same properties without any patent concerns (which is presumably why AES-GCM is widely deployed in TLS and OCB isn't); the IV is the nonce which could be a counter. Not sure, maybe missing an important detail, but there are probably quite a lot of people that'd know about that :) I guess you will stick with AEZ, but it does slightly worry me that it's not widely used. |
With aez, there's no explicit MAC. It comes in the from of "cipher-text expansion". So you can specify a number of bits of redundancy that'll be verified upon decryption. It's even possible to exploit existing redundancy in the plaintext itself (like a message header or something) in order to reduce the number of redundant bits appended before encryption. In the above description, we don't use an explicit nonce at all, as we assume uniqueness of the plaintext. For traditional cipher modes, we'd need to truncate the max to avoid having too many encoded words (with the params we have in mind, we'd have 24-words). Also for traditional modes, we'd need to add additional padding to ensure the last block was the same width as block cipher, further blowing up the size of the ciphertext. You can think of |
Of course.
Yes, I referred to that (CBC as example), I was specifically talking about OCB (and possibly GCM) because they don't have this problem; they are block ciphers that function as stream ciphers, and do not require more ciphertext than plaintext. To give an example, I can encrypt 53 bytes of plaintext in AES OCB and get 53 bytes of ciphertext. The tag functions as authentication so you append ciphertext||tag ; this, as I was trying to assert above, is not really different from appending redundancy before the enciphering step. And it's tunable so e.g. 8 bytes of it is fine. So the length arithmetic would be basically the same, with N bytes redundancy in tag instead of plaintext. However your point that you can exploit existing redundancy in the plaintext format to reduce the length expansion required for authentication is a good one, I think. Btw this does remind me a bit of the old "cryptographic doom principle" of Marlinspike, aka the old mac-then-encrypt vs encrypt-then-mac. I think there's a subtlety here I'm missing though. |
A decryption failure doesn't tell you whether you made a mistake writing down or entering the seed mnemonic or you forgot the password. This can be an important distinction when you are trying to recover your wallet. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice! Getting close to not having to completely wipe our nodes before upgrading :) Couple small things, but changes look solid on first pass!
cmd/lncli/commands.go
Outdated
// We'll now prompt the user to enter in their 24-word | ||
// mnemonic. | ||
fmt.Printf("Input your 24-word mnemonic separated by spaces: ") | ||
mnemonic, err := terminal.ReadPassword(int(syscall.Stdin)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think this requires ReadPassword
since the mnemonic is itself a ciphertext
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also, it's hard to double check you typed it in correctly. No one will copy paste, and typing a long phrase is screaming for typos... so being able to see what you typed on the screen is a must... if there's a way to securely delete the stdin/terminal window from the app after they hit Enter that would be best.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
just remembered that in this context this is actually a bip 39 mnemonic, so it is semi private
cmd/lncli/commands.go
Outdated
@@ -757,8 +759,26 @@ func listPeers(ctx *cli.Context) error { | |||
} | |||
|
|||
var createCommand = cli.Command{ | |||
Name: "create", | |||
Usage: "used to set the wallet password at lnd startup", | |||
Name: "create", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I know this command was first created in a previous PR, but just wanted to propose renaming to init
? i think it's more descriptive of how/what the command does
cmd/lncli/commands.go
Outdated
Name: "unlock", | ||
Description: ` | ||
The unlock command is used to decrypt lnd's wallet state in order to | ||
start up. This command MUST be run after booting up lnd before it's |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add caveat about --noencryptwallet
?
lnd.go
Outdated
return nil, nil, err | ||
} | ||
|
||
// If we generated the seed to create he wallet ourselves, then |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
create the*
walletunlocker/service.go
Outdated
@@ -11,13 +11,49 @@ import ( | |||
"gopkg.in/macaroon-bakery.v2/bakery" | |||
) | |||
|
|||
// SeedEntropySize is the default number of bytes that will be used to generate | |||
// a seed if the user hasn't specified one themselves. We'll also enforce that | |||
// the see is at least this large |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
seed* is at least
cmd/lncli/commands.go
Outdated
|
||
fmt.Println("Generated mnemonic seed:", mnemonic) | ||
|
||
fmt.Println("\n!!!YOU MUST WRITE DOWN THIS SEED TO BE ABLE TO " + |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Was thinking a little more on how we display the mnemonic to the user in lncli. There's a lot going on there, and think it needs to be more obvious as to what exactly needs to be copied. I would propose printing out the mnemonic in a format similar to text encodings for keys/certs:
-----BEGIN LND CIPHER SEED-----
field soup wing canvas
survey borrow story analyst
useless clap before cheap
giggle middle color visa
cabbage shell vessel rent
deposit exchange coil sample
------END LND CIPHER SEED------
I think this will greatly reduce the errors people make in writing down the seed. Humans are best at remembering things in 3's and 4's, plus the formatting allows users to check if they're missing a word in each line, instead of hoping they correctly copied all 24 words in a single run-on sentence.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would also say to add numbers...
Japanese users sometimes try to write top to bottom first.
-----BEGIN LND CIPHER SEED-----
1. field 2. soup 3. wing 4. canvas
5. survey 6. borrow 7. story 8. analyst
9. useless 10. clap 11. before 12. cheap
13. giggle 14. middle 15. color 16. visa
17. cabbage 18. shell 19. vessel 20. rent
21. deposit 22. exchange 23. coil 24. sample
------END LND CIPHER SEED------
@AbdussamadA good point, we can improve. I'll be updating the |
About to push a new version with the feedback incorporated: we'll now display the mnemonic (so echo it back), and also the seed is formatted as such:
Twiddled for a while to try to get up to line up really nicely column wise, but this current formatting is a stop gap for now. Here's a playground to adjust some of the spacing: https://play.golang.org/p/cPBPo8KgN7m |
Which part of the two step does the WALLET encryption password get set? (not the aezeed optional passphrase) During the ACK step, I hope? |
Yes after the ack step. The current flow is:
1. User does GenSeed. This gives the user a new seed, allowing them the
option of specifying their own source of entropy.
2. Front-end (cli in this case) should present the seed to the user (and
possibly do a random challenge).
3. Once this is complete, the front end then sends InitWallet. This carries
the wallet encryption password. The response to this is synchronous,
meaning it only returns once encryption is complete. This is the "ACK"
step.
On Mar 2, 2018 9:42 PM, "Dabura667" <notifications@github.com> wrote:
Which part of the two step does the encryption password get set?
During the ACK step, I hope?
—
You are receiving this because you authored the thread.
Reply to this email directly, view it on GitHub
<#719 (comment)>,
or mute the thread
<https://github.com/notifications/unsubscribe-auth/AA87LsnyuhMkjHtiorb0qFf7mZxVj-GTks5tai1GgaJpZM4R2r4n>
.
|
@Roasbeef the user doesn’t need to call genseed manually, right? Sounds like they can though? |
On the RPC level it's optional, as the user may already be restoring from
an existing seed. On the cli it's done for them transparently.
On Mar 2, 2018 10:11 PM, "Conner Fromknecht" <notifications@github.com> wrote:
@Roasbeef <https://github.com/roasbeef> the user doesn’t need to call
genseed manually, right? Sounds like they can though?
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
<#719 (comment)>,
or mute the thread
<https://github.com/notifications/unsubscribe-auth/AA87LlTgxPcmyjnxTC69_xJ4cvVk3_pKks5tajQUgaJpZM4R2r4n>
.
|
AWESOME!!!!!!! Killing it! Totally... Now all we need is a method for encrypting+exporting channel.db and all info for recovering the node in a fatal crash scenario are covered.
|
Great feature! I agree an export/import feature for channel.db that encrypts/decrypts with a key from the wallet and will merge latest-takes-precedence when importing would be great. |
In this commit, we revamp the WalletUnlocker service to now have a two-stage init process. The first (optional) is for the user instantiating a new lnd instance to call the GenSeed method with an optional aezeed passphrase. The response to this will be a freshly generated aezeed mnemonic along with the original enciphered seed. The second step will be the actual wallet initaliztion. By separating this step from seed generation, UI's will be able to ensure that the user has written down the seed, before proceeding and committing the seed to the internal wallet. The new method InitWallet accepts a wallet passphrase, the aezeed mnemonic, and the optional passphrase.
In this commit, we extend the UnlockerService to account for the new changes in the lnrpc definition. Setting up the daemon for the first time is now two step process: first the user will generate a new seed via the GenSeed method, then the user will present this new seed (and optional pass) to the InitWallet method which then will finalize the wallet creation. This two step process ensures that we don't commit the wallet changes in the case that the user doesn't actually "ACK" the new seed. In the case that the user already has an existing seed, they can re-enter it and skip straight to the InitWallet step. We also update the tests to account for the new API changes.
…ntropy In this commit, we extend the initial wallet creation set up case with the goal of giving the user the ability to restore a prior wallet from seed, or obtain the mnemonic for a newly generated wallet. As the WalletUnlocker has been extended to allow passing a user source of entropy, if this is detected, then we’ll use BIP39 to covert it into an HD wallet seed. Otherwise, we’ll generate our own entropy, then convert that into the wallet seed. In order to make this change, we’ll now manually create the default wallet ourselves. In the case that the user didn’t provide their own seed, we’ll send the seed we generated back to the user. This will allow frontends to display the newly generated seed to the end user.
…ting wallet In this commit, due to the recent changes within lnd itself, it may be possible that a wallet already exists when the wallet has been signaled to be created. As a result, *always* open the wallet ourselves, but allow an existing wallet to already be in place.
In this commit, we extend the `lncli create` command to allow users to specify their own side (if they want). In the case that the user *doesn’t* specify their own seed, we’ll return the entropy generated by the wallet in a 24-word mnemonic format for easy backup. With this change, it’s now possible for users to restore an existing lnd wallet seed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I like the last minute change to make genseed stateful, user onboarding flow is now much clearer! LGTM 🌱
@dabura667 why do you think it should be cron for auto backup? If you missed a single state update and then crashed, you lose all of your money. It must be something ongoing after every payment. So it must support backup of every new state out of box. |
And we could do that if we had an easy command like:
and the equivalent in GRPC. No, copying channel.db from the folder directly does not give certain guarantees. So I could say in my app:
Or I could say in my server:
Or I could say anything I want. Currently we have no method for backing up channel.db... if my disk blows up, ALL my channels are borked, and even if I remembered their info, I could get funds stolen from ALL channels. Loading a backup that has all my channels but one or two of them are in an old state will only risk funds in one or two channels. Right now the only way you could "back up" would be to set your .lnd folder to be inside a dropbox folder or something. |
Yes, and this is not production ready for sure. Some people don't like dropbox etc. Also even though channel db is tiny, if you have 1000 channels it makes sense to only backup some encrypted diff instead of everything. |
The plan isn't to have a cron job tool to export encrypted channel data or
anything like that. The plan is two fold: dynamic and static Chanel channel
updates. Dynamic updates are of course private outsourcers of which we have
an ~70% complete code of (new design talked about in my BPASE talk). Static
updates are also to be collocated on them (and can also be stored safely),
and include the static description of a channel. From this static
description, and the users seed, we can re derive all keys necessary to
sweep our output on chain when we enter the funds recovery protocol
(basically a set of social `contractResolvers`) . Both update variants are
encrypted with an AEAD.
We have newer channel designs that tradeoff the danger of having stale
backups (you can broadcast and not care), but they modify the game theory
of attesting to channel states. I think both commitment invalidation
mechanisms can co exist heterogeneously within a channel (sub commitments,
etc). Some of the newly proposed updates to Script also let us take this
even further, greatly augmenting the power of channels on Bitcoin (beyond
just simple payments). However as always, one step at a time.
…On Sun, Mar 11, 2018, 6:51 AM Egor Homakov ***@***.***> wrote:
Right now the only way you could "back up" would be to set your .lnd
folder to be inside a dropbox folder or something.
Yes, and this is not production ready for sure. Some people don't like
dropbox etc.
Also even though channel db is tiny, if you have 1000 channels it makes
sense to only backup some encrypted diff instead of everything.
—
You are receiving this because you modified the open/close state.
Reply to this email directly, view it on GitHub
<#719 (comment)>,
or mute the thread
<https://github.com/notifications/unsubscribe-auth/AA87Lk72HIft-u_0TrK0MfHILbUcLsoiks5tdSvXgaJpZM4R2r4n>
.
|
@Roasbeef I didn't exactly understand the process, who stores the backup, and how often backups are made... Do you plan to explain it in RFC? All implementations/wallets would need it anyway. |
We'll roll out our code before adding it to the rfc to ensure we get some
real world usage before attempting to standardize it. The missing component
(code wise, conceptually it's dunzo) is more or less adding mix-net
inspired batching/flushing to avoid allowing private outsourcers to be a
giant side channel on a large portion of the network.
…On Sun, Mar 11, 2018, 12:41 PM Egor Homakov ***@***.***> wrote:
@Roasbeef <https://github.com/roasbeef> I didn't exactly understand the
process, who stores the backup, and how often backups are made... Do you
plan to explain it in RFC? All implementations/wallets would need it anyway.
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
<#719 (comment)>,
or mute the thread
<https://github.com/notifications/unsubscribe-auth/AA87LgaFSiavUt6DmrsFtF8azXWwAPFxks5tdX36gaJpZM4R2r4n>
.
|
So... the answer for now is “don’t break your disk, or kiss all your channels and money goodbye!” What is the current recommendation for managing channel.db backup and recovery? |
The answer for now is don't put 1 billion USD into a channel ;) Automated tools are in development to manage the backup, recovery, etc. That PR open that just slings backups isn't safe (with current commitment design), so it won't be merged. |
#RANDOMI’m sorry, it feels like the ship has sailed and I’m talking about last year snow, water under the bridge. This: raspiblitz/raspiblitz#500 (comment)
Also this: https://twitter.com/slush/status/974584070603706368 Breaking
|
@marsrobertson Dude, you need to stop spamming this thread and everywhere else. This is not only crazy but you are very rude and disrespectful to the devs. Just totally uncool yourself, so stop it. |
BIP39 was not "carefully engineered" it was obviously rushed to the point where ThomasV had them take his name off the BIP because they had to rush and push it out the door to make money on selling Trezors. SatoshiLabs does tons of good for Bitcoin, and BIP39 was overall a good for Bitcoin, yes, but it was rushed. Acting otherwise is disingenuous. Also "dig up my cryptosteel for every feature" is disingenuous. The lack of versioning might be great for a developer. But for my mom, she called me in a panic because she restored her BIP39, and suddenly Ledger played 20 questions with her. She didn't understand, it shows the wrong wallet "p2sh-p2wpkh instead of p2pkh" and she literally said "I lost my Bitcoins" Some people might throw away their HW wallet and phrase if they thought they lost everything anyway. with versioning, all you need is to create a new phrase. No need to dig up. If you want a new feature, you're going to move to a new address anyways. and if done correctly, you could even add an hidden advanced "version override" feature on your wallet if the version is not tied to the entropy. tl:dr Aezeed > BIP39 and SLIP39 |
@junderw Hi Jon, thanks for this interesting piece of history which I didn't even know... I saw that tweet over a year ago and wondered why someone who's not a dev of this project, cares less about it, but got upset that bip39 isn't used... LOL and roasbeef had to explain to him again... Just for the reference if anyone else hasn't read why aezeed is used, it's explained on this thread and specifically from here: |
New Functionality
In this PR, we extend the initial
lncli create
command to allow the user to specify their own entropy when creating the wallet. This capability means that it'll be possible for a user to restore an existing on-chain wallet given their initial source of entropy. Additionally, thelncli create
command will now also return a BIP 39 mnemonic generated from lnd's generated entropy in the case that the user opts not to specify their own.Internally, when accepting a mnemonic from the user, we'll convert that into the original entropy bytes using BIP 39. From there we'll map that to an HD wallet seed and initialize the internal wallet using that value. If the user doesn't specify a seed, we'll generate our own entropy (always 256-bits), and send the generated entropy over RPC. This final step allows any frontends to
lnd
to display the entropy as 24-word mnemonic for easy backup.New
lncli create
workflowWhat follows is an interactive session with this PR that illustrates the ability to create a new wallet, then restore the wallet using the return mnemonic:
Implementation Details
One point of discussion is whether to use the user pass phrase when generating the final seed from the mnemonic. As is now, the contents of the wallet database are encrypted with the passphrase. As is this means that one can't access their wallet (before this PR) if they forgot the passphrase. When generating their seed (atm) we'll use the wallet passphrase as input into the KDF. As a result, if the user forgets their wallet passphrase they won't be able to re-generate the seed.
On one hand, by using the passphrase, this means that for a given mnemonic, any passphrase generates a "valid" wallet. On the other hand, if the user forgets their passphrase, then they won't be able to restore the same wallet.