C# FNV1a128 Implementation
/// <summary> | |
/// No collisions with 20M random byte arrays. 32x slower than FNV1a64. | |
/// https://en.wikipedia.org/wiki/Fowler%E2%80%93Noll%E2%80%93Vo_hash_function | |
/// </summary> | |
public class FNV1a128 : HashAlgorithm | |
{ | |
private readonly BigInteger _K = "309485009821345068724781371".NewBigInteger10(); | |
private BigInteger _hash; | |
private readonly BigInteger Seed = "144066263297769815596495629667062367629".NewBigInteger10(); | |
public FNV1a128() | |
{ | |
} | |
public FNV1a128(string seed) | |
{ | |
Seed = seed.NewBigInteger10(); | |
Initialize(); | |
} | |
public override int HashSize => 128; | |
public override void Initialize() | |
{ | |
_hash = Seed; | |
public class FNV1a128 : HashAlgorithm | |
{ | |
private readonly BigInteger _K = "309485009821345068724781371".NewBigInteger10(); | |
private BigInteger _hash; | |
private readonly BigInteger Seed = "144066263297769815596495629667062367629".NewBigInteger10(); | |
public FNV1a128() | |
{ | |
_hash = Seed; | |
} | |
public FNV1a128(string seed) | |
{ | |
Seed = seed.NewBigInteger10(); | |
_hash = Seed; | |
} | |
public override int HashSize => 128; | |
public override void Initialize() | |
{ | |
_hash = Seed; | |
} | |
protected override void HashCore(byte[] bytes, int ibStart, int cbSize) | |
{ | |
Hash64(bytes, ibStart, cbSize); | |
} | |
private void Hash64(byte[] bytes, int ibStart, int cbSize) | |
{ | |
if (bytes == null) | |
return; | |
if (ibStart >= bytes.Length || cbSize > bytes.Length) | |
return; | |
var p = 0; | |
while (cbSize > 0) | |
{ | |
_hash ^= bytes[p + ibStart]; | |
_hash *= _K; | |
cbSize--; | |
p++; | |
} | |
_hash = _hash ^ (_hash >> 64); | |
} | |
/// <summary> | |
/// BigInteger does not overflow, so we limit the output to 128Bits. | |
/// </summary> | |
protected override byte[] HashFinal() | |
{ | |
return _hash.ToByteArray().SubByte(0, 16); | |
} | |
} } | |
protected override void HashCore(byte[] bytes, int ibStart, int cbSize) | |
{ | |
Hash64(bytes, ibStart, cbSize); | |
} | |
private void Hash64(byte[] bytes, int ibStart, int cbSize) | |
{ | |
if (bytes == null) | |
return; | |
if (ibStart >= bytes.Length || cbSize > bytes.Length) | |
return; | |
var p = 0; | |
while (cbSize > 0) | |
{ | |
_hash ^= bytes[p + ibStart]; | |
_hash *= _K; | |
cbSize--; | |
p++; | |
} | |
_hash = _hash ^ (_hash >> 64); | |
} | |
/// <summary> | |
/// BigInteger does not overflow, so we limit the output to 128Bits. | |
/// </summary> | |
protected override byte[] HashFinal() | |
{ | |
return _hash.ToByteArray().SubByte(0, 16); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment