예제 #1
0
        private static unsafe bool Loop23Hash(Sha256Fo sha, uint *wPt, uint *hPt, byte *tmp, ICompareService comparer)
        {
            // The added value below is the fixed first char('S')=0x53 shifted left 24 places
            wPt[0] = 0b01010011_00000000_00000000_00000000U | (uint)tmp[1] << 16 | (uint)tmp[2] << 8 | tmp[3];
            wPt[1] = (uint)tmp[4] << 24 | (uint)tmp[5] << 16 | (uint)tmp[6] << 8 | tmp[7];
            wPt[2] = (uint)tmp[8] << 24 | (uint)tmp[9] << 16 | (uint)tmp[10] << 8 | tmp[11];
            wPt[3] = (uint)tmp[12] << 24 | (uint)tmp[13] << 16 | (uint)tmp[14] << 8 | tmp[15];
            wPt[4] = (uint)tmp[16] << 24 | (uint)tmp[17] << 16 | (uint)tmp[18] << 8 | tmp[19];
            // The added value below is the SHA padding and the last added ? char equal to 0x3f shifted right 8 places
            wPt[5] = (uint)tmp[20] << 24 | (uint)tmp[21] << 16 | 0b00000000_00000000_00111111_10000000U;
            // from 6 to 14 = 0
            wPt[15] = 184; // 23 *8 = 184

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

            if ((hPt[0] & 0b11111111_00000000_00000000_00000000U) == 0)
            {
                // The actual key is SHA256 of 22 char key (without '?')
                // SHA working vector is already set, only the last 2 bytes ('?' and pad) and the length have to change
                wPt[5] ^= 0b00000000_00000000_10111111_10000000U;
                // from 6 to 14 (remain) = 0
                wPt[15] = 176; // 22 *8 = 176

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

                return(comparer.Compare(hPt));
            }
        public void OrderShouldBeValid()
        {
            // Arrange
            var models = new List <TariffModel>
            {
                new BasicElectricityTariff {
                    Consumption = 3500
                },
                new BasicElectricityTariff {
                    Consumption = 4500
                },
                new BasicElectricityTariff {
                    Consumption = 6000
                },
                new PackagedTariff {
                    Consumption = 3500
                },
                new PackagedTariff {
                    Consumption = 4500
                },
                new PackagedTariff {
                    Consumption = 6000
                }
            };

            // Act
            var result = compareService.Compare(models);

            // Assert
            Assert.IsTrue(result[0].AnnualCost < result[1].AnnualCost &&
                          result[1].AnnualCost < result[2].AnnualCost &&
                          result[2].AnnualCost < result[3].AnnualCost &&
                          result[3].AnnualCost < result[4].AnnualCost &&
                          result[4].AnnualCost < result[5].AnnualCost);
        }
예제 #3
0
        public async Task <IActionResult> Post([FromBody] RequestBody input)
        {
            try
            {
                if (!string.IsNullOrEmpty(input.backImage))
                {
                    var frontTask = Task.Run(() => _service.Compare(input.frontImage, _configuration));
                    var backTask  = Task.Run(() => _service.Compare(input.backImage, _configuration, false));
                    await Task.WhenAll(frontTask, backTask);

                    if (frontTask.Result + backTask.Result >= _configuration.FailedTreshold)
                    {
                        return(Ok(ResultEnum.Fail));
                    }

                    if (frontTask.Result + backTask.Result >= _configuration.NotOkayTreshold)
                    {
                        return(Ok(ResultEnum.NotOk));
                    }
                }
                else
                {
                    var frontTask = await Task.Run(() => _service.Compare(input.frontImage, _configuration));

                    if (frontTask >= _configuration.NotOkayTreshold)
                    {
                        return(Ok(ResultEnum.NotOk));
                    }

                    if (frontTask >= _configuration.FailedTreshold)
                    {
                        return(Ok(ResultEnum.Fail));
                    }
                }

                return(Ok(ResultEnum.Ok));
            }
            catch (Exception e)
            {
                return(BadRequest(e.Message));
            }
        }
예제 #4
0
        public async Task <IActionResult> Compare([FromBody] CompareInputDTO compareInputDTO)
        {
            if (!ModelState.IsValid)
            {
                return(BadRequest());
            }

            var result = await compareService.Compare(compareInputDTO);

            return(Ok(result));
        }
        public void CloneTest()
        {
            PrvToAddrNestedComparer original = new();

            Assert.True(original.Init(KeyHelper.Pub1NestedSegwit)); // Make sure it is successfully initialized
            ICompareService cloned = original.Clone();

            // Change original field value to make sure it is cloned not a reference copy
            Assert.True(original.Init(KeyHelper.Pub2NestedSegwit));

            byte[] key = KeyHelper.Prv1.ToBytes();

            // Since the original was changed it should fail when comparing
            Assert.False(original.Compare(key));
            Assert.True(cloned.Compare(key));
        }
예제 #6
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.");
        }
예제 #7
0
        public async Task Handle(object parameterObj)
        {
            var parameter = parameterObj as CompareParameter;

            Console.WriteLine("Start Compare the Files:");
            Console.WriteLine($"{parameter.Path1}");
            Console.WriteLine("And:");
            Console.WriteLine($"{parameter.Path2}");
            Console.WriteLine($"Config File: {parameter.ConfigFile}");
            Console.WriteLine($"Result will Save to: {parameter.OutputPath}");

            var progress = new Progress <IProgressReport>(report =>
            {
                TextProgressBar.Draw(report.Current, report.Total);
            });
            var compareFiles = await compareService.Compare(parameter.Path1, parameter.Path2, parameter.ConfigFile, progress);

            Thread.Sleep(200);
            await reportService.Output(compareFiles, parameter.Path1, parameter.Path2, parameter.OutputPath, false);
        }
예제 #8
0
        public async Task <IActionResult> OnPost()
        {
            try
            {
                var places = await turistPlaceService.ShowAll();

                ViewData["Places"] = new SelectList(places, "Name", "Name");
                if (!ModelState.IsValid)
                {
                    return(Page());
                }
                compareOutput = await compareService.Compare(compareInput);

                State = true;
                return(Page());
            }
            catch (Exception e)
            {
                State = false;
                ViewData["Errore"] = e.Message;
                return(Page());
            }
        }
예제 #9
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.");
        }
예제 #10
0
        public async Task <string> Diff(int?id)
        {
            ValidateIdAndData(id, string.Empty);

            return(JsonConvert.SerializeObject(await _service.Compare(id.Value)));
        }
예제 #11
0
        public unsafe bool SetBip32(ulong *bigBuffer, ICompareService comparer)
        {
            ulong *hPt    = bigBuffer;
            ulong *wPt    = hPt + Sha512Fo.HashStateSize;
            ulong *seedPt = wPt + Sha512Fo.WorkingVectorSize;
            ulong *iPt    = seedPt + Sha512Fo.HashStateSize;
            ulong *oPt    = iPt + Sha512Fo.WorkingVectorSize;

            // *** 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)
            Sha512Fo.Init_InnerPad_Bitcoinseed(hPt);
            *(Block64 *)wPt = *(Block64 *)seedPt;
            // from wPt[8] to wPt[15] didn't change
            Sha512Fo.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
            Sha512Fo.Init_OuterPad_Bitcoinseed(hPt);
            Sha512Fo.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:
            // TODO: this part can be set by the caller outside its loop
            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;

            Scalar sclrParent = new(hPt, out int overflow);

            if (overflow != 0)
            {
                return(false);
            }

            foreach (uint 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
                    wPt[0] = (ulong)sclrParent.b7 << 24 | (ulong)sclrParent.b6 >> 8;
                    wPt[1] = (ulong)sclrParent.b6 << 56 | (ulong)sclrParent.b5 << 24 | (ulong)sclrParent.b4 >> 8;
                    wPt[2] = (ulong)sclrParent.b4 << 56 | (ulong)sclrParent.b3 << 24 | (ulong)sclrParent.b2 >> 8;
                    wPt[3] = (ulong)sclrParent.b2 << 56 | (ulong)sclrParent.b1 << 24 | (ulong)sclrParent.b0 >> 8;
                    wPt[4] = (ulong)sclrParent.b0 << 56 |
                             (ulong)index << 24 |
                             0b00000000_00000000_00000000_00000000_00000000_10000000_00000000_00000000UL;
                }
                else
                {
                    Span <byte> pubkeyBytes = comparer.Calc.GetPubkey(sclrParent, true);
                    fixed(byte *pubXPt = &pubkeyBytes[0])
                    {
                        wPt[0] = (ulong)pubXPt[0] << 56 |
                                 (ulong)pubXPt[1] << 48 |
                                 (ulong)pubXPt[2] << 40 |
                                 (ulong)pubXPt[3] << 32 |
                                 (ulong)pubXPt[4] << 24 |
                                 (ulong)pubXPt[5] << 16 |
                                 (ulong)pubXPt[6] << 8 |
                                 pubXPt[7];
                        wPt[1] = (ulong)pubXPt[8] << 56 |
                                 (ulong)pubXPt[9] << 48 |
                                 (ulong)pubXPt[10] << 40 |
                                 (ulong)pubXPt[11] << 32 |
                                 (ulong)pubXPt[12] << 24 |
                                 (ulong)pubXPt[13] << 16 |
                                 (ulong)pubXPt[14] << 8 |
                                 pubXPt[15];
                        wPt[2] = (ulong)pubXPt[16] << 56 |
                                 (ulong)pubXPt[17] << 48 |
                                 (ulong)pubXPt[18] << 40 |
                                 (ulong)pubXPt[19] << 32 |
                                 (ulong)pubXPt[20] << 24 |
                                 (ulong)pubXPt[21] << 16 |
                                 (ulong)pubXPt[22] << 8 |
                                 pubXPt[23];
                        wPt[3] = (ulong)pubXPt[24] << 56 |
                                 (ulong)pubXPt[25] << 48 |
                                 (ulong)pubXPt[26] << 40 |
                                 (ulong)pubXPt[27] << 32 |
                                 (ulong)pubXPt[28] << 24 |
                                 (ulong)pubXPt[29] << 16 |
                                 (ulong)pubXPt[30] << 8 |
                                 pubXPt[31];
                        wPt[4] = (ulong)pubXPt[32] << 56 |
                                 (ulong)index << 24 |
                                 0b00000000_00000000_00000000_00000000_00000000_10000000_00000000_00000000UL;
                    }
                }

                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] = 1320; // (1+32+4 + 128)*8

                // 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];

                Sha512Fo.Init(hPt);
                Sha512Fo.SetW(iPt);
                Sha512Fo.CompressBlockWithWSet(hPt, iPt);
                Sha512Fo.Compress165SecondBlock(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; // (128+64)*8

                Sha512Fo.Init(hPt);
                Sha512Fo.SetW(oPt);
                Sha512Fo.CompressBlockWithWSet(hPt, oPt);
                Sha512Fo.Compress192SecondBlock(hPt, wPt);

                // New private key is (parentPrvKey + int(hPt)) % order
                sclrParent = sclrParent.Add(new Scalar(hPt, out _), out _);
            }

            // 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] = (ulong)sclrParent.b7 << 32 | sclrParent.b6;
            hPt[1] = (ulong)sclrParent.b5 << 32 | sclrParent.b4;
            hPt[2] = (ulong)sclrParent.b3 << 32 | sclrParent.b2;
            hPt[3] = (ulong)sclrParent.b1 << 32 | sclrParent.b0;

            return(comparer.Compare(hPt));
        }
예제 #12
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)));
            }
        }
예제 #13
0
        private unsafe void Loop2(byte[] preComputed, int missCount1, int missCount2,
                                  uint mask1, uint mask2, uint comp1, uint comp2)
        {
            // Note that in the following context HMAC is NOT HMACSHA256 despite the name
            // because it is using wrong inner/outer pads. For reference:
            // https://github.com/etotheipi/BitcoinArmory/blob/2a6fc5355bb0c6fe26e387ccba30a5baafe8cd98/armoryengine/ArmoryUtils.py#L1823

            // ChainCode is result of HMAC with 2x hash of private key as HMAC key
            // and "Derive Chaincode from Root Key" as its message

            using Sha256Fo sha = new Sha256Fo();
            byte *kPt   = stackalloc byte[32 + missingIndexes.Length];
            byte *item1 = kPt + 32;
            byte *item2 = item1 + missCount1;
            uint *oPt   = stackalloc uint[8];

            fixed(byte *pre = &preComputed[0])
            fixed(int *mi   = &missingIndexes[0])
            fixed(uint *wPt = &sha.w[0], hPt = &sha.hashState[0])
            {
                do
                {
                    *(Block32 *)kPt = *(Block32 *)pre;
                    int mIndex = 0;
                    for (int i = 0; i < missCount1; i++)
                    {
                        int index = mi[mIndex++];
                        kPt[index / 2] |= (index % 2 == 0) ? (byte)(item1[i] << 4) : item1[i];
                    }

                    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] = 0b10000000_00000000_00000000_00000000U;
                    wPt[5] = 0;
                    wPt[6] = 0;
                    wPt[7] = 0;
                    wPt[8] = 0;
                    // From 9 to 14 remain 0
                    wPt[15] = 128;

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

                    if ((hPt[0] & mask1) == comp1)
                    {
                        int mIndexInternal = mIndex;
                        do
                        {
                            for (int i = 0; i < missCount2; i++)
                            {
                                int index = mi[mIndex++];
                                kPt[(index / 2) + 16] |= (index % 2 == 0) ? (byte)(item2[i] << 4) : item2[i];
                            }

                            wPt[0] = (uint)((kPt[16] << 24) | (kPt[17] << 16) | (kPt[18] << 8) | kPt[19]);
                            wPt[1] = (uint)((kPt[20] << 24) | (kPt[21] << 16) | (kPt[22] << 8) | kPt[23]);
                            wPt[2] = (uint)((kPt[24] << 24) | (kPt[25] << 16) | (kPt[26] << 8) | kPt[27]);
                            wPt[3] = (uint)((kPt[28] << 24) | (kPt[29] << 16) | (kPt[30] << 8) | kPt[31]);
                            wPt[4] = 0b10000000_00000000_00000000_00000000U;
                            wPt[5] = 0;
                            wPt[6] = 0;
                            wPt[7] = 0;
                            wPt[8] = 0;
                            // From 9 to 14 remain 0
                            wPt[15] = 128;

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

                            if ((hPt[0] & mask2) == comp2)
                            {
                                BigInteger secexp = ComputeKey(sha, hPt, wPt, oPt, kPt);
                                if (comparer.Compare(secexp))
                                {
                                    SetResult(kPt);
                                    return;
                                }
                            }

                            // Reset second part for next round
                            *(Block16 *)(kPt + 16) = *(Block16 *)(pre + 16);
                            mIndex = mIndexInternal;
                        } while (MoveNext(item2, missCount2));

                        // Checking second line reached the end and failed, item2 must be reset to 0
                        for (int i = 0; i < missCount2; i++)
                        {
                            item2[i] = 0;
                        }
                    }
                } while (MoveNext(item1, missCount1));
            }
        }
예제 #14
0
        private unsafe bool Loop23()
        {
            // The actual data that is changing is 22 bytes (22 char long mini key) with a fixed starting character ('S')
            // plus an additional byte added to the end (char('?')=0x3f) during checking loop.
            // Checksum is replaced by checking if first byte of hash result is zero.
            // The actual key itself is the hash of the same 22 bytes (without '?') using a single SHA256
            // Note characters are decoded using UTF-8

            var cartesian = CartesianProduct.Create(Enumerable.Repeat(Encoding.UTF8.GetBytes(ConstantsFO.Base58Chars), missCount));

            using Sha256Fo sha = new Sha256Fo();
            bool success = false;

            byte[] temp = new byte[precomputed.Length];
            fixed(uint *hPt = &sha.hashState[0], wPt = &sha.w[0])
            fixed(byte *pre = &precomputed[0], tmp = &temp[0])
            fixed(int *mi   = &missingIndexes[0])
            {
                foreach (var item in cartesian)
                {
                    Buffer.MemoryCopy(pre, tmp, 22, 22);
                    int mis = 0;
                    foreach (var keyItem in item)
                    {
                        tmp[mi[mis]] = keyItem;
                        mis++;
                    }

                    // The added value below is the fixed first char(S)=0x53 shifted left 24 places
                    wPt[0] = 0b01010011_00000000_00000000_00000000U | (uint)tmp[1] << 16 | (uint)tmp[2] << 8 | tmp[3];
                    wPt[1] = (uint)tmp[4] << 24 | (uint)tmp[5] << 16 | (uint)tmp[6] << 8 | tmp[7];
                    wPt[2] = (uint)tmp[8] << 24 | (uint)tmp[9] << 16 | (uint)tmp[10] << 8 | tmp[11];
                    wPt[3] = (uint)tmp[12] << 24 | (uint)tmp[13] << 16 | (uint)tmp[14] << 8 | tmp[15];
                    wPt[4] = (uint)tmp[16] << 24 | (uint)tmp[17] << 16 | (uint)tmp[18] << 8 | tmp[19];
                    // The added value below is the SHA padding and the last added ? char equal to 0x3f shifted right 8 places
                    wPt[5] = (uint)tmp[20] << 24 | (uint)tmp[21] << 16 | 0b00000000_00000000_00111111_10000000U;
                    // from 6 to 14 = 0
                    wPt[15] = 184; // 23 *8 = 184

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

                    if ((hPt[0] & 0b11111111_00000000_00000000_00000000U) == 0)
                    {
                        // The actual key is SHA256 of 22 char key (without '?')
                        // SHA working vector is already set, only the last 2 bytes ('?' and pad) and the length have to change
                        wPt[5] ^= 0b00000000_00000000_10111111_10000000U;
                        // from 6 to 14 (remain) = 0
                        wPt[15] = 176; // 22 *8 = 176

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

                        if (comparer.Compare(sha.GetBytes(hPt)))
                        {
                            SetResult(item);
                            success = true;
                            break;
                        }
                    }
                }
            }

            return(success);
        }