Skip to content

Commit b98f423

Browse files
jonathanpeppersjonpryor
authored andcommitted
[crc64] changes to fix a collision (#493)
When testing out the new `Crc64` hash type I found a collision: Hash ("") == Hash(new byte[32]) Both values were `00-00-00-00-00-00-00-00`. It seems that a value of length 0 would get the same hash as an all-zero `byte[]`. Two changes to the algorithm: * The `crc` value starts at `ulong.MaxValue`. Many CRC algorithms do this. * XOR the length of the bytes. Many CRC algorithms XOR a constant value at the end, but using the `length` should provide further uniqueness. This should reduce the chance for collisions. This changes the type names mentioned in commit 397013e: * `Example.Name, Lib1`: * Old: `crc64aae7d955a89b38db.Name` * New: `crc644f8201c0277b26af.Name` * `Example.Name, Lib2`: * Old: `crc64217c8705f00a5054.Name` * New: `crc64c4195f907fea4e20.Name`
1 parent d85c6e6 commit b98f423

File tree

3 files changed

+21
-6
lines changed

3 files changed

+21
-6
lines changed

src/Java.Interop.Tools.JavaCallableWrappers/Java.Interop.Tools.JavaCallableWrappers/Crc64.cs

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,9 @@ namespace Java.Interop.Tools.JavaCallableWrappers
3636
/// <summary>
3737
/// CRC64 variant: crc-64-jones 64-bit
3838
/// * Poly: 0xad93d23594c935a9
39+
/// Changes beyond initial implementation:
40+
/// * Starting Value: ulong.MaxValue
41+
/// * XOR length in HashFinal()
3942
/// </summary>
4043
public class Crc64 : HashAlgorithm
4144
{
@@ -170,7 +173,8 @@ public class Crc64 : HashAlgorithm
170173
0x536fa08fdfd90e51, 0x29b7d047efec8728,
171174
};
172175

173-
ulong crc;
176+
ulong crc = ulong.MaxValue;
177+
ulong length = 0;
174178

175179
public override void Initialize () { }
176180

@@ -179,8 +183,9 @@ protected override void HashCore (byte [] array, int ibStart, int cbSize)
179183
for (int i = ibStart; i < cbSize; i++) {
180184
crc = Table [(byte) (crc ^ array [i])] ^ (crc >> 8);
181185
}
186+
length += (ulong) cbSize;
182187
}
183188

184-
protected override byte [] HashFinal () => BitConverter.GetBytes (crc);
189+
protected override byte [] HashFinal () => BitConverter.GetBytes (crc ^ length);
185190
}
186191
}

src/Java.Interop.Tools.JavaCallableWrappers/Test/Java.Interop.Tools.JavaCallableWrappers/Crc64Tests.cs

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,11 @@ public class Crc64Tests
99
{
1010
static string ToHash (string value)
1111
{
12-
var data = Encoding.UTF8.GetBytes (value);
12+
return ToHash (Encoding.UTF8.GetBytes (value));
13+
}
14+
15+
static string ToHash (byte[] data)
16+
{
1317
using (var crc = new Crc64 ()) {
1418
var hash = crc.ComputeHash (data);
1519
var buf = new StringBuilder (hash.Length * 2);
@@ -23,14 +27,20 @@ static string ToHash (string value)
2327
public void Hello ()
2428
{
2529
var actual = ToHash ("hello");
26-
Assert.AreEqual ("a27666cb10ddb0d6", actual);
30+
Assert.AreEqual ("ad3d04bd697eb3c5", actual);
2731
}
2832

2933
[Test]
3034
public void XmlDocument ()
3135
{
3236
var actual = ToHash ("System.Xml.XmlDocument, System.Xml");
33-
Assert.AreEqual ("2fbc43b3a95193ae", actual);
37+
Assert.AreEqual ("348bbd9fecf1b865", actual);
38+
}
39+
40+
[Test]
41+
public void Collision ()
42+
{
43+
Assert.AreNotEqual (ToHash (""), ToHash (new byte [32]));
3444
}
3545
}
3646
}

src/Java.Interop.Tools.JavaCallableWrappers/Test/Java.Interop.Tools.JavaCallableWrappers/JavaNativeTypeManagerTests.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ public void MD5 ()
3636
public void Crc64 ()
3737
{
3838
JavaNativeTypeManager.PackageNamingPolicy = PackageNamingPolicy.LowercaseCrc64;
39-
Assert.AreEqual ("crc640005e817d0491b19", JavaNativeTypeManager.GetPackageName (typeof (string)));
39+
Assert.AreEqual ("crc64b74743e9328eed0a", JavaNativeTypeManager.GetPackageName (typeof (string)));
4040
}
4141

4242
[Test]

0 commit comments

Comments
 (0)