MetacoSA / NBitcoin

Comprehensive Bitcoin library for the .NET framework.
MIT License
1.88k stars 847 forks source link

Is it possible to get Mnemonic from ExtKey? #341

Closed bazooka70 closed 6 years ago

bazooka70 commented 6 years ago

I am generating my master ExtKey e.g.:

Mnemonic mnemonic = new Mnemonic(Wordlist.English, WordCount.TwentyFour);
Console.WriteLine(mnemonic.ToString());
ExtKey masterKey = mnemonic.DeriveExtKey();

Can I get the word list back from masterKey?

nopara73 commented 6 years ago

No, you cannot. Mnemonic is a "one time thing." I've just created a key manager yesterday, that may help you, depending on how complex system you want to create:
https://github.com/nopara73/MagicalCryptoWallet/blob/master/MagicalCryptoWallet/KeyManagement/KeyManager.cs

Look at the tests on how to use it: https://github.com/nopara73/MagicalCryptoWallet/blob/master/MagicalCryptoWallet.Tests/KeyManagementTests.cs

It's a work in progress, but the basics are done. (create, restore wallet, creating new keys, labelling keys, save to file and load from file, marking keys as locked, clean, used, etc..) What is important to your question and what you want to take a look at: When you create a wallet it gives you a mnemonic, but that mnemonic is not used anymore, rather an ecnrypted secret key is used along with the chain code in the wallet file. That mnemonic can be used to restore the encrypted secret - chaincode pair. If you have the encrypted secret you can decrypt it with your password and get extended keys, extended public keys, etc...
HD wallets are quite complicated and NBitcoin only implements the lego pieces, it doesn't puts them together for you. I'm pretty sure a general purpose keymanager would go a long way, but that's quite a long job to create and there is not BIP for that.

NicolasDorier commented 6 years ago

As @nopara73 said, you can't mnemonic to HDKey is one way operation.

bazooka70 commented 6 years ago

Thanks. Go it. At the moment I am creating a wallet that contains only ONE address. BUT I want it to HD ready in the future. Is this code OK?

Mnemonic mnemonic = new Mnemonic(Wordlist.English, WordCount.TwentyFour);
Console.WriteLine(mnemonic.ToString());
ExtKey masterKey = mnemonic.DeriveExtKey();
Key privateKey = extKey.PrivateKey;
PubKey publicKey = privateKey.PubKey;
// get the public address
BitcoinPubKeyAddress myPublicAddress = publicKey.GetAddress(Network.TestNet);

And LATER be able to derive new addresses:

            for (int i = 0; i < 5; i++)
            {
                ExtKey key = masterKey.Derive((uint)i);
                Console.WriteLine("Key " + i + " : " + key.ToString(network));
                Console.WriteLine("Key PrivateKey : " + key.PrivateKey.ToString(network));
            }

I want to save the mnemonic for later use and be able to display it to the user (it is encrypted in a "safe"). Also, does the WordCount (currently TwentyFour) determines the strength of the ExtKey? or can I just use "Twelve"?

NicolasDorier commented 6 years ago

yes your code seems fine.

WordCount is the number of words in the mnemonic. Normally users decide what they prefer. More is better strength.

nopara73 commented 6 years ago

Normally users decide what they prefer.

I don't think that's the case: not many wallets (if any) gives the choice on word count.

More is better strength.

From another point of view it's hard enough to get people write down their mnemonic words in the first place, using bigger word counts exponentially increases this issue and if a "security method is not used, then it's not very secure."

I'd suggest you to go with WordCount.Twelve.

Anyway, it's more of a design philosophical issue I guess.

bazooka70 commented 6 years ago

Thank you all. You have be more than helpful :+1: Keep on with this great library! cheers.

bazooka70 commented 6 years ago

It has been a long time, but maybe there is way to do this: A user wants to import an existing HD master private key (e.g. xprv9s21ZrQH143K2HnfyaYRCARZsjZPCrxMU5skQcj9jNTwUnvQkXDT7qX2rUxsRENZnifodBVtYD688cqkkDEy4ak276twqa7b6zPMVrWXCGU) and create a new wallet in my system.

Isn't there any way I can generate a word list mnemonic for this key, so the user have a mnemonic which he can later use to restore/import his wallet?

lontivero commented 6 years ago

There is no way to generate mnemonics for an existing extprvkey.

What you can do is generate a new seed A, import the xprvkey and swipe the funds from A to B.