public static bool Verification(string mnemonic) { var words = mnemonic.Trim().Split(' '); //判断助记词的单数数是否合法 var allowLength = new int[] { 12, 15, 18, 21, 24 }; if (!allowLength.Contains(words.Length)) { throw new ArgumentException("Mnemonic words count error!"); } //检测助记语言 Wordlist wordList = new English(); if (words.ToList().All(p => new ChineseSimplified().WordList.Contains(p))) { wordList = new ChineseSimplified(); } //将助记词转为二进制字符串(每个单词转为 11 位的二进制数) var sb = new StringBuilder(); foreach (var item in words) { var index = wordList.WordList.IndexOf(item); if (index < 0) { throw new ArgumentException($"The \"{item}\" isn't the correct mnemonic word!"); } var str = Convert.ToString(index, 2); while (str.Length < 11) { str = "0" + str; } sb.Append(str); } var entcsString = sb.ToString(); var entropyString = entcsString.Substring(0, sb.Length * 32 / 33); //将二进制字符串转了字节数组 var entropyBytes = new List <byte>(); for (int i = 0; i < entropyString.Length / 8; i++) { var binaryString = new string(entropyString.Substring(i * 8, 8).Reverse().ToArray()); var temp = 0; for (int j = 0; j < binaryString.Length; j++) { temp += (int)Math.Pow(2, j) * (binaryString[j] == '1' ? 1 : 0); } entropyBytes.Add((byte)temp); } var checksum = entropyBytes.ToArray().Sha256(); var checksumString = ToBinaryString(checksum).Substring(0, entropyBytes.Count / 4); if (!entcsString.EndsWith(checksumString)) { throw new ArgumentException($"The mnemonic verification doesn't pass!"); } return(true); }
/// <summary> /// 生成助记词 /// </summary> /// <param name="entLength">随机序列(熵)的长度,为了防止错误,可选范围为 {128, 160, 192, 224, 256}</param> /// <param name="language">助词词语言</param> /// <returns>助记词列表</returns> public static string GenerateMnemonic(EntropyLength entLength = EntropyLength._128, Language language = Language.English) { //创建一个 128 到 256 位的随机序列(熵) var entropyBytes = GetRandom((int)entLength / 8); var entropyString = ToBinaryString(entropyBytes); //提出 SHA256 哈希前几位(ENT/ 32),就可以创造一个随机序列的校验和 var checksum = entropyBytes.Sha256(); var checksumString = ToBinaryString(checksum).Substring(0, (int)entLength / 32); //将校验和添加到随机序列的末尾。 var entcsString = entropyString + checksumString; //将序列划分为包含 11 位的不同部分。 if (entcsString.Length % 11 != 0) { throw new Exception(); } //将每个包含 11 位部分的值与一个已经预先定义 2048 个单词的字典做对应 var index = new List <int>(); for (int i = 0; i < entcsString.Length / 11; i++) { var binaryString = new string(entcsString.Skip(11 * i).Take(11).Reverse().ToArray()); var temp = 0; for (int j = 0; j < binaryString.Length; j++) { temp += (int)Math.Pow(2, j) * (binaryString[j] == '1' ? 1 : 0); } index.Add(temp); } //生成的有顺序的单词组就是助记码 var words = new List <string>(); Wordlist wordList; if (language == Language.ChineseSimplified) { wordList = new ChineseSimplified(); } else { wordList = new English(); } index.ForEach(p => words.Add(wordList.WordList[p])); return(string.Join(' ', words)); }