GHash128.cs

Generic 128-Bit Hash

using System;
using System.Security.Cryptography;
public class GHash128 : HashAlgorithm
{
    private readonly Int128[] table = new Int128[256];
    private          Int128   hash;
    private          Int128   k    = new Int128("129143687381477724263020268747464783");
    private          Int128   seed = new Int128("5967883051065466352865241413511");
    public GHash128()
    {
        hash     = seed;
        table[0] = k;
        Expand(table);
    }
    public override int HashSize => 128;
    public void SetSeed(Int128 s, Int128 k)
    {
        seed   = s;
        this.k = k;
        Array.Clear(table, 0, table.Length);
        table[0] = this.k;
        Expand(table);
    }
    private static void Expand(Int128[] x)
    {
        var length = x.Length;
        for (var i = 0; i < length; ++i)
        {
            Int128 n = 0;
            for (var j = 0; j < length; ++j)
                n = n ^ x[j];
            x[i] = (n << 1) | (n >> 120) | 1;
        }
    }
    public override void Initialize()
    {
        hash = seed;
    }
    protected override void HashCore(byte[] bytes, int ibStart, int cbSize)
    {
        Transform128(bytes, ibStart, cbSize);
    }
    protected override byte[] HashFinal()
    {
        return hash.ToByteArray();
    }
    public void Transform128(byte[] bytes, int ibStart, int cbSize)
    {
        if (bytes == null)
            return;
        if (ibStart >= bytes.Length || cbSize > bytes.Length)
            return;
        var i = 0;
        do
        {
            hash = (hash ^ bytes[i]) * table[bytes[i++]];
        } while (i < cbSize);
    }
}

Mapping64BitToHash32Bit.cs

Maps a 64-Bit Hash Into a 32-Bit Space

using System.Security.Cryptography;
/// <summary>
///     Pros: ~no Collisions within int bit space ~(2,147,483,647)
///     Cons: Maintains a TinyDictionary(byte[],byte[]), non-deterministic across application or
///     method domains
///     Cannot Transform or reuse.
/// </summary>
public class Mapping64BitToHash32Bit : HashAlgorithm
{
    private readonly FNV1a64                        hasher = new FNV1a64();
    public readonly  TinyDictionary<byte[], byte[]> map    = new TinyDictionary<byte[], byte[]>(101, new ArrayComparer());
    private          byte[]                         h64;
    public override  int                            HashSize => 32;
    public override void Initialize()
    {
    }
    /// <inheritdoc />
    /// <summary>
    ///     Compute the 64 Bit hash value and add it and the original array to the map to create a unique position within the
    ///     TinyDictionary.
    /// </summary>
    protected override void HashCore(byte[] bytes, int ibStart, int cbSize)
    {
        h64 = hasher.ComputeHash(bytes, ibStart, cbSize);
        map.Add(h64, bytes);
    }
    /// <inheritdoc />
    /// <summary>
    ///     Return the unique position within the TinyDictionary as the hash value (index).
    /// </summary>
    protected override byte[] HashFinal()
    {
        HashValue = (byte[]) map.FindKeyIndex(h64).GetBytes().Clone();
        return HashValue;
    }
}

FNV1a64.cs

Fowler–Noll–Vo hash function 64-Bit

using System;
using System.Security.Cryptography;
/// <summary>
///     Works very well for a 64 bit hashing algorithm.
///     No collisions with 10M random byte arrays.(64Bit version only) MJS 
///     https://en.wikipedia.org/wiki/Fowler%E2%80%93Noll%E2%80%93Vo_hash_function
///     Very fast 88MBpS.
/// </summary>
[Serializable]
public class FNV1a64 : HashAlgorithm
{
    private const ulong K = 0x100000001B3;
    public        ulong _hash;
    public        ulong Hash;
    public        ulong Seed = 0xCBF29CE484222325;
    public FNV1a64()
    {
        _hash = Seed;
    }
    public FNV1a64(ulong seed)
    {
        Seed  = seed;
        _hash = Seed;
    }
    public override int HashSize => 64;
    public override void Initialize()
    {
        _hash = Seed;
    }
    protected override void HashCore(byte[] bytes, int ibStart, int cbSize)
    {
        Hash64(bytes, ibStart, cbSize);
    }
    private unsafe void Hash64(byte[] bytes, int ibStart, int cbSize)
    {
        if (bytes == null)
            return;
        if (ibStart >= bytes.Length || cbSize > bytes.Length)
            return;
        fixed (byte* pb = bytes)
        {
            var nb = pb + ibStart;
            while (cbSize >= 8)
            {
                _hash  ^= *(ulong*) nb;
                nb     += 8;
                cbSize -= 8;
                _hash  *= K;
            }
            switch (cbSize & 7)
            {
                case 7:
                    _hash ^= *(ulong*) (nb + 6);
                    _hash *= K;
                    goto case 6;
                case 6:
                    _hash ^= *(ulong*) (nb + 5);
                    _hash *= K;
                    goto case 5;
                case 5:
                    _hash ^= *(ulong*) (nb + 4);
                    _hash *= K;
                    goto case 4;
                case 4:
                    _hash ^= *(ulong*) (nb + 3);
                    _hash *= K;
                    goto case 3;
                case 3:
                    _hash ^= *(ulong*) (nb + 2);
                    _hash *= K;
                    goto case 2;
                case 2:
                    _hash ^= *(ulong*) (nb + 1);
                    _hash *= K;
                    goto case 1;
                case 1:
                    _hash ^= *nb;
                    _hash *= K;
                    break;
            }
        }
    }
    /// <summary>
    ///     Exposed so that hash64 can be used externally.
    /// </summary>
    public unsafe ulong Hash64(byte[] bytes)
    {
        var cbSize = bytes.Length;
        _hash = Seed;
        fixed (byte* pb = bytes)
        {
            var nb = pb;
            while (cbSize >= 8)
            {
                _hash  ^= *(ulong*) nb;
                nb     += 8;
                cbSize -= 8;
                _hash  *= K;
            }
            switch (cbSize & 7)
            {
                case 7:
                    _hash ^= *(ulong*) (nb + 6);
                    _hash *= K;
                    goto case 6;
                case 6:
                    _hash ^= *(ulong*) (nb + 5);
                    _hash *= K;
                    goto case 5;
                case 5:
                    _hash ^= *(ulong*) (nb + 4);
                    _hash *= K;
                    goto case 4;
                case 4:
                    _hash ^= *(ulong*) (nb + 3);
                    _hash *= K;
                    goto case 3;
                case 3:
                    _hash ^= *(ulong*) (nb + 2);
                    _hash *= K;
                    goto case 2;
                case 2:
                    _hash ^= *(ulong*) (nb + 1);
                    _hash *= K;
                    goto case 1;
                case 1:
                    _hash ^= *nb;
                    _hash *= K;
                    break;
            }
        }
        return _hash;
    }
    protected override byte[] HashFinal()
    {
        Hash = _hash;
        return _hash.GetBytes();
    }
}

Mapping160BitTo64BitHash.cs

Maps a 160-Bit Hash Into a 64-Bit Space

using System.Security.Cryptography;
/// <summary>
///     Pros: ~no Collisions within long bit space ~(9,223,372,036,854,775,807)
///     Cons: Maintains a TinyDictionary(byte[],byte[]), non-deterministic across application or
///     method domains
///     Cannot Transform or reuse.
/// </summary>
public class Mapping160BitTo64BitHash : HashAlgorithm
{
    public readonly  TinyDictionary<byte[], byte[]> map = new TinyDictionary<byte[], byte[]>(101, new ArrayComparer());
    private          byte[]                         h160;
    private readonly SHA1Managed                    hasher = new SHA1Managed();
    public override  int                            HashSize => 64;
    public override void Initialize()
    {
    }
    /// <inheritdoc />
    /// <summary>
    ///     Compute the 64 Bit hash value and add it and the original array to the map to create a unique position within the
    ///     TinyDictionary.
    /// </summary>
    protected override void HashCore(byte[] bytes, int ibStart, int cbSize)
    {
        h160 = hasher.ComputeHash(bytes, ibStart, cbSize);
        map.Add(h160, bytes);
    }
    /// <inheritdoc />
    /// <summary>
    ///     Return the unique position within the TinyDictionary as the hash value (index).
    /// </summary>
    protected override byte[] HashFinal()
    {
        HashValue = (byte[])map.FindKeyIndex(h160).GetBytes().Clone();
        return HashValue;
    }
}