Standard CRC 64
using System;
using System.Globalization;
using System.Security.Cryptography;
using System.Text;
public class CRC64 : HashAlgorithm
{
/// <summary>
/// https://en.wikipedia.org/wiki/Polynomial_representations_of_cyclic_redundancy_checks
/// </summary>
public enum PolyType : ulong
{
ECMA182 = 0xD800000000000000,
ISOPoly = 0xC96C5795D7870F42
}
private const ulong Seed = 0x0;
private static ulong[] _table;
private ulong _hash;
public CRC64(PolyType pt = PolyType.ECMA182)
{
HashSizeValue = 64;
InitializeTable((ulong) pt);
Initialize();
}
public override void Initialize()
{
_hash = Seed;
}
protected override void HashCore(byte[] data, int start, int size)
{
State = 1;
for (var i = start; i < start + size; i++)
unchecked
{
_hash = (_hash >> 8) ^ _table[(data[i] ^ _hash) & 0xff];
}
}
protected override byte[] HashFinal()
{
HashValue = UInt64ToBigEndianBytes(_hash);
State = 0;
_hash = Seed;
return HashValue;
}
private static byte[] UInt64ToBigEndianBytes(ulong value)
{
var result = BitConverter.GetBytes(value);
if (BitConverter.IsLittleEndian)
Array.Reverse(result);
return result;
}
public static string ToHex(byte[] data)
{
var builder = new StringBuilder();
foreach (var item in data)
builder.Append(item.ToString("X2", CultureInfo.InvariantCulture));
return builder.ToString();
}
private static void InitializeTable(ulong polynomial)
{
_table = new ulong[256];
for (var i = 0; i < 256; ++i)
{
var entry = (ulong) i;
for (var j = 0; j < 8; ++j)
if ((entry & 1) == 1)
entry = (entry >> 1) ^ polynomial;
else
entry = entry >> 1;
_table[i] = entry;
}
}
}