/
Crc32.cs
126 lines (109 loc) · 3.04 KB
/
Crc32.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
using System;
using System.Security.Cryptography;
namespace Rhino.DistributedHashTable.Client.Util
{
/// <summary>
/// Taken from
/// http://damieng.com/blog/2006/08/08/calculating_crc32_in_c_and_net
/// </summary>
public class Crc32 : HashAlgorithm
{
public const UInt32 DefaultPolynomial = 0xedb88320;
public const UInt32 DefaultSeed = 0xffffffff;
private static UInt32[] defaultTable;
private UInt32 hash;
private readonly UInt32 seed;
private readonly UInt32[] table;
public Crc32()
{
table = InitializeTable(DefaultPolynomial);
seed = DefaultSeed;
Initialize();
}
public Crc32(UInt32 polynomial,
UInt32 seed)
{
table = InitializeTable(polynomial);
this.seed = seed;
Initialize();
}
public override int HashSize
{
get { return 32; }
}
public override void Initialize()
{
hash = seed;
}
protected override void HashCore(byte[] buffer,
int start,
int length)
{
hash = CalculateHash(table, hash, buffer, start, length);
}
protected override byte[] HashFinal()
{
var hashBuffer = UInt32ToBigEndianBytes(~hash);
HashValue = hashBuffer;
return hashBuffer;
}
public static UInt32 Compute(byte[] buffer)
{
return ~CalculateHash(InitializeTable(DefaultPolynomial), DefaultSeed, buffer, 0, buffer.Length);
}
public static UInt32 Compute(UInt32 seed,
byte[] buffer)
{
return ~CalculateHash(InitializeTable(DefaultPolynomial), seed, buffer, 0, buffer.Length);
}
public static UInt32 Compute(UInt32 polynomial,
UInt32 seed,
byte[] buffer)
{
return ~CalculateHash(InitializeTable(polynomial), seed, buffer, 0, buffer.Length);
}
private static UInt32[] InitializeTable(UInt32 polynomial)
{
if (polynomial == DefaultPolynomial && defaultTable != null)
return defaultTable;
var createTable = new UInt32[256];
for (var i = 0; i < 256; i++)
{
var entry = (UInt32) i;
for (var j = 0; j < 8; j++)
if ((entry & 1) == 1)
entry = (entry >> 1) ^ polynomial;
else
entry = entry >> 1;
createTable[i] = entry;
}
if (polynomial == DefaultPolynomial)
defaultTable = createTable;
return createTable;
}
private static UInt32 CalculateHash(UInt32[] table,
UInt32 seed,
byte[] buffer,
int start,
int size)
{
var crc = seed;
for (var i = start; i < size; i++)
unchecked
{
crc = (crc >> 8) ^ table[buffer[i] ^ crc & 0xff];
}
return crc;
}
private static byte[] UInt32ToBigEndianBytes(UInt32 x)
{
return new byte[]
{
(byte) ((x >> 24) & 0xff),
(byte) ((x >> 16) & 0xff),
(byte) ((x >> 8) & 0xff),
(byte) (x & 0xff)
};
}
}
}