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; }
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; }
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."); }
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; }
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; }
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."); }
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; }); }
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); }
// 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(); }
private bool SetResult(int mnLen) { report.AddMessageSafe($"Found a key: {Encoding.UTF8.GetString(mnBytes.SubArray(0, mnLen))}"); return(true); }
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; }
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); }