private unsafe void SetResult(byte *kPt)
        {
            string res = EncodeFull(new ReadOnlySpan <byte>(kPt, 32));

            report.AddMessageSafe($"Found the correct recovery phrase:{Environment.NewLine}{res}");
            report.FoundAnyResult = true;
        }
示例#2
0
        private void SetResultParallelWifEnd(int added)
        {
            using PrivateKey tempKey = new(wifEndStart + added);
            string tempWif = tempKey.ToWif(isWifEndCompressed);

            report.AddMessageSafe($"Found the key: {tempWif}");
            report.FoundAnyResult = true;
        }
示例#3
0
        public void Loop(BIP0032 bip32, uint count)
        {
            BIP0032Path[] allPaths = new BIP0032Path[]
            {
                new BIP0032Path("m/0"),
                new BIP0032Path("m/0'"),
                new BIP0032Path("m/0'/0/"),
                new BIP0032Path("m/0'/0'"),
                // BIP-44 xprv/xpub P2PKH
                new BIP0032Path("m/44'/0'/0'/0"),
                new BIP0032Path("m/44'/0'/0'"),
                // BIP-49 yprv/upub P2SH-P2WPKH
                new BIP0032Path("m/49'/0'/0'/0"),
                new BIP0032Path("m/49'/0'/0'"),
                // BIP-84 zprv/zpub P2WPKH
                new BIP0032Path("m/84'/0'/0'/0"),
                new BIP0032Path("m/84'/0'/0'/"),
                new BIP0032Path("m/84'/0'/2147483644'/0"),
                new BIP0032Path("m/84'/0'/2147483645'/0"),
                new BIP0032Path("m/84'/0'/2147483646'/0"),
                new BIP0032Path("m/84'/0'/2147483647'/0"),
                new BIP0032Path("m/49'/0'/2147483647'/0"),
                new BIP0032Path("m/44'/0'/2147483647'/0"),
                new BIP0032Path("m/141'/0'/0'/0"),
            };


            foreach (BIP0032Path path in allPaths)
            {
                PrivateKey[] keys = bip32.GetPrivateKeys(path, count);
                for (int i = 0; i < keys.Length; i++)
                {
                    if (comparer.Compare(keys[i].ToBytes()))
                    {
                        report.AddMessageSafe($"The correct key path is: {path}/{i}");
                        report.FoundAnyResult = true;
                        return;
                    }
                }
            }

            report.AddMessageSafe("Could not find any correct paths.");
        }
示例#4
0
        private void SetResultParallel(uint[] missingItems, int firstItem)
        {
            // Chances of finding more than 1 correct result is very small in base-58 and even if it happened
            // this method would be called in very long intervals, meaning UI updates here are not an issue.
            report.AddMessageSafe($"Found a possible result (will continue checking the rest):");

            char[] temp = keyToCheck.ToCharArray();
            int    i    = 0;

            if (firstItem != -1)
            {
                temp[temp.Length - missingIndexes[i++] - 1] = ConstantsFO.Base58Chars[firstItem];
            }
            foreach (var index in missingItems)
            {
                temp[temp.Length - missingIndexes[i++] - 1] = ConstantsFO.Base58Chars[(int)index];
            }

            report.AddMessageSafe(new string(temp));
            report.FoundAnyResult = true;
        }
示例#5
0
        private unsafe void SetResultParallel(int *items, int firstItem)
        {
            char[] origHex = key.ToCharArray();
            origHex[missingIndexes[0]] = GetHex(firstItem);
            for (int i = 0; i < missCount - 1; i++)
            {
                int index = missingIndexes[i + 1];
                origHex[index] = GetHex(items[i]);
            }

            report.AddMessageSafe($"Found the key: {new string(origHex)}");
            report.FoundAnyResult = true;
        }
示例#6
0
        public void Loop(BIP0032 bip32, uint count, bool isPubkey)
        {
            BIP0032Path[] allPaths = isPubkey ?
                                     new BIP0032Path[]
            {
                new BIP0032Path("m/0")
            } :
            new BIP0032Path[]
            {
                new BIP0032Path("m/0"),
                new BIP0032Path("m/0'"),
                new BIP0032Path("m/0'/0/"),
                // BIP-44 xprv/xpub P2PKH
                new BIP0032Path("m/44'/0'/0'/0"),
                // BIP-49 yprv/upub P2SH-P2WPKH
                new BIP0032Path("m/49'/0'/0'/0"),
                // BIP-84 zprv/zpub P2WPKH
                new BIP0032Path("m/84'/0'/0'/0"),
            };


            foreach (var path in allPaths)
            {
                PublicKey[] pubkeys = bip32.GetPublicKeys(path, count);
                for (int i = 0; i < pubkeys.Length; i++)
                {
                    if (comparer.Compare(pubkeys[i].ToPoint()))
                    {
                        report.AddMessageSafe($"The correct key path is: {path}/{i}");
                        report.FoundAnyResult = true;
                        return;
                    }
                }
            }

            report.AddMessageSafe("Could not find any correct paths.");
        }
示例#7
0
        private void SetResult(IEnumerable <byte> item)
        {
            Task.Run(() =>
            {
                char[] temp = keyToCheck.ToCharArray();
                int i       = 0;
                foreach (var index in item)
                {
                    temp[missingIndexes[i++]] = (char)index;
                }

                report.AddMessageSafe($"Found a possible result: {new string(temp)}");
                return;
            });
        }
示例#8
0
        private unsafe bool LoopComp(string key, int missingCount, char missingChar, byte[] expectedHash)
        {
            int[]  missingIndexes = new int[missingCount];
            byte[] ba             = new byte[32];
            for (int i = 0, j = 0; i < ba.Length; i++)
            {
                int hi, lo;
                if (key[i * 2] == missingChar)
                {
                    hi = 0;
                    missingIndexes[j++] = i * 2;
                }
                else
                {
                    hi = key[i * 2] - 65;
                    hi = hi + 10 + ((hi >> 31) & 7);
                }
                if (key[i * 2 + 1] == '*')
                {
                    lo = 0;
                    missingIndexes[j++] = i * 2 + 1;
                }
                else
                {
                    lo = key[i * 2 + 1] - 65;
                    lo = lo + 10 + ((lo >> 31) & 7) & 0x0f;
                }

                ba[i] = (byte)(lo | hi << 4);
            }

            var    cartesian = CartesianProduct.Create(Enumerable.Repeat(Enumerable.Range(0, 16), missingCount));
            ECCalc calc      = new ECCalc();


            BigInteger         smallVal = new BigInteger(ba, true, true);
            EllipticCurvePoint smallPub = calc.MultiplyByG(smallVal);
            bool foundAny = false;

            Parallel.ForEach(cartesian, (item, loopState) =>
            {
                Span <byte> temp = new byte[32];

                int mis = 0;
                foreach (int keyItem in item)
                {
                    int misIndex = missingIndexes[mis];
                    if (misIndex % 2 == 0)
                    {
                        temp[misIndex / 2] |= (byte)(keyItem << 4);
                    }
                    else
                    {
                        temp[misIndex / 2] |= (byte)keyItem;
                    }
                    mis++;
                }

                BigInteger tempVal         = new BigInteger(temp, true, true);
                EllipticCurvePoint tempPub = calc.MultiplyByG(tempVal);
                EllipticCurvePoint pub     = calc.AddChecked(tempPub, smallPub);
                byte[] toHash = new byte[33];
                toHash[0]     = pub.Y.IsEven ? (byte)2 : (byte)3;
                byte[] xBytes = pub.X.ToByteArray(true, true);
                Buffer.BlockCopy(xBytes, 0, toHash, 33 - xBytes.Length, xBytes.Length);

                Hash160 hash = new Hash160();
                ReadOnlySpan <byte> actual = hash.ComputeHash(toHash);
                if (actual.SequenceEqual(expectedHash))
                {
                    char[] origHex = key.ToCharArray();
                    int index      = 0;
                    foreach (var keyItem in item)
                    {
                        origHex[missingIndexes[index++]] = GetHex(keyItem);
                    }
                    report.AddMessageSafe($"Found a key: {new string(origHex)}");
                    foundAny = true;
                    loopState.Break();
                }
            });

            if (!foundAny)
            {
                report.AddMessageSafe("Failed to find any key.");
            }
            return(foundAny);
        }
示例#9
0
        // pads are HMAC inner and outer pad hashstates that are already computed using mnemonic
        public unsafe void LoopBip39(ulong[] pads, byte[] salt, byte[] allValues, int passLength, ParallelLoopState loopState)
        {
            Debug.Assert(pads != null && pads.Length == Sha512Fo.HashStateSize * 2);
            Debug.Assert(salt != null && salt.Length == Sha512Fo.BlockByteSize);

            ulong *bigBuffer = stackalloc ulong[Sha512Fo.UBufferSize + Sha512Fo.HashStateSize + (2 * Sha512Fo.WorkingVectorSize)];
            ulong *hPt       = bigBuffer;
            ulong *wPt       = hPt + Sha512Fo.HashStateSize;
            ulong *seedPt    = wPt + Sha512Fo.WorkingVectorSize;

            Debug.Assert(passLength - 1 > 0);
            int[] items = new int[passLength - 1];

            fixed(byte *dPt = &salt[0], valPt = &allValues[0])
            fixed(ulong *iPt   = &pads[0], oPt = &pads[Sha512Fo.HashStateSize])
            fixed(int *itemsPt = &items[0])
            {
                do
                {
                    if (loopState.IsStopped)
                    {
                        return;
                    }

                    int startIndex = 9;
                    for (int i = 0; i < items.Length; i++)
                    {
                        Debug.Assert(itemsPt[i] < allValues.Length);
                        dPt[startIndex++] = valPt[itemsPt[i]];
                    }

                    // 1. SHA512(inner_pad | data) -> 2 blocks; first one is already compressed
                    *(Block64 *)hPt = *(Block64 *)iPt;
                    // Data length is unknown and an initial block of 128 bytes was already compressed
                    // but we already reject anything big that needs another block (there is only one more block to compress)
                    // The pad and data length is also already set
                    Sha512Fo.CompressSingleBlock(dPt, hPt, wPt);

                    // 2. SHA512(outer_pad | hash) -> 2 blocks; first one is already compressed
                    // Copy hashstate into next block before changing it
                    *(Block64 *)wPt = *(Block64 *)hPt;
                    wPt[8]          = 0b10000000_00000000_00000000_00000000_00000000_00000000_00000000_00000000UL;
                    wPt[9]          = 0;
                    wPt[10]         = 0;
                    wPt[11]         = 0;
                    wPt[12]         = 0;
                    wPt[13]         = 0;
                    wPt[14]         = 0;
                    wPt[15]         = 1536; // oPad.Length(=128) + hashState.Lengh(=64) = 192 byte *8 = 1,536 bit

                    *(Block64 *)hPt = *(Block64 *)oPt;
                    Sha512Fo.Compress192SecondBlock(hPt, wPt);

                    // Copy u1 to result of F() to be XOR'ed with each result on iterations, and result of F() is the seed
                    *(Block64 *)seedPt = *(Block64 *)hPt;

                    // Compute u2 to u(c-1) where c is iteration and each u is the HMAC of previous u
                    for (int j = 1; j < 2048; j++)
                    {
                        // Each u is calculated by computing HMAC(previous_u) where previous_u is 64 bytes hPt
                        // Start by making a copy of hPt so Init() can be called
                        *(Block64 *)wPt = *(Block64 *)hPt;

                        // Final result is SHA512(outer_pad | SHA512(inner_pad | 64_byte_data))
                        // 1. Compute SHA512(inner_pad | 64_byte_data)
                        // 2. Compute SHA512(outer_pad | hash)
                        //    Since pads don't change and each step is Init() then Compress(pad) the hashState is always the same
                        //    after these 2 steps and is already computed and stored in temp arrays above
                        //    by doing this 2*2047=4094 SHA512 block compressions are skipped

                        // Replace: sha.Init(hPt); sha.CompressBlockWithWSet(hPt, iPt); with line below:
                        *(Block64 *)hPt = *(Block64 *)iPt;
                        Sha512Fo.Compress192SecondBlock(hPt, wPt);

                        // 2. Compute SHA512(outer_pad | hash)
                        *(Block64 *)wPt = *(Block64 *)hPt;
                        // The rest of wPt is set above and is unchanged

                        // Replace: sha.Init(hPt); sha.CompressBlock(hPt, oPt); with line below:
                        *(Block64 *)hPt = *(Block64 *)oPt;
                        Sha512Fo.Compress192SecondBlock(hPt, wPt);

                        // result of F() is XOR sum of all u arrays
                        seedPt[0] ^= hPt[0];
                        seedPt[1] ^= hPt[1];
                        seedPt[2] ^= hPt[2];
                        seedPt[3] ^= hPt[3];
                        seedPt[4] ^= hPt[4];
                        seedPt[5] ^= hPt[5];
                        seedPt[6] ^= hPt[6];
                        seedPt[7] ^= hPt[7];
                    }

                    if (SetBip32(bigBuffer, comparer))
                    {
                        loopState.Stop();
                        report.FoundAnyResult = true;

                        byte[] temp = new byte[items.Length + 1];
                        temp[0] = dPt[8];
                        for (int i = 1; i < temp.Length; i++)
                        {
                            temp[i] = valPt[items[i - 1]];
                        }
                        string finalResult = Encoding.UTF8.GetString(temp);

                        report.AddMessageSafe($"Passphrase is: {finalResult}");

                        return;
                    }
                } while (MoveNext(itemsPt, items.Length, allValues.Length));
            }

            report.IncrementProgress();
        }
示例#10
0
 private bool SetResult(int mnLen)
 {
     report.AddMessageSafe($"Found a key: {Encoding.UTF8.GetString(mnBytes.SubArray(0, mnLen))}");
     return(true);
 }
示例#11
0
 private unsafe void SetResultParallel(byte *keyBytes, int len)
 {
     // This method is called once and after it is called the execution stops so GUI update is not a problem.
     report.AddMessageSafe($"Found the correct key: {Encoding.UTF8.GetString(keyBytes, len)}");
     report.FoundAnyResult = true;
 }
示例#12
0
        private unsafe bool SpecialLoopComp(string key)
        {
            byte[] padded;
            int    uLen;

            // Maximum result (58^52) is 39 bytes = 39/4 = 10 uint
            uLen = 10;
            uint[] powers58 = new uint[ConstantsFO.PrivKeyCompWifLen * uLen];
            padded = new byte[4 * uLen];

            for (int i = 0, j = 0; i < ConstantsFO.PrivKeyCompWifLen; i++)
            {
                BigInteger val  = BigInteger.Pow(58, i);
                byte[]     temp = val.ToByteArray(true, false);

                Array.Clear(padded, 0, padded.Length);
                Buffer.BlockCopy(temp, 0, padded, 0, temp.Length);

                for (int k = 0; k < padded.Length; j++, k += 4)
                {
                    powers58[j] = (uint)(padded[k] << 0 | padded[k + 1] << 8 | padded[k + 2] << 16 | padded[k + 3] << 24);
                }
            }

            int[] values = new int[key.Length];
            for (int i = 0; i < values.Length; i++)
            {
                values[i] = ConstantsFO.Base58Chars.IndexOf(key[i]);
            }

            uint[] precomputed = new uint[uLen];

            fixed(uint *pre = &precomputed[0], pow = &powers58[0])
            {
                // i starts from 1 becaue it is compressed (K or L)
                for (int i = 1; i < ConstantsFO.PrivKeyCompWifLen - 2; i++)
                {
                    for (int j = i + 1; j < ConstantsFO.PrivKeyCompWifLen - 1; j++)
                    {
                        for (int k = j + 1; k < ConstantsFO.PrivKeyCompWifLen; k++)
                        {
                            ((Span <uint>)precomputed).Clear();

                            for (int index = 0; index < i; index++)
                            {
                                ulong carry    = 0;
                                ulong val      = (ulong)values[index];
                                int   powIndex = (ConstantsFO.PrivKeyCompWifLen - 1 - index) * uLen;
                                for (int m = uLen - 1; m >= 0; m--, powIndex++)
                                {
                                    ulong result = (pow[powIndex] * val) + pre[m] + carry;
                                    pre[m] = (uint)result;
                                    carry  = (uint)(result >> 32);
                                }
                            }

                            for (int index = i + 1; index < j; index++)
                            {
                                ulong carry    = 0;
                                ulong val      = (ulong)values[index - 1];
                                int   powIndex = (ConstantsFO.PrivKeyCompWifLen - 1 - index) * uLen;
                                for (int m = uLen - 1; m >= 0; m--, powIndex++)
                                {
                                    ulong result = (pow[powIndex] * val) + pre[m] + carry;
                                    pre[m] = (uint)result;
                                    carry  = (uint)(result >> 32);
                                }
                            }

                            for (int index = j + 1; index < k; index++)
                            {
                                ulong carry    = 0;
                                ulong val      = (ulong)values[index - 2];
                                int   powIndex = (ConstantsFO.PrivKeyCompWifLen - 1 - index) * uLen;
                                for (int m = uLen - 1; m >= 0; m--, powIndex++)
                                {
                                    ulong result = (pow[powIndex] * val) + pre[m] + carry;
                                    pre[m] = (uint)result;
                                    carry  = (uint)(result >> 32);
                                }
                            }

                            for (int index = k + 1; index < ConstantsFO.PrivKeyCompWifLen; index++)
                            {
                                ulong carry    = 0;
                                ulong val      = (ulong)values[index - 3];
                                int   powIndex = (ConstantsFO.PrivKeyCompWifLen - 1 - index) * uLen;
                                for (int m = uLen - 1; m >= 0; m--, powIndex++)
                                {
                                    ulong result = (pow[powIndex] * val) + pre[m] + carry;
                                    pre[m] = (uint)result;
                                    carry  = (uint)(result >> 32);
                                }
                            }

                            var cancelToken = new CancellationTokenSource();
                            var options     = new ParallelOptions
                            {
                                CancellationToken = cancelToken.Token,
                            };

                            try
                            {
                                Parallel.For(0, 58, options, (c1, loopState) =>
                                {
                                    for (int c2 = 0; c2 < 58; c2++)
                                    {
                                        for (int c3 = 0; c3 < 58; c3++)
                                        {
                                            options.CancellationToken.ThrowIfCancellationRequested();

                                            Span <uint> temp = new uint[uLen];
                                            ((ReadOnlySpan <uint>)precomputed).CopyTo(temp);

                                            ulong carry  = 0;
                                            ulong val    = (ulong)c1;
                                            int powIndex = (ConstantsFO.PrivKeyCompWifLen - 1 - i) * uLen;
                                            for (int m = uLen - 1; m >= 0; m--, powIndex++)
                                            {
                                                ulong result = (powers58[powIndex] * val) + temp[m] + carry;
                                                temp[m]      = (uint)result;
                                                carry        = (uint)(result >> 32);
                                            }

                                            carry    = 0;
                                            val      = (ulong)c2;
                                            powIndex = (ConstantsFO.PrivKeyCompWifLen - 1 - j) * uLen;
                                            for (int m = uLen - 1; m >= 0; m--, powIndex++)
                                            {
                                                ulong result = (powers58[powIndex] * val) + temp[m] + carry;
                                                temp[m]      = (uint)result;
                                                carry        = (uint)(result >> 32);
                                            }

                                            carry    = 0;
                                            val      = (ulong)c3;
                                            powIndex = (ConstantsFO.PrivKeyCompWifLen - 1 - k) * uLen;
                                            for (int m = uLen - 1; m >= 0; m--, powIndex++)
                                            {
                                                ulong result = (powers58[powIndex] * val) + temp[m] + carry;
                                                temp[m]      = (uint)result;
                                                carry        = (uint)(result >> 32);
                                            }

                                            if (ComputeSpecialHash(temp))
                                            {
                                                string foundRes = key.Insert(i, $"{ConstantsFO.Base58Chars[c1]}")
                                                                  .Insert(j, $"{ConstantsFO.Base58Chars[c2]}")
                                                                  .Insert(k, $"{ConstantsFO.Base58Chars[c3]}");
                                                report.AddMessageSafe($"Found a key: {foundRes}");
                                                //Task.Run(() => cancelToken.Cancel());
                                            }
                                        }
                                    }
                                });
                            }
                            catch (Exception)
                            {
                                return(true);
                            }
                        }
                    }
                }
            }

            return(false);
        }