Last active
January 9, 2020 14:22
-
-
Save DurtyFree/eb9498eaf23ebe6128b96a0746ef6727 to your computer and use it in GitHub Desktop.
Pokemon Go PokeMobBot niantic hashing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
internal static class HashConstants | |
{ | |
#region Constants | |
/* | |
#if 1 | |
// IOS 1.13.3 | |
static uint64_t magic_table[16] = { | |
0x95C05F4D1512959E, 0xE4F3C46EEF0DCF07, | |
0x6238DC228F980AD2, 0x53F3E3BC49607092, | |
0x4E7BE7069078D625, 0x1016D709D1AD25FC, | |
0x044E89B8AC76E045, 0xE0B684DDA364BFA1, | |
0x90C533B835E89E5F, 0x3DAF462A74FA874F, | |
0xFEA54965DD3EF5A0, 0x287A5D7CCB31B970, | |
0xAE681046800752F8, 0x121C2D6EAF66EC6E, | |
0xEE8F8CA7E090FB20, 0xCE1AE25F48FE0A52, | |
}; | |
#define ROUND_MAGIC U128(0x78F32468CD48D6DE,0x14C983660183C0AE) | |
#define FINAL_MAGIC0 0xBDB31B10864F3F87 | |
#define FINAL_MAGIC1 0x5B7E9E828A9B8ABD | |
#endif | |
#if 0 | |
// Android 0.43.4 | |
static uint64_t magic_table[16] = { | |
0x48CD0D725609F95F, 0x25D4A39B5ACB4330, | |
0x1C0C27978A3649A3, 0x5C7068B9C51C5E4B, | |
0x69A054CBE1369106, 0x4C318ED6A12B9645, | |
0xC751EECD2715C836, 0xAAEDCC7A92014B7A, | |
0xE91DB51D36F47460, 0x78EA4A974D9157B8, | |
0xE4E65C1A929E8AB1, 0x6BC61BB9C5988769, | |
0x78C7794B899D8819, 0xB338727B9C7600F7, | |
0x26BA60FCB9EDC151, 0xE7D74B3CD6293E6B, | |
}; | |
#define ROUND_MAGIC U128(0x1A32C90D816A2F1F,0x76327D13FD037D57) | |
#define FINAL_MAGIC0 0x106245053E723AD8 | |
#define FINAL_MAGIC1 0x1CDA65FFA125C8F6 | |
#endif | |
#if | |
// Android 0.41.4 | |
static uint64_t magic_table[16] = { | |
0x475BD60F17CE7238, 0xC11B0E0066794E31, | |
0x75F5BD04F566D70C, 0x09F4F46E7CEC785C, | |
0x6A52B40820F5EBFF, 0x27F300DB7195A066, | |
0xBDFDE4DAC75939BF, 0xF7F239CFD77A36AB, | |
0x7013DEFA151CD579, 0x8864183CFD4C24F9, | |
0x21C426C79EA1445A, 0xB188FEAE415747BA, | |
0x127421C8D0BD9352, 0x8C7E6FC0526AD558, | |
0x7E33F449C404A71A, 0xE955B7D15DE757DC, | |
}; | |
#define ROUND_MAGIC U128(0x232B242A99C10878,0x667EFDF872801CD8) | |
#define FINAL_MAGIC0 0xF6AC14F2D12AB0C1 | |
#define FINAL_MAGIC1 0x101FF0340EC93F87 | |
#endif | |
*/ | |
#endregion | |
public const ulong FinalMagic0 = 0x106245053E723AD8; | |
public const ulong FinalMagic1 = 0x1CDA65FFA125C8F6; | |
public static UInt128 RoundMagic = new UInt128(0x1A32C90D816A2F1F, 0x76327D13FD037D57); | |
public static readonly ulong[] MagicTable = { | |
0x48CD0D725609F95F, 0x25D4A39B5ACB4330, | |
0x1C0C27978A3649A3, 0x5C7068B9C51C5E4B, | |
0x69A054CBE1369106, 0x4C318ED6A12B9645, | |
0xC751EECD2715C836, 0xAAEDCC7A92014B7A, | |
0xE91DB51D36F47460, 0x78EA4A974D9157B8, | |
0xE4E65C1A929E8AB1, 0x6BC61BB9C5988769, | |
0x78C7794B899D8819, 0xB338727B9C7600F7, | |
0x26BA60FCB9EDC151, 0xE7D74B3CD6293E6B, | |
}; | |
} | |
public class NiaHash | |
{ | |
static ulong read_int64(byte[] p, int offset) | |
{ | |
return BitConverter.ToUInt64(p, offset); | |
} | |
public static ulong compute_hash(byte[] input, uint len) | |
{ | |
uint numChunks = len / 128; | |
// copy tail, pad with zeroes | |
byte[] tail = new byte[128]; | |
uint tailSize = len % 128; | |
Array.Copy(input, len - tailSize, tail, 0, tailSize); | |
UInt128 hash; | |
if (numChunks != 0) hash = hash_chunk(input, 128, 0); | |
else hash = hash_chunk(tail, tailSize, 0); | |
hash += HashConstants.RoundMagic; | |
int offset = 0; | |
if (numChunks != 0) | |
{ | |
while (--numChunks > 0) | |
{ | |
offset += 128; | |
hash = hash_muladd(hash, HashConstants.RoundMagic, hash_chunk(input, 128, offset)); | |
} | |
if (tailSize > 0) | |
{ | |
hash = hash_muladd(hash, HashConstants.RoundMagic, hash_chunk(tail, tailSize, 0)); | |
} | |
} | |
hash += new UInt128(tailSize * 8, 0); | |
if (hash > new UInt128(0x7fffffffffffffff, 0xffffffffffffffff)) hash++; | |
hash = hash << 1 >> 1; | |
ulong x = hash.Hi + (hash.Lo >> 32); | |
x = ((x + (x >> 32) + 1) >> 32) + hash.Hi; | |
ulong y = (x << 32) + hash.Lo; | |
ulong a = x + HashConstants.FinalMagic0; | |
if (a < x) a += 0x101; | |
ulong b = y + HashConstants.FinalMagic1; | |
if (b < y) b += 0x101; | |
UInt128 h = new UInt128(a) * b; | |
UInt128 mul = new UInt128(0x101); | |
h = (mul * h.Hi) + h.Lo; | |
h = (mul * h.Hi) + h.Lo; | |
if (h.Hi > 0) h += mul; | |
if (h.Lo > 0xFFFFFFFFFFFFFEFE) h += mul; | |
return h.Lo; | |
} | |
private static UInt128 hash_chunk(byte[] chunk, long size, int off) | |
{ | |
UInt128 hash = new UInt128(0); | |
for (int i = 0; i < 8; i++) | |
{ | |
int offset = i * 16; | |
if (offset >= size) break; | |
ulong a = read_int64(chunk, off + offset); | |
ulong b = read_int64(chunk, off + offset + 8); | |
hash += (new UInt128(a + HashConstants.MagicTable[i * 2])) * (new UInt128(b + HashConstants.MagicTable[i * 2 + 1])); | |
} | |
return hash << 2 >> 2; | |
} | |
private static UInt128 hash_muladd(UInt128 hash, UInt128 mul, UInt128 add) | |
{ | |
ulong a0 = add.Lo & 0xffffffff, | |
a1 = add.Lo >> 32, | |
a23 = add.Hi; | |
ulong m0 = mul.Lo & 0xffffffff, | |
m1 = mul.Lo >> 32, | |
m2 = mul.Hi & 0xffffffff, | |
m3 = mul.Hi >> 32; | |
ulong h0 = hash.Lo & 0xffffffff, | |
h1 = hash.Lo >> 32, | |
h2 = hash.Hi & 0xffffffff, | |
h3 = hash.Hi >> 32; | |
ulong c0 = (h0 * m0), | |
c1 = (h0 * m1) + (h1 * m0), | |
c2 = (h0 * m2) + (h1 * m1) + (h2 * m0), | |
c3 = (h0 * m3) + (h1 * m2) + (h2 * m1) + (h3 * m0), | |
c4 = (h1 * m3) + (h2 * m2) + (h3 * m1), | |
c5 = (h2 * m3) + (h3 * m2), | |
c6 = (h3 * m3); | |
ulong r2 = c2 + (c6 << 1) + a23, | |
r3 = c3 + (r2 >> 32), | |
r0 = c0 + (c4 << 1) + a0 + (r3 >> 31), | |
r1 = c1 + (c5 << 1) + a1 + (r0 >> 32); | |
ulong res0 = ((r3 << 33 >> 1) | (r2 & 0xffffffff)) + (r1 >> 32); | |
return new UInt128(res0, (r1 << 32) | (r0 & 0xffffffff)); | |
} | |
} | |
public struct UInt128 | |
{ | |
public ulong Hi, Lo; | |
#region constructors | |
public UInt128(ulong high, ulong low) | |
{ | |
Hi = high; Lo = low; | |
} | |
public UInt128(ulong low) | |
{ | |
Hi = 0; Lo = low; | |
} | |
#endregion | |
#region comparators | |
public bool Equals(UInt128 other) | |
{ | |
return (Hi == other.Hi && Lo == other.Lo); | |
} | |
public static bool operator >(UInt128 a, UInt128 b) | |
{ | |
if (a.Hi == b.Hi) return a.Lo > b.Lo; | |
return a.Hi > b.Hi; | |
} | |
public static bool operator <(UInt128 a, UInt128 b) | |
{ | |
if (a.Hi == b.Hi) return a.Lo < b.Lo; | |
return a.Hi < b.Hi; | |
} | |
#endregion | |
#region arithmetic | |
public static UInt128 operator ++(UInt128 a) | |
{ | |
a.Lo++; | |
if (a.Lo == 0) a.Hi++; | |
return a; | |
} | |
public static UInt128 operator +(UInt128 a, UInt128 b) | |
{ | |
ulong c = (((a.Lo & b.Lo) & 1) + (a.Lo >> 1) + (b.Lo >> 1)) >> 63; | |
return new UInt128(a.Hi + b.Hi + c, a.Lo + b.Lo); | |
} | |
public static UInt128 operator +(UInt128 a, ulong b) | |
{ | |
return a + new UInt128(b); | |
} | |
public static UInt128 operator -(UInt128 a, UInt128 b) | |
{ | |
ulong l = a.Lo - b.Lo; | |
ulong c = (((l & b.Lo) & 1) + (b.Lo >> 1) + (l >> 1)) >> 63; | |
return new UInt128(a.Hi - (b.Hi + c), l); | |
} | |
#endregion | |
#region bitwise operations | |
public static UInt128 operator &(UInt128 a, UInt128 b) | |
{ | |
return new UInt128(a.Hi & b.Hi, a.Lo & b.Lo); | |
} | |
public static UInt128 operator <<(UInt128 a, int b) | |
{ | |
a.Hi <<= b; | |
a.Hi |= (a.Lo >> (64 - b)); | |
a.Lo <<= b; | |
return a; | |
} | |
public static UInt128 operator >>(UInt128 a, int b) | |
{ | |
a.Lo >>= b; | |
a.Lo |= (a.Hi << (64 - b)); | |
a.Hi >>= b; | |
return a; | |
} | |
#endregion | |
#region multiplication | |
private static UInt128 M64(ulong a, ulong b) | |
{ | |
ulong a1 = (a & 0xffffffff), b1 = (b & 0xffffffff), | |
t = (a1 * b1), w3 = (t & 0xffffffff), k = (t >> 32); | |
a >>= 32; | |
t = (a * b1) + k; | |
k = (t & 0xffffffff); | |
var w1 = (t >> 32); | |
b >>= 32; | |
t = (a1 * b) + k; | |
k = (t >> 32); | |
return new UInt128((a * b) + w1 + k, (t << 32) + w3); | |
} | |
public static UInt128 operator *(UInt128 a, int b) | |
{ | |
return a * (ulong)b; | |
} | |
public static UInt128 operator *(UInt128 a, ulong b) | |
{ | |
UInt128 ans = M64(a.Lo, b); | |
ans.Hi += (a.Hi * b); | |
return ans; | |
} | |
public static UInt128 operator *(UInt128 a, UInt128 b) | |
{ | |
UInt128 ans = M64(a.Lo, b.Lo); | |
ans.Hi += (a.Hi * b.Lo) + (a.Lo * b.Hi); | |
return ans; | |
} | |
#endregion | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment