Beispiel #1
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);
        }
        private unsafe BigInteger ComputeKey(Sha256Fo sha, uint *hPt, uint *wPt, uint *oPt, byte *kPt)
        {
            byte[] chainCode;
            if (hasChainCode)
            {
                chainCode = this.chainCode;
            }
            else
            {
                // Compute chain-code
                // h1 = SHA256( SHA256(SHA256(key)) XOR 0x36 | "Derive Chaincode from Root Key")
                // Chain-code = SHA256( SHA256(SHA256(key)) XOR 0x5c | h1)
                sha.Init(hPt);
                wPt[0] = (uint)((kPt[0] << 24) | (kPt[1] << 16) | (kPt[2] << 8) | kPt[3]);
                wPt[1] = (uint)((kPt[4] << 24) | (kPt[5] << 16) | (kPt[6] << 8) | kPt[7]);
                wPt[2] = (uint)((kPt[8] << 24) | (kPt[9] << 16) | (kPt[10] << 8) | kPt[11]);
                wPt[3] = (uint)((kPt[12] << 24) | (kPt[13] << 16) | (kPt[14] << 8) | kPt[15]);
                wPt[4] = (uint)((kPt[16] << 24) | (kPt[17] << 16) | (kPt[18] << 8) | kPt[19]);
                wPt[5] = (uint)((kPt[20] << 24) | (kPt[21] << 16) | (kPt[22] << 8) | kPt[23]);
                wPt[6] = (uint)((kPt[24] << 24) | (kPt[25] << 16) | (kPt[26] << 8) | kPt[27]);
                wPt[7] = (uint)((kPt[28] << 24) | (kPt[29] << 16) | (kPt[30] << 8) | kPt[31]);
                wPt[8] = 0b10000000_00000000_00000000_00000000U;
                // From 9 to 14 remain 0
                wPt[15] = 256;

                sha.CompressDouble32(hPt, wPt);

                // Use hPt in both iPt and oPt here before it is changed
                oPt[0] = hPt[0] ^ 0x5c5c5c5cU;
                oPt[1] = hPt[1] ^ 0x5c5c5c5cU;
                oPt[2] = hPt[2] ^ 0x5c5c5c5cU;
                oPt[3] = hPt[3] ^ 0x5c5c5c5cU;
                oPt[4] = hPt[4] ^ 0x5c5c5c5cU;
                oPt[5] = hPt[5] ^ 0x5c5c5c5cU;
                oPt[6] = hPt[6] ^ 0x5c5c5c5cU;
                oPt[7] = hPt[7] ^ 0x5c5c5c5cU;

                wPt[0]  = hPt[0] ^ 0x36363636U;
                wPt[1]  = hPt[1] ^ 0x36363636U;
                wPt[2]  = hPt[2] ^ 0x36363636U;
                wPt[3]  = hPt[3] ^ 0x36363636U;
                wPt[4]  = hPt[4] ^ 0x36363636U;
                wPt[5]  = hPt[5] ^ 0x36363636U;
                wPt[6]  = hPt[6] ^ 0x36363636U;
                wPt[7]  = hPt[7] ^ 0x36363636U;
                wPt[8]  = 0x44657269; // Deri
                wPt[9]  = 0x76652043; // ve C
                wPt[10] = 0x6861696e; // hain
                wPt[11] = 0x636f6465; // code
                wPt[12] = 0x2066726f; //  fro
                wPt[13] = 0x6d20526f; // m Ro
                wPt[14] = 0x6f74204b; // ot K
                wPt[15] = 0x65798000; // ey + 0x80 pad

                sha.Init(hPt);
                sha.CompressBlock(hPt, wPt);

                wPt[0]  = 0;
                wPt[1]  = 0;
                wPt[2]  = 0;
                wPt[3]  = 0;
                wPt[4]  = 0;
                wPt[5]  = 0;
                wPt[6]  = 0;
                wPt[7]  = 0;
                wPt[8]  = 0;
                wPt[9]  = 0;
                wPt[10] = 0;
                wPt[11] = 0;
                wPt[12] = 0;
                wPt[13] = 0;
                wPt[14] = 0;
                wPt[15] = 496; // 32+30 * 8

                sha.Compress62SecondBlock(hPt, wPt);

                *(Block32 *)wPt = *(Block32 *)oPt;
                wPt[8]          = hPt[0];
                wPt[9]          = hPt[1];
                wPt[10]         = hPt[2];
                wPt[11]         = hPt[3];
                wPt[12]         = hPt[4];
                wPt[13]         = hPt[5];
                wPt[14]         = hPt[6];
                wPt[15]         = hPt[7];

                sha.Init(hPt);
                sha.CompressBlock(hPt, wPt);

                wPt[0]  = 0b10000000_00000000_00000000_00000000U;
                wPt[1]  = 0;
                wPt[2]  = 0;
                wPt[3]  = 0;
                wPt[4]  = 0;
                wPt[5]  = 0;
                wPt[6]  = 0;
                wPt[7]  = 0;
                wPt[8]  = 0;
                wPt[9]  = 0;
                wPt[10] = 0;
                wPt[11] = 0;
                wPt[12] = 0;
                wPt[13] = 0;
                wPt[14] = 0;
                wPt[15] = 512; // 32+32 * 8

                sha.Compress64SecondBlock(hPt, wPt);

                // TODO: this could be improved a bit
                chainCode = sha.GetBytes(hPt);
            }

            // hPt is chain-code now
            ReadOnlySpan <byte> key   = new ReadOnlySpan <byte>(kPt, 32);
            BigInteger          k     = new BigInteger(key, true, true);
            EllipticCurvePoint  point = calc.MultiplyByG(k);

            byte[] pubBa = new byte[65];
            pubBa[0] = 4;
            byte[] xBytes = point.X.ToByteArray(true, true);
            byte[] yBytes = point.Y.ToByteArray(true, true);
            Buffer.BlockCopy(xBytes, 0, pubBa, 33 - xBytes.Length, xBytes.Length);
            Buffer.BlockCopy(yBytes, 0, pubBa, 65 - yBytes.Length, yBytes.Length);

            byte[] chainXor = sha.CompressDouble65(pubBa);
            for (var i = 0; i < chainXor.Length; i++)
            {
                chainXor[i] ^= chainCode[i];
            }

            BigInteger A = new BigInteger(chainXor, true, true);
            BigInteger B = new BigInteger(key, true, true);

            BigInteger secexp = (A * B).Mod(N);

            return(secexp);
        }