예제 #1
0
        private void PushByte(uint value)
        {
            var data = pending;

            unsafe
            {
                ((byte *)&data)[pendingLength] = (byte)value;
            }

            if (pendingLength == 15)
            {
                HashBlock(ref hash, ref data);
                pending       = default(Value128);
                pendingLength = 0;
            }
            else
            {
                pending = data;
                pendingLength++;
            }
        }
예제 #2
0
        /// <summary>NOTE: Rewrites hash and clobbers data</summary>
        private static void HashBlock(ref Value128 hash, ref Value128 data)
        {
            data.v1 *= c1;
            data.v1  = ROTL32(data.v1, 15);
            data.v1 *= c2;
            hash.v1 ^= data.v1;

            hash.v1  = ROTL32(hash.v1, 19);
            hash.v1 += hash.v2;
            hash.v1  = hash.v1 * 5 + 0x561ccd1b;

            data.v2 *= c2;
            data.v2  = ROTL32(data.v2, 16);
            data.v2 *= c3;
            hash.v2 ^= data.v2;

            hash.v2  = ROTL32(hash.v2, 17);
            hash.v2 += hash.v3;
            hash.v2  = hash.v2 * 5 + 0x0bcaa747;

            data.v3 *= c3;
            data.v3  = ROTL32(data.v3, 17);
            data.v3 *= c4;
            hash.v3 ^= data.v3;

            hash.v3  = ROTL32(hash.v3, 15);
            hash.v3 += hash.v4;
            hash.v3  = hash.v3 * 5 + 0x96cd1c35;

            data.v4 *= c4;
            data.v4  = ROTL32(data.v4, 18);
            data.v4 *= c1;
            hash.v4 ^= data.v4;

            hash.v4  = ROTL32(hash.v4, 13);
            hash.v4 += hash.v1;
            hash.v4  = hash.v4 * 5 + 0x32ac3b17;
        }
예제 #3
0
        /// <summary>NOTE: Rewrites hash and clobbers tail</summary>
        private static void HashTailAndFinalize(ref Value128 hash, ref Value128 tail, uint length)
        {
            // NOTE: We're truncating length to 32-bits, because it will almost always be small enough


            //
            // Tail:
            var tailLength = length & 15;

            switch ((tailLength + 3) >> 2)             // Number of dwords of data in the tail, rounded up
            {
            case 4:
                tail.v4 *= c4;
                tail.v4  = ROTL32(tail.v4, 18);
                tail.v4 *= c1;
                hash.v4 ^= tail.v4;
                goto case 3;

            case 3:
                tail.v3 *= c3;
                tail.v3  = ROTL32(tail.v3, 17);
                tail.v3 *= c4;
                hash.v3 ^= tail.v3;
                goto case 2;

            case 2:
                tail.v2 *= c2;
                tail.v2  = ROTL32(tail.v2, 16);
                tail.v2 *= c3;
                hash.v2 ^= tail.v2;
                goto case 1;

            case 1:
                tail.v1 *= c1;
                tail.v1  = ROTL32(tail.v1, 15);
                tail.v1 *= c2;
                hash.v1 ^= tail.v1;
                break;
            }


            //
            // Finalization:

            hash.v1 ^= length;
            hash.v2 ^= length;
            hash.v3 ^= length;
            hash.v4 ^= length;

            hash.v1 += hash.v2;
            hash.v1 += hash.v3;
            hash.v1 += hash.v4;
            hash.v2 += hash.v1;
            hash.v3 += hash.v1;
            hash.v4 += hash.v1;

            hash.v1 = fmix32(hash.v1);
            hash.v2 = fmix32(hash.v2);
            hash.v3 = fmix32(hash.v3);
            hash.v4 = fmix32(hash.v4);

            hash.v1 += hash.v2;
            hash.v1 += hash.v3;
            hash.v1 += hash.v4;
            hash.v2 += hash.v1;
            hash.v3 += hash.v1;
            hash.v4 += hash.v1;
        }