The mnemonics are the private key separated in 12 words which, together in the same order, produce the private key.
It's wrong. A mnemonic represents an entropy that is passed to a PBKDF2 key stretch function with 2048 hash turns to generate a 512-bit seed. This seed then acts as a keychain used to generate different keys. Check the last section of the answer to see how private keys are generated from the seed.
How are the mnemonics generated?
As noted above, the mnemonics are a representation of entropy with a checksum. The first step is to decide which entropy you consider safe for your operations. Suppose for the moment that you have opted for 128 bits of entropy. Below are the steps to convert this entropy into a mnemonic.
- Use a cryptographically secure entropy generator to generate 128 bits of entropy.
- Calculate the
SHA256 of entropy.
- Add the first
entropy_length/32 pieces of
SHA256 from entropy to the end of entropy. For example, in our case, we will add the first 4 bits of the
SHA256(entropy) to entropy since our entropy is 128 bits.
- Each word in the mnemonic represents 11 bits. Therefore, if you look at the word list, you will find 2048 unique words. Now divide the
entropy + checksum in parts of 11 bits each.
- Match these 11-bit fragments with the words in the search table of the word list. Since we used 128 bits of entropy, our checksum was 4 bits. Thus, our entropy with the checksum represented a total of 132 bits. Thus, our mnemonic will be 12 words.
If you had used 256 bits of entropy, your checksum would have been (256/32 =) 8 bits. That would represent (264/11) = 24 words.
One thing to note is that every 12/24 words can not be used as mnemonics. Part of the last word usually contains the checksum of the words chosen and must be calculated. It is also discouraged to generate words directly from thought and to use a secure cryptographic function to do so.
Why Ledger Mnemonics has 24 words?
This is a security design choice. The higher the number of words, the higher the entropy. 24 words will provide 256 bits of entropy. It is also important to note that a mnemonic phrase can not be used between different words. For example, you can not convert a representation of 24 words into 12 words and vice versa.
How are these words converted to a private key?
The mnemonic is passed to the PBKDF2 key stretch function with 2048 hash cycles. The PBKDF2 function also has the ability to take a "salt" which can be an optional passphrase. This passphrase provides an extra layer of security and prevents brute force attacks with lookup tables. The output of this function is a seed of 512 bits.
This seed is then transmitted to
HMAC-SHA512 with the key "Bitcoin seed". The resulting hash is used to create the primary private key (m) and the main string code (c). The left 256 bits represent m, while the right 256 bits represent c. The main private key
m is then used to generate the main public key M (M = m * G).
From there, a number of diversion paths exist for different portfolios. The most common is a BIP 44 enhanced derivation method. We will use it in the section below. k and K respectively represent the private key and the associated public key.
We must first show that we have used the BIP 44 bypass path. This can be done with an index number and generate a private key at a deeper level from the primary private key. The private key child a deeper level:
kchild = kpar + hash(kpar, cpar, i) or
i is the index number. To derive hardened from BIP 44,
i will be
0x80000044 (we use this last 231 half of the index for hardened derivation). This result will give us a number of 512 bits. The remaining 256 bits will represent the child's private key and the right-hand 256 bits, the child string code.
The next level represents the part. For Bitcoin, it's
0x80000000 in hardened bypass. You then calculate the private key and the channel code using the form above.
The next level represents the account. You can use multiple accounts to represent different functions and better manage your funds. You can use the logic above to generate the private key and the account string code.
From there, we do not use hardened derivation. The next level represents the receiving address with respect to the change. This allows you to have a different group to receive private keys and a different group for private modification keys. The function we will use to generate the private child from the parent will be:
kchild = kpar + hash(Kpar, cpar, i). Now
i will be
0x00000000 to receive and
0x00000001 for change. Also note that we now have the public key in the hash function rather than the private key.
At the next level, we use these receivers and modify the key group to generate individual private keys. Use the above to generate private keys and a string code, then pass them to the above function.
kchild = kpar + hash(Kpar, cpar, i) generate individual keys. Each increment of
i will give you a different private key.
Now, use these private keys to generate Bitcoin addresses.