Mnemonic seeds (BIP39)
A BIP39 mnemonic is a list of 12 to 24 words that encodes random entropy plus a checksum. Users write it down,
and software turns it into the seed for an HD key tree. The
mnemonics appendix in the Developer Guide describes the encoding. In
Bitcoin4J the MnemonicCode class handles all of it, with the English word list built in.
Generating a phrase
Section titled “Generating a phrase”// 16 bytes of entropy give us 12 words, and 32 bytes give 24.byte[] entropy = new byte[16];new SecureRandom().nextBytes(entropy);
MnemonicCode mnemonicCode = new MnemonicCode(); // the English BIP39 word listList<String> words = mnemonicCode.toMnemonic(entropy);The entropy length decides the number of words. 16, 20, 24, 28 or 32 bytes give us 12, 15, 18, 21 or 24
words, and any other length throws MnemonicException.MnemonicLengthException.
Please note that the phrase is only as unpredictable as the entropy bytes, so we always use a
SecureRandomfor them.
Turning a phrase into a seed
Section titled “Turning a phrase into a seed”List<String> words = Arrays.asList( "abandon", "abandon", "abandon", "abandon", "abandon", "abandon", "abandon", "abandon", "abandon", "abandon", "abandon", "about");
// The passphrase is optional. We pass "" for none (null throws).byte[] seed = MnemonicCode.toSeed(words, "TREZOR");toSeed() is static, and does not check the words. Any list produces a seed. The optional passphrase (BIP39
calls it an extension word) changes the seed completely, so the same phrase with a different passphrase is a
different wallet.
The value above is the official BIP39 test vector.
Checking a phrase
Section titled “Checking a phrase”We check what a user typed before we derive anything from it.
MnemonicCode mnemonicCode = new MnemonicCode();List<String> typo = Arrays.asList( "abandon", "abandon", "abandon", "abandon", "abandon", "abandon", "abandon", "abandon", "abandon", "abandon", "abandon", "abandon");
// check() throws a MnemonicException subclass for a bad length, an unknown word or a bad checksum.assertThrows(MnemonicException.MnemonicChecksumException.class, () -> mnemonicCode.check(typo));check() throws one of:
MnemonicLengthException, for the wrong number of words,MnemonicWordException, for a word that is not in the list,MnemonicChecksumException, when all the words are valid but the checksum does not match. That usually means a typo or a swapped word.
toEntropy() runs the same checks and returns the entropy bytes.
From phrase to Address
Section titled “From phrase to Address”Let’s put the common wallet flow together: phrase, seed, master key, BIP44 path and finally an Address.
List<String> words = Utils.WHITESPACE_SPLITTER.splitToList( "abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about");byte[] seed = MnemonicCode.toSeed(words, "");
DeterministicKey master = HDKeyDerivation.createMasterPrivateKey(seed);DeterministicKey first = new DeterministicHierarchy(master) .get(HDPath.parsePath("m/44H/0H/0H/0/0"), false, true);
Address address = Address.fromKey(NetworkAddressType.MAIN_PKH, PublicKey.fromBytes(first.getPubKey()));
Utils.WHITESPACE_SPLITTERsplits a phrase on any run of whitespace, which is more forgiving of user input thanString.split(" "). It is a good idea to lower-case the input as well, since the word list is in lower case.

