public async Task <bool> FindMissing(string mnemonic, char missingChar, MnemonicTypes mnType, WordLists wl)
        {
            InitReport();

            if (!TrySetWordList(wl))
            {
                return(false);
            }
            if (!IsMissingCharValid(missingChar))
            {
                return(Fail("Missing character is not accepted."));
            }
            if (!TrySplitMnemonic(mnemonic, missingChar, out words))
            {
                return(false);
            }

            Stopwatch watch = Stopwatch.StartNew();

            bool success = await Task.Run(() =>
            {
                return(words.Length switch
                {
                    24 => Loop24(),
                    21 => Loop21(),
                    18 => Loop18(),
                    15 => Loop15(),
                    _ => Loop12(),
                });
            });
Beispiel #2
0
        private bool TrySetEntropy(string mnemonic, MnemonicTypes mnType)
        {
            if (string.IsNullOrWhiteSpace(mnemonic))
            {
                return(report.Fail("Mnemonic can not be null or empty."));
            }

            return(report.Fail("Not yet implemented."));
        }
Beispiel #3
0
        public async void Find(string mnemonic, MnemonicTypes mnType, BIP0039.WordLists wl,
                               string extra, InputType extraType, string path, int passLength, byte[] allValues)
        {
            report.Init();

            if (mnType != MnemonicTypes.BIP39 && mnType != MnemonicTypes.Electrum)
            {
                report.Fail("Mnemonic type is not defined.");
            }
            if (!MnemonicSevice.TrySetWordList(wl, out string[] allWords, out int maxWordLen))
Beispiel #4
0
        private bool TrySetSalt(int len, MnemonicTypes mnType, out byte[] result)
        {
            if (len < 1)
            {
                result = null;
                report.Fail("Password length must be at least 1.");
                return(false);
            }

            // Each SHA512 block is 128 bytes, last 16 bytes are data length, PBKDF2 adds 4 byte block int,
            // BIP39 and Electrum both add a string that is 8 bytes
            // Anything smaller than that is a single block. We reject big passphrases (>=100 byte) to make things simple
            // and it doesn't matter because recovering such big passphrases is already impossible!
            if (len >= Sha512Fo.BlockByteSize - 16 - Pbkdf2BlockNumberLength - MnStartStringLen)
            {
                result = null;
                report.Fail($"Password length={len} are not supported. Start a new issue on GitHub if you need this.");
                return(false);
            }

            result = new byte[Sha512Fo.BlockByteSize];
            // Pad:
            result[len + MnStartStringLen + Pbkdf2BlockNumberLength] = 0b1000_0000;
            // PBKDF2 block number = 1
            result[len + MnStartStringLen + 3] = 1;
            // Salt is used in HMACSHA512 where a block (inner pad) is already compressed so total data length is +128
            int totalLen = len + MnStartStringLen + Pbkdf2BlockNumberLength + 128;

            // See SHA512 to understand why this is correct:
            result[127] = (byte)(totalLen << 3);
            result[126] = (byte)(totalLen >> 5);
            result[125] = (byte)(totalLen >> 13);
            result[124] = (byte)(totalLen >> 21);
            result[123] = (byte)(totalLen >> 29);

            byte[] start = mnType == MnemonicTypes.BIP39 ? Encoding.UTF8.GetBytes("mnemonic") : Encoding.UTF8.GetBytes("electrum");
            Debug.Assert(start.Length == MnStartStringLen);
            Buffer.BlockCopy(start, 0, result, 0, start.Length);

            return(true);
        }
Beispiel #5
0
        public bool TryDecodeMnemonic(string mnemonic, MnemonicTypes mnType, string[] allWords, out byte[] bytes)
        {
            bytes = null;
            if (string.IsNullOrWhiteSpace(mnemonic))
            {
                return(report.Fail("Mnemonic can not be null or empty."));
            }
            else
            {
                string[] words = mnemonic.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
                if (!MnemonicSevice.allowedWordLengths.Contains(words.Length))
                {
                    return(report.Fail("Invalid mnemonic length."));
                }

                bool invalidWord = false;
                for (int i = 0; i < words.Length; i++)
                {
                    if (!allWords.Contains(words[i]))
                    {
                        invalidWord = true;
                        report.Fail($"Given mnemonic contains invalid word at index {i} ({words[i]}).");
                    }
                }
                if (invalidWord)
                {
                    return(false);
                }

                string temp       = string.Join(' ', words);
                string normalized = mnType == MnemonicTypes.Electrum ? ElectrumMnemonic.Normalize(temp) : temp;

                bytes = Encoding.UTF8.GetBytes(normalized);
                return(true);
            }
        }