示例#1
0
        public bool Compare(byte[] key)
        {
            BigInteger kVal = new BigInteger(key, true, true);

            if (kVal >= curve.N || kVal == 0)
            {
                return(false);
            }

            EllipticCurvePoint actual = calc.MultiplyByG(kVal);

            return(actual == point);
        }
示例#2
0
        public PublicKey[] GetPublicKeys(BIP0032Path path, uint count, uint startIndex = 0, uint step = 1)
        {
            if (isDisposed)
            {
                throw new ObjectDisposedException(nameof(BIP0032));
            }
            if (path is null)
            {
                throw new ArgumentNullException(nameof(path), "Path can not be null!");
            }
            if (ExtendedKeyDepth == byte.MaxValue || ExtendedKeyDepth + path.Indexes.Length + 1 > byte.MaxValue)
            {
                throw new ArgumentOutOfRangeException(nameof(ExtendedKeyDepth), "Can not get children since " +
                                                      "depth will be bigger than 1 byte");
            }

            PublicKey[] result = new PublicKey[count];
            if (!(PrvKey is null))
            {
                PrivateKey[] tempPK = GetPrivateKeys(path, count, startIndex, step);
                for (int j = 0; j < tempPK.Length; j++)
                {
                    result[j] = tempPK[j].ToPublicKey();
                    tempPK[j].Dispose();
                }
                return(result);
            }

            // If we are here it means PrivateKey was null
            bool anyHardened = path.Indexes.Any(x => IsHardendedIndex(x));

            if (anyHardened || IsHardendedIndex(startIndex))
            {
                throw new ArgumentException();
            }

            // Two quick fixes:
            if (count == 0)
            {
                return(null);
            }
            if (step < 1)
            {
                step = 1;
            }

            // First start deriving the extended keys for each index
            BigInteger prevPrvInt = PrvKey.ToBigInt();

            byte[]             prevPubBa    = PubKey.ToByteArray(true);
            EllipticCurvePoint prevPubPoint = PubKey.ToPoint();

            byte[] tempCC = ChainCode;
            byte[] tempLeft;
            EllipticCurveCalculator calc = new EllipticCurveCalculator();

            foreach (var index in path.Indexes)
            {
                // There is no hardened indexes thanks to first check
                FastStream stream = new FastStream(33 + 4);
                stream.Write(prevPubBa);
                stream.WriteBigEndian(index);
                HmacAndSplitData(stream.ToByteArray(), tempCC, out tempLeft, out tempCC);

                BigInteger kTemp = tempLeft.ToBigInt(true, true);
                // Note that we throw an exception here if the values were invalid (highly unlikely)
                // because it is the extended keys, we can't skip anything here.
                if (kTemp == 0 || kTemp >= N)
                {
                    throw new ArgumentException();
                }
                EllipticCurvePoint pt      = calc.AddChecked(calc.MultiplyByG(kTemp), prevPubPoint);
                PublicKey          tempPub = new PublicKey(pt);
                prevPubPoint = tempPub.ToPoint();
                prevPubBa    = tempPub.ToByteArray(true);
            }

            // Then derive the actual keys

            int  i          = 0;
            uint childIndex = startIndex;

            while (i < count)
            {
                // There is no hardened indexes thanks to first check
                FastStream stream = new FastStream(33 + 4);
                stream.Write(prevPubBa);
                stream.WriteBigEndian(childIndex);
                HmacAndSplitData(stream.ToByteArray(), tempCC, out tempLeft, out _);

                BigInteger kTemp = tempLeft.ToBigInt(true, true);
                // Note: we don't throw any exceptions here. We simply ignore invalid values (highly unlikely)
                // and move on to the next index. The returned value will always be filled with expected number of items.
                if (kTemp == 0 || kTemp >= N)
                {
                    continue;
                }
                EllipticCurvePoint pt   = calc.AddChecked(calc.MultiplyByG(kTemp), prevPubPoint);
                PublicKey          temp = new PublicKey(pt);
                result[i++] = temp;

                childIndex += step;
            }
            return(result);
        }
示例#3
0
        public unsafe bool SetBip32(Sha512Fo sha, byte *mnPt, int mnLen, ulong *iPt, ulong *oPt)
        {
            // The process is: PBKDF2(password=UTF8(mnemonic), salt=UTF8("mnemonic+passphrase") -> BIP32 seed
            //                 BIP32 -> HMACSHA(data=seed, key=MasterKeyHashKey) -> HMACSHA(data=key|index, key=ChainCode)
            // All HMACSHAs are using 512 variant

            // *** PBKDF2 ***
            // dkLen/HmacLen=1 => only 1 block => no loop needed
            // Salt is the "mnemonic+passPhrase" + blockNumber(=1) => fixed and set during precomputing
            ulong[] resultOfF = new ulong[8];
            ulong[] uTemp     = new ulong[80];

            ulong[] iPadHashStateTemp = new ulong[8];
            ulong[] oPadHashStateTemp = new ulong[8];

            ulong parkey0, parkey1, parkey2, parkey3, carry;

            fixed(byte *dPt = &pbkdf2Salt[0])
            fixed(ulong *hPt = &sha.hashState[0], wPt = &sha.w[0], seedPt = &resultOfF[0], uPt = &uTemp[0],
                  ihPt       = &iPadHashStateTemp[0], ohPt = &oPadHashStateTemp[0])
            {
                // Setting values in uTemp that never change
                uPt[8]  = 0b10000000_00000000_00000000_00000000_00000000_00000000_00000000_00000000UL;
                uPt[9]  = 0;
                uPt[10] = 0;
                uPt[11] = 0;
                uPt[12] = 0;
                uPt[13] = 0;
                uPt[14] = 0;
                uPt[15] = 1536;


                // Set HMAC key ie. set pads (used as working vectors)
                if (mnLen > Sha512Fo.BlockByteSize)
                {
                    // Key bytes must be hashed first
                    sha.Init(hPt);
                    sha.CompressData(mnPt, mnLen, mnLen, hPt, wPt);
                    // Set pads to be used as working vectors
                    iPt[0]  = 0x3636363636363636U ^ hPt[0];
                    iPt[1]  = 0x3636363636363636U ^ hPt[1];
                    iPt[2]  = 0x3636363636363636U ^ hPt[2];
                    iPt[3]  = 0x3636363636363636U ^ hPt[3];
                    iPt[4]  = 0x3636363636363636U ^ hPt[4];
                    iPt[5]  = 0x3636363636363636U ^ hPt[5];
                    iPt[6]  = 0x3636363636363636U ^ hPt[6];
                    iPt[7]  = 0x3636363636363636U ^ hPt[7];
                    iPt[8]  = 0x3636363636363636U;
                    iPt[9]  = 0x3636363636363636U;
                    iPt[10] = 0x3636363636363636U;
                    iPt[11] = 0x3636363636363636U;
                    iPt[12] = 0x3636363636363636U;
                    iPt[13] = 0x3636363636363636U;
                    iPt[14] = 0x3636363636363636U;
                    iPt[15] = 0x3636363636363636U;

                    oPt[0]  = 0x5c5c5c5c5c5c5c5cU ^ hPt[0];
                    oPt[1]  = 0x5c5c5c5c5c5c5c5cU ^ hPt[1];
                    oPt[2]  = 0x5c5c5c5c5c5c5c5cU ^ hPt[2];
                    oPt[3]  = 0x5c5c5c5c5c5c5c5cU ^ hPt[3];
                    oPt[4]  = 0x5c5c5c5c5c5c5c5cU ^ hPt[4];
                    oPt[5]  = 0x5c5c5c5c5c5c5c5cU ^ hPt[5];
                    oPt[6]  = 0x5c5c5c5c5c5c5c5cU ^ hPt[6];
                    oPt[7]  = 0x5c5c5c5c5c5c5c5cU ^ hPt[7];
                    oPt[8]  = 0x5c5c5c5c5c5c5c5cU;
                    oPt[9]  = 0x5c5c5c5c5c5c5c5cU;
                    oPt[10] = 0x5c5c5c5c5c5c5c5cU;
                    oPt[11] = 0x5c5c5c5c5c5c5c5cU;
                    oPt[12] = 0x5c5c5c5c5c5c5c5cU;
                    oPt[13] = 0x5c5c5c5c5c5c5c5cU;
                    oPt[14] = 0x5c5c5c5c5c5c5c5cU;
                    oPt[15] = 0x5c5c5c5c5c5c5c5cU;
                }
                else
                {
                    byte[] temp = new byte[Sha512Fo.BlockByteSize];
                    fixed(byte *tPt = &temp[0])
                    {
                        Buffer.MemoryCopy(mnPt, tPt, Sha512Fo.BlockByteSize, mnLen);
                        for (int i = 0, j = 0; i < 16; i++, j += 8)
                        {
                            ulong val =
                                ((ulong)tPt[j] << 56) |
                                ((ulong)tPt[j + 1] << 48) |
                                ((ulong)tPt[j + 2] << 40) |
                                ((ulong)tPt[j + 3] << 32) |
                                ((ulong)tPt[j + 4] << 24) |
                                ((ulong)tPt[j + 5] << 16) |
                                ((ulong)tPt[j + 6] << 8) |
                                tPt[j + 7];

                            iPt[i] = 0x3636363636363636U ^ val;
                            oPt[i] = 0x5c5c5c5c5c5c5c5cU ^ val;
                        }
                    }
                }

                // F()
                // compute u1 = hmac.ComputeHash(data=pbkdf2Salt);

                // Final result is SHA512(outer_pad | SHA512(inner_pad | data)) where data is pbkdf2Salt
                // 1. Compute SHA512(inner_pad | data)
                sha.Init(hPt);
                sha.CompressBlock(hPt, iPt);
                // Make a copy of hashState of inner-pad to be used in the loop below (explaination in the loop)
                *(Block64 *)ihPt = *(Block64 *)hPt;
                // Data length is unknown and an initial block of 128 bytes was already compressed
                sha.CompressData(dPt, pbkdf2Salt.Length, pbkdf2Salt.Length + 128, hPt, wPt);
                // 2. Compute SHA512(outer_pad | hash)
                *(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

                sha.Init(hPt);
                sha.CompressBlock(hPt, oPt);
                // Make a copy of hashState of outer-pad to be used in the loop below (explaination in the loop)
                *(Block64 *)ohPt = *(Block64 *)hPt;
                sha.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 *)uPt = *(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 *)ihPt;
                    sha.Compress192SecondBlock(hPt, uPt);

                    // 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 *)ohPt;
                    sha.Compress192SecondBlock(hPt, wPt);

                    // result of F() is XOR sum of all u arrays
                    if (Avx2.IsSupported) // AVX512 :(
                    {
                        Vector256 <ulong> part1 = Avx2.Xor(Avx2.LoadVector256(seedPt), Avx2.LoadVector256(hPt));
                        Vector256 <ulong> part2 = Avx2.Xor(Avx2.LoadVector256(seedPt + 4), Avx2.LoadVector256(hPt + 4));

                        Avx2.Store(seedPt, part1);
                        Avx2.Store(seedPt + 4, part2);
                    }
                    else
                    {
                        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];
                    }
                }


                // *** BIP32 ***
                // Set from entropy/seed by computing HMAC(data=seed, key="Bitcoin seed")

                // Final result is SHA512(outer_pad | SHA512(inner_pad | data)) where data is 64-byte seed
                // 1. Compute SHA512(inner_pad | data)
                sha.Init_InnerPad_Bitcoinseed(hPt);
                *(Block64 *)wPt = *(Block64 *)seedPt;
                // from wPt[8] to wPt[15] didn't change
                sha.Compress192SecondBlock(hPt, wPt);

                // 2. Compute SHA512(outer_pad | hash)
                *(Block64 *)wPt = *(Block64 *)hPt; // ** Copy hashState before changing it **
                // from wPt[8] to wPt[15] didn't change
                sha.Init_OuterPad_Bitcoinseed(hPt);
                sha.Compress192SecondBlock(hPt, wPt);
                // Master key is set. PrivateKey= first 32-bytes of hPt and ChainCode is second 32-bytes

                // Each child is derived by computing HMAC(data=(hardened? 0|prvKey : pubkey) | index, key=ChainCode)
                // ChainCode is the second 32-byte half of the hash. Set pad items that never change here:
                iPt[4]  = 0x3636363636363636U;
                iPt[5]  = 0x3636363636363636U;
                iPt[6]  = 0x3636363636363636U;
                iPt[7]  = 0x3636363636363636U;
                iPt[8]  = 0x3636363636363636U;
                iPt[9]  = 0x3636363636363636U;
                iPt[10] = 0x3636363636363636U;
                iPt[11] = 0x3636363636363636U;
                iPt[12] = 0x3636363636363636U;
                iPt[13] = 0x3636363636363636U;
                iPt[14] = 0x3636363636363636U;
                iPt[15] = 0x3636363636363636U;

                oPt[4]  = 0x5c5c5c5c5c5c5c5cU;
                oPt[5]  = 0x5c5c5c5c5c5c5c5cU;
                oPt[6]  = 0x5c5c5c5c5c5c5c5cU;
                oPt[7]  = 0x5c5c5c5c5c5c5c5cU;
                oPt[8]  = 0x5c5c5c5c5c5c5c5cU;
                oPt[9]  = 0x5c5c5c5c5c5c5c5cU;
                oPt[10] = 0x5c5c5c5c5c5c5c5cU;
                oPt[11] = 0x5c5c5c5c5c5c5c5cU;
                oPt[12] = 0x5c5c5c5c5c5c5c5cU;
                oPt[13] = 0x5c5c5c5c5c5c5c5cU;
                oPt[14] = 0x5c5c5c5c5c5c5c5cU;
                oPt[15] = 0x5c5c5c5c5c5c5c5cU;

                uPt[5]  = 0;
                uPt[6]  = 0;
                uPt[7]  = 0;
                uPt[8]  = 0;
                uPt[9]  = 0;
                uPt[10] = 0;
                uPt[11] = 0;
                uPt[12] = 0;
                uPt[13] = 0;
                uPt[14] = 0;
                uPt[15] = 1320; // (1+32+4 + 128)*8

                BigInteger kParent = new BigInteger(sha.GetFirst32Bytes(hPt), true, true);

                if (kParent == 0 || kParent >= order)
                {
                    return(false);
                }
                parkey0 = hPt[3];
                parkey1 = hPt[2];
                parkey2 = hPt[1];
                parkey3 = hPt[0];

                foreach (var index in path.Indexes)
                {
                    if ((index & 0x80000000) != 0) // IsHardened
                    {
                        // First _byte_ is zero
                        // private-key is the first 32 bytes (4 items) of hPt (total 33 bytes)
                        // 4 bytes index + SHA padding are also added
                        uPt[0] = parkey3 >> 8;
                        uPt[1] = parkey3 << 56 | parkey2 >> 8;
                        uPt[2] = parkey2 << 56 | parkey1 >> 8;
                        uPt[3] = parkey1 << 56 | parkey0 >> 8;
                        uPt[4] = parkey0 << 56 |
                                 (ulong)index << 24 |
                                 0b00000000_00000000_00000000_00000000_00000000_10000000_00000000_00000000UL;
                    }
                    else
                    {
                        var    point  = calc.MultiplyByG(kParent);
                        byte[] xBytes = point.X.ToByteArray(true, true).PadLeft(32);
                        fixed(byte *pubXPt = &xBytes[0])
                        {
                            uPt[0] = (point.Y.IsEven ? 0x0200000000000000UL : 0x0300000000000000UL) |
                                     (ulong)pubXPt[0] << 48 |
                                     (ulong)pubXPt[1] << 40 |
                                     (ulong)pubXPt[2] << 32 |
                                     (ulong)pubXPt[3] << 24 |
                                     (ulong)pubXPt[4] << 16 |
                                     (ulong)pubXPt[5] << 8 |
                                     pubXPt[6];
                            uPt[1] = (ulong)pubXPt[7] << 56 |
                                     (ulong)pubXPt[8] << 48 |
                                     (ulong)pubXPt[9] << 40 |
                                     (ulong)pubXPt[10] << 32 |
                                     (ulong)pubXPt[11] << 24 |
                                     (ulong)pubXPt[12] << 16 |
                                     (ulong)pubXPt[13] << 8 |
                                     pubXPt[14];
                            uPt[2] = (ulong)pubXPt[15] << 56 |
                                     (ulong)pubXPt[16] << 48 |
                                     (ulong)pubXPt[17] << 40 |
                                     (ulong)pubXPt[18] << 32 |
                                     (ulong)pubXPt[19] << 24 |
                                     (ulong)pubXPt[20] << 16 |
                                     (ulong)pubXPt[21] << 8 |
                                     pubXPt[22];
                            uPt[3] = (ulong)pubXPt[23] << 56 |
                                     (ulong)pubXPt[24] << 48 |
                                     (ulong)pubXPt[25] << 40 |
                                     (ulong)pubXPt[26] << 32 |
                                     (ulong)pubXPt[27] << 24 |
                                     (ulong)pubXPt[28] << 16 |
                                     (ulong)pubXPt[29] << 8 |
                                     pubXPt[30];
                            uPt[4] = (ulong)pubXPt[31] << 56 |
                                     (ulong)index << 24 |
                                     0b00000000_00000000_00000000_00000000_00000000_10000000_00000000_00000000UL;
                        }
                    }


                    // Final result is SHA512(outer_pad | SHA512(inner_pad | 37_byte_data))
                    // 1. Compute SHA512(inner_pad | 37_byte_data)
                    // Set pads to be used as working vectors (key is ChainCode that is the second 32 bytes of SHA512
                    iPt[0] = 0x3636363636363636U ^ hPt[4];
                    iPt[1] = 0x3636363636363636U ^ hPt[5];
                    iPt[2] = 0x3636363636363636U ^ hPt[6];
                    iPt[3] = 0x3636363636363636U ^ hPt[7];

                    oPt[0] = 0x5c5c5c5c5c5c5c5cU ^ hPt[4];
                    oPt[1] = 0x5c5c5c5c5c5c5c5cU ^ hPt[5];
                    oPt[2] = 0x5c5c5c5c5c5c5c5cU ^ hPt[6];
                    oPt[3] = 0x5c5c5c5c5c5c5c5cU ^ hPt[7];

                    sha.Init(hPt);
                    sha.CompressBlock(hPt, iPt);
                    sha.Compress165SecondBlock(hPt, uPt);

                    // 2. Compute SHA512(outer_pad | hash)
                    *(Block64 *)wPt = *(Block64 *)hPt;

                    // from wPt[8] to wPt[15] didn't change
                    sha.Init(hPt);
                    sha.CompressBlock(hPt, oPt);
                    sha.Compress192SecondBlock(hPt, wPt);

                    // New private key is (parentPrvKey + int(hPt)) % order
                    // TODO: this is a bottleneck and needs to be replaced by a ModularUInt256 instance
                    kParent = (kParent + new BigInteger(sha.GetFirst32Bytes(hPt), true, true)) % order;

                    ulong toAdd = hPt[3];
                    parkey0 += toAdd;
                    if (parkey0 < toAdd)
                    {
                        parkey1++;
                    }

                    toAdd    = hPt[2];
                    parkey1 += toAdd;
                    if (parkey1 < toAdd)
                    {
                        parkey2++;
                    }

                    toAdd    = hPt[1];
                    parkey2 += toAdd;
                    if (parkey2 < toAdd)
                    {
                        parkey3++;
                    }

                    toAdd    = hPt[0];
                    parkey3 += toAdd;
                    if (parkey3 < toAdd)
                    {
                        carry = 1;
                    }
                    else
                    {
                        carry = 0;
                    }

                    bool bigger = false;
                    if (carry == 1)
                    {
                        bigger = true;
                    }
                    else if (parkey3 == N3)
                    {
                        if (parkey2 > N2)
                        {
                            bigger = true;
                        }
                        else if (parkey2 == N2)
                        {
                            if (parkey1 > N1)
                            {
                                bigger = true;
                            }
                            else if (parkey1 == N1)
                            {
                                if (parkey0 >= N0)
                                {
                                    bigger = true;
                                }
                            }
                        }
                    }

                    if (bigger)
                    {
                        if (parkey0 < N0)
                        {
                            parkey1--;
                        }
                        parkey0 -= N0;

                        if (parkey1 < N1)
                        {
                            parkey2--;
                        }
                        parkey1 -= N1;

                        if (parkey2 < N2)
                        {
                            parkey3--;
                        }
                        parkey2 -= N2;

                        parkey3 -= N3;
                    }
                }

                // Child extended key (private key + chianCode) should be set by adding the index to the end of the Path
                // and have been computed already
                hPt[0] = parkey3;
                hPt[1] = parkey2;
                hPt[2] = parkey1;
                hPt[3] = parkey0;

                return(comparer.Compare(sha.GetFirst32Bytes(hPt)));
            }
        }
示例#4
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));
            EllipticCurveCalculator calc = new EllipticCurveCalculator();



            BigInteger         smallVal = new BigInteger(ba, true, true);
            EllipticCurvePoint smallPub = calc.MultiplyByG(smallVal);
            Ripemd160Sha256    hash     = new Ripemd160Sha256();

            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);

                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);
                    }
                    AddQueue($"Found a key: {new string(origHex)}");
                    loopState.Break();
                }
            });


            AddQueue("Failed to find any key.");
            return(false);
        }
示例#5
0
 public bool Compare(BigInteger key) => Compare(calc.MultiplyByG(key));