private unsafe bool Loop31() { 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, 30, 30); 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]; wPt[5] = (uint)tmp[20] << 24 | (uint)tmp[21] << 16 | (uint)tmp[22] << 8 | tmp[23]; wPt[6] = (uint)tmp[24] << 24 | (uint)tmp[25] << 16 | (uint)tmp[26] << 8 | tmp[27]; // The added value below is the SHA padding and the last added ? char equal to 0x3f shifted right 8 places wPt[7] = (uint)tmp[28] << 24 | (uint)tmp[29] << 16 | 0b00000000_00000000_00111111_10000000U; // from 8 to 14 = 0 wPt[15] = 248; // 31 *8 = 184 sha.Init(hPt); sha.Compress31(hPt, wPt); if ((hPt[0] & 0b11111111_00000000_00000000_00000000U) == 0) { // Same as above wPt[7] ^= 0b00000000_00000000_10111111_10000000U; // from 8 to 14 (remain) = 0 wPt[15] = 240; // 30 *8 = 240 sha.Init(hPt); sha.Compress30(hPt, wPt); if (comparer.Compare(sha.GetBytes(hPt))) { SetResult(item); success = true; break; } } } } return(success); }
private unsafe bool Loop21() { using Sha512Fo sha512 = new Sha512Fo(); ulong[] ipad = new ulong[80]; ulong[] opad = new ulong[80]; using Sha256Fo sha256 = new Sha256Fo(); var cartesian = CartesianProduct.Create(Enumerable.Repeat(Enumerable.Range(0, 2048), missCount)); fixed(ulong *iPt = ipad, oPt = opad) fixed(uint *wPt = &sha256.w[0], hPt = &sha256.hashState[0], wrd = &wordIndexes[0]) fixed(int *mi = &missingIndexes[0]) fixed(byte *mnPt = &mnBytes[0]) { wPt[7] = 0b10000000_00000000_00000000_00000000U; wPt[15] = 224; foreach (var item in cartesian) { int j = 0; foreach (var k in item) { wrd[mi[j]] = (uint)k; j++; } wPt[0] = wrd[0] << 21 | wrd[1] << 10 | wrd[2] >> 1; wPt[1] = wrd[2] << 31 | wrd[3] << 20 | wrd[4] << 9 | wrd[5] >> 2; wPt[2] = wrd[5] << 30 | wrd[6] << 19 | wrd[7] << 8 | wrd[8] >> 3; wPt[3] = wrd[8] << 29 | wrd[9] << 18 | wrd[10] << 7 | wrd[11] >> 4; wPt[4] = wrd[11] << 28 | wrd[12] << 17 | wrd[13] << 6 | wrd[14] >> 5; wPt[5] = wrd[14] << 27 | wrd[15] << 16 | wrd[16] << 5 | wrd[17] >> 6; wPt[6] = wrd[17] << 26 | wrd[18] << 15 | wrd[19] << 4 | wrd[20] >> 7; sha256.Init(hPt); sha256.Compress28(hPt, wPt); if ((wrd[20] & 0b111_1111) == hPt[0] >> 25) { int mnLen = 0; for (int i = 0; i < 21; i++) { foreach (byte b in wordBytes[wrd[i]]) { mnPt[mnLen++] = b; } mnPt[mnLen++] = SpaceByte; } if (SetBip32(sha512, mnPt, --mnLen, iPt, oPt)) { return(SetResult(mnLen)); } } } } return(false); }
private unsafe bool Loop27() { // Same as above but key is 26 chars 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, 26, 26); int mis = 0; foreach (var keyItem in item) { tmp[mi[mis]] = keyItem; mis++; } 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]; wPt[5] = (uint)tmp[20] << 24 | (uint)tmp[21] << 16 | (uint)tmp[22] << 8 | tmp[23]; wPt[6] = (uint)tmp[24] << 24 | (uint)tmp[25] << 16 | 0b00000000_00000000_00111111_10000000U; // from 7 to 14 = 0 wPt[15] = 216; // 27 *8 = 216 sha.Init(hPt); sha.Compress27(hPt, wPt); if ((hPt[0] & 0b11111111_00000000_00000000_00000000U) == 0) { wPt[6] ^= 0b00000000_00000000_10111111_10000000U; // from 7 to 14 (remain) = 0 wPt[15] = 208; // 26 *8 = 208 sha.Init(hPt); sha.Compress26(hPt, wPt); if (comparer.Compare(sha.GetBytes(hPt))) { SetResult(item); success = true; break; } } } } return(success); }
private unsafe bool LoopComp() { report.ChangeProgressVisibilitySafe(false); var cartesian = CartesianProduct.Create(Enumerable.Repeat(Enumerable.Range(0, 58), missCount)); using Sha256Fo sha = new Sha256Fo(); bool success = false; uint[] temp = new uint[precomputed.Length]; fixed(uint *hPt = &sha.hashState[0], wPt = &sha.w[0]) fixed(uint *pow = &powers58[0], res = &precomputed[0], tmp = &temp[0]) fixed(int *mi = &missingIndexes[0]) { foreach (var item in cartesian) { Buffer.MemoryCopy(res, tmp, 40, 40); int mis = 0; foreach (var keyItem in item) { ulong carry = 0; for (int k = 9, j = 0; k >= 0; k--, j++) { ulong result = (pow[(mi[mis] * 10) + j] * (ulong)keyItem) + tmp[k] + carry; tmp[k] = (uint)result; carry = (uint)(result >> 32); } mis++; } wPt[0] = (tmp[0] << 16) | (tmp[1] >> 16); wPt[1] = (tmp[1] << 16) | (tmp[2] >> 16); wPt[2] = (tmp[2] << 16) | (tmp[3] >> 16); wPt[3] = (tmp[3] << 16) | (tmp[4] >> 16); wPt[4] = (tmp[4] << 16) | (tmp[5] >> 16); wPt[5] = (tmp[5] << 16) | (tmp[6] >> 16); wPt[6] = (tmp[6] << 16) | (tmp[7] >> 16); wPt[7] = (tmp[7] << 16) | (tmp[8] >> 16); wPt[8] = (tmp[8] << 16) | 0b00000000_00000000_10000000_00000000U; // from 9 to 14 =0 wPt[15] = 272; // 34 *8 = 272 sha.Init(hPt); sha.CompressDouble34(hPt, wPt); if (hPt[0] == tmp[9]) { SetResult(item); success = true; } } } return(success); }
private unsafe bool LoopUncomp() { var cartesian = CartesianProduct.Create(Enumerable.Repeat(Enumerable.Range(0, 58), missCount)); bool success = false; uint[] temp = new uint[precomputed.Length]; fixed(uint *hPt = &sha.hashState[0], wPt = &sha.w[0]) fixed(uint *pow = &powers58[0], res = &precomputed[0], tmp = &temp[0]) fixed(int *mi = &missingIndexes[0]) { foreach (var item in cartesian) { Buffer.MemoryCopy(res, tmp, 40, 40); int mis = 0; foreach (var keyItem in item) { ulong carry = 0; for (int k = 9, j = 0; k >= 0; k--, j++) { ulong result = (pow[(mi[mis] * 10) + j] * (ulong)keyItem) + tmp[k] + carry; tmp[k] = (uint)result; carry = (uint)(result >> 32); } mis++; } wPt[0] = (tmp[0] << 24) | (tmp[1] >> 8); wPt[1] = (tmp[1] << 24) | (tmp[2] >> 8); wPt[2] = (tmp[2] << 24) | (tmp[3] >> 8); wPt[3] = (tmp[3] << 24) | (tmp[4] >> 8); wPt[4] = (tmp[4] << 24) | (tmp[5] >> 8); wPt[5] = (tmp[5] << 24) | (tmp[6] >> 8); wPt[6] = (tmp[6] << 24) | (tmp[7] >> 8); wPt[7] = (tmp[7] << 24) | (tmp[8] >> 8); wPt[8] = (tmp[8] << 24) | 0b00000000_10000000_00000000_00000000U; // from 9 to 14 = 0 wPt[15] = 264; // 33 *8 = 264 sha.Init(hPt); sha.CompressDouble33(hPt, wPt); if (hPt[0] == tmp[9]) { SetResult(item); success = true; } } } AddQueue(success ? "Found some keys" : "Could not find anything"); return(success); }
private unsafe bool Loop21() { var cartesian = CartesianProduct.Create(Enumerable.Repeat(Enumerable.Range(0, 2048), missCount)); fixed(uint *wPt = &sha.w[0], hPt = &sha.hashState[0], wrd = &wordIndexes[0]) fixed(int *mi = &missingIndexes[0]) { wPt[7] = 0b10000000_00000000_00000000_00000000U; wPt[15] = 224; foreach (var item in cartesian) { int j = 0; foreach (var k in item) { wrd[mi[j]] = (uint)k; j++; } wPt[0] = wrd[0] << 21 | wrd[1] << 10 | wrd[2] >> 1; wPt[1] = wrd[2] << 31 | wrd[3] << 20 | wrd[4] << 9 | wrd[5] >> 2; wPt[2] = wrd[5] << 30 | wrd[6] << 19 | wrd[7] << 8 | wrd[8] >> 3; wPt[3] = wrd[8] << 29 | wrd[9] << 18 | wrd[10] << 7 | wrd[11] >> 4; wPt[4] = wrd[11] << 28 | wrd[12] << 17 | wrd[13] << 6 | wrd[14] >> 5; wPt[5] = wrd[14] << 27 | wrd[15] << 16 | wrd[16] << 5 | wrd[17] >> 6; wPt[6] = wrd[17] << 26 | wrd[18] << 15 | wrd[19] << 4 | wrd[20] >> 7; sha.Compress28(hPt, wPt); if ((wrd[20] & 0b111_1111) == hPt[0] >> 25) { StringBuilder sb = new StringBuilder(21); for (int i = 0; i < 20; i++) { sb.Append($"{allWords[wrd[i]]} "); } // no space at the end. sb.Append($"{allWords[wrd[20]]}"); SetBip32(Encoding.UTF8.GetBytes(sb.ToString())); } } } return(Final.Count != 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 void Loop12(int firstItem, int firstIndex, ParallelLoopState loopState) { var cartesian = CartesianProduct.Create(Enumerable.Repeat(Enumerable.Range(0, 2048), missCount - 1)); using Sha512Fo sha512 = new Sha512Fo(); ulong[] ipad = new ulong[80]; ulong[] opad = new ulong[80]; using Sha256Fo sha256 = new Sha256Fo(); byte[] localMnBytes = new byte[mnBytes.Length]; var localCopy = new byte[allWordsBytes.Length][]; Array.Copy(allWordsBytes, localCopy, allWordsBytes.Length); uint[] localWIndex = new uint[wordIndexes.Length]; Array.Copy(wordIndexes, localWIndex, wordIndexes.Length); fixed(ulong *iPt = &ipad[0], oPt = &opad[0]) fixed(uint *wPt = &sha256.w[0], hPt = &sha256.hashState[0], wrd = &localWIndex[0]) fixed(int *mi = &missingIndexes[1]) fixed(byte *mnPt = &localMnBytes[0]) { wPt[4] = 0b10000000_00000000_00000000_00000000U; wPt[15] = 128; wrd[firstIndex] = (uint)firstItem; foreach (var item in cartesian) { if (loopState.IsStopped) { return; } int j = 0; foreach (var k in item) { wrd[mi[j]] = (uint)k; j++; } wPt[0] = wrd[0] << 21 | wrd[1] << 10 | wrd[2] >> 1; wPt[1] = wrd[2] << 31 | wrd[3] << 20 | wrd[4] << 9 | wrd[5] >> 2; wPt[2] = wrd[5] << 30 | wrd[6] << 19 | wrd[7] << 8 | wrd[8] >> 3; wPt[3] = wrd[8] << 29 | wrd[9] << 18 | wrd[10] << 7 | wrd[11] >> 4; sha256.Init(hPt); sha256.Compress16(hPt, wPt); if ((wrd[11] & 0b1111) == hPt[0] >> 28) { int mnLen = 0; for (int i = 0; i < 12; i++) { var temp = localCopy[wrd[i]]; Buffer.BlockCopy(temp, 0, mnBytes, mnLen, temp.Length); mnLen += temp.Length; } if (SetBip32(sha512, mnPt, --mnLen, iPt, oPt)) { SetResultParallel(mnPt, mnLen); loopState.Stop(); break; } } } } report.IncrementProgress(); }
private unsafe bool Loop24() { using Sha512Fo sha512 = new Sha512Fo(); ulong[] ipad = new ulong[80]; ulong[] opad = new ulong[80]; using Sha256Fo sha256 = new Sha256Fo(); var cartesian = CartesianProduct.Create(Enumerable.Repeat(Enumerable.Range(0, 2048), missCount)); fixed(ulong *iPt = ipad, oPt = opad) fixed(uint *wPt = &sha256.w[0], hPt = &sha256.hashState[0], wrd = &wordIndexes[0]) fixed(int *mi = &missingIndexes[0]) fixed(byte *mnPt = &mnBytes[0]) { wPt[8] = 0b10000000_00000000_00000000_00000000U; wPt[15] = 256; foreach (var item in cartesian) { int j = 0; foreach (var k in item) { wrd[mi[j]] = (uint)k; j++; } // 0000_0000 0000_0000 0000_0111 1111_1111 -> 1111_1111 1110_0000 0000_0000 0000_0000 // 0000_0000 0000_0000 0000_0222 2222_2222 -> 0000_0000 0002_2222 2222_2200 0000_0000 // 0000_0000 0000_0000 0000_0333 3333_3333 -> 0000_0000 0000_0000 0000_0033 3333_3333 -> 3 // 1111_1111 1112_2222 2222_2233 3333_3333 wPt[0] = wrd[0] << 21 | wrd[1] << 10 | wrd[2] >> 1; // 0000_0000 0000_0000 0000_0000 0000_0003 -> 3000_0000 0000_0000 0000_0000 0000_0000 // 0000_0000 0000_0000 0000_0444 4444_4444 -> 0444_4444 4444_0000 0000_0000 0000_0000 // 0000_0000 0000_0000 0000_0555 5555_5555 -> 0000_0000 0000_5555 5555_5550 0000_0000 // 0000_0000 0000_0000 0000_0666 6666_6666 -> 0000_0000 0000_0000 0000_0006 6666_6666 -> 66 // 3444_4444 4444_5555 5555_5556 6666_6666 wPt[1] = wrd[2] << 31 | wrd[3] << 20 | wrd[4] << 9 | wrd[5] >> 2; // 0000_0000 0000_0000 0000_0000 0000_0066 -> 6600_0000 0000_0000 0000_0000 0000_0000 // 0000_0000 0000_0000 0000_0777 7777_7777 -> 0077_7777 7777_7000 0000_0000 0000_0000 // 0000_0000 0000_0000 0000_0888 8888_8888 -> 0000_0000 0000_0888 8888_8888 0000_0000 // 0000_0000 0000_0000 0000_0999 9999_9999 -> 0000_0000 0000_0000 0000_0000 9999_9999 -> 999 // 6677_7777 7777_7888 8888_8888 9999_9999 wPt[2] = wrd[5] << 30 | wrd[6] << 19 | wrd[7] << 8 | wrd[8] >> 3; // 0000_0000 0000_0000 0000_0000 0000_0999 -> 9990_0000 0000_0000 0000_0000 0000_0000 // 0000_0000 0000_0000 0000_0AAA AAAA_AAAA -> 000A_AAAA AAAA_AA00 0000_0000 0000_0000 // 0000_0000 0000_0000 0000_0BBB BBBB_BBBB -> 0000_0000 0000_00BB BBBB_BBBB B000_0000 // 0000_0000 0000_0000 0000_0CCC CCCC_CCCC -> 0000_0000 0000_0000 0000_0000 0CCC_CCCC -> CCCC // 999A_AAAA AAAA_AABB BBBB_BBBB BCCC_CCCC wPt[3] = wrd[8] << 29 | wrd[9] << 18 | wrd[10] << 7 | wrd[11] >> 4; // 0000_0000 0000_0000 0000_0000 0000_CCCC -> CCCC_0000 0000_0000 0000_0000 0000_0000 // 0000_0000 0000_0000 0000_0DDD DDDD_DDDD -> 0000_DDDD DDDD_DDD0 0000_0000 0000_0000 // 0000_0000 0000_0000 0000_0EEE EEEE_EEEE -> 0000_0000 0000_000E EEEE_EEEE EE00_0000 // 0000_0000 0000_0000 0000_0FFF FFFF_FFFF -> 0000_0000 0000_0000 0000_0000 00FF_FFFF -> FFFF_F // CCCC_DDDD DDDD_DDDE EEEE_EEEE EEFF_FFFF wPt[4] = wrd[11] << 28 | wrd[12] << 17 | wrd[13] << 6 | wrd[14] >> 5; // 0000_0000 0000_0000 0000_0000 000F_FFFF -> FFFF_F000 0000_0000 0000_0000 0000_0000 // 0000_0000 0000_0000 0000_0GGG GGGG_GGGG -> 0000_0GGG GGGG_GGGG 0000_0000 0000_0000 // 0000_0000 0000_0000 0000_0HHH HHHH_HHHH -> 0000_0000 0000_0000 HHHH_HHHH HHH0_0000 // 0000_0000 0000_0000 0000_0III IIII_IIII -> 0000_0000 0000_0000 0000_0000 000I_IIII -> IIII_II // -> FFFF_FGGG GGGG_GGGG HHHH_HHHH HHHI_IIII wPt[5] = wrd[14] << 27 | wrd[15] << 16 | wrd[16] << 5 | wrd[17] >> 6; // 0000_0000 0000_0000 0000_0000 00II_IIII -> IIII_II00 0000_0000 0000_0000 0000_0000 // 0000_0000 0000_0000 0000_0JJJ JJJJ_JJJJ -> 0000_00JJ JJJJ_JJJJ J000_0000 0000_0000 // 0000_0000 0000_0000 0000_0KKK KKKK_KKKK -> 0000_0000 0000_0000 0KKK_KKKK KKKK_0000 // 0000_0000 0000_0000 0000_0LLL LLLL_LLLL -> 0000_0000 0000_0000 0000_0000 0000_LLLL -> LLLL_LLL // -> IIII_IIJJ JJJJ_JJJJ JKKK_KKKK KKKK_LLLL wPt[6] = wrd[17] << 26 | wrd[18] << 15 | wrd[19] << 4 | wrd[20] >> 7; // 0000_0000 0000_0000 0000_0000 0LLL_LLLL -> LLLL_LLL0 0000_0000 0000_0000 0000_0000 // 0000_0000 0000_0000 0000_0MMM MMMM_MMMM -> 0000_000M MMMM_MMMM MM00_0000 0000_0000 // 0000_0000 0000_0000 0000_0NNN NNNN_NNNN -> 0000_0000 0000_0000 00NN_NNNN NNNN_N000 // 0000_0000 0000_0000 0000_0OOO OOOO_OOOO -> 0000_0000 0000_0000 0000_0000 0000_0OOO -> OOOO_OOOO // -> LLLL_LLLM MMMM_MMMM MMNN_NNNN NNNN_NOOO wPt[7] = wrd[20] << 25 | wrd[21] << 14 | wrd[22] << 3 | wrd[23] >> 8; sha256.Init(hPt); sha256.Compress32(hPt, wPt); if ((byte)wrd[23] == hPt[0] >> 24) { int mnLen = 0; for (int i = 0; i < 24; i++) { foreach (byte b in wordBytes[wrd[i]]) { mnPt[mnLen++] = b; } mnPt[mnLen++] = SpaceByte; } if (SetBip32(sha512, mnPt, --mnLen, iPt, oPt)) { return(SetResult(mnLen)); } } } } return(false); }
private unsafe bool Loop24() { var cartesian = CartesianProduct.Create(Enumerable.Repeat(Enumerable.Range(0, 2048), missCount)); fixed(uint *wPt = &sha.w[0], hPt = &sha.hashState[0], wrd = &wordIndexes[0]) fixed(int *mi = &missingIndexes[0]) { wPt[8] = 0b10000000_00000000_00000000_00000000U; wPt[15] = 256; foreach (var item in cartesian) { int j = 0; foreach (var k in item) { wrd[mi[j]] = (uint)k; j++; } // 0000_0000 0000_0000 0000_0111 1111_1111 -> 1111_1111 1110_0000 0000_0000 0000_0000 // 0000_0000 0000_0000 0000_0222 2222_2222 -> 0000_0000 0002_2222 2222_2200 0000_0000 // 0000_0000 0000_0000 0000_0333 3333_3333 -> 0000_0000 0000_0000 0000_0033 3333_3333 -> 3 // 1111_1111 1112_2222 2222_2233 3333_3333 wPt[0] = wrd[0] << 21 | wrd[1] << 10 | wrd[2] >> 1; // 0000_0000 0000_0000 0000_0000 0000_0003 -> 3000_0000 0000_0000 0000_0000 0000_0000 // 0000_0000 0000_0000 0000_0444 4444_4444 -> 0444_4444 4444_0000 0000_0000 0000_0000 // 0000_0000 0000_0000 0000_0555 5555_5555 -> 0000_0000 0000_5555 5555_5550 0000_0000 // 0000_0000 0000_0000 0000_0666 6666_6666 -> 0000_0000 0000_0000 0000_0006 6666_6666 -> 66 // 3444_4444 4444_5555 5555_5556 6666_6666 wPt[1] = wrd[2] << 31 | wrd[3] << 20 | wrd[4] << 9 | wrd[5] >> 2; // 0000_0000 0000_0000 0000_0000 0000_0066 -> 6600_0000 0000_0000 0000_0000 0000_0000 // 0000_0000 0000_0000 0000_0777 7777_7777 -> 0077_7777 7777_7000 0000_0000 0000_0000 // 0000_0000 0000_0000 0000_0888 8888_8888 -> 0000_0000 0000_0888 8888_8888 0000_0000 // 0000_0000 0000_0000 0000_0999 9999_9999 -> 0000_0000 0000_0000 0000_0000 9999_9999 -> 999 // 6677_7777 7777_7888 8888_8888 9999_9999 wPt[2] = wrd[5] << 30 | wrd[6] << 19 | wrd[7] << 8 | wrd[8] >> 3; // 0000_0000 0000_0000 0000_0000 0000_0999 -> 9990_0000 0000_0000 0000_0000 0000_0000 // 0000_0000 0000_0000 0000_0AAA AAAA_AAAA -> 000A_AAAA AAAA_AA00 0000_0000 0000_0000 // 0000_0000 0000_0000 0000_0BBB BBBB_BBBB -> 0000_0000 0000_00BB BBBB_BBBB B000_0000 // 0000_0000 0000_0000 0000_0CCC CCCC_CCCC -> 0000_0000 0000_0000 0000_0000 0CCC_CCCC -> CCCC // 999A_AAAA AAAA_AABB BBBB_BBBB BCCC_CCCC wPt[3] = wrd[8] << 29 | wrd[9] << 18 | wrd[10] << 7 | wrd[11] >> 4; // 0000_0000 0000_0000 0000_0000 0000_CCCC -> CCCC_0000 0000_0000 0000_0000 0000_0000 // 0000_0000 0000_0000 0000_0DDD DDDD_DDDD -> 0000_DDDD DDDD_DDD0 0000_0000 0000_0000 // 0000_0000 0000_0000 0000_0EEE EEEE_EEEE -> 0000_0000 0000_000E EEEE_EEEE EE00_0000 // 0000_0000 0000_0000 0000_0FFF FFFF_FFFF -> 0000_0000 0000_0000 0000_0000 00FF_FFFF -> FFFF_F // CCCC_DDDD DDDD_DDDE EEEE_EEEE EEFF_FFFF wPt[4] = wrd[11] << 28 | wrd[12] << 17 | wrd[13] << 6 | wrd[14] >> 5; // 0000_0000 0000_0000 0000_0000 000F_FFFF -> FFFF_F000 0000_0000 0000_0000 0000_0000 // 0000_0000 0000_0000 0000_0GGG GGGG_GGGG -> 0000_0GGG GGGG_GGGG 0000_0000 0000_0000 // 0000_0000 0000_0000 0000_0HHH HHHH_HHHH -> 0000_0000 0000_0000 HHHH_HHHH HHH0_0000 // 0000_0000 0000_0000 0000_0III IIII_IIII -> 0000_0000 0000_0000 0000_0000 000I_IIII -> IIII_II // -> FFFF_FGGG GGGG_GGGG HHHH_HHHH HHHI_IIII wPt[5] = wrd[14] << 27 | wrd[15] << 16 | wrd[16] << 5 | wrd[17] >> 6; // 0000_0000 0000_0000 0000_0000 00II_IIII -> IIII_II00 0000_0000 0000_0000 0000_0000 // 0000_0000 0000_0000 0000_0JJJ JJJJ_JJJJ -> 0000_00JJ JJJJ_JJJJ J000_0000 0000_0000 // 0000_0000 0000_0000 0000_0KKK KKKK_KKKK -> 0000_0000 0000_0000 0KKK_KKKK KKKK_0000 // 0000_0000 0000_0000 0000_0LLL LLLL_LLLL -> 0000_0000 0000_0000 0000_0000 0000_LLLL -> LLLL_LLL // -> IIII_IIJJ JJJJ_JJJJ JKKK_KKKK KKKK_LLLL wPt[6] = wrd[17] << 26 | wrd[18] << 15 | wrd[19] << 4 | wrd[20] >> 7; // 0000_0000 0000_0000 0000_0000 0LLL_LLLL -> LLLL_LLL0 0000_0000 0000_0000 0000_0000 // 0000_0000 0000_0000 0000_0MMM MMMM_MMMM -> 0000_000M MMMM_MMMM MM00_0000 0000_0000 // 0000_0000 0000_0000 0000_0NNN NNNN_NNNN -> 0000_0000 0000_0000 00NN_NNNN NNNN_N000 // 0000_0000 0000_0000 0000_0OOO OOOO_OOOO -> 0000_0000 0000_0000 0000_0000 0000_0OOO -> OOOO_OOOO // -> LLLL_LLLM MMMM_MMMM MMNN_NNNN NNNN_NOOO wPt[7] = wrd[20] << 25 | wrd[21] << 14 | wrd[22] << 3 | wrd[23] >> 8; sha.Compress32(hPt, wPt); if ((byte)wrd[23] == hPt[0] >> 24) { StringBuilder sb = new StringBuilder(24); for (int i = 0; i < 23; i++) { sb.Append($"{allWords[wrd[i]]} "); } // no space at the end. sb.Append($"{allWords[wrd[23]]}"); SetBip32(Encoding.UTF8.GetBytes(sb.ToString())); } } } return(Final.Count != 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); }