public static byte[] GenerateEntropyFromWords(string[] words, Wordlist wordList) { // Should always have at least 12 words if (words.Length % 3 > 0 || words.Length == 0) { throw new FormatException("Word list size must be a multiple of three words"); } int concatLenBits = words.Length * 11; Array concatBits = Array.CreateInstance(typeof(bool), concatLenBits); int[] wordIndices = wordList.ToIndices(words); int wordindex = 0; foreach (int wordIndice in wordIndices) { // 11 bits per word (2048) for (int i = 0; i < 11; ++i) { bool bit = (wordIndice & (1 << (10 - i))) != 0; concatBits.SetValue(bit, (wordindex * 11) + i); } ++wordindex; } int checksumLengthBits = concatLenBits / 33; int entropyLengthBits = concatLenBits - checksumLengthBits; byte[] entropy = new byte[entropyLengthBits / 8]; for (int i = 0; i < entropy.Length; ++i) { // 8 bits per byte... for (int j = 0; j < 8; ++j) { bool bit = (bool)concatBits.GetValue((i * 8) + j); if (bit) { entropy[i] |= (byte)(1 << (7 - j)); } } } byte[] hash = SHA256.Create().ComputeHash(entropy); BitArray hashBitArray = new BitArray(BytesToBoolArray(hash)); Array hashBits = Array.CreateInstance(typeof(bool), checksumLengthBits); for (int i = 0; i < checksumLengthBits; i++) { hashBits.SetValue(hashBitArray.Get(i), i); } for (int i = 0; i < checksumLengthBits; ++i) { bool concatbit = (bool)concatBits.GetValue(entropyLengthBits + i); bool hashbit = (bool)hashBits.GetValue(i); if (concatbit != hashbit) { throw new Bip39CrcException("CRC Checksum validation failed"); } } return(entropy); }