/** Convert mnemonic word list to original entropy value. */ public byte[] toEntropy(List<String> words) throws MnemonicException.MnemonicLengthException, MnemonicException.MnemonicWordException, MnemonicException.MnemonicChecksumException { if (words.size() % 3 > 0) throw new MnemonicException.MnemonicLengthException( "Word list size must be multiple of three words."); if (words.size() == 0) throw new MnemonicException.MnemonicLengthException("Word list is empty."); // Look up all the words in the list and construct the // concatenation of the original entropy and the checksum. // int concatLenBits = words.size() * 11; boolean[] concatBits = new boolean[concatLenBits]; int wordindex = 0; for (String word : words) { // Find the words index in the wordlist. int ndx = Collections.binarySearch(this.wordList, word); if (ndx < 0) throw new MnemonicException.MnemonicWordException(word); // Set the next 11 bits to the value of the index. for (int ii = 0; ii < 11; ++ii) concatBits[(wordindex * 11) + ii] = (ndx & (1 << (10 - ii))) != 0; ++wordindex; } int checksumLengthBits = concatLenBits / 33; int entropyLengthBits = concatLenBits - checksumLengthBits; // Extract original entropy as bytes. byte[] entropy = new byte[entropyLengthBits / 8]; for (int ii = 0; ii < entropy.length; ++ii) for (int jj = 0; jj < 8; ++jj) if (concatBits[(ii * 8) + jj]) entropy[ii] |= 1 << (7 - jj); // Take the digest of the entropy. byte[] hash = Sha256Hash.create(entropy).getBytes(); boolean[] hashBits = bytesToBits(hash); // Check all the checksum bits. for (int i = 0; i < checksumLengthBits; ++i) if (concatBits[entropyLengthBits + i] != hashBits[i]) throw new MnemonicException.MnemonicChecksumException(); return entropy; }
/** Convert entropy data to mnemonic word list. */ public List<String> toMnemonic(byte[] entropy) throws MnemonicException.MnemonicLengthException { if (entropy.length % 4 > 0) throw new MnemonicException.MnemonicLengthException( "Entropy length not multiple of 32 bits."); if (entropy.length == 0) throw new MnemonicException.MnemonicLengthException("Entropy is empty."); // We take initial entropy of ENT bits and compute its // checksum by taking first ENT / 32 bits of its SHA256 hash. byte[] hash = Sha256Hash.create(entropy).getBytes(); boolean[] hashBits = bytesToBits(hash); boolean[] entropyBits = bytesToBits(entropy); int checksumLengthBits = entropyBits.length / 32; // We append these bits to the end of the initial entropy. boolean[] concatBits = new boolean[entropyBits.length + checksumLengthBits]; System.arraycopy(entropyBits, 0, concatBits, 0, entropyBits.length); System.arraycopy(hashBits, 0, concatBits, entropyBits.length, checksumLengthBits); // Next we take these concatenated bits and split them into // groups of 11 bits. Each group encodes number from 0-2047 // which is a position in a wordlist. We convert numbers into // words and use joined words as mnemonic sentence. ArrayList<String> words = new ArrayList<String>(); int nwords = concatBits.length / 11; for (int i = 0; i < nwords; ++i) { int index = 0; for (int j = 0; j < 11; ++j) { index <<= 1; if (concatBits[(i * 11) + j]) index |= 0x1; } words.add(this.wordList.get(index)); } return words; }
public static ByteString hashToByteString(Sha256Hash hash) { return ByteString.copyFrom(hash.getBytes()); }