mirror of
https://github.com/SabreTools/SabreTools.Hashing.git
synced 2026-07-08 18:06:40 +00:00
Add CRC-82/DARC
This commit is contained in:
@@ -268,6 +268,10 @@ namespace Hasher.Features
|
||||
"crc64_we" => HashType.CRC64_WE,
|
||||
"crc64_xz" => HashType.CRC64_XZ,
|
||||
|
||||
#if NET7_0_OR_GREATER
|
||||
"crc82_darc" => HashType.CRC82_DARC,
|
||||
#endif
|
||||
|
||||
"fletcher16" => HashType.Fletcher16,
|
||||
"fletcher32" => HashType.Fletcher32,
|
||||
"fletcher64" => HashType.Fletcher64,
|
||||
|
||||
@@ -38,7 +38,7 @@ All hash and checksum types here have been written to ensure compatibility acros
|
||||
| Hash / Checksum Type | Notes |
|
||||
| --- | --- |
|
||||
| Adler-32 | Based on the [zlib source code](https://github.com/madler/zlib/blob/v1.2.11/adler32.c) |
|
||||
| CRC | All CRC values documented [here](https://reveng.sourceforge.io/crc-catalogue/all.htm) except for CRC-82 due to bit-length restrictions |
|
||||
| CRC | All CRC values documented [here](https://reveng.sourceforge.io/crc-catalogue/all.htm), with CRC-82 only supported in `net7.0` and above |
|
||||
| Fletcher | 16-, 32-, and 64-bit variants |
|
||||
| FNV | 32-, and 64-bit variants; 0, 1, and 1a algorithms |
|
||||
| Message Digest | MD2 and MD4 only |
|
||||
|
||||
@@ -162,6 +162,10 @@ namespace SabreTools.Hashing.Test
|
||||
{HashType.CRC64_WE, "91812be748f941c4"},
|
||||
{HashType.CRC64_XZ, "fb49044e8331f6e5"},
|
||||
|
||||
#if NET7_0_OR_GREATER
|
||||
{ HashType.CRC82_DARC, "14a892baa6688e66f55f3"},
|
||||
#endif
|
||||
|
||||
{HashType.Fletcher16, "46c1"},
|
||||
{HashType.Fletcher32, "073f2d94"},
|
||||
{HashType.Fletcher64, "000b073400002d94"},
|
||||
|
||||
@@ -11,7 +11,11 @@ namespace SabreTools.Hashing.Checksum
|
||||
public static byte[] ClampValueToBytes(ulong value, int bitWidth)
|
||||
#endif
|
||||
{
|
||||
#if NET7_0_OR_GREATER
|
||||
value &= System.UInt128.MaxValue >> (128 - bitWidth);
|
||||
#else
|
||||
value &= ulong.MaxValue >> (64 - bitWidth);
|
||||
#endif
|
||||
byte[] bytes = new byte[(bitWidth + 7) / 8];
|
||||
|
||||
for (int i = 0; i < bytes.Length; i++)
|
||||
|
||||
@@ -7,7 +7,89 @@ namespace SabreTools.Hashing.Checksum
|
||||
/// </summary>
|
||||
public abstract class ChecksumBase : System.Security.Cryptography.HashAlgorithm
|
||||
{
|
||||
// No common, untyped functionality
|
||||
#if NET7_0_OR_GREATER
|
||||
/// <summary>
|
||||
/// Convert an Int64 to a byte array
|
||||
/// </summary>
|
||||
/// <remarks>Reads in little-endian format</remarks>
|
||||
internal static byte[] GetBytes(Int128 value)
|
||||
{
|
||||
byte[] output =
|
||||
[
|
||||
(byte)(value & 0xFF),
|
||||
(byte)((value >> 8) & 0xFF),
|
||||
(byte)((value >> 16) & 0xFF),
|
||||
(byte)((value >> 24) & 0xFF),
|
||||
(byte)((value >> 32) & 0xFF),
|
||||
(byte)((value >> 40) & 0xFF),
|
||||
(byte)((value >> 48) & 0xFF),
|
||||
(byte)((value >> 56) & 0xFF),
|
||||
(byte)((value >> 64) & 0xFF),
|
||||
(byte)((value >> 72) & 0xFF),
|
||||
(byte)((value >> 80) & 0xFF),
|
||||
(byte)((value >> 88) & 0xFF),
|
||||
(byte)((value >> 96) & 0xFF),
|
||||
(byte)((value >> 104) & 0xFF),
|
||||
(byte)((value >> 112) & 0xFF),
|
||||
(byte)((value >> 120) & 0xFF),
|
||||
];
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Convert a UInt64 to a byte array
|
||||
/// </summary>
|
||||
/// <remarks>Reads in little-endian format</remarks>
|
||||
internal static byte[] GetBytes(UInt128 value)
|
||||
{
|
||||
byte[] output =
|
||||
[
|
||||
(byte)(value & 0xFF),
|
||||
(byte)((value >> 8) & 0xFF),
|
||||
(byte)((value >> 16) & 0xFF),
|
||||
(byte)((value >> 24) & 0xFF),
|
||||
(byte)((value >> 32) & 0xFF),
|
||||
(byte)((value >> 40) & 0xFF),
|
||||
(byte)((value >> 48) & 0xFF),
|
||||
(byte)((value >> 56) & 0xFF),
|
||||
(byte)((value >> 64) & 0xFF),
|
||||
(byte)((value >> 72) & 0xFF),
|
||||
(byte)((value >> 80) & 0xFF),
|
||||
(byte)((value >> 88) & 0xFF),
|
||||
(byte)((value >> 96) & 0xFF),
|
||||
(byte)((value >> 104) & 0xFF),
|
||||
(byte)((value >> 112) & 0xFF),
|
||||
(byte)((value >> 120) & 0xFF),
|
||||
];
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Convert a byte array at an offset to a UInt128
|
||||
/// </summary>
|
||||
/// <remarks>Reads in little-endian format</remarks>
|
||||
internal static UInt128 ToUInt128(byte[] value)
|
||||
{
|
||||
return value[0]
|
||||
| ((UInt128)value[1] << 8)
|
||||
| ((UInt128)value[2] << 16)
|
||||
| ((UInt128)value[3] << 24)
|
||||
| ((UInt128)value[4] << 32)
|
||||
| ((UInt128)value[5] << 40)
|
||||
| ((UInt128)value[6] << 48)
|
||||
| ((UInt128)value[7] << 56)
|
||||
| ((UInt128)value[8] << 64)
|
||||
| ((UInt128)value[9] << 72)
|
||||
| ((UInt128)value[10] << 80)
|
||||
| ((UInt128)value[11] << 88)
|
||||
| ((UInt128)value[12] << 96)
|
||||
| ((UInt128)value[13] << 104)
|
||||
| ((UInt128)value[14] << 112)
|
||||
| ((UInt128)value[15] << 120);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -51,65 +133,5 @@ namespace SabreTools.Hashing.Checksum
|
||||
Array.Reverse(hashArr);
|
||||
return hashArr;
|
||||
}
|
||||
|
||||
#if NET7_0_OR_GREATER
|
||||
/// <summary>
|
||||
/// Convert an Int64 to a byte array
|
||||
/// </summary>
|
||||
/// <remarks>Reads in little-endian format</remarks>
|
||||
private static byte[] GetBytes(Int128 value)
|
||||
{
|
||||
byte[] output =
|
||||
[
|
||||
(byte)(value & 0xFF),
|
||||
(byte)((value >> 8) & 0xFF),
|
||||
(byte)((value >> 16) & 0xFF),
|
||||
(byte)((value >> 24) & 0xFF),
|
||||
(byte)((value >> 32) & 0xFF),
|
||||
(byte)((value >> 40) & 0xFF),
|
||||
(byte)((value >> 48) & 0xFF),
|
||||
(byte)((value >> 56) & 0xFF),
|
||||
(byte)((value >> 64) & 0xFF),
|
||||
(byte)((value >> 72) & 0xFF),
|
||||
(byte)((value >> 80) & 0xFF),
|
||||
(byte)((value >> 88) & 0xFF),
|
||||
(byte)((value >> 96) & 0xFF),
|
||||
(byte)((value >> 104) & 0xFF),
|
||||
(byte)((value >> 112) & 0xFF),
|
||||
(byte)((value >> 120) & 0xFF),
|
||||
];
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Convert a UInt64 to a byte array
|
||||
/// </summary>
|
||||
/// <remarks>Reads in little-endian format</remarks>
|
||||
private static byte[] GetBytes(UInt128 value)
|
||||
{
|
||||
byte[] output =
|
||||
[
|
||||
(byte)(value & 0xFF),
|
||||
(byte)((value >> 8) & 0xFF),
|
||||
(byte)((value >> 16) & 0xFF),
|
||||
(byte)((value >> 24) & 0xFF),
|
||||
(byte)((value >> 32) & 0xFF),
|
||||
(byte)((value >> 40) & 0xFF),
|
||||
(byte)((value >> 48) & 0xFF),
|
||||
(byte)((value >> 56) & 0xFF),
|
||||
(byte)((value >> 64) & 0xFF),
|
||||
(byte)((value >> 72) & 0xFF),
|
||||
(byte)((value >> 80) & 0xFF),
|
||||
(byte)((value >> 88) & 0xFF),
|
||||
(byte)((value >> 96) & 0xFF),
|
||||
(byte)((value >> 104) & 0xFF),
|
||||
(byte)((value >> 112) & 0xFF),
|
||||
(byte)((value >> 120) & 0xFF),
|
||||
];
|
||||
|
||||
return output;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,7 +32,11 @@ namespace SabreTools.Hashing.Checksum
|
||||
public Crc(CrcDefinition def)
|
||||
{
|
||||
// Check for a valid bit width
|
||||
#if NET7_0_OR_GREATER
|
||||
if (def.Width < 0 || def.Width > 128)
|
||||
#else
|
||||
if (def.Width < 0 || def.Width > 64)
|
||||
#endif
|
||||
throw new ArgumentOutOfRangeException(nameof(def));
|
||||
|
||||
Def = def;
|
||||
|
||||
@@ -24,7 +24,7 @@ namespace SabreTools.Hashing.Checksum
|
||||
/// Bit mask based on the CRC width
|
||||
/// </summary>
|
||||
#if NET7_0_OR_GREATER
|
||||
private UInt128 BitMask => 1UL << (_definition.Width - 1);
|
||||
private UInt128 BitMask => UInt128.Parse("1") << (_definition.Width - 1);
|
||||
#else
|
||||
private ulong BitMask => 1UL << (_definition.Width - 1);
|
||||
#endif
|
||||
@@ -87,7 +87,11 @@ namespace SabreTools.Hashing.Checksum
|
||||
point = ReverseBits(point, def.Width);
|
||||
|
||||
// Shift back to account for storage
|
||||
#if NET7_0_OR_GREATER
|
||||
point &= UInt128.MaxValue >> (128 - def.Width);
|
||||
#else
|
||||
point &= ulong.MaxValue >> (64 - def.Width);
|
||||
#endif
|
||||
|
||||
// Assign to the table
|
||||
_table[0, i] = point;
|
||||
|
||||
@@ -1700,5 +1700,25 @@ namespace SabreTools.Hashing.Checksum
|
||||
};
|
||||
|
||||
#endregion
|
||||
|
||||
#region CRC-82
|
||||
|
||||
#if NET7_0_OR_GREATER
|
||||
/// <summary>
|
||||
/// CRC-82/DARC
|
||||
/// </summary>
|
||||
public static readonly CrcDefinition CRC82_DARC = new()
|
||||
{
|
||||
Name = "CRC-82/DARC",
|
||||
Width = 82,
|
||||
Poly = ChecksumBase.ToUInt128([0x11, 0x04, 0x44, 0x01, 0x14, 0x01, 0x11, 0x01, 0x8c, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]),
|
||||
Init = ChecksumBase.ToUInt128([0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]),
|
||||
ReflectIn = true,
|
||||
ReflectOut = true,
|
||||
XorOut = ChecksumBase.ToUInt128([0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]),
|
||||
};
|
||||
#endif
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
@@ -50,6 +50,29 @@ namespace SabreTools.Hashing
|
||||
return result;
|
||||
}
|
||||
|
||||
#if NET7_0_OR_GREATER
|
||||
/// <summary>
|
||||
/// Convert a byte array to a UInt64
|
||||
/// </summary>
|
||||
/// <param name="bytes">Byte array to convert</param>
|
||||
/// <returns>UInt64 representing the byte array</returns>
|
||||
/// <link>https://stackoverflow.com/questions/66750224/how-to-convert-a-byte-array-of-any-size-to-ulong-in-c</link>
|
||||
public static UInt128 BytesToUInt128(byte[]? bytes)
|
||||
{
|
||||
// If we get null in, we send 0 out
|
||||
if (bytes is null)
|
||||
return default;
|
||||
|
||||
UInt128 result = 0;
|
||||
for (int i = 0; i < bytes.Length; i++)
|
||||
{
|
||||
result |= (UInt128)bytes[i] << (i * 8);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
#endif
|
||||
|
||||
#endregion
|
||||
|
||||
#region Read Big-Endian
|
||||
|
||||
@@ -1116,6 +1116,20 @@ namespace SabreTools.Hashing
|
||||
|
||||
#endregion
|
||||
|
||||
#region CRC-82
|
||||
|
||||
#if NET7_0_OR_GREATER
|
||||
/// <summary>
|
||||
/// CRC 82-bit checksum (CRC-82/DARC)
|
||||
/// </summary>
|
||||
public static readonly HashType CRC82_DARC = new("CRC-82/DARC",
|
||||
"CRC 82-bit checksum (CRC-82/DARC)",
|
||||
[0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00],
|
||||
"000000000000000000000");
|
||||
#endif
|
||||
|
||||
#endregion
|
||||
|
||||
#endregion
|
||||
|
||||
#region Fletcher
|
||||
@@ -1652,6 +1666,10 @@ namespace SabreTools.Hashing
|
||||
CRC64_WE,
|
||||
CRC64_XZ,
|
||||
|
||||
#if NET7_0_OR_GREATER
|
||||
CRC82_DARC,
|
||||
#endif
|
||||
|
||||
Fletcher16,
|
||||
Fletcher32,
|
||||
Fletcher64,
|
||||
@@ -2000,6 +2018,11 @@ namespace SabreTools.Hashing
|
||||
else if (hashType == CRC64_XZ)
|
||||
return new Crc(StandardDefinitions.CRC64_XZ);
|
||||
|
||||
#if NET7_0_OR_GREATER
|
||||
else if (hashType == CRC82_DARC)
|
||||
return new Crc(StandardDefinitions.CRC82_DARC);
|
||||
#endif
|
||||
|
||||
else if (hashType == Fletcher16)
|
||||
return new Fletcher16();
|
||||
else if (hashType == Fletcher32)
|
||||
|
||||
@@ -147,7 +147,11 @@ namespace SabreTools.Hashing
|
||||
return null;
|
||||
|
||||
// Get the total number of characters needed
|
||||
#if NET7_0_OR_GREATER
|
||||
UInt128 hash = BytesToUInt128(cr.Hash);
|
||||
#else
|
||||
ulong hash = BytesToUInt64(cr.Hash);
|
||||
#endif
|
||||
int length = (cr.Def.Width / 4) + (cr.Def.Width % 4 > 0 ? 1 : 0);
|
||||
return hash.ToString($"x{length}");
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user