Advertisement
ibuckshot5

niahash

Nov 6th, 2016
118
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 5.17 KB | None | 0 0
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4.  
  5. class NiaHash
  6. {
  7.  
  8.     /* IOS 1.13.3 */
  9.     static ulong[] magic_table = {
  10.         0x95C05F4D1512959E, 0xE4F3C46EEF0DCF07,
  11.         0x6238DC228F980AD2, 0x53F3E3BC49607092,
  12.         0x4E7BE7069078D625, 0x1016D709D1AD25FC,
  13.         0x044E89B8AC76E045, 0xE0B684DDA364BFA1,
  14.         0x90C533B835E89E5F, 0x3DAF462A74FA874F,
  15.         0xFEA54965DD3EF5A0, 0x287A5D7CCB31B970,
  16.         0xAE681046800752F8, 0x121C2D6EAF66EC6E,
  17.         0xEE8F8CA7E090FB20, 0xCE1AE25F48FE0A52,
  18.     };
  19.  
  20.     static UInt128 ROUND_MAGIC = new UInt128(0x78F32468CD48D6DE, 0x14C983660183C0AE);
  21.     static ulong FINAL_MAGIC0 = 0xBDB31B10864F3F87;
  22.     static ulong FINAL_MAGIC1 = 0x5B7E9E828A9B8ABD;
  23.  
  24.     static ulong read_int64(byte[] p, int offset) { return BitConverter.ToUInt64(p, offset); }
  25.  
  26.     public static ulong compute_hash64(byte[] input, UInt32 seed)
  27.     {
  28.         byte[] inputWithSeed = new byte[input.Length + 4];
  29.         byte[] seedArr = BitConverter.GetBytes(seed).Reverse().ToArray();
  30.         Array.Copy(seedArr, inputWithSeed, 4);
  31.         Array.Copy(input, 0, inputWithSeed, 4, input.Length);
  32.         return compute_hash(inputWithSeed);
  33.     }
  34.     public static uint compute_hash32(byte[] input, UInt32 seed)
  35.     {
  36.         byte[] inputWithSeed = new byte[input.Length + 4];
  37.         byte[] seedArr = BitConverter.GetBytes(seed).Reverse().ToArray();
  38.         Array.Copy(seedArr, inputWithSeed, 4);
  39.         Array.Copy(input, 0, inputWithSeed, 4, input.Length);
  40.         ulong hash = compute_hash(inputWithSeed);
  41.         return ((uint)hash) ^ ((uint)(hash >> 32));
  42.     }
  43.     public static ulong compute_hash64(byte[] input, UInt64 seed)
  44.     {
  45.         byte[] inputWithSeed = new byte[input.Length + 8];
  46.         byte[] seedArr = BitConverter.GetBytes(seed).Reverse().ToArray();
  47.         Array.Copy(seedArr, inputWithSeed, 8);
  48.         Array.Copy(input, 0, inputWithSeed, 8, input.Length);
  49.         return compute_hash(inputWithSeed);
  50.     }
  51.  
  52.     public static ulong compute_hash(byte[] input)
  53.     {
  54.         uint num_chunks = (uint)input.Length / 128;
  55.  
  56.         // copy tail, pad with zeroes
  57.         byte[] tail = new byte[128];
  58.         uint tail_size = (uint)input.Length % 128;
  59.         Array.Copy(input, (int)(input.Length - tail_size), tail, 0, (int)tail_size);
  60.  
  61.         UInt128 hash;
  62.  
  63.         if (num_chunks != 0) hash = hash_chunk(input, 128, 0);
  64.         else hash = hash_chunk(tail, tail_size, 0);
  65.  
  66.         hash += ROUND_MAGIC;
  67.  
  68.         int offset = 0;
  69.  
  70.         if (num_chunks != 0)
  71.         {
  72.             while (--num_chunks > 0)
  73.             {
  74.                 offset += 128;
  75.                 hash = hash_muladd(hash, ROUND_MAGIC, hash_chunk(input, 128, offset));
  76.             }
  77.  
  78.             if (tail_size > 0)
  79.             {
  80.                 hash = hash_muladd(hash, ROUND_MAGIC, hash_chunk(tail, tail_size, 0));
  81.             }
  82.         }
  83.  
  84.         hash += new UInt128(tail_size * 8, 0);
  85.  
  86.         if (hash > new UInt128(0x7fffffffffffffff, 0xffffffffffffffff)) hash++;
  87.  
  88.         hash = hash << 1 >> 1;
  89.  
  90.         ulong X = hash.hi + (hash.lo >> 32);
  91.         X = ((X + (X >> 32) + 1) >> 32) + hash.hi;
  92.         ulong Y = (X << 32) + hash.lo;
  93.  
  94.         ulong A = X + FINAL_MAGIC0;
  95.         if (A < X) A += 0x101;
  96.  
  97.         ulong B = Y + FINAL_MAGIC1;
  98.         if (B < Y) B += 0x101;
  99.  
  100.         UInt128 H = new UInt128(A) * B;
  101.         UInt128 mul = new UInt128(0x101);
  102.         H = (mul * H.hi) + H.lo;
  103.         H = (mul * H.hi) + H.lo;
  104.  
  105.         if (H.hi > 0) H += mul;
  106.         if (H.lo > 0xFFFFFFFFFFFFFEFE) H += mul;
  107.         return H.lo;
  108.     }
  109.  
  110.     static UInt128 hash_chunk(byte[] chunk, long size, int off)
  111.     {
  112.         UInt128 hash = new UInt128(0);
  113.         for (int i = 0; i < 8; i++)
  114.         {
  115.             int offset = i * 16;
  116.             if (offset >= size) break;
  117.             ulong a = read_int64(chunk, off + offset);
  118.             ulong b = read_int64(chunk, off + offset + 8);
  119.             hash += (new UInt128(a + magic_table[i * 2])) * (new UInt128(b + magic_table[i * 2 + 1]));
  120.         }
  121.         return hash << 2 >> 2;
  122.     }
  123.  
  124.     static UInt128 hash_muladd(UInt128 hash, UInt128 mul, UInt128 add)
  125.     {
  126.         ulong a0 = add.lo & 0xffffffff,
  127.             a1 = add.lo >> 32,
  128.             a23 = add.hi;
  129.  
  130.         ulong m0 = mul.lo & 0xffffffff,
  131.             m1 = mul.lo >> 32,
  132.             m2 = mul.hi & 0xffffffff,
  133.             m3 = mul.hi >> 32;
  134.  
  135.         ulong h0 = hash.lo & 0xffffffff,
  136.             h1 = hash.lo >> 32,
  137.             h2 = hash.hi & 0xffffffff,
  138.             h3 = hash.hi >> 32;
  139.  
  140.         ulong c0 = (h0 * m0),
  141.             c1 = (h0 * m1) + (h1 * m0),
  142.             c2 = (h0 * m2) + (h1 * m1) + (h2 * m0),
  143.             c3 = (h0 * m3) + (h1 * m2) + (h2 * m1) + (h3 * m0),
  144.             c4 = (h1 * m3) + (h2 * m2) + (h3 * m1),
  145.             c5 = (h2 * m3) + (h3 * m2),
  146.             c6 = (h3 * m3);
  147.  
  148.         ulong r2 = c2 + (c6 << 1) + a23,
  149.             r3 = c3 + (r2 >> 32),
  150.             r0 = c0 + (c4 << 1) + a0 + (r3 >> 31),
  151.             r1 = c1 + (c5 << 1) + a1 + (r0 >> 32);
  152.  
  153.         ulong res0 = ((r3 << 33 >> 1) | (r2 & 0xffffffff)) + (r1 >> 32);
  154.         return new UInt128(res0, (r1 << 32) | (r0 & 0xffffffff));
  155.     }
  156. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement