Last active
January 12, 2021 14:25
-
-
Save mjs3339/850e143b26289d1a32f1344e548e08f0 to your computer and use it in GitHub Desktop.
C# Implementation of the FNV1a Hashing Algorithm.
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
using System; | |
using System.Security.Cryptography; | |
[Serializable] | |
public class FNV1a64 : HashAlgorithm | |
{ | |
private const ulong K = 0x100000001B3; | |
private const ulong M = 0x1000000000000000; | |
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; | |
_hash %= M; | |
} | |
switch (cbSize & 7) | |
{ | |
case 7: | |
_hash ^= *(ulong*) (nb + 6); | |
_hash *= K; | |
_hash %= M; | |
goto case 6; | |
case 6: | |
_hash ^= *(ulong*) (nb + 5); | |
_hash *= K; | |
_hash %= M; | |
goto case 5; | |
case 5: | |
_hash ^= *(ulong*) (nb + 4); | |
_hash *= K; | |
_hash %= M; | |
goto case 4; | |
case 4: | |
_hash ^= *(ulong*) (nb + 3); | |
_hash *= K; | |
_hash %= M; | |
goto case 3; | |
case 3: | |
_hash ^= *(ulong*) (nb + 2); | |
_hash *= K; | |
_hash %= M; | |
goto case 2; | |
case 2: | |
_hash ^= *(ulong*) (nb + 1); | |
_hash *= K; | |
_hash %= M; | |
goto case 1; | |
case 1: | |
_hash ^= *nb; | |
_hash *= K; | |
_hash %= M; | |
break; | |
} | |
} | |
} | |
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; | |
_hash %= M; | |
} | |
switch (cbSize & 7) | |
{ | |
case 7: | |
_hash ^= *(ulong*) (nb + 6); | |
_hash *= K; | |
_hash %= M; | |
goto case 6; | |
case 6: | |
_hash ^= *(ulong*) (nb + 5); | |
_hash *= K; | |
_hash %= M; | |
goto case 5; | |
case 5: | |
_hash ^= *(ulong*) (nb + 4); | |
_hash *= K; | |
_hash %= M; | |
goto case 4; | |
case 4: | |
_hash ^= *(ulong*) (nb + 3); | |
_hash *= K; | |
_hash %= M; | |
goto case 3; | |
case 3: | |
_hash ^= *(ulong*) (nb + 2); | |
_hash *= K; | |
_hash %= M; | |
goto case 2; | |
case 2: | |
_hash ^= *(ulong*) (nb + 1); | |
_hash *= K; | |
_hash %= M; | |
goto case 1; | |
case 1: | |
_hash ^= *nb; | |
_hash *= K; | |
_hash %= M; | |
break; | |
} | |
} | |
return _hash; | |
} | |
protected override byte[] HashFinal() | |
{ | |
Hash = _hash; | |
return _hash.GetBytes(); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment