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 unsafe void Compress23Test() { int dataLen = 23; byte[] data = GetRandomBytes(dataLen); byte[] expected = ComputeSingleSha(data); using Sha256Fo sha = new Sha256Fo(); fixed(uint *hPt = &sha.hashState[0], wPt = &sha.w[0]) { int dIndex = 0; for (int i = 0; i < 5; i++, dIndex += 4) { wPt[i] = (uint)((data[dIndex] << 24) | (data[dIndex + 1] << 16) | (data[dIndex + 2] << 8) | data[dIndex + 3]); } wPt[5] = (uint)((data[20] << 24) | (data[21] << 16) | (data[22] << 8) | 0b00000000_00000000_00000000_10000000U); wPt[15] = (uint)dataLen * 8; sha.Init(hPt); sha.Compress23(hPt, wPt); byte[] actual = sha.GetBytes(hPt); Assert.Equal(expected, actual); } }
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); }