mirror of
https://github.com/SabreTools/SabreTools.Hashing.git
synced 2026-02-08 13:49:54 +00:00
Compare commits
190 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ba7a1cd8b7 | ||
|
|
165bbdfd72 | ||
|
|
4a9fc1a144 | ||
|
|
563d293f4b | ||
|
|
39c2451354 | ||
|
|
b8ec4ac9c4 | ||
|
|
adc918ea8a | ||
|
|
186f8a1ece | ||
|
|
d8cb2e2955 | ||
|
|
83f008919c | ||
|
|
72a98e3e03 | ||
|
|
32fe421af4 | ||
|
|
3382c20217 | ||
|
|
6700f603f2 | ||
|
|
e1c1c8322d | ||
|
|
7b9580c991 | ||
|
|
75e536df4f | ||
|
|
3e18ddce9f | ||
|
|
f4d5e88f0a | ||
|
|
a5f7e7d91d | ||
|
|
2e3e16e8ae | ||
|
|
8fa100eb89 | ||
|
|
bf1cfa0e1f | ||
|
|
4e86e0ef86 | ||
|
|
d57396612f | ||
|
|
1b06751c68 | ||
|
|
89582a56ac | ||
|
|
ac1cacc247 | ||
|
|
27276ce05d | ||
|
|
841f5708a3 | ||
|
|
6df184fa4e | ||
|
|
d9cf9fd3b2 | ||
|
|
21b49921ac | ||
|
|
d1b60f7951 | ||
|
|
bb9d4155d2 | ||
|
|
5b66eaf253 | ||
|
|
7c4d6a6862 | ||
|
|
79c10cf2fb | ||
|
|
ffc6bc045d | ||
|
|
7a43f6c0de | ||
|
|
d096cbf07e | ||
|
|
bb67c3e2f3 | ||
|
|
f2e5033bb4 | ||
|
|
0f7d373751 | ||
|
|
8231ab18a6 | ||
|
|
bd8055b7d5 | ||
|
|
bd0f76ef08 | ||
|
|
70e79a68eb | ||
|
|
a087abf3d3 | ||
|
|
bd363ca1ec | ||
|
|
e4a53f3d62 | ||
|
|
1401775c15 | ||
|
|
a3ba52adee | ||
|
|
544d6f1cc8 | ||
|
|
62da665c07 | ||
|
|
8480ec8d92 | ||
|
|
c763d402d9 | ||
|
|
7c090b76c0 | ||
|
|
2be7850b9e | ||
|
|
611a0934ae | ||
|
|
16826f4c8b | ||
|
|
4732de1268 | ||
|
|
f74c9ddffd | ||
|
|
58f2475099 | ||
|
|
1d1fe196cf | ||
|
|
2af987bb1d | ||
|
|
effb2f9db6 | ||
|
|
b728aa77c7 | ||
|
|
fefdcd72a3 | ||
|
|
5d25a017eb | ||
|
|
c0643e3bca | ||
|
|
65a57f6c60 | ||
|
|
9c27523612 | ||
|
|
5ed7ad7802 | ||
|
|
41be02c57d | ||
|
|
0ec9c1f91d | ||
|
|
de8e510f71 | ||
|
|
82f051354f | ||
|
|
7559ba2edc | ||
|
|
4a408ded7e | ||
|
|
3469d424af | ||
|
|
3fa04bba65 | ||
|
|
f135693c7e | ||
|
|
0d6806cf59 | ||
|
|
4dde900195 | ||
|
|
a383bb39a6 | ||
|
|
92554705cc | ||
|
|
c5e4cb1495 | ||
|
|
9bb8a07c32 | ||
|
|
7878591107 | ||
|
|
6f536b8e2a | ||
|
|
dee69d1d88 | ||
|
|
0e8694cc90 | ||
|
|
a7f8e0664a | ||
|
|
b1e4546697 | ||
|
|
51d1a81e08 | ||
|
|
1a941b44fc | ||
|
|
ea601eed8d | ||
|
|
c1a9e007c5 | ||
|
|
fb83427c91 | ||
|
|
57f9aa9133 | ||
|
|
dbcb654f8a | ||
|
|
16d3472fc6 | ||
|
|
aced21c9f0 | ||
|
|
2a81a65f99 | ||
|
|
9819a5975a | ||
|
|
e36cd9bf3c | ||
|
|
4eec52241e | ||
|
|
98c646d579 | ||
|
|
d8da0d6312 | ||
|
|
d259dca9ab | ||
|
|
188483b4d1 | ||
|
|
6b33bec6e2 | ||
|
|
1fc4c13683 | ||
|
|
2ef3a6f254 | ||
|
|
827239a08a | ||
|
|
c1e847c1cf | ||
|
|
f01d801421 | ||
|
|
483a74f8c9 | ||
|
|
d0660472eb | ||
|
|
5718c62157 | ||
|
|
63eff1ab18 | ||
|
|
7de1c6464f | ||
|
|
f900eca029 | ||
|
|
cb3585ae49 | ||
|
|
9610e1756f | ||
|
|
45d0e2dde1 | ||
|
|
389c609a9d | ||
|
|
71d88d3467 | ||
|
|
3905905301 | ||
|
|
adc03c90eb | ||
|
|
4c006317be | ||
|
|
21498f6d52 | ||
|
|
2dcf0e7eea | ||
|
|
0cf07ae13a | ||
|
|
74d74fdfae | ||
|
|
9e48cca1a3 | ||
|
|
23679266b4 | ||
|
|
992e22cc76 | ||
|
|
5cfe0dcb09 | ||
|
|
3ebb489f23 | ||
|
|
94b9e91718 | ||
|
|
445c3473d9 | ||
|
|
d8bc77a938 | ||
|
|
10406fa90c | ||
|
|
08f5ae5b8b | ||
|
|
e5010f1856 | ||
|
|
d6b00b1a42 | ||
|
|
8aa10ff06b | ||
|
|
7eeb11261b | ||
|
|
a0fc83b617 | ||
|
|
fbc81459ee | ||
|
|
7d53e07e90 | ||
|
|
e83c31b89c | ||
|
|
ca08f97336 | ||
|
|
bd1e23dad4 | ||
|
|
b22f3d2743 | ||
|
|
23ed4e9849 | ||
|
|
4bc26b824f | ||
|
|
d5b0b2ad02 | ||
|
|
3fa3ece655 | ||
|
|
87fb62d772 | ||
|
|
ce9887ef19 | ||
|
|
dcd4555027 | ||
|
|
b11ded8756 | ||
|
|
28b33b67f8 | ||
|
|
cb7c84293d | ||
|
|
83c6346114 | ||
|
|
eef5fdc29b | ||
|
|
84d319867c | ||
|
|
83c69f895c | ||
|
|
826d629d98 | ||
|
|
6e8f13089e | ||
|
|
632b11ef2b | ||
|
|
c8f7497bf3 | ||
|
|
7dc19b8127 | ||
|
|
a3bca2abb4 | ||
|
|
c19509944b | ||
|
|
076686bc04 | ||
|
|
1aea60880a | ||
|
|
9e5cadd8d2 | ||
|
|
11c03d8a08 | ||
|
|
ff113dfcad | ||
|
|
fe9fe268c9 | ||
|
|
71a45e5cd9 | ||
|
|
f0c42d3707 | ||
|
|
3c31839ee2 | ||
|
|
3ddc4397de | ||
|
|
bf0cc50ded | ||
|
|
99d4b5d62f |
2
.github/workflows/build_nupkg.yml
vendored
2
.github/workflows/build_nupkg.yml
vendored
@@ -16,7 +16,7 @@ jobs:
|
||||
- name: Setup .NET
|
||||
uses: actions/setup-dotnet@v4
|
||||
with:
|
||||
dotnet-version: 8.0.x
|
||||
dotnet-version: 9.0.x
|
||||
|
||||
- name: Restore dependencies
|
||||
run: dotnet restore
|
||||
|
||||
2
.github/workflows/check_pr.yml
vendored
2
.github/workflows/check_pr.yml
vendored
@@ -11,7 +11,7 @@ jobs:
|
||||
- name: Setup .NET
|
||||
uses: actions/setup-dotnet@v4
|
||||
with:
|
||||
dotnet-version: 8.0.x
|
||||
dotnet-version: 9.0.x
|
||||
|
||||
- name: Build
|
||||
run: dotnet build
|
||||
|
||||
30
README.MD
30
README.MD
@@ -1,13 +1,33 @@
|
||||
# SabreTools.Hashing
|
||||
|
||||
This library comprises of methods and helpers to simplify the process of getting checksums and hashes from both files and streams. See the following table for information about where each of the various components comes from:
|
||||
This library comprises of methods and helpers to simplify the process of getting checksums and hashes from both files and streams.
|
||||
|
||||
## Internal Implementations
|
||||
|
||||
All hash and checksum types here have been written to ensure compatibility across all .NET versions. Some may have been adapted to ensure this compatibility. These can be treated as reference implementations, not always optimized.
|
||||
|
||||
| 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 |
|
||||
| Fletcher | 16-, 32-, and 64-bit variants |
|
||||
| FNV | 32-, and 64-bit variants; 0, 1, and 1a algorithms |
|
||||
| Message Digest | MD2 and MD4 only |
|
||||
| RIPEMD | 128-, 160-, 256-, and 320-bit variants |
|
||||
| Tiger | 128-, 160-, and 192-bit variants; 3- and 4-pass; `0x01` and `0x80` (Tiger2) pad-initialized |
|
||||
| xxHash | xxHash-32 and xxHash-64 only |
|
||||
|
||||
## External Implementations
|
||||
|
||||
External implementations of hash and checksum types may not be compatible with all .NET versions. Please see the table below for more information about support.
|
||||
|
||||
| Source | Hash / Checksum Types | Notes |
|
||||
| --- | --- | --- |
|
||||
| [Aaru.Checksums](https://github.com/aaru-dps/Aaru.Checksums) | SpamSum | Some code tweaks made to support older .NET versions |
|
||||
| [Compress](https://github.com/RomVault/RVWorld/tree/master/Compress) | N/A | Used for threaded hashing |
|
||||
| [CRC32 / OptimizedCRC](https://gitlab.com/eugene77/CRC32) | CRC-32 | Used in `net20`, `net35`, `net40`, and `net452` |
|
||||
| [System.IO.Hashing](https://www.nuget.org/packages/System.IO.Hashing) | CRC-32, CRC-64, xxHash32, xxHash64, XXH3, XXH128 | Used in `net462` and above |
|
||||
| [System.Security.Cryptography](https://learn.microsoft.com/en-us/dotnet/api/system.security.cryptography) | MD5, SHA-1, SHA-256, SHA-384, SHA-512 | Built-in library |
|
||||
| [Blake3.NET](https://github.com/xoofx/Blake3.NET) | BLAKE3 | Used in `net7.0` and above |
|
||||
| [System.IO.Hashing](https://www.nuget.org/packages/System.IO.Hashing) | XXH3, XXH128 | Used in `net462` and above |
|
||||
| [System.Security.Cryptography](https://learn.microsoft.com/en-us/dotnet/api/system.security.cryptography) | MD5, SHA-1, SHA-256, SHA-384, SHA-512, SHA3-256, SHA3-384, SHA3-512, SHAKE128, SHAKE256 | Built-in library; SHA3-256, SHA3-384, SHA3-512, SHAKE128, and SHAKE256 are `net8.0` and above only for [supported platforms](https://learn.microsoft.com/en-us/dotnet/standard/security/cross-platform-cryptography) |
|
||||
|
||||
**Note:** If all you care about is performance, I encourage you to forego this library and use the ones listed above directly instead.
|
||||
|
||||
Find the link to the Nuget package [here](https://www.nuget.org/packages/SabreTools.Hashing).
|
||||
|
||||
58
SabreTools.Hashing.Test/CompressedStreamTests.cs
Normal file
58
SabreTools.Hashing.Test/CompressedStreamTests.cs
Normal file
@@ -0,0 +1,58 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.IO.Compression;
|
||||
using Xunit;
|
||||
|
||||
namespace SabreTools.Hashing.Test
|
||||
{
|
||||
public class CompressedStreamTests
|
||||
{
|
||||
/// <summary>
|
||||
/// Path to PKZIP archive containing a single compressed file to hash
|
||||
/// </summary>
|
||||
private static readonly string _singleGzipFilePath
|
||||
= Path.Combine(Environment.CurrentDirectory, "TestData", "file-to-hash.bin.gz");
|
||||
|
||||
/// <summary>
|
||||
/// Path to PKZIP archive containing a single compressed file to hash
|
||||
/// </summary>
|
||||
private static readonly string _singleZipFilePath
|
||||
= Path.Combine(Environment.CurrentDirectory, "TestData", "file-to-hash.zip");
|
||||
|
||||
/// <summary>
|
||||
/// Path to PKZIP archive containing a multiple compressed files to hash
|
||||
/// </summary>
|
||||
private static readonly string _multiZipFilePath
|
||||
= Path.Combine(Environment.CurrentDirectory, "TestData", "file-to-hash-multi.zip");
|
||||
|
||||
[Fact]
|
||||
public void GetSingleGzipStreamHashesTest()
|
||||
{
|
||||
var gzipStream = new GZipStream(File.OpenRead(_singleGzipFilePath), CompressionMode.Decompress);
|
||||
var hashDict = HashTool.GetStreamHashes(gzipStream);
|
||||
TestHelper.ValidateHashes(hashDict);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void GetSingleDeflateStreamHashesTest()
|
||||
{
|
||||
var zipFile = ZipFile.OpenRead(_singleZipFilePath);
|
||||
var fileStream = zipFile.Entries[0].Open();
|
||||
var hashDict = HashTool.GetStreamHashes(fileStream);
|
||||
TestHelper.ValidateHashes(hashDict);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void GetMultiDeflateStreamHashesTest()
|
||||
{
|
||||
var zipFile = ZipFile.OpenRead(_multiZipFilePath);
|
||||
|
||||
for (int i = 0; i < zipFile.Entries.Count; i++)
|
||||
{
|
||||
var fileStream = zipFile.Entries[i].Open();
|
||||
var hashDict = HashTool.GetStreamHashes(fileStream);
|
||||
TestHelper.ValidateHashes(hashDict);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,5 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using Xunit;
|
||||
|
||||
@@ -6,25 +7,29 @@ namespace SabreTools.Hashing.Test
|
||||
{
|
||||
public class HashToolTests
|
||||
{
|
||||
private static readonly string _hashFilePath = Path.Combine(Environment.CurrentDirectory, "TestData", "file-to-hash.bin");
|
||||
/// <summary>
|
||||
/// Path to the uncompressed file to hash
|
||||
/// </summary>
|
||||
private static readonly string _hashFilePath
|
||||
= Path.Combine(Environment.CurrentDirectory, "TestData", "file-to-hash.bin");
|
||||
|
||||
#region Known File Information
|
||||
/// <summary>
|
||||
/// Get an array of all hash types
|
||||
/// </summary>
|
||||
public static List<object[]> AllHashTypes
|
||||
{
|
||||
get
|
||||
{
|
||||
var values = Enum.GetValues(typeof(HashType));
|
||||
var set = new List<object[]>();
|
||||
foreach (var value in values)
|
||||
{
|
||||
set.Add([value]);
|
||||
}
|
||||
|
||||
private const long _hashFileSize = 125;
|
||||
private const string _crc32 = "ba02a660";
|
||||
private const string _crc64 = "a0e0009c18b5338d";
|
||||
private const string _md5 = "b722871eaa950016296184d026c5dec9";
|
||||
private const string _sha1 = "eea1ee2d801d830c4bdad4df3c8da6f9f52d1a9f";
|
||||
private const string _sha256 = "fdb02dee8c319c52087382c45f099c90d0b6cc824850aff28c1bfb2884b7b855";
|
||||
private const string _sha384 = "e276c49618fff25bc1fe2e0659cd0ef0e7c1186563b063e07c52323b9899f3ce9b091be04d6208444b3ef1265e879074";
|
||||
private const string _sha512 = "15d69514eb628c2403e945a7cafd1d27e557f6e336c69b63ea17e7ed9d256cc374ee662f09305836d6de37fdae59d83883b982aa8446e4ff26346b6b6b50b240";
|
||||
private const string _spamsum = "3:hMCPQCE6AFQxWyENFACBE+rW6Tj7SMQmKozr9MVERkL:hZRdxZENFs+rPSromekL";
|
||||
private const string _xxhash32 = "8e331daa";
|
||||
private const string _xxhash64 = "082bf6f0a49e1e18";
|
||||
private const string _xxhash3 = "040474eb0eda9ff2";
|
||||
private const string _xxhash128 = "d934b4b4a5e1e11baeef8012fbcd11e8";
|
||||
|
||||
#endregion
|
||||
return set;
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void GetStandardHashesTest()
|
||||
@@ -32,59 +37,33 @@ namespace SabreTools.Hashing.Test
|
||||
bool gotHashes = HashTool.GetStandardHashes(_hashFilePath, out long actualSize, out string? crc32, out string? md5, out string? sha1);
|
||||
|
||||
Assert.True(gotHashes);
|
||||
Assert.Equal(_hashFileSize, actualSize);
|
||||
Assert.Equal(_crc32, crc32);
|
||||
Assert.Equal(_md5, md5);
|
||||
Assert.Equal(_sha1, sha1);
|
||||
TestHelper.ValidateSize(actualSize);
|
||||
TestHelper.ValidateHash(HashType.CRC32, crc32);
|
||||
TestHelper.ValidateHash(HashType.MD5, md5);
|
||||
TestHelper.ValidateHash(HashType.SHA1, sha1);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void GetFileHashesTest()
|
||||
public void GetFileHashesParallelTest()
|
||||
{
|
||||
var hashDict = HashTool.GetFileHashes(_hashFilePath);
|
||||
TestHelper.ValidateHashes(hashDict);
|
||||
}
|
||||
|
||||
Assert.NotNull(hashDict);
|
||||
Assert.Equal(_crc32, hashDict![HashType.CRC32]);
|
||||
#if NET462_OR_GREATER || NETCOREAPP
|
||||
Assert.Equal(_crc64, hashDict[HashType.CRC64]);
|
||||
#endif
|
||||
Assert.Equal(_md5, hashDict[HashType.MD5]);
|
||||
Assert.Equal(_sha1, hashDict[HashType.SHA1]);
|
||||
Assert.Equal(_sha256, hashDict[HashType.SHA256]);
|
||||
Assert.Equal(_sha384, hashDict[HashType.SHA384]);
|
||||
Assert.Equal(_sha512, hashDict[HashType.SHA512]);
|
||||
Assert.Equal(_spamsum, hashDict[HashType.SpamSum]);
|
||||
#if NET462_OR_GREATER || NETCOREAPP
|
||||
Assert.Equal(_xxhash32, hashDict[HashType.XxHash32]);
|
||||
Assert.Equal(_xxhash64, hashDict[HashType.XxHash64]);
|
||||
Assert.Equal(_xxhash3, hashDict[HashType.XxHash3]);
|
||||
Assert.Equal(_xxhash128, hashDict[HashType.XxHash128]);
|
||||
#endif
|
||||
[Theory]
|
||||
[MemberData(nameof(AllHashTypes))]
|
||||
public void GetFileHashesSerialTest(HashType hashType)
|
||||
{
|
||||
var hashValue = HashTool.GetFileHash(_hashFilePath, hashType);
|
||||
TestHelper.ValidateHash(hashType, hashValue);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void GetFileHashesAndSizeTest()
|
||||
{
|
||||
var hashDict = HashTool.GetFileHashesAndSize(_hashFilePath, out long actualSize);
|
||||
|
||||
Assert.Equal(_hashFileSize, actualSize);
|
||||
Assert.NotNull(hashDict);
|
||||
Assert.Equal(_crc32, hashDict![HashType.CRC32]);
|
||||
#if NET462_OR_GREATER || NETCOREAPP
|
||||
Assert.Equal(_crc64, hashDict[HashType.CRC64]);
|
||||
#endif
|
||||
Assert.Equal(_md5, hashDict[HashType.MD5]);
|
||||
Assert.Equal(_sha1, hashDict[HashType.SHA1]);
|
||||
Assert.Equal(_sha256, hashDict[HashType.SHA256]);
|
||||
Assert.Equal(_sha384, hashDict[HashType.SHA384]);
|
||||
Assert.Equal(_sha512, hashDict[HashType.SHA512]);
|
||||
Assert.Equal(_spamsum, hashDict[HashType.SpamSum]);
|
||||
#if NET462_OR_GREATER || NETCOREAPP
|
||||
Assert.Equal(_xxhash32, hashDict[HashType.XxHash32]);
|
||||
Assert.Equal(_xxhash64, hashDict[HashType.XxHash64]);
|
||||
Assert.Equal(_xxhash3, hashDict[HashType.XxHash3]);
|
||||
Assert.Equal(_xxhash128, hashDict[HashType.XxHash128]);
|
||||
#endif
|
||||
TestHelper.ValidateSize(actualSize);
|
||||
TestHelper.ValidateHashes(hashDict);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
@@ -92,24 +71,7 @@ namespace SabreTools.Hashing.Test
|
||||
{
|
||||
byte[] fileBytes = File.ReadAllBytes(_hashFilePath);
|
||||
var hashDict = HashTool.GetByteArrayHashes(fileBytes);
|
||||
|
||||
Assert.NotNull(hashDict);
|
||||
Assert.Equal(_crc32, hashDict![HashType.CRC32]);
|
||||
#if NET462_OR_GREATER || NETCOREAPP
|
||||
Assert.Equal(_crc64, hashDict[HashType.CRC64]);
|
||||
#endif
|
||||
Assert.Equal(_md5, hashDict[HashType.MD5]);
|
||||
Assert.Equal(_sha1, hashDict[HashType.SHA1]);
|
||||
Assert.Equal(_sha256, hashDict[HashType.SHA256]);
|
||||
Assert.Equal(_sha384, hashDict[HashType.SHA384]);
|
||||
Assert.Equal(_sha512, hashDict[HashType.SHA512]);
|
||||
Assert.Equal(_spamsum, hashDict[HashType.SpamSum]);
|
||||
#if NET462_OR_GREATER || NETCOREAPP
|
||||
Assert.Equal(_xxhash32, hashDict[HashType.XxHash32]);
|
||||
Assert.Equal(_xxhash64, hashDict[HashType.XxHash64]);
|
||||
Assert.Equal(_xxhash3, hashDict[HashType.XxHash3]);
|
||||
Assert.Equal(_xxhash128, hashDict[HashType.XxHash128]);
|
||||
#endif
|
||||
TestHelper.ValidateHashes(hashDict);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
@@ -117,24 +79,7 @@ namespace SabreTools.Hashing.Test
|
||||
{
|
||||
var fileStream = File.OpenRead(_hashFilePath);
|
||||
var hashDict = HashTool.GetStreamHashes(fileStream);
|
||||
|
||||
Assert.NotNull(hashDict);
|
||||
Assert.Equal(_crc32, hashDict![HashType.CRC32]);
|
||||
#if NET462_OR_GREATER || NETCOREAPP
|
||||
Assert.Equal(_crc64, hashDict[HashType.CRC64]);
|
||||
#endif
|
||||
Assert.Equal(_md5, hashDict[HashType.MD5]);
|
||||
Assert.Equal(_sha1, hashDict[HashType.SHA1]);
|
||||
Assert.Equal(_sha256, hashDict[HashType.SHA256]);
|
||||
Assert.Equal(_sha384, hashDict[HashType.SHA384]);
|
||||
Assert.Equal(_sha512, hashDict[HashType.SHA512]);
|
||||
Assert.Equal(_spamsum, hashDict[HashType.SpamSum]);
|
||||
#if NET462_OR_GREATER || NETCOREAPP
|
||||
Assert.Equal(_xxhash32, hashDict[HashType.XxHash32]);
|
||||
Assert.Equal(_xxhash64, hashDict[HashType.XxHash64]);
|
||||
Assert.Equal(_xxhash3, hashDict[HashType.XxHash3]);
|
||||
Assert.Equal(_xxhash128, hashDict[HashType.XxHash128]);
|
||||
#endif
|
||||
TestHelper.ValidateHashes(hashDict);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,50 +1,40 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFrameworks>net452;net462;net6.0;net7.0;net8.0</TargetFrameworks>
|
||||
<CheckEolTargetFramework>false</CheckEolTargetFramework>
|
||||
<IsPackable>false</IsPackable>
|
||||
<LangVersion>latest</LangVersion>
|
||||
<Nullable>enable</Nullable>
|
||||
<SuppressTfmSupportBuildWarnings>true</SuppressTfmSupportBuildWarnings>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<TargetFrameworks>net462;net472;net48;net6.0;net7.0;net8.0;net9.0</TargetFrameworks>
|
||||
<CheckEolTargetFramework>false</CheckEolTargetFramework>
|
||||
<IsPackable>false</IsPackable>
|
||||
<LangVersion>latest</LangVersion>
|
||||
<Nullable>enable</Nullable>
|
||||
<SuppressTfmSupportBuildWarnings>true</SuppressTfmSupportBuildWarnings>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<None Remove="TestData\*" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Remove="TestData\*" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Content Include="TestData\*">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Content Include="TestData\*">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
</ItemGroup>
|
||||
|
||||
<!-- Support for old .NET versions -->
|
||||
<ItemGroup Condition="$(TargetFramework.StartsWith(`net452`))">
|
||||
<PackageReference Include="xunit" Version="2.4.1" />
|
||||
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.1">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
|
||||
</PackageReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup Condition="$(TargetFramework.StartsWith(`net462`)) OR $(TargetFramework.StartsWith(`net6`)) OR $(TargetFramework.StartsWith(`net7`)) OR $(TargetFramework.StartsWith(`net8`))">
|
||||
<PackageReference Include="xunit" Version="2.6.2" />
|
||||
<PackageReference Include="xunit.runner.visualstudio" Version="2.5.4">
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
</PackageReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="coverlet.collector" Version="6.0.2">
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.11.1" />
|
||||
<PackageReference Include="System.IO.Compression" Version="4.3.0" />
|
||||
<PackageReference Include="xunit" Version="2.9.2" />
|
||||
<PackageReference Include="xunit.runner.visualstudio" Version="2.8.2">
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
</PackageReference>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="coverlet.collector" Version="6.0.0">
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.8.0" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\SabreTools.Hashing\SabreTools.Hashing.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\SabreTools.Hashing\SabreTools.Hashing.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
</Project>
|
||||
BIN
SabreTools.Hashing.Test/TestData/file-to-hash-multi.zip
Normal file
BIN
SabreTools.Hashing.Test/TestData/file-to-hash-multi.zip
Normal file
Binary file not shown.
BIN
SabreTools.Hashing.Test/TestData/file-to-hash.bin.gz
Normal file
BIN
SabreTools.Hashing.Test/TestData/file-to-hash.bin.gz
Normal file
Binary file not shown.
BIN
SabreTools.Hashing.Test/TestData/file-to-hash.zip
Normal file
BIN
SabreTools.Hashing.Test/TestData/file-to-hash.zip
Normal file
Binary file not shown.
245
SabreTools.Hashing.Test/TestHelper.cs
Normal file
245
SabreTools.Hashing.Test/TestHelper.cs
Normal file
@@ -0,0 +1,245 @@
|
||||
using System.Collections.Generic;
|
||||
using Xunit;
|
||||
|
||||
namespace SabreTools.Hashing.Test
|
||||
{
|
||||
/// <summary>
|
||||
/// Helper class for tests
|
||||
/// </summary>
|
||||
/// CRC values confirmed with <see href="https://emn178.github.io/online-tools/crc/"/>
|
||||
internal static class TestHelper
|
||||
{
|
||||
#region Known File Information
|
||||
|
||||
private const long _hashFileSize = 125;
|
||||
|
||||
private static readonly Dictionary<HashType, string> _knownHashes = new()
|
||||
{
|
||||
{HashType.Adler32, "08562d95"},
|
||||
|
||||
#if NET7_0_OR_GREATER
|
||||
{HashType.BLAKE3, "d4bd7ca6f1ebea9580d9381106b248eb5b6069170d0bfd00b17d659fcd10dcdc"},
|
||||
#endif
|
||||
|
||||
{HashType.CRC1_ZERO, "0"},
|
||||
{HashType.CRC1_ONE, "1"},
|
||||
|
||||
{HashType.CRC3_GSM, "4"},
|
||||
{HashType.CRC3_ROHC, "3"},
|
||||
|
||||
{HashType.CRC4_G704, "6"},
|
||||
{HashType.CRC4_INTERLAKEN, "0"},
|
||||
|
||||
{HashType.CRC5_EPCC1G2, "1f"},
|
||||
{HashType.CRC5_G704, "06"},
|
||||
{HashType.CRC5_USB, "0a"},
|
||||
|
||||
{HashType.CRC6_CDMA2000A, "3c"},
|
||||
{HashType.CRC6_CDMA2000B, "12"},
|
||||
{HashType.CRC6_DARC, "0f"},
|
||||
{HashType.CRC6_G704, "09"},
|
||||
{HashType.CRC6_GSM, "21"},
|
||||
|
||||
{HashType.CRC7_MMC, "2f"},
|
||||
{HashType.CRC7_ROHC, "68"},
|
||||
{HashType.CRC7_UMTS, "66"},
|
||||
|
||||
{HashType.CRC8, "fc"},
|
||||
{HashType.CRC8_AUTOSAR, "ca"},
|
||||
{HashType.CRC8_BLUETOOTH, "00"},
|
||||
{HashType.CRC8_CDMA2000, "2d"},
|
||||
{HashType.CRC8_DARC, "35"},
|
||||
{HashType.CRC8_DVBS2, "5c"},
|
||||
{HashType.CRC8_GSMA, "d8"},
|
||||
{HashType.CRC8_GSMB, "f3"},
|
||||
{HashType.CRC8_HITAG, "aa"},
|
||||
{HashType.CRC8_I4321, "a9"},
|
||||
{HashType.CRC8_ICODE, "61"},
|
||||
{HashType.CRC8_LTE, "d7"},
|
||||
{HashType.CRC8_MAXIMDOW, "bd"},
|
||||
{HashType.CRC8_MIFAREMAD, "9b"},
|
||||
{HashType.CRC8_NRSC5, "e2"},
|
||||
{HashType.CRC8_OPENSAFETY, "fc"},
|
||||
{HashType.CRC8_ROHC, "17"},
|
||||
{HashType.CRC8_SAEJ1850, "55"},
|
||||
{HashType.CRC8_SMBUS, "fc"},
|
||||
{HashType.CRC8_TECH3250, "7d"},
|
||||
{HashType.CRC8_WCDMA, "c6"},
|
||||
|
||||
{HashType.CRC10_ATM, "26b"},
|
||||
{HashType.CRC10_CDMA2000, "14f"},
|
||||
{HashType.CRC10_GSM, "0e7"},
|
||||
|
||||
{HashType.CRC11_FLEXRAY, "18b"},
|
||||
{HashType.CRC11_UMTS, "347"},
|
||||
|
||||
{HashType.CRC12_CDMA2000, "f9c"},
|
||||
{HashType.CRC12_DECT, "d62"},
|
||||
{HashType.CRC12_GSM, "975"},
|
||||
{HashType.CRC12_UMTS, "46b"},
|
||||
|
||||
{HashType.CRC13_BBC, "074f"},
|
||||
|
||||
{HashType.CRC14_DARC, "0add"},
|
||||
{HashType.CRC14_GSM, "0c7d"},
|
||||
|
||||
{HashType.CRC15_CAN, "66c3"},
|
||||
{HashType.CRC15_MPT1327, "013b"},
|
||||
|
||||
{HashType.CRC16, "7573"},
|
||||
{HashType.CRC16_ARC, "7573"},
|
||||
{HashType.CRC16_CDMA2000, "8b5f"},
|
||||
{HashType.CRC16_CMS, "1a37"},
|
||||
{HashType.CRC16_DDS110, "241d"},
|
||||
{HashType.CRC16_DECTR, "7390"},
|
||||
{HashType.CRC16_DECTX, "7391"},
|
||||
{HashType.CRC16_DNP, "4bbb"},
|
||||
{HashType.CRC16_EN13757, "e28b"},
|
||||
{HashType.CRC16_GENIBUS, "b65d"},
|
||||
{HashType.CRC16_GSM, "482d"},
|
||||
{HashType.CRC16_IBM3740, "49a2"},
|
||||
{HashType.CRC16_IBMSDLC, "4f52"},
|
||||
{HashType.CRC16_ISOIEC144433A, "85cd"},
|
||||
{HashType.CRC16_KERMIT, "bed2"},
|
||||
{HashType.CRC16_LJ1200, "3533"},
|
||||
{HashType.CRC16_M17, "5223"},
|
||||
{HashType.CRC16_MAXIMDOW, "8a8c"},
|
||||
{HashType.CRC16_MCRF4XX, "b0ad"},
|
||||
{HashType.CRC16_MODBUS, "9e54"},
|
||||
{HashType.CRC16_NRSC5, "4857"},
|
||||
{HashType.CRC16_OPENSAFETYA, "abcd"},
|
||||
{HashType.CRC16_OPENSAFETYB, "76f4"},
|
||||
{HashType.CRC16_PROFIBUS, "3099"},
|
||||
{HashType.CRC16_RIELLO, "23e0"},
|
||||
{HashType.CRC16_SPIFUJITSU, "f98b"},
|
||||
{HashType.CRC16_T10DIF, "2642"},
|
||||
{HashType.CRC16_TELEDISK, "7e05"},
|
||||
{HashType.CRC16_TMS37157, "dba0"},
|
||||
{HashType.CRC16_UMTS, "fee0"},
|
||||
{HashType.CRC16_USB, "61ab"},
|
||||
{HashType.CRC16_XMODEM, "b7d2"},
|
||||
|
||||
{HashType.CRC17_CANFD, "0706d"},
|
||||
|
||||
{HashType.CRC21_CANFD, "117d4b"},
|
||||
|
||||
{HashType.CRC24_BLE, "2969f2"},
|
||||
{HashType.CRC24_FLEXRAYA, "ce9dc7"},
|
||||
{HashType.CRC24_FLEXRAYB, "0f49d7"},
|
||||
{HashType.CRC24_INTERLAKEN, "fb4725"},
|
||||
{HashType.CRC24_LTEA, "675e55"},
|
||||
{HashType.CRC24_LTEB, "c91203"},
|
||||
{HashType.CRC24_OPENPGP, "0c6012"},
|
||||
{HashType.CRC24_OS9, "610e21"},
|
||||
|
||||
{HashType.CRC30_CDMA, "2ce682b2"},
|
||||
|
||||
{HashType.CRC31_PHILIPS, "247c3cbe"},
|
||||
|
||||
{HashType.CRC32, "ba02a660"},
|
||||
{HashType.CRC32_AIXM, "6174a75a"},
|
||||
{HashType.CRC32_AUTOSAR, "c050428e"},
|
||||
{HashType.CRC32_BASE91D, "e741ba25"},
|
||||
{HashType.CRC32_BZIP2, "18aa4603"},
|
||||
{HashType.CRC32_CDROMEDC, "b8ced467"},
|
||||
{HashType.CRC32_CKSUM, "f27b3c27"},
|
||||
{HashType.CRC32_ISCSI, "544d37db"},
|
||||
{HashType.CRC32_ISOHDLC, "ba02a660"},
|
||||
{HashType.CRC32_JAMCRC, "45fd599f"},
|
||||
{HashType.CRC32_MEF, "d9d98444"},
|
||||
{HashType.CRC32_MPEG2, "e755b9fc"},
|
||||
{HashType.CRC32_XFER, "55bdf222"},
|
||||
|
||||
{HashType.CRC40_GSM, "c9843306eb"},
|
||||
|
||||
{HashType.CRC64, "8d33b5189c00e0a0"},
|
||||
{HashType.CRC64_ECMA182, "8d33b5189c00e0a0"},
|
||||
{HashType.CRC64_GOISO, "6c3bf747ccfa1e3b"},
|
||||
{HashType.CRC64_MS, "799edc0db430d7be"},
|
||||
{HashType.CRC64_NVME, "9242023bbcf6bbf9"},
|
||||
{HashType.CRC64_REDIS, "408dab12b9f45dad"},
|
||||
{HashType.CRC64_WE, "91812be748f941c4"},
|
||||
{HashType.CRC64_XZ, "fb49044e8331f6e5"},
|
||||
|
||||
{HashType.Fletcher16, "46c1"},
|
||||
{HashType.Fletcher32, "073f2d94"},
|
||||
{HashType.Fletcher64, "000b073400002d94"},
|
||||
|
||||
{HashType.FNV0_32, "33d28b00"},
|
||||
{HashType.FNV0_64, "778e818addd23280"},
|
||||
{HashType.FNV1_32, "ac09cbeb"},
|
||||
{HashType.FNV1_64, "23229308c1f9252b"},
|
||||
{HashType.FNV1a_32, "9086769b"},
|
||||
{HashType.FNV1a_64, "399dd1cd965b73db"},
|
||||
|
||||
{HashType.MD2, "362e1a6931668e6a9de5c159c52c71b5"},
|
||||
{HashType.MD4, "61bef59d7a754874fccbd67b4ec2fb10"},
|
||||
{HashType.MD5, "b722871eaa950016296184d026c5dec9"},
|
||||
|
||||
{HashType.RIPEMD128, "6356cc18225245de3ca9afcb4fa22ce6"},
|
||||
{HashType.RIPEMD160, "346361e1d7fdb836650cecdb842b0dbe660eed66"},
|
||||
{HashType.RIPEMD256, "c2fe11922529651bc615be3d8a296820b6681ecaed5ce051439c86bf3d942276"},
|
||||
{HashType.RIPEMD320, "a523bec87b0738f89d8ae5cf0edd3ee9c7b9811f1051e32893e32e820db33841b9d5042e738d20c9"},
|
||||
|
||||
{HashType.SHA1, "eea1ee2d801d830c4bdad4df3c8da6f9f52d1a9f"},
|
||||
{HashType.SHA256, "fdb02dee8c319c52087382c45f099c90d0b6cc824850aff28c1bfb2884b7b855"},
|
||||
{HashType.SHA384, "e276c49618fff25bc1fe2e0659cd0ef0e7c1186563b063e07c52323b9899f3ce9b091be04d6208444b3ef1265e879074"},
|
||||
{HashType.SHA512, "15d69514eb628c2403e945a7cafd1d27e557f6e336c69b63ea17e7ed9d256cc374ee662f09305836d6de37fdae59d83883b982aa8446e4ff26346b6b6b50b240"},
|
||||
#if NET8_0_OR_GREATER
|
||||
{HashType.SHA3_256, "1d76459e68c865b5911ada5104067cc604c5c60b345c4e81b3905e916a43c868"},
|
||||
{HashType.SHA3_384, "1bcbed87b73f25c0adf486c3afbf0ea3105763c387af3f8b2bd79b0a1964d42832b1d7c6a2225f9153ead26f442e8b67"},
|
||||
{HashType.SHA3_512, "89852144df37c58d01f5912124f1942dd00bac0346eb3971943416699c3094cff087fb42c356019c3d91f8e8f55b9254c8caec48e9414af6817297d06725ffeb"},
|
||||
{HashType.SHAKE128, "e5f88d0db79a71c39490beb9ebac21eaf4a5d6368438fca20f5e4ce77cfee9aa"},
|
||||
{HashType.SHAKE256, "24d9e83198bbc7baf4dcd293bfc35ae3fff05399786c37318f1b1ef85f41970c66926f8a2a1f912d96e2d8e45535af88a301a1c200697437c1a65d7e980344bc"},
|
||||
#endif
|
||||
|
||||
{HashType.SpamSum, "3:hMCPQCE6AFQxWyENFACBE+rW6Tj7SMQmKozr9MVERkL:hZRdxZENFs+rPSromekL"},
|
||||
|
||||
{HashType.Tiger128_3, "afc7ac1c3c031b675562f917b59f0885"},
|
||||
{HashType.Tiger128_4, "e7609126923009f733cd0fcbc5a733fa"},
|
||||
{HashType.Tiger160_3, "afc7ac1c3c031b675562f917b59f088533405e1a"},
|
||||
{HashType.Tiger160_4, "e7609126923009f733cd0fcbc5a733fa4f4ccf7a"},
|
||||
{HashType.Tiger192_3, "afc7ac1c3c031b675562f917b59f088533405e1a2f72912d"},
|
||||
{HashType.Tiger192_4, "e7609126923009f733cd0fcbc5a733fa4f4ccf7ab7c0e2a3"},
|
||||
{HashType.Tiger2_128_3, "b26271774e66519b1c746f210e0be05c"},
|
||||
{HashType.Tiger2_128_4, "f1df540d3f2521b87a957c9b2b00fc7c"},
|
||||
{HashType.Tiger2_160_3, "b26271774e66519b1c746f210e0be05c4fd9efde"},
|
||||
{HashType.Tiger2_160_4, "f1df540d3f2521b87a957c9b2b00fc7c589306dc"},
|
||||
{HashType.Tiger2_192_3, "b26271774e66519b1c746f210e0be05c4fd9efde26e46e89"},
|
||||
{HashType.Tiger2_192_4, "f1df540d3f2521b87a957c9b2b00fc7c589306dcf094acb5"},
|
||||
|
||||
{HashType.XxHash32, "aa1d338e"},
|
||||
{HashType.XxHash64, "181e9ea4f0f62b08"},
|
||||
#if NET462_OR_GREATER || NETCOREAPP
|
||||
{HashType.XxHash3, "f29fda0eeb740404"},
|
||||
{HashType.XxHash128, "e811cdfb1280efae1be1e1a5b4b434d9"},
|
||||
#endif
|
||||
};
|
||||
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// Validate the hashes in a hash dictionary
|
||||
/// </summary>
|
||||
public static void ValidateHashes(Dictionary<HashType, string?>? hashDict)
|
||||
{
|
||||
Assert.NotNull(hashDict);
|
||||
foreach (var hashType in _knownHashes.Keys)
|
||||
{
|
||||
ValidateHash(hashType, hashDict![hashType]);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Validate a single hash
|
||||
/// </summary>
|
||||
public static void ValidateHash(HashType hashType, string? hashValue)
|
||||
=> Assert.Equal(_knownHashes[hashType], hashValue);
|
||||
|
||||
/// <summary>
|
||||
/// Validate the file size
|
||||
/// </summary>
|
||||
public static void ValidateSize(long fileSize)
|
||||
=> Assert.Equal(_hashFileSize, fileSize);
|
||||
}
|
||||
}
|
||||
49
SabreTools.Hashing.Test/ZeroHashTests.cs
Normal file
49
SabreTools.Hashing.Test/ZeroHashTests.cs
Normal file
@@ -0,0 +1,49 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Xunit;
|
||||
|
||||
namespace SabreTools.Hashing.Test
|
||||
{
|
||||
public class ZeroHashTests
|
||||
{
|
||||
/// <summary>
|
||||
/// Get an array of all hash types
|
||||
/// </summary>
|
||||
public static List<object[]> AllHashTypes
|
||||
{
|
||||
get
|
||||
{
|
||||
var values = Enum.GetValues(typeof(HashType));
|
||||
var set = new List<object[]>();
|
||||
foreach (var value in values)
|
||||
{
|
||||
set.Add([value]);
|
||||
}
|
||||
|
||||
return set;
|
||||
}
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[MemberData(nameof(AllHashTypes))]
|
||||
public void GetZeroByteHashes(HashType hashType)
|
||||
{
|
||||
var expected = ZeroHash.GetBytes(hashType);
|
||||
var actual = HashTool.GetByteArrayHashArray([], hashType);
|
||||
|
||||
Assert.NotNull(actual);
|
||||
Assert.Equal(expected.Length, actual.Length);
|
||||
Assert.True(actual.SequenceEqual(expected));
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[MemberData(nameof(AllHashTypes))]
|
||||
public void GetZeroStringHashes(HashType hashType)
|
||||
{
|
||||
var expected = ZeroHash.GetString(hashType);
|
||||
var actual = HashTool.GetByteArrayHash([], hashType);
|
||||
Assert.Equal(expected, actual);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -65,7 +65,7 @@ internal sealed class SpamSumContext : IChecksum
|
||||
const uint FUZZY_MAX_RESULT = 2 * SPAMSUM_LENGTH + 20;
|
||||
|
||||
//"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
||||
#if NET20 || NET35 || NET40
|
||||
#if NET20 || NET35 || NET40 || NET452
|
||||
readonly byte[] _b64 = Encoding.UTF8.GetBytes("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/");
|
||||
#else
|
||||
readonly byte[] _b64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"u8.ToArray();
|
||||
|
||||
139
SabreTools.Hashing/Checksum/Adler32.cs
Normal file
139
SabreTools.Hashing/Checksum/Adler32.cs
Normal file
@@ -0,0 +1,139 @@
|
||||
using System;
|
||||
using static SabreTools.Hashing.Checksum.Constants;
|
||||
|
||||
namespace SabreTools.Hashing.Checksum
|
||||
{
|
||||
/// <see href="https://github.com/madler/zlib/blob/v1.2.11/adler32.c"/>
|
||||
public class Adler32 : ChecksumBase<uint>
|
||||
{
|
||||
public Adler32()
|
||||
{
|
||||
Reset();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reset the internal hashing state
|
||||
/// </summary>
|
||||
public override void Reset()
|
||||
{
|
||||
_hash = 1;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override void TransformBlock(byte[] data, int offset, int length)
|
||||
{
|
||||
// Split Adler-32 into component sums
|
||||
uint sum2 = (_hash >> 16) & 0xffff;
|
||||
_hash &= 0xffff;
|
||||
|
||||
// In case user likes doing a byte at a time, keep it fast
|
||||
if (length == 1)
|
||||
{
|
||||
_hash += data[offset];
|
||||
if (_hash >= A32BASE)
|
||||
_hash -= A32BASE;
|
||||
|
||||
sum2 += _hash;
|
||||
if (sum2 >= A32BASE)
|
||||
sum2 -= A32BASE;
|
||||
|
||||
_hash |= sum2 << 16;
|
||||
return;
|
||||
}
|
||||
|
||||
// In case short lengths are provided, keep it somewhat fast
|
||||
if (length < 16)
|
||||
{
|
||||
while (length-- > 0)
|
||||
{
|
||||
_hash += data[offset]++;
|
||||
sum2 += _hash;
|
||||
}
|
||||
|
||||
if (_hash >= A32BASE)
|
||||
_hash -= A32BASE;
|
||||
|
||||
// Only added so many BASE's
|
||||
sum2 %= A32BASE;
|
||||
_hash |= sum2 << 16;
|
||||
return;
|
||||
}
|
||||
|
||||
// Do length NMAX blocks -- requires just one modulo operation
|
||||
while (length >= A32NMAX)
|
||||
{
|
||||
// NMAX is divisible by 16
|
||||
length -= A32NMAX;
|
||||
uint n = A32NMAX / 16;
|
||||
do
|
||||
{
|
||||
_hash += data[offset + 0]; sum2 += _hash;
|
||||
_hash += data[offset + 1]; sum2 += _hash;
|
||||
_hash += data[offset + 2]; sum2 += _hash;
|
||||
_hash += data[offset + 3]; sum2 += _hash;
|
||||
_hash += data[offset + 4]; sum2 += _hash;
|
||||
_hash += data[offset + 5]; sum2 += _hash;
|
||||
_hash += data[offset + 6]; sum2 += _hash;
|
||||
_hash += data[offset + 7]; sum2 += _hash;
|
||||
_hash += data[offset + 8]; sum2 += _hash;
|
||||
_hash += data[offset + 9]; sum2 += _hash;
|
||||
_hash += data[offset + 10]; sum2 += _hash;
|
||||
_hash += data[offset + 11]; sum2 += _hash;
|
||||
_hash += data[offset + 12]; sum2 += _hash;
|
||||
_hash += data[offset + 13]; sum2 += _hash;
|
||||
_hash += data[offset + 14]; sum2 += _hash;
|
||||
_hash += data[offset + 15]; sum2 += _hash;
|
||||
|
||||
offset += 16;
|
||||
} while (--n > 0);
|
||||
}
|
||||
|
||||
// Do remaining bytes (less than NMAX, still just one modulo)
|
||||
if (length > 0)
|
||||
{
|
||||
// Avoid modulos if none remaining
|
||||
while (length >= 16)
|
||||
{
|
||||
length -= 16;
|
||||
|
||||
_hash += data[offset + 0]; sum2 += _hash;
|
||||
_hash += data[offset + 1]; sum2 += _hash;
|
||||
_hash += data[offset + 2]; sum2 += _hash;
|
||||
_hash += data[offset + 3]; sum2 += _hash;
|
||||
_hash += data[offset + 4]; sum2 += _hash;
|
||||
_hash += data[offset + 5]; sum2 += _hash;
|
||||
_hash += data[offset + 6]; sum2 += _hash;
|
||||
_hash += data[offset + 7]; sum2 += _hash;
|
||||
_hash += data[offset + 8]; sum2 += _hash;
|
||||
_hash += data[offset + 9]; sum2 += _hash;
|
||||
_hash += data[offset + 10]; sum2 += _hash;
|
||||
_hash += data[offset + 11]; sum2 += _hash;
|
||||
_hash += data[offset + 12]; sum2 += _hash;
|
||||
_hash += data[offset + 13]; sum2 += _hash;
|
||||
_hash += data[offset + 14]; sum2 += _hash;
|
||||
_hash += data[offset + 15]; sum2 += _hash;
|
||||
|
||||
offset += 16;
|
||||
}
|
||||
|
||||
while (length-- > 0)
|
||||
{
|
||||
_hash += data[offset++];
|
||||
sum2 += _hash;
|
||||
}
|
||||
|
||||
_hash %= A32BASE;
|
||||
sum2 %= A32BASE;
|
||||
}
|
||||
|
||||
// Return recombined sums
|
||||
_hash |= sum2 << 16;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override byte[] Finalize()
|
||||
{
|
||||
return BitConverter.GetBytes(_hash);
|
||||
}
|
||||
}
|
||||
}
|
||||
22
SabreTools.Hashing/Checksum/BitOperations.cs
Normal file
22
SabreTools.Hashing/Checksum/BitOperations.cs
Normal file
@@ -0,0 +1,22 @@
|
||||
namespace SabreTools.Hashing.Checksum
|
||||
{
|
||||
internal static class BitOperations
|
||||
{
|
||||
/// <summary>
|
||||
/// Clamp a value to a certain bit width and convert to a byte array
|
||||
/// </summary>
|
||||
public static byte[] ClampValueToBytes(ulong value, int bitWidth)
|
||||
{
|
||||
value &= ulong.MaxValue >> (64 - bitWidth);
|
||||
byte[] bytes = new byte[(bitWidth + 7) / 8];
|
||||
|
||||
for (int i = 0; i < bytes.Length; i++)
|
||||
{
|
||||
bytes[i] = (byte)value;
|
||||
value >>= 8;
|
||||
}
|
||||
|
||||
return bytes;
|
||||
}
|
||||
}
|
||||
}
|
||||
60
SabreTools.Hashing/Checksum/ChecksumBase.cs
Normal file
60
SabreTools.Hashing/Checksum/ChecksumBase.cs
Normal file
@@ -0,0 +1,60 @@
|
||||
using System;
|
||||
|
||||
namespace SabreTools.Hashing.Checksum
|
||||
{
|
||||
/// <summary>
|
||||
/// Common base class for Fletcher checksums
|
||||
/// </summary>
|
||||
public abstract class ChecksumBase
|
||||
{
|
||||
/// <summary>
|
||||
/// Hash a block of data and append it to the existing hash
|
||||
/// </summary>
|
||||
/// <param name="data">Byte array representing the data</param>
|
||||
/// <param name="offset">Offset in the byte array to include</param>
|
||||
/// <param name="length">Length of the data to hash</param>
|
||||
public abstract void TransformBlock(byte[] data, int offset, int length);
|
||||
|
||||
/// <summary>
|
||||
/// Finalize the hash and return as a byte array
|
||||
/// </summary>
|
||||
public abstract byte[] Finalize();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Common base class for checksums
|
||||
/// </summary>
|
||||
public abstract class ChecksumBase<T> : ChecksumBase where T : struct
|
||||
{
|
||||
/// <summary>
|
||||
/// The current value of the hash
|
||||
/// </summary>
|
||||
protected T _hash;
|
||||
|
||||
/// <summary>
|
||||
/// Reset the internal hashing state
|
||||
/// </summary>
|
||||
public virtual void Reset()
|
||||
{
|
||||
_hash = default;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override byte[] Finalize()
|
||||
{
|
||||
return _hash switch
|
||||
{
|
||||
short s => BitConverter.GetBytes(s),
|
||||
ushort s => BitConverter.GetBytes(s),
|
||||
|
||||
int i => BitConverter.GetBytes(i),
|
||||
uint i => BitConverter.GetBytes(i),
|
||||
|
||||
long l => BitConverter.GetBytes(l),
|
||||
ulong l => BitConverter.GetBytes(l),
|
||||
|
||||
_ => [],
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
39
SabreTools.Hashing/Checksum/Constants.cs
Normal file
39
SabreTools.Hashing/Checksum/Constants.cs
Normal file
@@ -0,0 +1,39 @@
|
||||
namespace SabreTools.Hashing.Checksum
|
||||
{
|
||||
internal static class Constants
|
||||
{
|
||||
#region Adler-32 / Fletcher-32
|
||||
|
||||
/// <summary>
|
||||
/// Largest prime smaller than 65536
|
||||
/// </summary>
|
||||
public const ushort A32BASE = 65521;
|
||||
|
||||
/// <summary>
|
||||
/// NMAX is the largest n such that 255n(n+1)/2 + (n+1)(<see cref="A32BASE">-1) <= 2^32-1
|
||||
/// </summary>
|
||||
public const ushort A32NMAX = 5552;
|
||||
|
||||
/// <summary>
|
||||
/// Max value for a single half of a Fletcher-32 checksum
|
||||
/// </summary>
|
||||
public const ushort F32BASE = 0xffff;
|
||||
|
||||
/// <summary>
|
||||
/// Max value for a single half of a Fletcher-64 checksum
|
||||
/// </summary>
|
||||
public const uint F64BASE = 0xffffffff;
|
||||
|
||||
#endregion
|
||||
|
||||
#region FNV
|
||||
|
||||
public const uint FNV32Basis = 0x811c9dc5;
|
||||
public const ulong FNV64Basis = 0xcbf29ce484222325;
|
||||
|
||||
public const uint FNV32Prime = 0x01000193;
|
||||
public const ulong FNV64Prime = 0x00000100000001b3;
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
56
SabreTools.Hashing/Checksum/Crc.cs
Normal file
56
SabreTools.Hashing/Checksum/Crc.cs
Normal file
@@ -0,0 +1,56 @@
|
||||
using System;
|
||||
using static SabreTools.Hashing.HashOperations;
|
||||
|
||||
namespace SabreTools.Hashing.Checksum
|
||||
{
|
||||
public class Crc : ChecksumBase<ulong>
|
||||
{
|
||||
/// <summary>
|
||||
/// Definition used to create the runner
|
||||
/// </summary>
|
||||
public readonly CrcDefinition Def;
|
||||
|
||||
/// <summary>
|
||||
/// Table used for calculation steps
|
||||
/// </summary>
|
||||
private readonly CrcTable _table;
|
||||
|
||||
public Crc(CrcDefinition def)
|
||||
{
|
||||
// Check for a valid bit width
|
||||
if (def.Width < 0 || def.Width > 64)
|
||||
throw new ArgumentOutOfRangeException(nameof(def));
|
||||
|
||||
Def = def;
|
||||
_table = new CrcTable(def);
|
||||
_hash = def.ReflectIn ? ReverseBits(def.Init, def.Width) : def.Init;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override void Reset()
|
||||
{
|
||||
_hash = Def.Init;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override void TransformBlock(byte[] data, int offset, int length)
|
||||
=> _table.TransformBlock(ref _hash, data, offset, length);
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override byte[] Finalize()
|
||||
{
|
||||
// Create a copy of the hash
|
||||
ulong localHash = _hash;
|
||||
|
||||
// Handle mutual reflection
|
||||
if (Def.ReflectIn ^ Def.ReflectOut)
|
||||
localHash = ReverseBits(localHash, Def.Width);
|
||||
|
||||
// Handle XOR
|
||||
localHash ^= Def.XorOut;
|
||||
|
||||
// Process the value and return
|
||||
return BitOperations.ClampValueToBytes(localHash, Def.Width);
|
||||
}
|
||||
}
|
||||
}
|
||||
65
SabreTools.Hashing/Checksum/CrcDefinition.cs
Normal file
65
SabreTools.Hashing/Checksum/CrcDefinition.cs
Normal file
@@ -0,0 +1,65 @@
|
||||
namespace SabreTools.Hashing.Checksum
|
||||
{
|
||||
/// <see href="https://reveng.sourceforge.io/crc-catalogue/all.htm#crc.legend"/>
|
||||
public class CrcDefinition
|
||||
{
|
||||
/// <summary>
|
||||
/// The name assigned to the model in this Catalogue.
|
||||
/// </summary>
|
||||
public string? Name { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The number of bit cells in the linear feedback shift register;
|
||||
/// the degree of the generator polynomial, less one.
|
||||
/// </summary>
|
||||
public int Width { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The generator polynomial that sets the feedback tap positions of
|
||||
/// the shift register. poly is written in the hexadecimal, direct
|
||||
/// notation found in MSB-first code. The least significant bit
|
||||
/// corresponds to the inward end of the shift register, and is always
|
||||
/// set. The highest-order term is omitted.
|
||||
/// </summary>
|
||||
public ulong Poly { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The settings of the bit cells at the start of each calculation,
|
||||
/// before reading the first message bit. init is written in the
|
||||
/// hexadecimal, direct notation found in MSB-first code. The least
|
||||
/// significant bit corresponds to the inward end of the shift register.
|
||||
/// </summary>
|
||||
public ulong Init { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// If equal to false, specifies that the characters of the message
|
||||
/// are read bit-by-bit, most significant bit (MSB) first; if equal to
|
||||
/// true, the characters are read bit-by-bit, least significant bit (LSB)
|
||||
/// first. Each sampled message bit is then XORed with the bit being
|
||||
/// simultaneously shifted out of the register at the most significant
|
||||
/// end, and the result is passed to the feedback taps.
|
||||
/// </summary>
|
||||
public bool ReflectIn { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// If equal to false, specifies that the contents of the register after
|
||||
/// reading the last message bit are unreflected before presentation;
|
||||
/// if equal to true, it specifies that they are reflected,
|
||||
/// character-by-character, before presentation. For the purpose of this
|
||||
/// definition, the reflection is performed by swapping the content of
|
||||
/// each cell with that of the cell an equal distance from the opposite
|
||||
/// end of the register; the characters of the CRC are then true images
|
||||
/// of parts of the reflected register, the character containing the
|
||||
/// original MSB always appearing first.
|
||||
/// </summary>
|
||||
public bool ReflectOut { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The XOR value applied to the contents of the register after the last
|
||||
/// message bit has been read and after the optional reflection. xorout
|
||||
/// is written in hexadecimal notation, having the same endianness as
|
||||
/// the CRC such that its true image appears in the characters of the CRC.
|
||||
/// </summary>
|
||||
public ulong XorOut { get; set; }
|
||||
}
|
||||
}
|
||||
333
SabreTools.Hashing/Checksum/CrcTable.cs
Normal file
333
SabreTools.Hashing/Checksum/CrcTable.cs
Normal file
@@ -0,0 +1,333 @@
|
||||
using static SabreTools.Hashing.HashOperations;
|
||||
|
||||
namespace SabreTools.Hashing.Checksum
|
||||
{
|
||||
internal class CrcTable
|
||||
{
|
||||
/// <summary>
|
||||
/// Indicates if CRC should be processed bitwise instead of bytewise
|
||||
/// </summary>
|
||||
private bool Bitwise => _definition.Width < 8;
|
||||
|
||||
/// <summary>
|
||||
/// Number of bits to process at a time
|
||||
/// </summary>
|
||||
private int BitsPerStep => Bitwise ? 1 : 8;
|
||||
|
||||
/// <summary>
|
||||
/// Bit shift based on the CRC width
|
||||
/// </summary>
|
||||
private int BitShift => _definition.Width - BitsPerStep;
|
||||
|
||||
/// <summary>
|
||||
/// Bit mask based on the CRC width
|
||||
/// </summary>
|
||||
private ulong BitMask => 1UL << (_definition.Width - 1);
|
||||
|
||||
/// <summary>
|
||||
/// Mapping table
|
||||
/// </summary>
|
||||
private readonly ulong[,] _table;
|
||||
|
||||
/// <summary>
|
||||
/// Definition used to build the table
|
||||
/// </summary>
|
||||
private readonly CrcDefinition _definition;
|
||||
|
||||
/// <summary>
|
||||
/// Number of slices in the optimized table
|
||||
/// </summary>
|
||||
private const int SliceCount = 8;
|
||||
|
||||
public CrcTable(CrcDefinition def)
|
||||
{
|
||||
// Initialize the internal
|
||||
_definition = def;
|
||||
_table = new ulong[SliceCount, 1 << BitsPerStep];
|
||||
|
||||
// Build the standard table
|
||||
for (uint i = 0; i < (1 << BitsPerStep); i++)
|
||||
{
|
||||
// Get the starting value for this index
|
||||
ulong point = i;
|
||||
if (!Bitwise && def.ReflectIn)
|
||||
point = ReverseBits(point, BitsPerStep);
|
||||
|
||||
// Shift to account for storage
|
||||
point <<= _definition.Width - BitsPerStep;
|
||||
|
||||
// Accumulate the value
|
||||
for (int j = 0; j < BitsPerStep; j++)
|
||||
{
|
||||
if ((point & BitMask) > 0UL)
|
||||
point = (point << 1) ^ def.Poly;
|
||||
else
|
||||
point <<= 1;
|
||||
}
|
||||
|
||||
// Reflect if necessary
|
||||
if (def.ReflectIn)
|
||||
point = ReverseBits(point, def.Width);
|
||||
|
||||
// Shift back to account for storage
|
||||
point &= ulong.MaxValue >> (64 - def.Width);
|
||||
|
||||
// Assign to the table
|
||||
_table[0, i] = point;
|
||||
}
|
||||
|
||||
// Skip building the optimized table for bitwise processing
|
||||
if (Bitwise)
|
||||
return;
|
||||
|
||||
// Build the optimized table for non-bitwise processing
|
||||
for (int i = 1; i < SliceCount; i++)
|
||||
{
|
||||
// Build each slice from the previous
|
||||
for (int j = 0; j < 1 << BitsPerStep; j++)
|
||||
{
|
||||
ulong last = _table[i - 1, j];
|
||||
if (_definition.ReflectIn)
|
||||
_table[i, j] = (last >> BitsPerStep) ^ _table[0, (byte)last];
|
||||
else
|
||||
_table[i, j] = (last << BitsPerStep) ^ _table[0, (byte)(last >> BitShift)];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Hash a block of data and append it to the existing hash
|
||||
/// </summary>
|
||||
/// <param name="hash">Current hash value, updated on run</param>
|
||||
/// <param name="data">Byte array representing the data</param>
|
||||
/// <param name="offset">Offset in the byte array to include</param>
|
||||
/// <param name="length">Length of the data to hash</param>
|
||||
public void TransformBlock(ref ulong hash, byte[] data, int offset, int length)
|
||||
{
|
||||
// Empty data just returns
|
||||
if (data.Length == 0)
|
||||
return;
|
||||
|
||||
// Check for valid offset and length
|
||||
if (offset > data.Length)
|
||||
throw new System.ArgumentOutOfRangeException(nameof(offset));
|
||||
else if (offset + length > data.Length)
|
||||
throw new System.ArgumentOutOfRangeException(nameof(length));
|
||||
|
||||
// Try transforming fast first
|
||||
if (TransformBlockFast(ref hash, data, offset, length))
|
||||
return;
|
||||
|
||||
// Process the data byte-wise
|
||||
for (int i = offset; i < offset + length; i++)
|
||||
{
|
||||
PerformChecksumStep(ref hash, data, i);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Perform a single checksum step
|
||||
/// </summary>
|
||||
/// <param name="hash">Current hash value, updated on run</param>
|
||||
/// <param name="data">Byte array representing the data</param>
|
||||
/// <param name="offset">Offset in the data to process</param>
|
||||
private void PerformChecksumStep(ref ulong hash, byte[] data, int offset)
|
||||
{
|
||||
// Per-bit processing
|
||||
if (Bitwise)
|
||||
{
|
||||
for (int b = 0; b < 8; b++)
|
||||
{
|
||||
if (_definition.ReflectIn)
|
||||
hash = (hash >> 1) ^ _table[0, (byte)(hash & 1) ^ ((byte)(data[offset] >> b) & 1)];
|
||||
else
|
||||
hash = (hash << 1) ^ _table[0, (byte)((hash >> BitShift) & 1) ^ ((byte)(data[offset] >> (7 - b)) & 1)];
|
||||
}
|
||||
}
|
||||
|
||||
// Per-byte processing
|
||||
else
|
||||
{
|
||||
if (_definition.ReflectIn)
|
||||
hash = (hash >> 8) ^ _table[0, (byte)hash ^ data[offset]];
|
||||
else
|
||||
hash = (hash << 8) ^ _table[0, ((byte)(hash >> BitShift)) ^ data[offset]];
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Perform an optimized transform step
|
||||
/// </summary>
|
||||
private bool TransformBlockFast(ref ulong hash, byte[] data, int offset, int length)
|
||||
{
|
||||
// Bitwise transformations are not optimized
|
||||
if (Bitwise)
|
||||
return false;
|
||||
|
||||
// All reflection-in implementations share an optimized path
|
||||
if (_definition.Width < 64 && _definition.ReflectIn)
|
||||
{
|
||||
TransformBlockFast8Reflect(ref hash, data, offset, length);
|
||||
return true;
|
||||
}
|
||||
else if (_definition.Width >= 64 && _definition.ReflectIn)
|
||||
{
|
||||
TransformBlockFast4Reflect(ref hash, data, offset, length);
|
||||
return true;
|
||||
}
|
||||
|
||||
// CRC-32 with no reflection-in has can be optimized
|
||||
if (_definition.Width == 32 && !_definition.ReflectIn)
|
||||
{
|
||||
TransformBlockFast8NoReflect(ref hash, data, offset, length);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Optimized transformation for CRC with reflection
|
||||
/// </summary>
|
||||
/// <remarks>Reads 4 bytes at a time</remarks>
|
||||
private void TransformBlockFast4Reflect(ref ulong hash, byte[] data, int offset, int length)
|
||||
{
|
||||
// Process on a copy of the hash
|
||||
ulong local = hash;
|
||||
|
||||
// Process aligned data
|
||||
if (length > 4)
|
||||
{
|
||||
long end = offset + (length & ~(uint)3);
|
||||
length &= 3;
|
||||
|
||||
while (offset < end)
|
||||
{
|
||||
ulong low = local ^ (uint)(
|
||||
(data[offset + 0])
|
||||
+ (data[offset + 1] << 8)
|
||||
+ (data[offset + 2] << 16)
|
||||
+ (data[offset + 3] << 24));
|
||||
offset += 4;
|
||||
|
||||
local = _table[3, (byte)(low)]
|
||||
^ _table[2, (byte)(low >> 8)]
|
||||
^ _table[1, (byte)(low >> 16)]
|
||||
^ _table[0, (byte)(low >> 24)]
|
||||
^ local >> 32;
|
||||
}
|
||||
}
|
||||
|
||||
// Process unaligned data
|
||||
while (length-- != 0)
|
||||
{
|
||||
PerformChecksumStep(ref local, data, offset++);
|
||||
}
|
||||
|
||||
// Assign the new hash value
|
||||
hash = local;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Optimized transformation for CRC with reflection
|
||||
/// </summary>
|
||||
/// <remarks>Reads 8 bytes at a time</remarks>
|
||||
private void TransformBlockFast8Reflect(ref ulong hash, byte[] data, int offset, int length)
|
||||
{
|
||||
// Process on a copy of the hash
|
||||
ulong local = hash;
|
||||
|
||||
// Process aligned data
|
||||
if (length > 8)
|
||||
{
|
||||
long end = offset + (length & ~(uint)7);
|
||||
length &= 7;
|
||||
|
||||
while (offset < end)
|
||||
{
|
||||
ulong low = local ^ (uint)(
|
||||
(data[offset + 0])
|
||||
+ (data[offset + 1] << 8)
|
||||
+ (data[offset + 2] << 16)
|
||||
+ (data[offset + 3] << 24));
|
||||
ulong high = (uint)(
|
||||
(data[offset + 4])
|
||||
+ (data[offset + 5] << 8)
|
||||
+ (data[offset + 6] << 16)
|
||||
+ (data[offset + 7] << 24));
|
||||
offset += 8;
|
||||
|
||||
local = _table[7, (byte)(low)]
|
||||
^ _table[6, (byte)(low >> 8)]
|
||||
^ _table[5, (byte)(low >> 16)]
|
||||
^ _table[4, (byte)(low >> 24)]
|
||||
^ _table[3, (byte)(high)]
|
||||
^ _table[2, (byte)(high >> 8)]
|
||||
^ _table[1, (byte)(high >> 16)]
|
||||
^ _table[0, (byte)(high >> 24)]
|
||||
^ local >> 32;
|
||||
}
|
||||
}
|
||||
|
||||
// Process unaligned data
|
||||
while (length-- != 0)
|
||||
{
|
||||
PerformChecksumStep(ref local, data, offset++);
|
||||
}
|
||||
|
||||
// Assign the new hash value
|
||||
hash = local;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Optimized transformation for 32-bit CRC with no reflection
|
||||
/// </summary>
|
||||
/// <remarks>Reads 8 bytes at a time</remarks>
|
||||
private void TransformBlockFast8NoReflect(ref ulong hash, byte[] data, int offset, int length)
|
||||
{
|
||||
// Process on a copy of the hash
|
||||
ulong local = hash;
|
||||
|
||||
// Process aligned data
|
||||
if (length > 8)
|
||||
{
|
||||
long end = offset + (length & ~(uint)7);
|
||||
length &= 7;
|
||||
|
||||
while (offset < end)
|
||||
{
|
||||
ulong low = local ^ (uint)(
|
||||
(data[offset + 3])
|
||||
+ (data[offset + 2] << 8)
|
||||
+ (data[offset + 1] << 16)
|
||||
+ (data[offset + 0] << 24));
|
||||
ulong high = (uint)(
|
||||
(data[offset + 7])
|
||||
+ (data[offset + 6] << 8)
|
||||
+ (data[offset + 5] << 16)
|
||||
+ (data[offset + 4] << 24));
|
||||
offset += 8;
|
||||
|
||||
local = _table[4, (byte)(low)]
|
||||
^ _table[5, (byte)(low >> 8)]
|
||||
^ _table[6, (byte)(low >> 16)]
|
||||
^ _table[7, (byte)(low >> 24)]
|
||||
^ _table[0, (byte)(high)]
|
||||
^ _table[1, (byte)(high >> 8)]
|
||||
^ _table[2, (byte)(high >> 16)]
|
||||
^ _table[3, (byte)(high >> 24)]
|
||||
^ local << 32;
|
||||
}
|
||||
}
|
||||
|
||||
// Process unaligned data
|
||||
while (length-- != 0)
|
||||
{
|
||||
PerformChecksumStep(ref local, data, offset++);
|
||||
}
|
||||
|
||||
// Assign the new hash value
|
||||
hash = local;
|
||||
}
|
||||
}
|
||||
}
|
||||
23
SabreTools.Hashing/Checksum/FNV0_32.cs
Normal file
23
SabreTools.Hashing/Checksum/FNV0_32.cs
Normal file
@@ -0,0 +1,23 @@
|
||||
using static SabreTools.Hashing.Checksum.Constants;
|
||||
|
||||
namespace SabreTools.Hashing.Checksum
|
||||
{
|
||||
public class FNV0_32 : FnvBase<uint>
|
||||
{
|
||||
public FNV0_32()
|
||||
{
|
||||
_basis = 0;
|
||||
_prime = FNV32Prime;
|
||||
Reset();
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override void TransformBlock(byte[] data, int offset, int length)
|
||||
{
|
||||
for (int i = offset; length > 0; i++, length--)
|
||||
{
|
||||
_hash = (_hash * _prime) ^ data[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
23
SabreTools.Hashing/Checksum/FNV0_64.cs
Normal file
23
SabreTools.Hashing/Checksum/FNV0_64.cs
Normal file
@@ -0,0 +1,23 @@
|
||||
using static SabreTools.Hashing.Checksum.Constants;
|
||||
|
||||
namespace SabreTools.Hashing.Checksum
|
||||
{
|
||||
public class FNV0_64 : FnvBase<ulong>
|
||||
{
|
||||
public FNV0_64()
|
||||
{
|
||||
_basis = 0;
|
||||
_prime = FNV64Prime;
|
||||
Reset();
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override void TransformBlock(byte[] data, int offset, int length)
|
||||
{
|
||||
for (int i = offset; length > 0; i++, length--)
|
||||
{
|
||||
_hash = (_hash * _prime) ^ data[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
23
SabreTools.Hashing/Checksum/FNV1_32.cs
Normal file
23
SabreTools.Hashing/Checksum/FNV1_32.cs
Normal file
@@ -0,0 +1,23 @@
|
||||
using static SabreTools.Hashing.Checksum.Constants;
|
||||
|
||||
namespace SabreTools.Hashing.Checksum
|
||||
{
|
||||
public class FNV1_32 : FnvBase<uint>
|
||||
{
|
||||
public FNV1_32()
|
||||
{
|
||||
_basis = FNV32Basis;
|
||||
_prime = FNV32Prime;
|
||||
Reset();
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override void TransformBlock(byte[] data, int offset, int length)
|
||||
{
|
||||
for (int i = offset; length > 0; i++, length--)
|
||||
{
|
||||
_hash = (_hash * _prime) ^ data[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
23
SabreTools.Hashing/Checksum/FNV1_64.cs
Normal file
23
SabreTools.Hashing/Checksum/FNV1_64.cs
Normal file
@@ -0,0 +1,23 @@
|
||||
using static SabreTools.Hashing.Checksum.Constants;
|
||||
|
||||
namespace SabreTools.Hashing.Checksum
|
||||
{
|
||||
public class FNV1_64 : FnvBase<ulong>
|
||||
{
|
||||
public FNV1_64()
|
||||
{
|
||||
_basis = FNV64Basis;
|
||||
_prime = FNV64Prime;
|
||||
Reset();
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override void TransformBlock(byte[] data, int offset, int length)
|
||||
{
|
||||
for (int i = offset; length > 0; i++, length--)
|
||||
{
|
||||
_hash = (_hash * _prime) ^ data[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
23
SabreTools.Hashing/Checksum/FNV1a_32.cs
Normal file
23
SabreTools.Hashing/Checksum/FNV1a_32.cs
Normal file
@@ -0,0 +1,23 @@
|
||||
using static SabreTools.Hashing.Checksum.Constants;
|
||||
|
||||
namespace SabreTools.Hashing.Checksum
|
||||
{
|
||||
public class FNV1a_32 : FnvBase<uint>
|
||||
{
|
||||
public FNV1a_32()
|
||||
{
|
||||
_basis = FNV32Basis;
|
||||
_prime = FNV32Prime;
|
||||
Reset();
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override void TransformBlock(byte[] data, int offset, int length)
|
||||
{
|
||||
for (int i = offset; length > 0; i++, length--)
|
||||
{
|
||||
_hash = (_hash ^ data[i]) * _prime;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
23
SabreTools.Hashing/Checksum/FNV1a_64.cs
Normal file
23
SabreTools.Hashing/Checksum/FNV1a_64.cs
Normal file
@@ -0,0 +1,23 @@
|
||||
using static SabreTools.Hashing.Checksum.Constants;
|
||||
|
||||
namespace SabreTools.Hashing.Checksum
|
||||
{
|
||||
public class FNV1a_64 : FnvBase<ulong>
|
||||
{
|
||||
public FNV1a_64()
|
||||
{
|
||||
_basis = FNV64Basis;
|
||||
_prime = FNV64Prime;
|
||||
Reset();
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override void TransformBlock(byte[] data, int offset, int length)
|
||||
{
|
||||
for (int i = offset; length > 0; i++, length--)
|
||||
{
|
||||
_hash = (_hash ^ data[i]) * _prime;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
40
SabreTools.Hashing/Checksum/Fletcher16.cs
Normal file
40
SabreTools.Hashing/Checksum/Fletcher16.cs
Normal file
@@ -0,0 +1,40 @@
|
||||
namespace SabreTools.Hashing.Checksum
|
||||
{
|
||||
/// <see href="https://en.wikipedia.org/wiki/Fletcher%27s_checksum#Optimizations"/>
|
||||
public class Fletcher16 : ChecksumBase<ushort>
|
||||
{
|
||||
public Fletcher16()
|
||||
{
|
||||
Reset();
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override void TransformBlock(byte[] data, int offset, int length)
|
||||
{
|
||||
// Split the existing hash
|
||||
uint c0 = (uint)(_hash & 0x00FF);
|
||||
uint c1 = (uint)(_hash << 16);
|
||||
|
||||
// Found by solving for c1 overflow:
|
||||
// n > 0 and n * (n+1) / 2 * (2^8-1) < (2^32-1).
|
||||
while (length > 0)
|
||||
{
|
||||
int blocklen = length;
|
||||
if (blocklen > 5802)
|
||||
blocklen = 5802;
|
||||
|
||||
length -= blocklen;
|
||||
do
|
||||
{
|
||||
c0 += data[offset++];
|
||||
c1 += c0;
|
||||
} while (--blocklen > 0);
|
||||
|
||||
c0 %= 255;
|
||||
c1 %= 255;
|
||||
}
|
||||
|
||||
_hash = (ushort)(c1 << 8 | c0);
|
||||
}
|
||||
}
|
||||
}
|
||||
125
SabreTools.Hashing/Checksum/Fletcher32.cs
Normal file
125
SabreTools.Hashing/Checksum/Fletcher32.cs
Normal file
@@ -0,0 +1,125 @@
|
||||
using static SabreTools.Hashing.Checksum.Constants;
|
||||
|
||||
namespace SabreTools.Hashing.Checksum
|
||||
{
|
||||
/// <see href="https://en.wikipedia.org/wiki/Fletcher%27s_checksum#Optimizations"/>
|
||||
/// <remarks>Uses an Adler-32-like implementation instead of the above</remarks>
|
||||
public class Fletcher32 : ChecksumBase<uint>
|
||||
{
|
||||
public Fletcher32()
|
||||
{
|
||||
Reset();
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override void TransformBlock(byte[] data, int offset, int length)
|
||||
{
|
||||
// Split Fletcher-32 into component sums
|
||||
uint c0 = _hash & 0xffff;
|
||||
uint c1 = (_hash >> 16) & 0xffff;
|
||||
|
||||
// In case user likes doing a byte at a time, keep it fast
|
||||
if (length == 1)
|
||||
{
|
||||
c0 += data[offset];
|
||||
if (c0 >= F32BASE)
|
||||
c0 -= F32BASE;
|
||||
|
||||
c1 += c0;
|
||||
if (c1 >= F32BASE)
|
||||
c1 -= F32BASE;
|
||||
|
||||
_hash = (uint)((c1 << 16) | c0);
|
||||
return;
|
||||
}
|
||||
|
||||
// In case short lengths are provided, keep it somewhat fast
|
||||
if (length < 16)
|
||||
{
|
||||
while (length-- > 0)
|
||||
{
|
||||
c0 += data[offset]++;
|
||||
c1 += c0;
|
||||
}
|
||||
|
||||
if (c0 >= F32BASE)
|
||||
c0 -= F32BASE;
|
||||
|
||||
// Only added so many BASE's
|
||||
c1 %= F32BASE;
|
||||
_hash = (uint)((c1 << 16) | c0);
|
||||
return;
|
||||
}
|
||||
|
||||
// Do length NMAX blocks -- requires just one modulo operation
|
||||
while (length >= A32NMAX)
|
||||
{
|
||||
// NMAX is divisible by 16
|
||||
length -= A32NMAX;
|
||||
uint n = A32NMAX / 16;
|
||||
do
|
||||
{
|
||||
c0 += data[offset + 0]; c1 += c0;
|
||||
c0 += data[offset + 1]; c1 += c0;
|
||||
c0 += data[offset + 2]; c1 += c0;
|
||||
c0 += data[offset + 3]; c1 += c0;
|
||||
c0 += data[offset + 4]; c1 += c0;
|
||||
c0 += data[offset + 5]; c1 += c0;
|
||||
c0 += data[offset + 6]; c1 += c0;
|
||||
c0 += data[offset + 7]; c1 += c0;
|
||||
c0 += data[offset + 8]; c1 += c0;
|
||||
c0 += data[offset + 9]; c1 += c0;
|
||||
c0 += data[offset + 10]; c1 += c0;
|
||||
c0 += data[offset + 11]; c1 += c0;
|
||||
c0 += data[offset + 12]; c1 += c0;
|
||||
c0 += data[offset + 13]; c1 += c0;
|
||||
c0 += data[offset + 14]; c1 += c0;
|
||||
c0 += data[offset + 15]; c1 += c0;
|
||||
|
||||
offset += 16;
|
||||
} while (--n > 0);
|
||||
}
|
||||
|
||||
// Do remaining bytes (less than NMAX, still just one modulo)
|
||||
if (length > 0)
|
||||
{
|
||||
// Avoid modulos if none remaining
|
||||
while (length >= 16)
|
||||
{
|
||||
length -= 16;
|
||||
|
||||
c0 += data[offset + 0]; c1 += c0;
|
||||
c0 += data[offset + 1]; c1 += c0;
|
||||
c0 += data[offset + 2]; c1 += c0;
|
||||
c0 += data[offset + 3]; c1 += c0;
|
||||
c0 += data[offset + 4]; c1 += c0;
|
||||
c0 += data[offset + 5]; c1 += c0;
|
||||
c0 += data[offset + 6]; c1 += c0;
|
||||
c0 += data[offset + 7]; c1 += c0;
|
||||
c0 += data[offset + 8]; c1 += c0;
|
||||
c0 += data[offset + 9]; c1 += c0;
|
||||
c0 += data[offset + 10]; c1 += c0;
|
||||
c0 += data[offset + 11]; c1 += c0;
|
||||
c0 += data[offset + 12]; c1 += c0;
|
||||
c0 += data[offset + 13]; c1 += c0;
|
||||
c0 += data[offset + 14]; c1 += c0;
|
||||
c0 += data[offset + 15]; c1 += c0;
|
||||
|
||||
offset += 16;
|
||||
}
|
||||
|
||||
while (length-- > 0)
|
||||
{
|
||||
c0 += data[offset++];
|
||||
c1 += c0;
|
||||
}
|
||||
|
||||
c0 %= F32BASE;
|
||||
c1 %= F32BASE;
|
||||
}
|
||||
|
||||
// Return recombined sums
|
||||
_hash = (c1 << 16) | c0;
|
||||
}
|
||||
}
|
||||
}
|
||||
125
SabreTools.Hashing/Checksum/Fletcher64.cs
Normal file
125
SabreTools.Hashing/Checksum/Fletcher64.cs
Normal file
@@ -0,0 +1,125 @@
|
||||
using static SabreTools.Hashing.Checksum.Constants;
|
||||
|
||||
namespace SabreTools.Hashing.Checksum
|
||||
{
|
||||
/// <see href="https://en.wikipedia.org/wiki/Fletcher%27s_checksum#Optimizations"/>
|
||||
/// <remarks>Uses an Adler-32-like implementation instead of the above</remarks>
|
||||
public class Fletcher64 : ChecksumBase<ulong>
|
||||
{
|
||||
public Fletcher64()
|
||||
{
|
||||
Reset();
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override void TransformBlock(byte[] data, int offset, int length)
|
||||
{
|
||||
// Split Fletcher-64 into component sums
|
||||
ulong c0 = _hash & 0xffffffff;
|
||||
ulong c1 = (_hash >> 32) & 0xffffffff;
|
||||
|
||||
// In case user likes doing a byte at a time, keep it fast
|
||||
if (length == 1)
|
||||
{
|
||||
c0 += data[offset];
|
||||
if (c0 >= F64BASE)
|
||||
c0 -= F64BASE;
|
||||
|
||||
c1 += c0;
|
||||
if (c1 >= F64BASE)
|
||||
c1 -= F64BASE;
|
||||
|
||||
_hash = (c1 << 32) | c0;
|
||||
return;
|
||||
}
|
||||
|
||||
// In case short lengths are provided, keep it somewhat fast
|
||||
if (length < 16)
|
||||
{
|
||||
while (length-- > 0)
|
||||
{
|
||||
c0 += data[offset]++;
|
||||
c1 += c0;
|
||||
}
|
||||
|
||||
if (c0 >= F64BASE)
|
||||
c0 -= F64BASE;
|
||||
|
||||
// Only added so many BASE's
|
||||
c1 %= F64BASE;
|
||||
_hash = (c1 << 32) | c0;
|
||||
return;
|
||||
}
|
||||
|
||||
// Do length NMAX blocks -- requires just one modulo operation
|
||||
while (length >= A32NMAX)
|
||||
{
|
||||
// NMAX is divisible by 16
|
||||
length -= A32NMAX;
|
||||
uint n = A32NMAX / 16;
|
||||
do
|
||||
{
|
||||
c0 += data[offset + 0]; c1 += c0;
|
||||
c0 += data[offset + 1]; c1 += c0;
|
||||
c0 += data[offset + 2]; c1 += c0;
|
||||
c0 += data[offset + 3]; c1 += c0;
|
||||
c0 += data[offset + 4]; c1 += c0;
|
||||
c0 += data[offset + 5]; c1 += c0;
|
||||
c0 += data[offset + 6]; c1 += c0;
|
||||
c0 += data[offset + 7]; c1 += c0;
|
||||
c0 += data[offset + 8]; c1 += c0;
|
||||
c0 += data[offset + 9]; c1 += c0;
|
||||
c0 += data[offset + 10]; c1 += c0;
|
||||
c0 += data[offset + 11]; c1 += c0;
|
||||
c0 += data[offset + 12]; c1 += c0;
|
||||
c0 += data[offset + 13]; c1 += c0;
|
||||
c0 += data[offset + 14]; c1 += c0;
|
||||
c0 += data[offset + 15]; c1 += c0;
|
||||
|
||||
offset += 16;
|
||||
} while (--n > 0);
|
||||
}
|
||||
|
||||
// Do remaining bytes (less than NMAX, still just one modulo)
|
||||
if (length > 0)
|
||||
{
|
||||
// Avoid modulos if none remaining
|
||||
while (length >= 16)
|
||||
{
|
||||
length -= 16;
|
||||
|
||||
c0 += data[offset + 0]; c1 += c0;
|
||||
c0 += data[offset + 1]; c1 += c0;
|
||||
c0 += data[offset + 2]; c1 += c0;
|
||||
c0 += data[offset + 3]; c1 += c0;
|
||||
c0 += data[offset + 4]; c1 += c0;
|
||||
c0 += data[offset + 5]; c1 += c0;
|
||||
c0 += data[offset + 6]; c1 += c0;
|
||||
c0 += data[offset + 7]; c1 += c0;
|
||||
c0 += data[offset + 8]; c1 += c0;
|
||||
c0 += data[offset + 9]; c1 += c0;
|
||||
c0 += data[offset + 10]; c1 += c0;
|
||||
c0 += data[offset + 11]; c1 += c0;
|
||||
c0 += data[offset + 12]; c1 += c0;
|
||||
c0 += data[offset + 13]; c1 += c0;
|
||||
c0 += data[offset + 14]; c1 += c0;
|
||||
c0 += data[offset + 15]; c1 += c0;
|
||||
|
||||
offset += 16;
|
||||
}
|
||||
|
||||
while (length-- > 0)
|
||||
{
|
||||
c0 += data[offset++];
|
||||
c1 += c0;
|
||||
}
|
||||
|
||||
c0 %= F64BASE;
|
||||
c1 %= F64BASE;
|
||||
}
|
||||
|
||||
// Return recombined sums
|
||||
_hash = (c1 << 32) | c0;
|
||||
}
|
||||
}
|
||||
}
|
||||
21
SabreTools.Hashing/Checksum/FnvBase.cs
Normal file
21
SabreTools.Hashing/Checksum/FnvBase.cs
Normal file
@@ -0,0 +1,21 @@
|
||||
namespace SabreTools.Hashing.Checksum
|
||||
{
|
||||
public abstract class FnvBase<T> : ChecksumBase<T> where T : struct
|
||||
{
|
||||
/// <summary>
|
||||
/// Initial value to use
|
||||
/// </summary>
|
||||
protected T _basis;
|
||||
|
||||
/// <summary>
|
||||
/// Round prime to use
|
||||
/// </summary>
|
||||
protected T _prime;
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override void Reset()
|
||||
{
|
||||
_hash = _basis;
|
||||
}
|
||||
}
|
||||
}
|
||||
1690
SabreTools.Hashing/Checksum/StandardDefinitions.cs
Normal file
1690
SabreTools.Hashing/Checksum/StandardDefinitions.cs
Normal file
File diff suppressed because it is too large
Load Diff
@@ -1,80 +0,0 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Threading;
|
||||
|
||||
namespace Compress.ThreadReaders
|
||||
{
|
||||
internal sealed class ThreadLoadBuffer : IDisposable
|
||||
{
|
||||
private readonly AutoResetEvent _waitEvent;
|
||||
private readonly AutoResetEvent _outEvent;
|
||||
private readonly Thread _tWorker;
|
||||
|
||||
private byte[]? _buffer;
|
||||
private int _size;
|
||||
private readonly Stream _ds;
|
||||
private bool _finished;
|
||||
public bool errorState;
|
||||
|
||||
public int SizeRead;
|
||||
|
||||
public ThreadLoadBuffer(Stream ds)
|
||||
{
|
||||
_waitEvent = new AutoResetEvent(false);
|
||||
_outEvent = new AutoResetEvent(false);
|
||||
_finished = false;
|
||||
_ds = ds;
|
||||
errorState = false;
|
||||
|
||||
_tWorker = new Thread(MainLoop);
|
||||
_tWorker.Start();
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_waitEvent.Close();
|
||||
_outEvent.Close();
|
||||
}
|
||||
|
||||
private void MainLoop()
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
_waitEvent.WaitOne();
|
||||
if (_finished)
|
||||
{
|
||||
break;
|
||||
}
|
||||
try
|
||||
{
|
||||
if (_buffer != null)
|
||||
SizeRead = _ds.Read(_buffer, 0, _size);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
errorState = true;
|
||||
}
|
||||
_outEvent.Set();
|
||||
}
|
||||
}
|
||||
|
||||
public void Trigger(byte[] buffer, int size)
|
||||
{
|
||||
_buffer = buffer;
|
||||
_size = size;
|
||||
_waitEvent.Set();
|
||||
}
|
||||
|
||||
public void Wait()
|
||||
{
|
||||
_outEvent.WaitOne();
|
||||
}
|
||||
|
||||
public void Finish()
|
||||
{
|
||||
_finished = true;
|
||||
_waitEvent.Set();
|
||||
_tWorker.Join();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -5,60 +5,6 @@ namespace SabreTools.Hashing
|
||||
#region 0-byte file constants
|
||||
|
||||
public const long SizeZero = 0;
|
||||
public const string CRCZero = "00000000";
|
||||
public static readonly byte[] CRCZeroBytes = [0x00, 0x00, 0x00, 0x00];
|
||||
public const string MD5Zero = "d41d8cd98f00b204e9800998ecf8427e";
|
||||
public static readonly byte[] MD5ZeroBytes = [ 0xd4, 0x1d, 0x8c, 0xd9,
|
||||
0x8f, 0x00, 0xb2, 0x04,
|
||||
0xe9, 0x80, 0x09, 0x98,
|
||||
0xec, 0xf8, 0x42, 0x7e ];
|
||||
public const string SHA1Zero = "da39a3ee5e6b4b0d3255bfef95601890afd80709";
|
||||
public static readonly byte[] SHA1ZeroBytes = [ 0xda, 0x39, 0xa3, 0xee,
|
||||
0x5e, 0x6b, 0x4b, 0x0d,
|
||||
0x32, 0x55, 0xbf, 0xef,
|
||||
0x95, 0x60, 0x18, 0x90,
|
||||
0xaf, 0xd8, 0x07, 0x09 ];
|
||||
public const string SHA256Zero = "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad";
|
||||
public static readonly byte[] SHA256ZeroBytes = [ 0xba, 0x78, 0x16, 0xbf,
|
||||
0x8f, 0x01, 0xcf, 0xea,
|
||||
0x41, 0x41, 0x40, 0xde,
|
||||
0x5d, 0xae, 0x22, 0x23,
|
||||
0xb0, 0x03, 0x61, 0xa3,
|
||||
0x96, 0x17, 0x7a, 0x9c,
|
||||
0xb4, 0x10, 0xff, 0x61,
|
||||
0xf2, 0x00, 0x15, 0xad ];
|
||||
public const string SHA384Zero = "cb00753f45a35e8bb5a03d699ac65007272c32ab0eded1631a8b605a43ff5bed8086072ba1e7cc2358baeca134c825a7";
|
||||
public static readonly byte[] SHA384ZeroBytes = [ 0xcb, 0x00, 0x75, 0x3f,
|
||||
0x45, 0xa3, 0x5e, 0x8b,
|
||||
0xb5, 0xa0, 0x3d, 0x69,
|
||||
0x9a, 0xc6, 0x50, 0x07,
|
||||
0x27, 0x2c, 0x32, 0xab,
|
||||
0x0e, 0xde, 0xd1, 0x63,
|
||||
0x1a, 0x8b, 0x60, 0x5a,
|
||||
0x43, 0xff, 0x5b, 0xed,
|
||||
0x80, 0x86, 0x07, 0x2b,
|
||||
0xa1, 0xe7, 0xcc, 0x23,
|
||||
0x58, 0xba, 0xec, 0xa1,
|
||||
0x34, 0xc8, 0x25, 0xa7 ];
|
||||
public const string SHA512Zero = "ddaf35a193617abacc417349ae20413112e6fa4e89a97ea20a9eeee64b55d39a2192992a274fc1a836ba3c23a3feebbd454d4423643ce80e2a9ac94fa54ca49f";
|
||||
public static readonly byte[] SHA512ZeroBytes = [ 0xdd, 0xaf, 0x35, 0xa1,
|
||||
0x93, 0x61, 0x7a, 0xba,
|
||||
0xcc, 0x41, 0x73, 0x49,
|
||||
0xae, 0x20, 0x41, 0x31,
|
||||
0x12, 0xe6, 0xfa, 0x4e,
|
||||
0x89, 0xa9, 0x7e, 0xa2,
|
||||
0x0a, 0x9e, 0xee, 0xe6,
|
||||
0x4b, 0x55, 0xd3, 0x9a,
|
||||
0x21, 0x92, 0x99, 0x2a,
|
||||
0x27, 0x4f, 0xc1, 0xa8,
|
||||
0x36, 0xba, 0x3c, 0x23,
|
||||
0xa3, 0xfe, 0xeb, 0xbd,
|
||||
0x45, 0x4d, 0x44, 0x23,
|
||||
0x64, 0x3c, 0xe8, 0x0e,
|
||||
0x2a, 0x9a, 0xc9, 0x4f,
|
||||
0xa5, 0x4c, 0xa4, 0x9f ];
|
||||
public const string SpamSumZero = "QXX";
|
||||
public static readonly byte[] SpamSumZeroBytes = [0x51, 0x58, 0x58];
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
181
SabreTools.Hashing/HashOperations.cs
Normal file
181
SabreTools.Hashing/HashOperations.cs
Normal file
@@ -0,0 +1,181 @@
|
||||
using System;
|
||||
|
||||
namespace SabreTools.Hashing
|
||||
{
|
||||
internal static class HashOperations
|
||||
{
|
||||
#region Conversions
|
||||
|
||||
/// <summary>
|
||||
/// Convert a byte array to a hex string
|
||||
/// </summary>
|
||||
/// <param name="bytes">Byte array to convert</param>
|
||||
/// <returns>Hex string representing the byte array</returns>
|
||||
/// <link>http://stackoverflow.com/questions/311165/how-do-you-convert-byte-array-to-hexadecimal-string-and-vice-versa</link>
|
||||
public static string? ByteArrayToString(byte[]? bytes)
|
||||
{
|
||||
// If we get null in, we send null out
|
||||
if (bytes == null)
|
||||
return null;
|
||||
|
||||
try
|
||||
{
|
||||
string hex = BitConverter.ToString(bytes);
|
||||
return hex.Replace("-", string.Empty).ToLowerInvariant();
|
||||
}
|
||||
catch
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <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 ulong BytesToUInt64(byte[]? bytes)
|
||||
{
|
||||
// If we get null in, we send 0 out
|
||||
if (bytes == null)
|
||||
return default;
|
||||
|
||||
ulong result = 0;
|
||||
for (int i = 0; i < bytes.Length; i++)
|
||||
{
|
||||
result |= (ulong)bytes[i] << (i * 8);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Read Big-Endian
|
||||
|
||||
/// <summary>
|
||||
/// 32-bit big-endian read
|
||||
/// </summary>
|
||||
public static uint ReadBE32(byte[] data, int offset)
|
||||
{
|
||||
return (uint)(data[offset + 3]
|
||||
| data[offset + 2] << 8
|
||||
| data[offset + 1] << 16
|
||||
| data[offset + 0] << 24);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 64-bit big-endian read
|
||||
/// </summary>
|
||||
public static ulong ReadBE64(byte[] data, int offset)
|
||||
{
|
||||
return data[offset + 7]
|
||||
| (ulong)data[offset + 6] << 8
|
||||
| (ulong)data[offset + 5] << 16
|
||||
| (ulong)data[offset + 4] << 24
|
||||
| (ulong)data[offset + 3] << 32
|
||||
| (ulong)data[offset + 2] << 40
|
||||
| (ulong)data[offset + 1] << 48
|
||||
| (ulong)data[offset + 0] << 56;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Read Litte-Endian
|
||||
|
||||
/// <summary>
|
||||
/// 32-bit little-endian read
|
||||
/// </summary>
|
||||
public static uint ReadLE32(byte[] data, int offset)
|
||||
{
|
||||
return (uint)(data[offset + 0]
|
||||
| data[offset + 1] << 8
|
||||
| data[offset + 2] << 16
|
||||
| data[offset + 3] << 24);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 64-bit little-endian read
|
||||
/// </summary>
|
||||
public static ulong ReadLE64(byte[] data, int offset)
|
||||
{
|
||||
return data[offset + 0]
|
||||
| (ulong)data[offset + 1] << 8
|
||||
| (ulong)data[offset + 2] << 16
|
||||
| (ulong)data[offset + 3] << 24
|
||||
| (ulong)data[offset + 4] << 32
|
||||
| (ulong)data[offset + 5] << 40
|
||||
| (ulong)data[offset + 6] << 48
|
||||
| (ulong)data[offset + 7] << 56;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Reverse
|
||||
|
||||
/// <summary>
|
||||
/// Reverse the endianness of a value
|
||||
/// </summary>
|
||||
public static ulong ReverseBits(ulong value, int bitWidth)
|
||||
{
|
||||
ulong reverse = 0;
|
||||
for (int i = 0; i < bitWidth; i++)
|
||||
{
|
||||
reverse <<= 1;
|
||||
reverse |= value & 1;
|
||||
value >>= 1;
|
||||
}
|
||||
|
||||
return reverse;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Rotate
|
||||
|
||||
/// <summary>
|
||||
/// 32-bit rotate left.
|
||||
/// </summary>
|
||||
public static uint RotateLeft32(uint x, int r)
|
||||
=> (x << r) | (x >> (32 - r));
|
||||
|
||||
/// <summary>
|
||||
/// 64-bit rotate left.
|
||||
/// </summary>
|
||||
public static ulong RotateLeft64(ulong x, int r)
|
||||
=> (x << r) | (x >> (64 - r));
|
||||
|
||||
#endregion
|
||||
|
||||
#region Swap
|
||||
|
||||
/// <summary>
|
||||
/// A 32-bit byteswap.
|
||||
/// </summary>
|
||||
public static uint Swap32(uint x)
|
||||
{
|
||||
return ((x << 24) & 0xff000000)
|
||||
| ((x << 8) & 0x00ff0000)
|
||||
| ((x >> 8) & 0x0000ff00)
|
||||
| ((x >> 24) & 0x000000ff);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// A 64-bit byteswap.
|
||||
/// </summary>
|
||||
public static ulong Swap64(ulong x)
|
||||
{
|
||||
return ((x << 56) & 0xff00000000000000)
|
||||
| ((x << 40) & 0x00ff000000000000)
|
||||
| ((x << 24) & 0x0000ff0000000000)
|
||||
| ((x << 8) & 0x000000ff00000000)
|
||||
| ((x >> 8) & 0x00000000ff000000)
|
||||
| ((x >> 24) & 0x0000000000ff0000)
|
||||
| ((x >> 40) & 0x000000000000ff00)
|
||||
| ((x >> 56) & 0x00000000000000ff);
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -4,7 +4,6 @@ using System.IO;
|
||||
#if NET40_OR_GREATER || NETCOREAPP
|
||||
using System.Threading.Tasks;
|
||||
#endif
|
||||
using Compress.ThreadReaders;
|
||||
|
||||
namespace SabreTools.Hashing
|
||||
{
|
||||
@@ -345,102 +344,37 @@ namespace SabreTools.Hashing
|
||||
|
||||
try
|
||||
{
|
||||
// Get a list of hashers to run over the buffer
|
||||
var hashers = new Dictionary<HashType, HashWrapper>();
|
||||
|
||||
// Add hashers based on requested types
|
||||
foreach (HashType hashType in hashTypes)
|
||||
// Shortcut if we have a 0-byte input
|
||||
if (input.Length == 0)
|
||||
{
|
||||
hashers[hashType] = new HashWrapper(hashType);
|
||||
}
|
||||
|
||||
// Initialize the hashing helpers
|
||||
var loadBuffer = new ThreadLoadBuffer(input);
|
||||
int buffersize = 3 * 1024 * 1024;
|
||||
byte[] buffer0 = new byte[buffersize];
|
||||
byte[] buffer1 = new byte[buffersize];
|
||||
|
||||
/*
|
||||
Please note that some of the following code is adapted from
|
||||
RomVault. This is a modified version of how RomVault does
|
||||
threaded hashing. As such, some of the terminology and code
|
||||
is the same, though variable names and comments may have
|
||||
been tweaked to better fit this code base.
|
||||
*/
|
||||
|
||||
// Pre load the first buffer
|
||||
long refsize = input.Length;
|
||||
int next = refsize > buffersize ? buffersize : (int)refsize;
|
||||
input.Read(buffer0, 0, next);
|
||||
int current = next;
|
||||
refsize -= next;
|
||||
bool bufferSelect = true;
|
||||
|
||||
while (current > 0)
|
||||
{
|
||||
// Trigger the buffer load on the second buffer
|
||||
next = refsize > buffersize ? buffersize : (int)refsize;
|
||||
if (next > 0)
|
||||
loadBuffer.Trigger(bufferSelect ? buffer1 : buffer0, next);
|
||||
|
||||
byte[] buffer = bufferSelect ? buffer0 : buffer1;
|
||||
|
||||
#if NET20 || NET35
|
||||
// Run hashers sequentially on each chunk
|
||||
foreach (var h in hashers)
|
||||
foreach (var hashType in hashTypes)
|
||||
{
|
||||
h.Value.Process(buffer, 0, current);
|
||||
hashDict[hashType] = ZeroHash.GetString(hashType);
|
||||
}
|
||||
#else
|
||||
// Run hashers in parallel on each chunk
|
||||
Parallel.ForEach(hashers, h => h.Value.Process(buffer, 0, current));
|
||||
#endif
|
||||
|
||||
// Wait for the load buffer worker, if needed
|
||||
if (next > 0)
|
||||
loadBuffer.Wait();
|
||||
|
||||
// Setup for the next hashing step
|
||||
current = next;
|
||||
refsize -= next;
|
||||
bufferSelect = !bufferSelect;
|
||||
return hashDict;
|
||||
}
|
||||
|
||||
// Finalize all hashing helpers
|
||||
loadBuffer.Finish();
|
||||
#if NET20 || NET35
|
||||
foreach (var h in hashers)
|
||||
{
|
||||
h.Value.Terminate();
|
||||
}
|
||||
#else
|
||||
Parallel.ForEach(hashers, h => h.Value.Terminate());
|
||||
#endif
|
||||
|
||||
// Get the results
|
||||
foreach (var hasher in hashers)
|
||||
{
|
||||
hashDict[hasher.Key] = hasher.Value.CurrentHashString;
|
||||
}
|
||||
|
||||
// Dispose of the hashers
|
||||
loadBuffer.Dispose();
|
||||
foreach (var hasher in hashers.Values)
|
||||
{
|
||||
hasher.Dispose();
|
||||
}
|
||||
|
||||
return hashDict;
|
||||
}
|
||||
catch (IOException)
|
||||
{
|
||||
catch { }
|
||||
|
||||
// Run the hashing
|
||||
var hashers = GetStreamHashesInternal(input, hashTypes, leaveOpen);
|
||||
if (hashers == null)
|
||||
return null;
|
||||
}
|
||||
finally
|
||||
|
||||
// Get the results
|
||||
foreach (var hasher in hashers)
|
||||
{
|
||||
if (!leaveOpen)
|
||||
input.Dispose();
|
||||
hashDict[hasher.Key] = hasher.Value.CurrentHashString;
|
||||
}
|
||||
|
||||
// Dispose of the hashers
|
||||
foreach (var hasher in hashers.Values)
|
||||
{
|
||||
hasher.Dispose();
|
||||
}
|
||||
|
||||
return hashDict;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -449,11 +383,58 @@ namespace SabreTools.Hashing
|
||||
/// <param name="input">Stream to hash</param>
|
||||
/// <param name="hashTypes">Array of hash types to get from the file</param>
|
||||
/// <returns>Dictionary containing hashes on success, null on error</returns>
|
||||
private static Dictionary<HashType, byte[]?>? GetStreamHashArrays(Stream input, HashType[] hashTypes, bool leaveOpen = false)
|
||||
public static Dictionary<HashType, byte[]?>? GetStreamHashArrays(Stream input, HashType[] hashTypes, bool leaveOpen = false)
|
||||
{
|
||||
// Create the output dictionary
|
||||
var hashDict = new Dictionary<HashType, byte[]?>();
|
||||
|
||||
try
|
||||
{
|
||||
// Shortcut if we have a 0-byte input
|
||||
if (input.Length == 0)
|
||||
{
|
||||
foreach (var hashType in hashTypes)
|
||||
{
|
||||
hashDict[hashType] = ZeroHash.GetBytes(hashType);
|
||||
}
|
||||
|
||||
return hashDict;
|
||||
}
|
||||
}
|
||||
catch { }
|
||||
|
||||
// Run the hashing
|
||||
var hashers = GetStreamHashesInternal(input, hashTypes, leaveOpen);
|
||||
if (hashers == null)
|
||||
return null;
|
||||
|
||||
// Get the results
|
||||
foreach (var hasher in hashers)
|
||||
{
|
||||
hashDict[hasher.Key] = hasher.Value.CurrentHashBytes;
|
||||
}
|
||||
|
||||
// Dispose of the hashers
|
||||
foreach (var hasher in hashers.Values)
|
||||
{
|
||||
hasher.Dispose();
|
||||
}
|
||||
|
||||
return hashDict;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get hashes from an input stream
|
||||
/// </summary>
|
||||
/// <param name="input"></param>
|
||||
/// <param name="hashTypes"></param>
|
||||
/// <param name="leaveOpen"></param>
|
||||
/// <returns></returns>
|
||||
private static Dictionary<HashType, HashWrapper>? GetStreamHashesInternal(Stream input, HashType[] hashTypes, bool leaveOpen)
|
||||
{
|
||||
// Create the output dictionary
|
||||
var hashDict = new Dictionary<HashType, string?>();
|
||||
|
||||
try
|
||||
{
|
||||
// Get a list of hashers to run over the buffer
|
||||
@@ -465,83 +446,44 @@ namespace SabreTools.Hashing
|
||||
hashers[hashType] = new HashWrapper(hashType);
|
||||
}
|
||||
|
||||
// Initialize the hashing helpers
|
||||
var loadBuffer = new ThreadLoadBuffer(input);
|
||||
// Create the buffer for holding data
|
||||
int buffersize = 3 * 1024 * 1024;
|
||||
byte[] buffer0 = new byte[buffersize];
|
||||
byte[] buffer1 = new byte[buffersize];
|
||||
byte[] buffer = new byte[buffersize];
|
||||
int lastRead;
|
||||
|
||||
/*
|
||||
Please note that some of the following code is adapted from
|
||||
RomVault. This is a modified version of how RomVault does
|
||||
threaded hashing. As such, some of the terminology and code
|
||||
is the same, though variable names and comments may have
|
||||
been tweaked to better fit this code base.
|
||||
*/
|
||||
|
||||
// Pre load the first buffer
|
||||
long refsize = input.Length;
|
||||
int next = refsize > buffersize ? buffersize : (int)refsize;
|
||||
input.Read(buffer0, 0, next);
|
||||
int current = next;
|
||||
refsize -= next;
|
||||
bool bufferSelect = true;
|
||||
|
||||
while (current > 0)
|
||||
// Hash the input data in blocks
|
||||
do
|
||||
{
|
||||
// Trigger the buffer load on the second buffer
|
||||
next = refsize > buffersize ? buffersize : (int)refsize;
|
||||
if (next > 0)
|
||||
loadBuffer.Trigger(bufferSelect ? buffer1 : buffer0, next);
|
||||
|
||||
byte[] buffer = bufferSelect ? buffer0 : buffer1;
|
||||
// Load the buffer and hold the number of bytes read
|
||||
lastRead = input.Read(buffer, 0, buffersize);
|
||||
if (lastRead == 0)
|
||||
break;
|
||||
|
||||
#if NET20 || NET35
|
||||
// Run hashers sequentially on each chunk
|
||||
foreach (var h in hashers)
|
||||
{
|
||||
h.Value.Process(buffer, 0, current);
|
||||
h.Value.Process(buffer, 0, lastRead);
|
||||
}
|
||||
#else
|
||||
// Run hashers in parallel on each chunk
|
||||
Parallel.ForEach(hashers, h => h.Value.Process(buffer, 0, current));
|
||||
Parallel.ForEach(hashers, h => h.Value.Process(buffer, 0, lastRead));
|
||||
#endif
|
||||
|
||||
// Wait for the load buffer worker, if needed
|
||||
if (next > 0)
|
||||
loadBuffer.Wait();
|
||||
|
||||
// Setup for the next hashing step
|
||||
current = next;
|
||||
refsize -= next;
|
||||
bufferSelect = !bufferSelect;
|
||||
}
|
||||
while (lastRead > 0);
|
||||
|
||||
// Finalize all hashing helpers
|
||||
loadBuffer.Finish();
|
||||
#if NET20 || NET35
|
||||
// Finalize all hashing helpers sequentially
|
||||
foreach (var h in hashers)
|
||||
{
|
||||
h.Value.Terminate();
|
||||
}
|
||||
#else
|
||||
// Finalize all hashing helpers in parallel
|
||||
Parallel.ForEach(hashers, h => h.Value.Terminate());
|
||||
#endif
|
||||
|
||||
// Get the results
|
||||
foreach (var hasher in hashers)
|
||||
{
|
||||
hashDict[hasher.Key] = hasher.Value.CurrentHashBytes;
|
||||
}
|
||||
|
||||
// Dispose of the hashers
|
||||
loadBuffer.Dispose();
|
||||
foreach (var hasher in hashers.Values)
|
||||
{
|
||||
hasher.Dispose();
|
||||
}
|
||||
|
||||
return hashDict;
|
||||
return hashers;
|
||||
}
|
||||
catch (IOException)
|
||||
{
|
||||
|
||||
@@ -5,23 +5,802 @@ namespace SabreTools.Hashing
|
||||
/// </summary>
|
||||
public enum HashType
|
||||
{
|
||||
/// <summary>
|
||||
/// Mark Adler's 32-bit checksum
|
||||
/// </summary>
|
||||
Adler32,
|
||||
|
||||
#if NET7_0_OR_GREATER
|
||||
/// <summary>
|
||||
/// BLAKE3 512-bit digest
|
||||
/// </summary>
|
||||
BLAKE3,
|
||||
#endif
|
||||
|
||||
#region CRC
|
||||
|
||||
#region CRC-1
|
||||
|
||||
/// <summary>
|
||||
/// CRC 1-bit checksum (CRC-1/ZERO [Parity bit with 0 start])
|
||||
/// </summary>
|
||||
CRC1_ZERO,
|
||||
|
||||
/// <summary>
|
||||
/// CRC 1-bit checksum (CRC-1/ONE [Parity bit with 1 start])
|
||||
/// </summary>
|
||||
CRC1_ONE,
|
||||
|
||||
#endregion
|
||||
|
||||
#region CRC-3
|
||||
|
||||
/// <summary>
|
||||
/// CRC 3-bit checksum (CRC-3/GSM)
|
||||
/// </summary>
|
||||
CRC3_GSM,
|
||||
|
||||
/// <summary>
|
||||
/// CRC 3-bit checksum (CRC-3/ROHC)
|
||||
/// </summary>
|
||||
CRC3_ROHC,
|
||||
|
||||
#endregion
|
||||
|
||||
#region CRC-4
|
||||
|
||||
/// <summary>
|
||||
/// CRC 4-bit checksum (CRC-4/G-704 [CRC-4/ITU])
|
||||
/// </summary>
|
||||
CRC4_G704,
|
||||
|
||||
/// <summary>
|
||||
/// CRC 4-bit checksum (CRC-4/INTERLAKEN)
|
||||
/// </summary>
|
||||
CRC4_INTERLAKEN,
|
||||
|
||||
#endregion
|
||||
|
||||
#region CRC-5
|
||||
|
||||
/// <summary>
|
||||
/// CRC 5-bit checksum (CRC-5/EPC-C1G2 [CRC-5/EPC])
|
||||
/// </summary>
|
||||
CRC5_EPCC1G2,
|
||||
|
||||
/// <summary>
|
||||
/// CRC 5-bit checksum (CRC-5/G-704 [CRC-5/ITU])
|
||||
/// </summary>
|
||||
CRC5_G704,
|
||||
|
||||
/// <summary>
|
||||
/// CRC 5-bit checksum (CRC-5/USB)
|
||||
/// </summary>
|
||||
CRC5_USB,
|
||||
|
||||
#endregion
|
||||
|
||||
#region CRC-6
|
||||
|
||||
/// <summary>
|
||||
/// CRC 6-bit checksum (CRC-6/CDMA2000-A)
|
||||
/// </summary>
|
||||
CRC6_CDMA2000A,
|
||||
|
||||
/// <summary>
|
||||
/// CRC 6-bit checksum (CRC-6/CDMA2000-B)
|
||||
/// </summary>
|
||||
CRC6_CDMA2000B,
|
||||
|
||||
/// <summary>
|
||||
/// CRC 6-bit checksum (CRC-6/DARC)
|
||||
/// </summary>
|
||||
CRC6_DARC,
|
||||
|
||||
/// <summary>
|
||||
/// CRC 6-bit checksum (CRC-6/G-704 [CRC-6/ITU])
|
||||
/// </summary>
|
||||
CRC6_G704,
|
||||
|
||||
/// <summary>
|
||||
/// CRC 6-bit checksum (CRC-6/GSM)
|
||||
/// </summary>
|
||||
CRC6_GSM,
|
||||
|
||||
#endregion
|
||||
|
||||
#region CRC-7
|
||||
|
||||
/// <summary>
|
||||
/// CRC 7-bit checksum (CRC-7/MMC [CRC-7])
|
||||
/// </summary>
|
||||
CRC7_MMC,
|
||||
|
||||
/// <summary>
|
||||
/// CRC 7-bit checksum (CRC-7/ROHC)
|
||||
/// </summary>
|
||||
CRC7_ROHC,
|
||||
|
||||
/// <summary>
|
||||
/// CRC 7-bit checksum (CRC-7/UMTS)
|
||||
/// </summary>
|
||||
CRC7_UMTS,
|
||||
|
||||
#endregion
|
||||
|
||||
#region CRC-8
|
||||
|
||||
/// <summary>
|
||||
/// CRC 8-bit checksum
|
||||
/// </summary>
|
||||
/// <remarks>Identical to <see cref="CRC8_SMBUS"/>
|
||||
CRC8,
|
||||
|
||||
/// <summary>
|
||||
/// CRC 8-bit checksum (CRC-8/AUTOSAR)
|
||||
/// </summary>
|
||||
CRC8_AUTOSAR,
|
||||
|
||||
/// <summary>
|
||||
/// CRC 8-bit checksum (CRC-8/BLUETOOTH)
|
||||
/// </summary>
|
||||
CRC8_BLUETOOTH,
|
||||
|
||||
/// <summary>
|
||||
/// CRC 8-bit checksum (CRC-8/CDMA2000)
|
||||
/// </summary>
|
||||
CRC8_CDMA2000,
|
||||
|
||||
/// <summary>
|
||||
/// CRC 8-bit checksum (CRC-8/DARC)
|
||||
/// </summary>
|
||||
CRC8_DARC,
|
||||
|
||||
/// <summary>
|
||||
/// CRC 8-bit checksum (CRC-8/DVB-S2)
|
||||
/// </summary>
|
||||
CRC8_DVBS2,
|
||||
|
||||
/// <summary>
|
||||
/// CRC 8-bit checksum (CRC-8/GSM-A)
|
||||
/// </summary>
|
||||
CRC8_GSMA,
|
||||
|
||||
/// <summary>
|
||||
/// CRC 8-bit checksum (CRC-8/GSM-B)
|
||||
/// </summary>
|
||||
CRC8_GSMB,
|
||||
|
||||
/// <summary>
|
||||
/// CRC 8-bit checksum (CRC-8/HITAG)
|
||||
/// </summary>
|
||||
CRC8_HITAG,
|
||||
|
||||
/// <summary>
|
||||
/// CRC 8-bit checksum (CRC-8/I-432-1 [CRC-8/ITU])
|
||||
/// </summary>
|
||||
CRC8_I4321,
|
||||
|
||||
/// <summary>
|
||||
/// CRC 8-bit checksum (CRC-8/I-CODE)
|
||||
/// </summary>
|
||||
CRC8_ICODE,
|
||||
|
||||
/// <summary>
|
||||
/// CRC 8-bit checksum (CRC-8/LTE)
|
||||
/// </summary>
|
||||
CRC8_LTE,
|
||||
|
||||
/// <summary>
|
||||
/// CRC 8-bit checksum (CRC-8/MAXIM-DOW [CRC-8/MAXIM, DOW-CRC])
|
||||
/// </summary>
|
||||
CRC8_MAXIMDOW,
|
||||
|
||||
/// <summary>
|
||||
/// CRC 8-bit checksum (CRC-8/MIFARE-MAD)
|
||||
/// </summary>
|
||||
CRC8_MIFAREMAD,
|
||||
|
||||
/// <summary>
|
||||
/// CRC 8-bit checksum (CRC-8/NRSC-5)
|
||||
/// </summary>
|
||||
CRC8_NRSC5,
|
||||
|
||||
/// <summary>
|
||||
/// CRC 8-bit checksum (CRC-8/OPENSAFETY)
|
||||
/// </summary>
|
||||
CRC8_OPENSAFETY,
|
||||
|
||||
/// <summary>
|
||||
/// CRC 8-bit checksum (CRC-8/ROHC)
|
||||
/// </summary>
|
||||
CRC8_ROHC,
|
||||
|
||||
/// <summary>
|
||||
/// CRC 8-bit checksum (CRC-8/SAE-J1850)
|
||||
/// </summary>
|
||||
CRC8_SAEJ1850,
|
||||
|
||||
/// <summary>
|
||||
/// CRC 8-bit checksum (CRC-8/SMBUS [CRC-8])
|
||||
/// </summary>
|
||||
CRC8_SMBUS,
|
||||
|
||||
/// <summary>
|
||||
/// CRC 8-bit checksum (CRC-8/TECH-3250 [CRC-8/AES, CRC-8/EBU])
|
||||
/// </summary>
|
||||
CRC8_TECH3250,
|
||||
|
||||
/// <summary>
|
||||
/// CRC 8-bit checksum (CRC-8/WCDMA)
|
||||
/// </summary>
|
||||
CRC8_WCDMA,
|
||||
|
||||
#endregion
|
||||
|
||||
#region CRC-10
|
||||
|
||||
/// <summary>
|
||||
/// CRC 10-bit checksum (CRC-10/ATM [CRC-10, CRC-10/I-610])
|
||||
/// </summary>
|
||||
CRC10_ATM,
|
||||
|
||||
/// <summary>
|
||||
/// CRC 10-bit checksum (CRC-10/CDMA2000)
|
||||
/// </summary>
|
||||
CRC10_CDMA2000,
|
||||
|
||||
/// <summary>
|
||||
/// CRC 10-bit checksum (CRC-10/GSM)
|
||||
/// </summary>
|
||||
CRC10_GSM,
|
||||
|
||||
#endregion
|
||||
|
||||
#region CRC-11
|
||||
|
||||
/// <summary>
|
||||
/// CRC 11-bit checksum (CRC-11/FLEXRAY [CRC-11])
|
||||
/// </summary>
|
||||
CRC11_FLEXRAY,
|
||||
|
||||
/// <summary>
|
||||
/// CRC 11-bit checksum (CRC-11/UMTS)
|
||||
/// </summary>
|
||||
CRC11_UMTS,
|
||||
|
||||
#endregion
|
||||
|
||||
#region CRC-12
|
||||
|
||||
/// <summary>
|
||||
/// CRC 12-bit checksum (CRC-12/CDMA2000)
|
||||
/// </summary>
|
||||
CRC12_CDMA2000,
|
||||
|
||||
/// <summary>
|
||||
/// CRC 12-bit checksum (CRC-12/DECT [X-CRC-12])
|
||||
/// </summary>
|
||||
CRC12_DECT,
|
||||
|
||||
/// <summary>
|
||||
/// CRC 12-bit checksum (CRC-12/GSM)
|
||||
/// </summary>
|
||||
CRC12_GSM,
|
||||
|
||||
/// <summary>
|
||||
/// CRC 12-bit checksum (CRC-12/UMTS [CRC-12/3GPP])
|
||||
/// </summary>
|
||||
CRC12_UMTS,
|
||||
|
||||
#endregion
|
||||
|
||||
#region CRC-13
|
||||
|
||||
/// <summary>
|
||||
/// CRC 13-bit checksum (CRC-13/BBC)
|
||||
/// </summary>
|
||||
CRC13_BBC,
|
||||
|
||||
#endregion
|
||||
|
||||
#region CRC-14
|
||||
|
||||
/// <summary>
|
||||
/// CRC 14-bit checksum (CRC-14/DARC)
|
||||
/// </summary>
|
||||
CRC14_DARC,
|
||||
|
||||
/// <summary>
|
||||
/// CRC 14-bit checksum (CRC-14/GSM)
|
||||
/// </summary>
|
||||
CRC14_GSM,
|
||||
|
||||
#endregion
|
||||
|
||||
#region CRC-15
|
||||
|
||||
/// <summary>
|
||||
/// CRC 15-bit checksum (CRC-15/CAN [CRC-15])
|
||||
/// </summary>
|
||||
CRC15_CAN,
|
||||
|
||||
/// <summary>
|
||||
/// CRC 15-bit checksum (CRC-15/MPT1327)
|
||||
/// </summary>
|
||||
CRC15_MPT1327,
|
||||
|
||||
#endregion
|
||||
|
||||
#region CRC-16
|
||||
|
||||
/// <summary>
|
||||
/// CRC 16-bit checksum
|
||||
/// </summary>
|
||||
/// <remarks>Identical to <see cref="CRC16_ARC"/>
|
||||
CRC16,
|
||||
|
||||
/// <summary>
|
||||
/// CRC 16-bit checksum (CRC-16/ARC [ARC, CRC-16, CRC-16/LHA, CRC-IBM])
|
||||
/// </summary>
|
||||
CRC16_ARC,
|
||||
|
||||
/// <summary>
|
||||
/// CRC 16-bit checksum (CRC-16/CDMA2000)
|
||||
/// </summary>
|
||||
CRC16_CDMA2000,
|
||||
|
||||
/// <summary>
|
||||
/// CRC 16-bit checksum (CRC-16/CMS)
|
||||
/// </summary>
|
||||
CRC16_CMS,
|
||||
|
||||
/// <summary>
|
||||
/// CRC 16-bit checksum (CRC-16/DDS-110)
|
||||
/// </summary>
|
||||
CRC16_DDS110,
|
||||
|
||||
/// <summary>
|
||||
/// CRC 16-bit checksum (CRC-16/DECT-R [R-CRC-16])
|
||||
/// </summary>
|
||||
CRC16_DECTR,
|
||||
|
||||
/// <summary>
|
||||
/// CRC 16-bit checksum (CRC-16/DECT-X [X-CRC-16])
|
||||
/// </summary>
|
||||
CRC16_DECTX,
|
||||
|
||||
/// <summary>
|
||||
/// CRC 16-bit checksum (CRC-16/DNP)
|
||||
/// </summary>
|
||||
CRC16_DNP,
|
||||
|
||||
/// <summary>
|
||||
/// CRC 16-bit checksum (CRC-16/EN-13757)
|
||||
/// </summary>
|
||||
CRC16_EN13757,
|
||||
|
||||
/// <summary>
|
||||
/// CRC 16-bit checksum (CRC-16/GENIBUS [CRC-16/DARC, CRC-16/EPC, CRC-16/EPC-C1G2, CRC-16/I-CODE])
|
||||
/// </summary>
|
||||
CRC16_GENIBUS,
|
||||
|
||||
/// <summary>
|
||||
/// CRC 16-bit checksum (CRC-16/GSM)
|
||||
/// </summary>
|
||||
CRC16_GSM,
|
||||
|
||||
/// <summary>
|
||||
/// CRC 16-bit checksum (CRC-16/IBM-3740 [CRC-16/AUTOSAR, CRC-16/CCITT-FALSE])
|
||||
/// </summary>
|
||||
CRC16_IBM3740,
|
||||
|
||||
/// <summary>
|
||||
/// CRC 16-bit checksum (CRC-16/IBM-SDLC [CRC-16/ISO-HDLC, CRC-16/ISO-IEC-14443-3-B, CRC-16/X-25, CRC-B, X-25])
|
||||
/// </summary>
|
||||
CRC16_IBMSDLC,
|
||||
|
||||
/// <summary>
|
||||
/// CRC 16-bit checksum (CRC-16/ISO-IEC-14443-3-A [CRC-A])
|
||||
/// </summary>
|
||||
CRC16_ISOIEC144433A,
|
||||
|
||||
/// <summary>
|
||||
/// CRC 16-bit checksum (CRC-16/KERMIT [CRC-16/BLUETOOTH, CRC-16/CCITT, CRC-16/CCITT-TRUE, CRC-16/V-41-LSB, CRC-CCITT, KERMIT])
|
||||
/// </summary>
|
||||
CRC16_KERMIT,
|
||||
|
||||
/// <summary>
|
||||
/// CRC 16-bit checksum (CRC-16/LJ1200)
|
||||
/// </summary>
|
||||
CRC16_LJ1200,
|
||||
|
||||
/// <summary>
|
||||
/// CRC 16-bit checksum (CRC-16/M17)
|
||||
/// </summary>
|
||||
CRC16_M17,
|
||||
|
||||
/// <summary>
|
||||
/// CRC 16-bit checksum (CRC-16/MAXIM-DOW [CRC-16/MAXIM])
|
||||
/// </summary>
|
||||
CRC16_MAXIMDOW,
|
||||
|
||||
/// <summary>
|
||||
/// CRC 16-bit checksum (CRC-16/MCRF4XX)
|
||||
/// </summary>
|
||||
CRC16_MCRF4XX,
|
||||
|
||||
/// <summary>
|
||||
/// CRC 16-bit checksum (CRC-16/MODBUS [MODBUS])
|
||||
/// </summary>
|
||||
CRC16_MODBUS,
|
||||
|
||||
/// <summary>
|
||||
/// CRC 16-bit checksum (CRC-16/NRSC-5)
|
||||
/// </summary>
|
||||
CRC16_NRSC5,
|
||||
|
||||
/// <summary>
|
||||
/// CRC 16-bit checksum (CRC-16/OPENSAFETY-A)
|
||||
/// </summary>
|
||||
CRC16_OPENSAFETYA,
|
||||
|
||||
/// <summary>
|
||||
/// CRC 16-bit checksum (CRC-16/OPENSAFETY-B)
|
||||
/// </summary>
|
||||
CRC16_OPENSAFETYB,
|
||||
|
||||
/// <summary>
|
||||
/// CRC 16-bit checksum (CRC-16/PROFIBUS [CRC-16/IEC-61158-2])
|
||||
/// </summary>
|
||||
CRC16_PROFIBUS,
|
||||
|
||||
/// <summary>
|
||||
/// CRC 16-bit checksum (CRC-16/RIELLO)
|
||||
/// </summary>
|
||||
CRC16_RIELLO,
|
||||
|
||||
/// <summary>
|
||||
/// CRC 16-bit checksum (CRC-16/SPI-FUJITSU [CRC-16/AUG-CCITT])
|
||||
/// </summary>
|
||||
CRC16_SPIFUJITSU,
|
||||
|
||||
/// <summary>
|
||||
/// CRC 16-bit checksum (CRC-16/T10-DIF)
|
||||
/// </summary>
|
||||
CRC16_T10DIF,
|
||||
|
||||
/// <summary>
|
||||
/// CRC 16-bit checksum (CRC-16/TELEDISK)
|
||||
/// </summary>
|
||||
CRC16_TELEDISK,
|
||||
|
||||
/// <summary>
|
||||
/// CRC 16-bit checksum (CRC-16/TMS37157)
|
||||
/// </summary>
|
||||
CRC16_TMS37157,
|
||||
|
||||
/// <summary>
|
||||
/// CRC 16-bit checksum (CRC-16/UMTS [CRC-16/BUYPASS, CRC-16/VERIFONE])
|
||||
/// </summary>
|
||||
CRC16_UMTS,
|
||||
|
||||
/// <summary>
|
||||
/// CRC 16-bit checksum (CRC-16/USB)
|
||||
/// </summary>
|
||||
CRC16_USB,
|
||||
|
||||
/// <summary>
|
||||
/// CRC 16-bit checksum (CRC-16/XMODEM [CRC-16/ACORN, CRC-16/LTE, CRC-16/V-41-MSB, XMODEM, ZMODEM])
|
||||
/// </summary>
|
||||
CRC16_XMODEM,
|
||||
|
||||
#endregion
|
||||
|
||||
#region CRC-17
|
||||
|
||||
/// <summary>
|
||||
/// CRC 17-bit checksum (CRC-17/CAN-FD)
|
||||
/// </summary>
|
||||
CRC17_CANFD,
|
||||
|
||||
#endregion
|
||||
|
||||
#region CRC-21
|
||||
|
||||
/// <summary>
|
||||
/// CRC 21-bit checksum (CRC-21/CAN-FD)
|
||||
/// </summary>
|
||||
CRC21_CANFD,
|
||||
|
||||
#endregion
|
||||
|
||||
#region CRC-24
|
||||
|
||||
/// <summary>
|
||||
/// CRC 24-bit checksum (CRC-24/BLE)
|
||||
/// </summary>
|
||||
CRC24_BLE,
|
||||
|
||||
/// <summary>
|
||||
/// CRC 24-bit checksum (CRC-24/FLEXRAY-A)
|
||||
/// </summary>
|
||||
CRC24_FLEXRAYA,
|
||||
|
||||
/// <summary>
|
||||
/// CRC 24-bit checksum (CRC-24/FLEXRAY-B)
|
||||
/// </summary>
|
||||
CRC24_FLEXRAYB,
|
||||
|
||||
/// <summary>
|
||||
/// CRC 24-bit checksum (CRC-24/INTERLAKEN)
|
||||
/// </summary>
|
||||
CRC24_INTERLAKEN,
|
||||
|
||||
/// <summary>
|
||||
/// CRC 24-bit checksum (CRC-24/LTE-A)
|
||||
/// </summary>
|
||||
CRC24_LTEA,
|
||||
|
||||
/// <summary>
|
||||
/// CRC 24-bit checksum (CRC-24/LTE-B)
|
||||
/// </summary>
|
||||
CRC24_LTEB,
|
||||
|
||||
/// <summary>
|
||||
/// CRC 24-bit checksum (CRC-24/OPENPGP)
|
||||
/// </summary>
|
||||
CRC24_OPENPGP,
|
||||
|
||||
/// <summary>
|
||||
/// CRC 24-bit checksum (CRC-24/OS-9)
|
||||
/// </summary>
|
||||
CRC24_OS9,
|
||||
|
||||
#endregion
|
||||
|
||||
#region CRC-30
|
||||
|
||||
/// <summary>
|
||||
/// CRC 30-bit checksum (CRC-30/CDMA)
|
||||
/// </summary>
|
||||
CRC30_CDMA,
|
||||
|
||||
#endregion
|
||||
|
||||
#region CRC-31
|
||||
|
||||
/// <summary>
|
||||
/// CRC 31-bit checksum (CRC-31/PHILIPS)
|
||||
/// </summary>
|
||||
CRC31_PHILIPS,
|
||||
|
||||
#endregion
|
||||
|
||||
#region CRC-32
|
||||
|
||||
/// <summary>
|
||||
/// CRC 32-bit checksum
|
||||
/// </summary>
|
||||
/// <remarks>Identical to <see cref="CRC32_ISOHDLC"/>
|
||||
CRC32,
|
||||
|
||||
#if NET462_OR_GREATER || NETCOREAPP
|
||||
/// <summary>
|
||||
/// CRC 32-bit checksum (CRC-32/AIXM)
|
||||
/// </summary>
|
||||
CRC32_AIXM,
|
||||
|
||||
/// <summary>
|
||||
/// CRC 32-bit checksum (CRC-32/AUTOSAR)
|
||||
/// </summary>
|
||||
CRC32_AUTOSAR,
|
||||
|
||||
/// <summary>
|
||||
/// CRC 32-bit checksum (CRC-32/BASE91-D)
|
||||
/// </summary>
|
||||
CRC32_BASE91D,
|
||||
|
||||
/// <summary>
|
||||
/// CRC 32-bit checksum (BZIP2)
|
||||
/// </summary>
|
||||
CRC32_BZIP2,
|
||||
|
||||
/// <summary>
|
||||
/// CRC 32-bit checksum (CRC-32/CD-ROM-EDC)
|
||||
/// </summary>
|
||||
CRC32_CDROMEDC,
|
||||
|
||||
/// <summary>
|
||||
/// CRC 32-bit checksum (CRC-32/CKSUM)
|
||||
/// </summary>
|
||||
CRC32_CKSUM,
|
||||
|
||||
/// <summary>
|
||||
/// CRC 32-bit checksum (CRC-32/ISCSI)
|
||||
/// </summary>
|
||||
CRC32_ISCSI,
|
||||
|
||||
/// <summary>
|
||||
/// CRC 32-bit checksum (CRC-32/ISO-HDLC)
|
||||
/// </summary>
|
||||
CRC32_ISOHDLC,
|
||||
|
||||
/// <summary>
|
||||
/// CRC 32-bit checksum (CRC-32/JAMCRC)
|
||||
/// </summary>
|
||||
CRC32_JAMCRC,
|
||||
|
||||
/// <summary>
|
||||
/// CRC 32-bit checksum (CRC-32/MEF)
|
||||
/// </summary>
|
||||
CRC32_MEF,
|
||||
|
||||
/// <summary>
|
||||
/// CRC 32-bit checksum (CRC-32/MPEG-2)
|
||||
/// </summary>
|
||||
CRC32_MPEG2,
|
||||
|
||||
/// <summary>
|
||||
/// CRC 32-bit checksum (CRC-32/XFER)
|
||||
/// </summary>
|
||||
CRC32_XFER,
|
||||
|
||||
#endregion
|
||||
|
||||
#region CRC-40
|
||||
|
||||
/// <summary>
|
||||
/// CRC 40-bit checksum (CRC-40/GSM)
|
||||
/// </summary>
|
||||
CRC40_GSM,
|
||||
|
||||
#endregion
|
||||
|
||||
#region CRC-64
|
||||
|
||||
/// <summary>
|
||||
/// CRC 64-bit checksum
|
||||
/// </summary>
|
||||
/// <remarks>Identical to <see cref="CRC64_ECMA182"/>
|
||||
CRC64,
|
||||
#endif
|
||||
|
||||
/// <summary>
|
||||
/// MD5 hash
|
||||
/// CRC 64-bit checksum (CRC-64/ECMA-182, Microsoft implementation)
|
||||
/// </summary>
|
||||
CRC64_ECMA182,
|
||||
|
||||
/// <summary>
|
||||
/// CRC 64-bit checksum (CRC-64/GO-ISO)
|
||||
/// </summary>
|
||||
CRC64_GOISO,
|
||||
|
||||
/// <summary>
|
||||
/// CRC 64-bit checksum (CRC-64/MS)
|
||||
/// </summary>
|
||||
CRC64_MS,
|
||||
|
||||
/// <summary>
|
||||
/// CRC 64-bit checksum (CRC-64/NVME)
|
||||
/// </summary>
|
||||
CRC64_NVME,
|
||||
|
||||
/// <summary>
|
||||
/// CRC 64-bit checksum (CRC-64/REDIS)
|
||||
/// </summary>
|
||||
CRC64_REDIS,
|
||||
|
||||
/// <summary>
|
||||
/// CRC 64-bit checksum (CRC-64/WE)
|
||||
/// </summary>
|
||||
CRC64_WE,
|
||||
|
||||
/// <summary>
|
||||
/// CRC 64-bit checksum (CRC-64/XZ)
|
||||
/// </summary>
|
||||
CRC64_XZ,
|
||||
|
||||
#endregion
|
||||
|
||||
#endregion
|
||||
|
||||
#region Fletcher
|
||||
|
||||
/// <summary>
|
||||
/// John G. Fletcher's 16-bit checksum
|
||||
/// </summary>
|
||||
Fletcher16,
|
||||
|
||||
/// <summary>
|
||||
/// John G. Fletcher's 32-bit checksum
|
||||
/// </summary>
|
||||
Fletcher32,
|
||||
|
||||
/// <summary>
|
||||
/// John G. Fletcher's 64-bit checksum
|
||||
/// </summary>
|
||||
Fletcher64,
|
||||
|
||||
#endregion
|
||||
|
||||
#region FNV
|
||||
|
||||
/// <summary>
|
||||
/// FNV hash (Variant 0, 32-bit)
|
||||
/// </summary>
|
||||
FNV0_32,
|
||||
|
||||
/// <summary>
|
||||
/// FNV hash (Variant 0, 64-bit)
|
||||
/// </summary>
|
||||
FNV0_64,
|
||||
|
||||
/// <summary>
|
||||
/// FNV hash (Variant 1, 32-bit)
|
||||
/// </summary>
|
||||
FNV1_32,
|
||||
|
||||
/// <summary>
|
||||
/// FNV hash (Variant 1, 64-bit)
|
||||
/// </summary>
|
||||
FNV1_64,
|
||||
|
||||
/// <summary>
|
||||
/// FNV hash (Variant 1a, 32-bit)
|
||||
/// </summary>
|
||||
FNV1a_32,
|
||||
|
||||
/// <summary>
|
||||
/// FNV hash (Variant 1a, 64-bit)
|
||||
/// </summary>
|
||||
FNV1a_64,
|
||||
|
||||
#endregion
|
||||
|
||||
#region Message Digest
|
||||
|
||||
/// <summary>
|
||||
/// MD2 message-digest algorithm
|
||||
/// </summary>
|
||||
MD2,
|
||||
|
||||
/// <summary>
|
||||
/// MD4 message-digest algorithm
|
||||
/// </summary>
|
||||
MD4,
|
||||
|
||||
/// <summary>
|
||||
/// MD5 message-digest algorithm
|
||||
/// </summary>
|
||||
MD5,
|
||||
|
||||
#endregion
|
||||
|
||||
#region RIPEMD
|
||||
|
||||
/// <summary>
|
||||
/// RIPEMD-128 hash
|
||||
/// </summary>
|
||||
RIPEMD128,
|
||||
|
||||
/// <summary>
|
||||
/// RIPEMD-160 hash
|
||||
/// </summary>
|
||||
RIPEMD160,
|
||||
|
||||
/// <summary>
|
||||
/// RIPEMD-256 hash
|
||||
/// </summary>
|
||||
RIPEMD256,
|
||||
|
||||
/// <summary>
|
||||
/// RIPEMD-320 hash
|
||||
/// </summary>
|
||||
RIPEMD320,
|
||||
|
||||
#endregion
|
||||
|
||||
#region SHA
|
||||
|
||||
/// <summary>
|
||||
/// SHA-1 hash
|
||||
/// </summary>
|
||||
@@ -42,12 +821,108 @@ namespace SabreTools.Hashing
|
||||
/// </summary>
|
||||
SHA512,
|
||||
|
||||
#if NET8_0_OR_GREATER
|
||||
/// <summary>
|
||||
/// SHA3-256 hash
|
||||
/// </summary>
|
||||
SHA3_256,
|
||||
|
||||
/// <summary>
|
||||
/// SHA3-384 hash
|
||||
/// </summary>
|
||||
SHA3_384,
|
||||
|
||||
/// <summary>
|
||||
/// SHA3-512 hash
|
||||
/// </summary>
|
||||
SHA3_512,
|
||||
|
||||
/// <summary>
|
||||
/// SHAKE128 SHA-3 family hash
|
||||
/// </summary>
|
||||
/// <remarks>Outputs a 256-bit (32-byte) hash</remarks>
|
||||
SHAKE128,
|
||||
|
||||
/// <summary>
|
||||
/// SHAKE256 SHA-3 family hash
|
||||
/// </summary>
|
||||
/// <remarks>Outputs a 512-bit (64-byte) hash</remarks>
|
||||
SHAKE256,
|
||||
#endif
|
||||
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// spamsum fuzzy hash
|
||||
/// </summary>
|
||||
SpamSum,
|
||||
|
||||
#if NET462_OR_GREATER || NETCOREAPP
|
||||
#region Tiger
|
||||
|
||||
/// <summary>
|
||||
/// Tiger 128-bit hash, 3 passes
|
||||
/// </summary>
|
||||
Tiger128_3,
|
||||
|
||||
/// <summary>
|
||||
/// Tiger 128-bit hash, 4 passes
|
||||
/// </summary>
|
||||
Tiger128_4,
|
||||
|
||||
/// <summary>
|
||||
/// Tiger 160-bit hash, 3 passes
|
||||
/// </summary>
|
||||
Tiger160_3,
|
||||
|
||||
/// <summary>
|
||||
/// Tiger 160-bit hash, 4 passes
|
||||
/// </summary>
|
||||
Tiger160_4,
|
||||
|
||||
/// <summary>
|
||||
/// Tiger 192-bit hash, 3 passes
|
||||
/// </summary>
|
||||
Tiger192_3,
|
||||
|
||||
/// <summary>
|
||||
/// Tiger 192-bit hash, 4 passes
|
||||
/// </summary>
|
||||
Tiger192_4,
|
||||
|
||||
/// <summary>
|
||||
/// Tiger2 128-bit hash, 3 passes
|
||||
/// </summary>
|
||||
Tiger2_128_3,
|
||||
|
||||
/// <summary>
|
||||
/// Tiger2 128-bit hash, 4 passes
|
||||
/// </summary>
|
||||
Tiger2_128_4,
|
||||
|
||||
/// <summary>
|
||||
/// Tiger2 160-bit hash, 3 passes
|
||||
/// </summary>
|
||||
Tiger2_160_3,
|
||||
|
||||
/// <summary>
|
||||
/// Tiger2 160-bit hash, 4 passes
|
||||
/// </summary>
|
||||
Tiger2_160_4,
|
||||
|
||||
/// <summary>
|
||||
/// Tiger2 192-bit hash, 3 passes
|
||||
/// </summary>
|
||||
Tiger2_192_3,
|
||||
|
||||
/// <summary>
|
||||
/// Tiger2 192-bit hash, 4 passes
|
||||
/// </summary>
|
||||
Tiger2_192_4,
|
||||
|
||||
#endregion
|
||||
|
||||
#region xxHash
|
||||
|
||||
/// <summary>
|
||||
/// xxHash32 hash
|
||||
/// </summary>
|
||||
@@ -58,6 +933,7 @@ namespace SabreTools.Hashing
|
||||
/// </summary>
|
||||
XxHash64,
|
||||
|
||||
#if NET462_OR_GREATER || NETCOREAPP
|
||||
/// <summary>
|
||||
/// XXH3 64-bit hash
|
||||
/// </summary>
|
||||
@@ -68,5 +944,7 @@ namespace SabreTools.Hashing
|
||||
/// </summary>
|
||||
XxHash128,
|
||||
#endif
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -2,10 +2,14 @@ using System;
|
||||
#if NET462_OR_GREATER || NETCOREAPP
|
||||
using System.IO.Hashing;
|
||||
#endif
|
||||
using System.Linq;
|
||||
using System.Security.Cryptography;
|
||||
using Aaru.Checksums;
|
||||
using Aaru.CommonTypes.Interfaces;
|
||||
#if NET7_0_OR_GREATER
|
||||
using Blake3;
|
||||
#endif
|
||||
using SabreTools.Hashing.Checksum;
|
||||
using static SabreTools.Hashing.HashOperations;
|
||||
|
||||
namespace SabreTools.Hashing
|
||||
{
|
||||
@@ -19,11 +23,7 @@ namespace SabreTools.Hashing
|
||||
/// <summary>
|
||||
/// Hash type associated with the current state
|
||||
/// </summary>
|
||||
#if NETFRAMEWORK || NETCOREAPP3_1
|
||||
public HashType HashType { get; private set; }
|
||||
#else
|
||||
public HashType HashType { get; init; }
|
||||
#endif
|
||||
public readonly HashType HashType;
|
||||
|
||||
/// <summary>
|
||||
/// Current hash in bytes
|
||||
@@ -32,17 +32,52 @@ namespace SabreTools.Hashing
|
||||
{
|
||||
get
|
||||
{
|
||||
return _hasher switch
|
||||
switch (_hasher)
|
||||
{
|
||||
HashAlgorithm ha => ha.Hash,
|
||||
IChecksum ic => ic.Final(),
|
||||
case ChecksumBase cb:
|
||||
var cbArr = cb.Finalize();
|
||||
Array.Reverse(cbArr);
|
||||
return cbArr;
|
||||
|
||||
case HashAlgorithm ha:
|
||||
return ha.Hash;
|
||||
|
||||
case IChecksum ic:
|
||||
return ic.Final();
|
||||
|
||||
case MessageDigest.MessageDigestBase mdb:
|
||||
return mdb.GetHash();
|
||||
|
||||
#if NET462_OR_GREATER || NETCOREAPP
|
||||
NonCryptographicHashAlgorithm ncha => ncha.GetCurrentHash().Reverse().ToArray(),
|
||||
#else
|
||||
OptimizedCRC.OptimizedCRC ocrc => BitConverter.GetBytes(ocrc.Value).Reverse().ToArray(),
|
||||
case XxHash3 xxh3:
|
||||
return xxh3.GetCurrentHash();
|
||||
case XxHash128 xxh128:
|
||||
return xxh128.GetCurrentHash();
|
||||
case NonCryptographicHashAlgorithm ncha:
|
||||
var nchaArr = ncha.GetCurrentHash();
|
||||
Array.Reverse(nchaArr);
|
||||
return nchaArr;
|
||||
#endif
|
||||
_ => null,
|
||||
};
|
||||
|
||||
#if NET8_0_OR_GREATER
|
||||
case Shake128 s128:
|
||||
return s128.GetCurrentHash(32);
|
||||
case Shake256 s256:
|
||||
return s256.GetCurrentHash(64);
|
||||
#endif
|
||||
|
||||
case XxHash.XxHash32 xxh32:
|
||||
var xxh32Arr = xxh32.Finalize();
|
||||
Array.Reverse(xxh32Arr);
|
||||
return xxh32Arr;
|
||||
case XxHash.XxHash64 xxh64:
|
||||
var xxh64Arr = xxh64.Finalize();
|
||||
Array.Reverse(xxh64Arr);
|
||||
return xxh64Arr;
|
||||
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -53,11 +88,19 @@ namespace SabreTools.Hashing
|
||||
{
|
||||
get
|
||||
{
|
||||
return _hasher switch
|
||||
switch (_hasher)
|
||||
{
|
||||
IChecksum ic => ic.End(),
|
||||
_ => ByteArrayToString(CurrentHashBytes),
|
||||
};
|
||||
case Crc cr:
|
||||
var crArr = cr.Finalize();
|
||||
ulong crHash = BytesToUInt64(crArr);
|
||||
int length = cr.Def.Width / 4 + (cr.Def.Width % 4 > 0 ? 1 : 0);
|
||||
return crHash.ToString($"x{length}");
|
||||
case IChecksum ic:
|
||||
return ic.End();
|
||||
|
||||
default:
|
||||
return ByteArrayToString(CurrentHashBytes);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -81,7 +124,7 @@ namespace SabreTools.Hashing
|
||||
/// <param name="hashType">Hash type to instantiate</param>
|
||||
public HashWrapper(HashType hashType)
|
||||
{
|
||||
this.HashType = hashType;
|
||||
HashType = hashType;
|
||||
GetHasher();
|
||||
}
|
||||
|
||||
@@ -92,21 +135,202 @@ namespace SabreTools.Hashing
|
||||
{
|
||||
_hasher = HashType switch
|
||||
{
|
||||
#if NET462_OR_GREATER || NETCOREAPP
|
||||
HashType.CRC32 => new Crc32(),
|
||||
HashType.CRC64 => new Crc64(),
|
||||
#else
|
||||
HashType.CRC32 => new OptimizedCRC.OptimizedCRC(),
|
||||
HashType.Adler32 => new Adler32(),
|
||||
|
||||
#if NET7_0_OR_GREATER
|
||||
HashType.BLAKE3 => new Blake3HashAlgorithm(),
|
||||
#endif
|
||||
|
||||
HashType.CRC1_ZERO => new Crc(StandardDefinitions.CRC1_ZERO),
|
||||
HashType.CRC1_ONE => new Crc(StandardDefinitions.CRC1_ONE),
|
||||
|
||||
HashType.CRC3_GSM => new Crc(StandardDefinitions.CRC3_GSM),
|
||||
HashType.CRC3_ROHC => new Crc(StandardDefinitions.CRC3_ROHC),
|
||||
|
||||
HashType.CRC4_G704 => new Crc(StandardDefinitions.CRC4_G704),
|
||||
HashType.CRC4_INTERLAKEN => new Crc(StandardDefinitions.CRC4_INTERLAKEN),
|
||||
|
||||
HashType.CRC5_EPCC1G2 => new Crc(StandardDefinitions.CRC5_EPCC1G2),
|
||||
HashType.CRC5_G704 => new Crc(StandardDefinitions.CRC5_G704),
|
||||
HashType.CRC5_USB => new Crc(StandardDefinitions.CRC5_USB),
|
||||
|
||||
HashType.CRC6_CDMA2000A => new Crc(StandardDefinitions.CRC6_CDMA2000A),
|
||||
HashType.CRC6_CDMA2000B => new Crc(StandardDefinitions.CRC6_CDMA2000B),
|
||||
HashType.CRC6_DARC => new Crc(StandardDefinitions.CRC6_DARC),
|
||||
HashType.CRC6_G704 => new Crc(StandardDefinitions.CRC6_G704),
|
||||
HashType.CRC6_GSM => new Crc(StandardDefinitions.CRC6_GSM),
|
||||
|
||||
HashType.CRC7_MMC => new Crc(StandardDefinitions.CRC7_MMC),
|
||||
HashType.CRC7_ROHC => new Crc(StandardDefinitions.CRC7_ROHC),
|
||||
HashType.CRC7_UMTS => new Crc(StandardDefinitions.CRC7_UMTS),
|
||||
|
||||
HashType.CRC8 => new Crc(StandardDefinitions.CRC8_SMBUS),
|
||||
HashType.CRC8_AUTOSAR => new Crc(StandardDefinitions.CRC8_AUTOSAR),
|
||||
HashType.CRC8_BLUETOOTH => new Crc(StandardDefinitions.CRC8_BLUETOOTH),
|
||||
HashType.CRC8_CDMA2000 => new Crc(StandardDefinitions.CRC8_CDMA2000),
|
||||
HashType.CRC8_DARC => new Crc(StandardDefinitions.CRC8_DARC),
|
||||
HashType.CRC8_DVBS2 => new Crc(StandardDefinitions.CRC8_DVBS2),
|
||||
HashType.CRC8_GSMA => new Crc(StandardDefinitions.CRC8_GSMA),
|
||||
HashType.CRC8_GSMB => new Crc(StandardDefinitions.CRC8_GSMB),
|
||||
HashType.CRC8_HITAG => new Crc(StandardDefinitions.CRC8_HITAG),
|
||||
HashType.CRC8_I4321 => new Crc(StandardDefinitions.CRC8_I4321),
|
||||
HashType.CRC8_ICODE => new Crc(StandardDefinitions.CRC8_ICODE),
|
||||
HashType.CRC8_LTE => new Crc(StandardDefinitions.CRC8_LTE),
|
||||
HashType.CRC8_MAXIMDOW => new Crc(StandardDefinitions.CRC8_MAXIMDOW),
|
||||
HashType.CRC8_MIFAREMAD => new Crc(StandardDefinitions.CRC8_MIFAREMAD),
|
||||
HashType.CRC8_NRSC5 => new Crc(StandardDefinitions.CRC8_NRSC5),
|
||||
HashType.CRC8_OPENSAFETY => new Crc(StandardDefinitions.CRC8_OPENSAFETY),
|
||||
HashType.CRC8_ROHC => new Crc(StandardDefinitions.CRC8_ROHC),
|
||||
HashType.CRC8_SAEJ1850 => new Crc(StandardDefinitions.CRC8_SAEJ1850),
|
||||
HashType.CRC8_SMBUS => new Crc(StandardDefinitions.CRC8_SMBUS),
|
||||
HashType.CRC8_TECH3250 => new Crc(StandardDefinitions.CRC8_TECH3250),
|
||||
HashType.CRC8_WCDMA => new Crc(StandardDefinitions.CRC8_WCDMA),
|
||||
|
||||
HashType.CRC10_ATM => new Crc(StandardDefinitions.CRC10_ATM),
|
||||
HashType.CRC10_CDMA2000 => new Crc(StandardDefinitions.CRC10_CDMA2000),
|
||||
HashType.CRC10_GSM => new Crc(StandardDefinitions.CRC10_GSM),
|
||||
|
||||
HashType.CRC11_FLEXRAY => new Crc(StandardDefinitions.CRC11_FLEXRAY),
|
||||
HashType.CRC11_UMTS => new Crc(StandardDefinitions.CRC11_UMTS),
|
||||
|
||||
HashType.CRC12_CDMA2000 => new Crc(StandardDefinitions.CRC12_CDMA2000),
|
||||
HashType.CRC12_DECT => new Crc(StandardDefinitions.CRC12_DECT),
|
||||
HashType.CRC12_GSM => new Crc(StandardDefinitions.CRC12_GSM),
|
||||
HashType.CRC12_UMTS => new Crc(StandardDefinitions.CRC12_UMTS),
|
||||
|
||||
HashType.CRC13_BBC => new Crc(StandardDefinitions.CRC13_BBC),
|
||||
|
||||
HashType.CRC14_DARC => new Crc(StandardDefinitions.CRC14_DARC),
|
||||
HashType.CRC14_GSM => new Crc(StandardDefinitions.CRC14_GSM),
|
||||
|
||||
HashType.CRC15_CAN => new Crc(StandardDefinitions.CRC15_CAN),
|
||||
HashType.CRC15_MPT1327 => new Crc(StandardDefinitions.CRC15_MPT1327),
|
||||
|
||||
HashType.CRC16 => new Crc(StandardDefinitions.CRC16_ARC),
|
||||
HashType.CRC16_ARC => new Crc(StandardDefinitions.CRC16_ARC),
|
||||
HashType.CRC16_CDMA2000 => new Crc(StandardDefinitions.CRC16_CDMA2000),
|
||||
HashType.CRC16_CMS => new Crc(StandardDefinitions.CRC16_CMS),
|
||||
HashType.CRC16_DDS110 => new Crc(StandardDefinitions.CRC16_DDS110),
|
||||
HashType.CRC16_DECTR => new Crc(StandardDefinitions.CRC16_DECTR),
|
||||
HashType.CRC16_DECTX => new Crc(StandardDefinitions.CRC16_DECTX),
|
||||
HashType.CRC16_DNP => new Crc(StandardDefinitions.CRC16_DNP),
|
||||
HashType.CRC16_EN13757 => new Crc(StandardDefinitions.CRC16_EN13757),
|
||||
HashType.CRC16_GENIBUS => new Crc(StandardDefinitions.CRC16_GENIBUS),
|
||||
HashType.CRC16_GSM => new Crc(StandardDefinitions.CRC16_GSM),
|
||||
HashType.CRC16_IBM3740 => new Crc(StandardDefinitions.CRC16_IBM3740),
|
||||
HashType.CRC16_IBMSDLC => new Crc(StandardDefinitions.CRC16_IBMSDLC),
|
||||
HashType.CRC16_ISOIEC144433A => new Crc(StandardDefinitions.CRC16_ISOIEC144433A),
|
||||
HashType.CRC16_KERMIT => new Crc(StandardDefinitions.CRC16_KERMIT),
|
||||
HashType.CRC16_LJ1200 => new Crc(StandardDefinitions.CRC16_LJ1200),
|
||||
HashType.CRC16_M17 => new Crc(StandardDefinitions.CRC16_M17),
|
||||
HashType.CRC16_MAXIMDOW => new Crc(StandardDefinitions.CRC16_MAXIMDOW),
|
||||
HashType.CRC16_MCRF4XX => new Crc(StandardDefinitions.CRC16_MCRF4XX),
|
||||
HashType.CRC16_MODBUS => new Crc(StandardDefinitions.CRC16_MODBUS),
|
||||
HashType.CRC16_NRSC5 => new Crc(StandardDefinitions.CRC16_NRSC5),
|
||||
HashType.CRC16_OPENSAFETYA => new Crc(StandardDefinitions.CRC16_OPENSAFETYA),
|
||||
HashType.CRC16_OPENSAFETYB => new Crc(StandardDefinitions.CRC16_OPENSAFETYB),
|
||||
HashType.CRC16_PROFIBUS => new Crc(StandardDefinitions.CRC16_PROFIBUS),
|
||||
HashType.CRC16_RIELLO => new Crc(StandardDefinitions.CRC16_RIELLO),
|
||||
HashType.CRC16_SPIFUJITSU => new Crc(StandardDefinitions.CRC16_SPIFUJITSU),
|
||||
HashType.CRC16_T10DIF => new Crc(StandardDefinitions.CRC16_T10DIF),
|
||||
HashType.CRC16_TELEDISK => new Crc(StandardDefinitions.CRC16_TELEDISK),
|
||||
HashType.CRC16_TMS37157 => new Crc(StandardDefinitions.CRC16_TMS37157),
|
||||
HashType.CRC16_UMTS => new Crc(StandardDefinitions.CRC16_UMTS),
|
||||
HashType.CRC16_USB => new Crc(StandardDefinitions.CRC16_USB),
|
||||
HashType.CRC16_XMODEM => new Crc(StandardDefinitions.CRC16_XMODEM),
|
||||
|
||||
HashType.CRC17_CANFD => new Crc(StandardDefinitions.CRC17_CANFD),
|
||||
|
||||
HashType.CRC21_CANFD => new Crc(StandardDefinitions.CRC21_CANFD),
|
||||
|
||||
HashType.CRC24_BLE => new Crc(StandardDefinitions.CRC24_BLE),
|
||||
HashType.CRC24_FLEXRAYA => new Crc(StandardDefinitions.CRC24_FLEXRAYA),
|
||||
HashType.CRC24_FLEXRAYB => new Crc(StandardDefinitions.CRC24_FLEXRAYB),
|
||||
HashType.CRC24_INTERLAKEN => new Crc(StandardDefinitions.CRC24_INTERLAKEN),
|
||||
HashType.CRC24_LTEA => new Crc(StandardDefinitions.CRC24_LTEA),
|
||||
HashType.CRC24_LTEB => new Crc(StandardDefinitions.CRC24_LTEB),
|
||||
HashType.CRC24_OPENPGP => new Crc(StandardDefinitions.CRC24_OPENPGP),
|
||||
HashType.CRC24_OS9 => new Crc(StandardDefinitions.CRC24_OS9),
|
||||
|
||||
HashType.CRC30_CDMA => new Crc(StandardDefinitions.CRC30_CDMA),
|
||||
|
||||
HashType.CRC31_PHILIPS => new Crc(StandardDefinitions.CRC31_PHILIPS),
|
||||
|
||||
HashType.CRC32 => new Crc(StandardDefinitions.CRC32_ISOHDLC),
|
||||
HashType.CRC32_AIXM => new Crc(StandardDefinitions.CRC32_AIXM),
|
||||
HashType.CRC32_AUTOSAR => new Crc(StandardDefinitions.CRC32_AUTOSAR),
|
||||
HashType.CRC32_BASE91D => new Crc(StandardDefinitions.CRC32_BASE91D),
|
||||
HashType.CRC32_BZIP2 => new Crc(StandardDefinitions.CRC32_BZIP2),
|
||||
HashType.CRC32_CDROMEDC => new Crc(StandardDefinitions.CRC32_CDROMEDC),
|
||||
HashType.CRC32_CKSUM => new Crc(StandardDefinitions.CRC32_CKSUM),
|
||||
HashType.CRC32_ISCSI => new Crc(StandardDefinitions.CRC32_ISCSI),
|
||||
HashType.CRC32_ISOHDLC => new Crc(StandardDefinitions.CRC32_ISOHDLC),
|
||||
HashType.CRC32_JAMCRC => new Crc(StandardDefinitions.CRC32_JAMCRC),
|
||||
HashType.CRC32_MEF => new Crc(StandardDefinitions.CRC32_MEF),
|
||||
HashType.CRC32_MPEG2 => new Crc(StandardDefinitions.CRC32_MPEG2),
|
||||
HashType.CRC32_XFER => new Crc(StandardDefinitions.CRC32_XFER),
|
||||
|
||||
HashType.CRC40_GSM => new Crc(StandardDefinitions.CRC40_GSM),
|
||||
|
||||
HashType.CRC64 => new Crc(StandardDefinitions.CRC64_ECMA182),
|
||||
HashType.CRC64_ECMA182 => new Crc(StandardDefinitions.CRC64_ECMA182),
|
||||
HashType.CRC64_GOISO => new Crc(StandardDefinitions.CRC64_GOISO),
|
||||
HashType.CRC64_MS => new Crc(StandardDefinitions.CRC64_MS),
|
||||
HashType.CRC64_NVME => new Crc(StandardDefinitions.CRC64_NVME),
|
||||
HashType.CRC64_REDIS => new Crc(StandardDefinitions.CRC64_REDIS),
|
||||
HashType.CRC64_WE => new Crc(StandardDefinitions.CRC64_WE),
|
||||
HashType.CRC64_XZ => new Crc(StandardDefinitions.CRC64_XZ),
|
||||
|
||||
HashType.Fletcher16 => new Fletcher16(),
|
||||
HashType.Fletcher32 => new Fletcher32(),
|
||||
HashType.Fletcher64 => new Fletcher64(),
|
||||
|
||||
HashType.FNV0_32 => new FNV0_32(),
|
||||
HashType.FNV0_64 => new FNV0_64(),
|
||||
HashType.FNV1_32 => new FNV1_32(),
|
||||
HashType.FNV1_64 => new FNV1_64(),
|
||||
HashType.FNV1a_32 => new FNV1a_32(),
|
||||
HashType.FNV1a_64 => new FNV1a_64(),
|
||||
|
||||
HashType.MD2 => new MessageDigest.MD2(),
|
||||
HashType.MD4 => new MessageDigest.MD4(),
|
||||
HashType.MD5 => MD5.Create(),
|
||||
|
||||
HashType.RIPEMD128 => new MessageDigest.RipeMD128(),
|
||||
HashType.RIPEMD160 => new MessageDigest.RipeMD160(),
|
||||
HashType.RIPEMD256 => new MessageDigest.RipeMD256(),
|
||||
HashType.RIPEMD320 => new MessageDigest.RipeMD320(),
|
||||
|
||||
HashType.SHA1 => SHA1.Create(),
|
||||
HashType.SHA256 => SHA256.Create(),
|
||||
HashType.SHA384 => SHA384.Create(),
|
||||
HashType.SHA512 => SHA512.Create(),
|
||||
#if NET8_0_OR_GREATER
|
||||
HashType.SHA3_256 => SHA3_256.IsSupported ? SHA3_256.Create() : null,
|
||||
HashType.SHA3_384 => SHA3_384.IsSupported ? SHA3_384.Create() : null,
|
||||
HashType.SHA3_512 => SHA3_512.IsSupported ? SHA3_512.Create() : null,
|
||||
HashType.SHAKE128 => Shake128.IsSupported ? new Shake128() : null,
|
||||
HashType.SHAKE256 => Shake256.IsSupported ? new Shake256() : null,
|
||||
#endif
|
||||
|
||||
HashType.SpamSum => new SpamSumContext(),
|
||||
|
||||
HashType.Tiger128_3 => new MessageDigest.Tiger128_3(),
|
||||
HashType.Tiger128_4 => new MessageDigest.Tiger128_4(),
|
||||
HashType.Tiger160_3 => new MessageDigest.Tiger160_3(),
|
||||
HashType.Tiger160_4 => new MessageDigest.Tiger160_4(),
|
||||
HashType.Tiger192_3 => new MessageDigest.Tiger192_3(),
|
||||
HashType.Tiger192_4 => new MessageDigest.Tiger192_4(),
|
||||
HashType.Tiger2_128_3 => new MessageDigest.Tiger2_128_3(),
|
||||
HashType.Tiger2_128_4 => new MessageDigest.Tiger2_128_4(),
|
||||
HashType.Tiger2_160_3 => new MessageDigest.Tiger2_160_3(),
|
||||
HashType.Tiger2_160_4 => new MessageDigest.Tiger2_160_4(),
|
||||
HashType.Tiger2_192_3 => new MessageDigest.Tiger2_192_3(),
|
||||
HashType.Tiger2_192_4 => new MessageDigest.Tiger2_192_4(),
|
||||
|
||||
HashType.XxHash32 => new XxHash.XxHash32(),
|
||||
HashType.XxHash64 => new XxHash.XxHash64(),
|
||||
#if NET462_OR_GREATER || NETCOREAPP
|
||||
HashType.XxHash32 => new XxHash32(),
|
||||
HashType.XxHash64 => new XxHash64(),
|
||||
HashType.XxHash3 => new XxHash3(),
|
||||
HashType.XxHash128 => new XxHash128(),
|
||||
#endif
|
||||
@@ -132,13 +356,22 @@ namespace SabreTools.Hashing
|
||||
{
|
||||
switch (_hasher)
|
||||
{
|
||||
case ChecksumBase cb:
|
||||
cb.TransformBlock(buffer, offset, size);
|
||||
break;
|
||||
|
||||
case HashAlgorithm ha:
|
||||
ha.TransformBlock(buffer, offset, size, null, 0);
|
||||
break;
|
||||
|
||||
case IChecksum ic:
|
||||
byte[] icBuffer = GetArraySegment(buffer, offset, size);
|
||||
ic.Update(icBuffer);
|
||||
byte[] icBlock = new byte[size];
|
||||
Array.Copy(buffer, offset, icBlock, 0, size);
|
||||
ic.Update(icBlock);
|
||||
break;
|
||||
|
||||
case MessageDigest.MessageDigestBase mdb:
|
||||
mdb.TransformBlock(buffer, offset, size);
|
||||
break;
|
||||
|
||||
#if NET462_OR_GREATER || NETCOREAPP
|
||||
@@ -146,18 +379,32 @@ namespace SabreTools.Hashing
|
||||
var nchaBufferSpan = new ReadOnlySpan<byte>(buffer, offset, size);
|
||||
ncha.Append(nchaBufferSpan);
|
||||
break;
|
||||
#else
|
||||
case OptimizedCRC.OptimizedCRC oc:
|
||||
oc.Update(buffer, offset, size);
|
||||
#endif
|
||||
|
||||
#if NET8_0_OR_GREATER
|
||||
case Shake128 s128:
|
||||
var s128BufferSpan = new ReadOnlySpan<byte>(buffer, offset, size);
|
||||
s128.AppendData(s128BufferSpan);
|
||||
break;
|
||||
case Shake256 s256:
|
||||
var s256BufferSpan = new ReadOnlySpan<byte>(buffer, offset, size);
|
||||
s256.AppendData(s256BufferSpan);
|
||||
break;
|
||||
#endif
|
||||
|
||||
case XxHash.XxHash32 xxh32:
|
||||
xxh32.TransformBlock(buffer, offset, size);
|
||||
break;
|
||||
case XxHash.XxHash64 xxh64:
|
||||
xxh64.TransformBlock(buffer, offset, size);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Finalize the internal hash algorigthm
|
||||
/// </summary>
|
||||
/// <remarks>NonCryptographicHashAlgorithm implementations do not need finalization</remarks>
|
||||
/// <remarks>NonCryptographicHashAlgorithm, SHAKE128, and SHAKE256 implementations do not need finalization</remarks>
|
||||
public void Terminate()
|
||||
{
|
||||
byte[] emptyBuffer = [];
|
||||
@@ -167,56 +414,12 @@ namespace SabreTools.Hashing
|
||||
ha.TransformFinalBlock(emptyBuffer, 0, 0);
|
||||
break;
|
||||
|
||||
#if NET20_OR_GREATER || NETCOREAPP3_1 || NET5_0
|
||||
case OptimizedCRC.OptimizedCRC oc:
|
||||
oc.Update([], 0, 0);
|
||||
case MessageDigest.MessageDigestBase mdb:
|
||||
mdb.Terminate();
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Helpers
|
||||
|
||||
/// <summary>
|
||||
/// Convert a byte array to a hex string
|
||||
/// </summary>
|
||||
/// <param name="bytes">Byte array to convert</param>
|
||||
/// <returns>Hex string representing the byte array</returns>
|
||||
/// <link>http://stackoverflow.com/questions/311165/how-do-you-convert-byte-array-to-hexadecimal-string-and-vice-versa</link>
|
||||
private static string? ByteArrayToString(byte[]? bytes)
|
||||
{
|
||||
// If we get null in, we send null out
|
||||
if (bytes == null)
|
||||
return null;
|
||||
|
||||
try
|
||||
{
|
||||
string hex = BitConverter.ToString(bytes);
|
||||
return hex.Replace("-", string.Empty).ToLowerInvariant();
|
||||
}
|
||||
catch
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get a segment from the array based on an offset and size
|
||||
/// </summary>
|
||||
private static byte[] GetArraySegment(byte[] buffer, int offset, int size)
|
||||
{
|
||||
#if NET452_OR_GREATER || NETCOREAPP
|
||||
var icBufferSpan = new ReadOnlySpan<byte>(buffer, offset, size);
|
||||
byte[] trimmedBuffer = icBufferSpan.ToArray();
|
||||
#else
|
||||
byte[] trimmedBuffer = new byte[size];
|
||||
Array.Copy(buffer, offset, trimmedBuffer, 0, size);
|
||||
#endif
|
||||
return trimmedBuffer;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
697
SabreTools.Hashing/MessageDigest/Constants.cs
Normal file
697
SabreTools.Hashing/MessageDigest/Constants.cs
Normal file
@@ -0,0 +1,697 @@
|
||||
namespace SabreTools.Hashing.MessageDigest
|
||||
{
|
||||
internal static class Constants
|
||||
{
|
||||
// <see href="https://datatracker.ietf.org/doc/html/rfc1115"/>
|
||||
#region MD2
|
||||
|
||||
/// <summary>
|
||||
/// S-Boxes
|
||||
/// </summary>
|
||||
public static readonly byte[] MD2SBox =
|
||||
[
|
||||
0x29, 0x2E, 0x43, 0xC9, 0xA2, 0xD8, 0x7C, 0x01, 0x3D, 0x36, 0x54, 0xA1, 0xEC, 0xF0, 0x06, 0x13,
|
||||
0x62, 0xA7, 0x05, 0xF3, 0xC0, 0xC7, 0x73, 0x8C, 0x98, 0x93, 0x2B, 0xD9, 0xBC, 0x4C, 0x82, 0xCA,
|
||||
0x1E, 0x9B, 0x57, 0x3C, 0xFD, 0xD4, 0xE0, 0x16, 0x67, 0x42, 0x6F, 0x18, 0x8A, 0x17, 0xE5, 0x12,
|
||||
0xBE, 0x4E, 0xC4, 0xD6, 0xDA, 0x9E, 0xDE, 0x49, 0xA0, 0xFB, 0xF5, 0x8E, 0xBB, 0x2F, 0xEE, 0x7A,
|
||||
0xA9, 0x68, 0x79, 0x91, 0x15, 0xB2, 0x07, 0x3F, 0x94, 0xC2, 0x10, 0x89, 0x0B, 0x22, 0x5F, 0x21,
|
||||
0x80, 0x7F, 0x5D, 0x9A, 0x5A, 0x90, 0x32, 0x27, 0x35, 0x3E, 0xCC, 0xE7, 0xBF, 0xF7, 0x97, 0x03,
|
||||
0xFF, 0x19, 0x30, 0xB3, 0x48, 0xA5, 0xB5, 0xD1, 0xD7, 0x5E, 0x92, 0x2A, 0xAC, 0x56, 0xAA, 0xC6,
|
||||
0x4F, 0xB8, 0x38, 0xD2, 0x96, 0xA4, 0x7D, 0xB6, 0x76, 0xFC, 0x6B, 0xE2, 0x9C, 0x74, 0x04, 0xF1,
|
||||
0x45, 0x9D, 0x70, 0x59, 0x64, 0x71, 0x87, 0x20, 0x86, 0x5B, 0xCF, 0x65, 0xE6, 0x2D, 0xA8, 0x02,
|
||||
0x1B, 0x60, 0x25, 0xAD, 0xAE, 0xB0, 0xB9, 0xF6, 0x1C, 0x46, 0x61, 0x69, 0x34, 0x40, 0x7E, 0x0F,
|
||||
0x55, 0x47, 0xA3, 0x23, 0xDD, 0x51, 0xAF, 0x3A, 0xC3, 0x5C, 0xF9, 0xCE, 0xBA, 0xC5, 0xEA, 0x26,
|
||||
0x2C, 0x53, 0x0D, 0x6E, 0x85, 0x28, 0x84, 0x09, 0xD3, 0xDF, 0xCD, 0xF4, 0x41, 0x81, 0x4D, 0x52,
|
||||
0x6A, 0xDC, 0x37, 0xC8, 0x6C, 0xC1, 0xAB, 0xFA, 0x24, 0xE1, 0x7B, 0x08, 0x0C, 0xBD, 0xB1, 0x4A,
|
||||
0x78, 0x88, 0x95, 0x8B, 0xE3, 0x63, 0xE8, 0x6D, 0xE9, 0xCB, 0xD5, 0xFE, 0x3B, 0x00, 0x1D, 0x39,
|
||||
0xF2, 0xEF, 0xB7, 0x0E, 0x66, 0x58, 0xD0, 0xE4, 0xA6, 0x77, 0x72, 0xF8, 0xEB, 0x75, 0x4B, 0x0A,
|
||||
0x31, 0x44, 0x50, 0xB4, 0x8F, 0xED, 0x1F, 0x1A, 0xDB, 0x99, 0x8D, 0x33, 0x9F, 0x11, 0x83, 0x14,
|
||||
];
|
||||
|
||||
#endregion
|
||||
|
||||
// <see href="https://datatracker.ietf.org/doc/html/rfc1320"/>
|
||||
#region MD4
|
||||
|
||||
public const uint MD4SeedA = 0x67452301;
|
||||
public const uint MD4SeedB = 0xefcdab89;
|
||||
public const uint MD4SeedC = 0x98badcfe;
|
||||
public const uint MD4SeedD = 0x10325476;
|
||||
|
||||
public const uint MD4Round1 = 0x00000000;
|
||||
public const uint MD4Round2 = 0x5A827999;
|
||||
public const uint MD4Round3 = 0x6ED9EBA1;
|
||||
|
||||
#endregion
|
||||
|
||||
// <see href="https://cdn.standards.iteh.ai/samples/39876/10f9f9f4bb614eaaaeba7e157e183ca3/ISO-IEC-10118-3-2004.pdf"/>
|
||||
#region RIPEMD-128 / RIPEMD-256
|
||||
|
||||
public const uint RMD128Round00To15 = 0x00000000;
|
||||
public const uint RMD128Round16To31 = 0x5A827999;
|
||||
public const uint RMD128Round32To47 = 0x6ED9EBA1;
|
||||
public const uint RMD128Round48To63 = 0x8F1BBCDC;
|
||||
|
||||
public const uint RMD128RoundPrime00To15 = 0x50A28BE6;
|
||||
public const uint RMD128RoundPrime16To31 = 0x5C4DD124;
|
||||
public const uint RMD128RoundPrime32To47 = 0x6D703EF3;
|
||||
public const uint RMD128RoundPrime48To63 = 0x00000000;
|
||||
|
||||
public const uint RMD128Y0 = 0x67452301;
|
||||
public const uint RMD128Y1 = 0xEFCDAB89;
|
||||
public const uint RMD128Y2 = 0x98BADCFE;
|
||||
public const uint RMD128Y3 = 0x10325476;
|
||||
public const uint RMD256Y4 = 0x76543210;
|
||||
public const uint RMD256Y5 = 0xFEDCBA98;
|
||||
public const uint RMD256Y6 = 0x89ABCDEF;
|
||||
public const uint RMD256Y7 = 0x01234567;
|
||||
|
||||
#endregion
|
||||
|
||||
// <see href="https://cdn.standards.iteh.ai/samples/39876/10f9f9f4bb614eaaaeba7e157e183ca3/ISO-IEC-10118-3-2004.pdf"/>
|
||||
#region RIPEMD-160 / RIPEMD-320
|
||||
|
||||
public const uint RMD160Round00To15 = 0x00000000;
|
||||
public const uint RMD160Round16To31 = 0x5A827999;
|
||||
public const uint RMD160Round32To47 = 0x6ED9EBA1;
|
||||
public const uint RMD160Round48To63 = 0x8F1BBCDC;
|
||||
public const uint RMD160Round64To79 = 0xA953FD4E;
|
||||
|
||||
public const uint RMD160RoundPrime00To15 = 0x50A28BE6;
|
||||
public const uint RMD160RoundPrime16To31 = 0x5C4DD124;
|
||||
public const uint RMD160RoundPrime32To47 = 0x6D703EF3;
|
||||
public const uint RMD160RoundPrime48To63 = 0x7A6D76E9;
|
||||
public const uint RMD160RoundPrime64To79 = 0x00000000;
|
||||
|
||||
public const uint RMD160Y0 = 0x67452301;
|
||||
public const uint RMD160Y1 = 0xEFCDAB89;
|
||||
public const uint RMD160Y2 = 0x98BADCFE;
|
||||
public const uint RMD160Y3 = 0x10325476;
|
||||
public const uint RMD160Y4 = 0xC3D2E1F0;
|
||||
public const uint RMD320Y5 = 0x76543210;
|
||||
public const uint RMD320Y6 = 0xFEDCBA98;
|
||||
public const uint RMD320Y7 = 0x89ABCDEF;
|
||||
public const uint RMD320Y8 = 0x01234567;
|
||||
public const uint RMD320Y9 = 0x3C2D1E0F;
|
||||
|
||||
/// <summary>
|
||||
/// t_i
|
||||
/// </summary>
|
||||
public static readonly byte[] RMD160Ti =
|
||||
[
|
||||
11, 14, 15, 12, 5, 8, 7, 9,
|
||||
11, 13, 14, 15, 6, 7, 9, 8,
|
||||
7, 6, 8, 13, 11, 9, 7, 15,
|
||||
7, 12, 15, 9, 11, 7, 13, 12,
|
||||
11, 13, 6, 7, 14, 9, 13, 15,
|
||||
14, 8, 13, 6, 5, 12, 7, 5,
|
||||
11, 12, 14, 15, 14, 15, 9, 8,
|
||||
9, 14, 5, 6, 8, 6, 5, 12,
|
||||
9, 15, 5, 11, 6, 8, 13, 12,
|
||||
5, 12, 13, 14, 11, 8, 5, 6,
|
||||
];
|
||||
|
||||
/// <summary>
|
||||
/// t'_i
|
||||
/// </summary>
|
||||
public static readonly byte[] RMD160Tpi =
|
||||
[
|
||||
8, 9, 9, 11, 13, 15, 15, 5,
|
||||
7, 7, 8, 11, 14, 14, 12, 6,
|
||||
9, 13, 15, 7, 12, 8, 9, 11,
|
||||
7, 7, 12, 7, 6, 15, 13, 11,
|
||||
9, 7, 15, 11, 8, 6, 6, 14,
|
||||
12, 13, 5, 14, 13, 13, 7, 5,
|
||||
15, 5, 8, 11, 14, 14, 6, 14,
|
||||
6, 9, 12, 9, 12, 5, 15, 8,
|
||||
8, 5, 12, 9, 12, 5, 14, 6,
|
||||
8, 13, 6, 5, 15, 13, 11, 11,
|
||||
];
|
||||
|
||||
/// <summary>
|
||||
/// a_i
|
||||
/// </summary>
|
||||
public static readonly byte[] RMD160Ai =
|
||||
[
|
||||
0, 1, 2, 3, 4, 5, 6, 7,
|
||||
8, 9, 10, 11, 12, 13, 14, 15,
|
||||
7, 4, 13, 1, 10, 6, 15, 3,
|
||||
12, 0, 9, 5, 2, 14, 11, 8,
|
||||
3, 10, 14, 4, 9, 15, 8, 1,
|
||||
2, 7, 0, 6, 13, 11, 5, 12,
|
||||
1, 9, 11, 10, 0, 8, 12, 4,
|
||||
13, 3, 7, 15, 14, 5, 6, 2,
|
||||
4, 0, 5, 9, 7, 12, 2, 10,
|
||||
14, 1, 3, 8, 11, 6, 15, 13,
|
||||
];
|
||||
|
||||
/// <summary>
|
||||
/// a'_i
|
||||
/// </summary>
|
||||
public static readonly byte[] RMD160Api =
|
||||
[
|
||||
5, 14, 7, 0, 9, 2, 11, 4,
|
||||
13, 6, 15, 8, 1, 10, 3, 12,
|
||||
6, 11, 3, 7, 0, 13, 5, 10,
|
||||
14, 15, 8, 12, 4, 9, 1, 2,
|
||||
15, 5, 1, 3, 7, 14, 6, 9,
|
||||
11, 8, 12, 2, 10, 0, 4, 13,
|
||||
8, 6, 4, 1, 3, 11, 15, 0,
|
||||
5, 12, 2, 13, 9, 7, 10, 14,
|
||||
12, 15, 10, 4, 1, 5, 8, 7,
|
||||
6, 2, 13, 14, 0, 3, 9, 11,
|
||||
];
|
||||
|
||||
#endregion
|
||||
|
||||
/// <see href="https://biham.cs.technion.ac.il/Reports/Tiger//>
|
||||
#region Tiger-128 / Tiger-160 / Tiger-192
|
||||
|
||||
public const ulong TigerSeedA = 0x0123456789ABCDEF;
|
||||
|
||||
public const ulong TigerSeedB = 0xFEDCBA9876543210;
|
||||
|
||||
public const ulong TigerSeedC = 0xF096A5B4C3B2E187;
|
||||
|
||||
/// <summary>
|
||||
/// S-Boxes
|
||||
/// </summary>
|
||||
public static readonly ulong[] TigerSBox =
|
||||
[
|
||||
0x02AAB17CF7E90C5E /* 0 */, 0xAC424B03E243A8EC /* 1 */,
|
||||
0x72CD5BE30DD5FCD3 /* 2 */, 0x6D019B93F6F97F3A /* 3 */,
|
||||
0xCD9978FFD21F9193 /* 4 */, 0x7573A1C9708029E2 /* 5 */,
|
||||
0xB164326B922A83C3 /* 6 */, 0x46883EEE04915870 /* 7 */,
|
||||
0xEAACE3057103ECE6 /* 8 */, 0xC54169B808A3535C /* 9 */,
|
||||
0x4CE754918DDEC47C /* 10 */, 0x0AA2F4DFDC0DF40C /* 11 */,
|
||||
0x10B76F18A74DBEFA /* 12 */, 0xC6CCB6235AD1AB6A /* 13 */,
|
||||
0x13726121572FE2FF /* 14 */, 0x1A488C6F199D921E /* 15 */,
|
||||
0x4BC9F9F4DA0007CA /* 16 */, 0x26F5E6F6E85241C7 /* 17 */,
|
||||
0x859079DBEA5947B6 /* 18 */, 0x4F1885C5C99E8C92 /* 19 */,
|
||||
0xD78E761EA96F864B /* 20 */, 0x8E36428C52B5C17D /* 21 */,
|
||||
0x69CF6827373063C1 /* 22 */, 0xB607C93D9BB4C56E /* 23 */,
|
||||
0x7D820E760E76B5EA /* 24 */, 0x645C9CC6F07FDC42 /* 25 */,
|
||||
0xBF38A078243342E0 /* 26 */, 0x5F6B343C9D2E7D04 /* 27 */,
|
||||
0xF2C28AEB600B0EC6 /* 28 */, 0x6C0ED85F7254BCAC /* 29 */,
|
||||
0x71592281A4DB4FE5 /* 30 */, 0x1967FA69CE0FED9F /* 31 */,
|
||||
0xFD5293F8B96545DB /* 32 */, 0xC879E9D7F2A7600B /* 33 */,
|
||||
0x860248920193194E /* 34 */, 0xA4F9533B2D9CC0B3 /* 35 */,
|
||||
0x9053836C15957613 /* 36 */, 0xDB6DCF8AFC357BF1 /* 37 */,
|
||||
0x18BEEA7A7A370F57 /* 38 */, 0x037117CA50B99066 /* 39 */,
|
||||
0x6AB30A9774424A35 /* 40 */, 0xF4E92F02E325249B /* 41 */,
|
||||
0x7739DB07061CCAE1 /* 42 */, 0xD8F3B49CECA42A05 /* 43 */,
|
||||
0xBD56BE3F51382F73 /* 44 */, 0x45FAED5843B0BB28 /* 45 */,
|
||||
0x1C813D5C11BF1F83 /* 46 */, 0x8AF0E4B6D75FA169 /* 47 */,
|
||||
0x33EE18A487AD9999 /* 48 */, 0x3C26E8EAB1C94410 /* 49 */,
|
||||
0xB510102BC0A822F9 /* 50 */, 0x141EEF310CE6123B /* 51 */,
|
||||
0xFC65B90059DDB154 /* 52 */, 0xE0158640C5E0E607 /* 53 */,
|
||||
0x884E079826C3A3CF /* 54 */, 0x930D0D9523C535FD /* 55 */,
|
||||
0x35638D754E9A2B00 /* 56 */, 0x4085FCCF40469DD5 /* 57 */,
|
||||
0xC4B17AD28BE23A4C /* 58 */, 0xCAB2F0FC6A3E6A2E /* 59 */,
|
||||
0x2860971A6B943FCD /* 60 */, 0x3DDE6EE212E30446 /* 61 */,
|
||||
0x6222F32AE01765AE /* 62 */, 0x5D550BB5478308FE /* 63 */,
|
||||
0xA9EFA98DA0EDA22A /* 64 */, 0xC351A71686C40DA7 /* 65 */,
|
||||
0x1105586D9C867C84 /* 66 */, 0xDCFFEE85FDA22853 /* 67 */,
|
||||
0xCCFBD0262C5EEF76 /* 68 */, 0xBAF294CB8990D201 /* 69 */,
|
||||
0xE69464F52AFAD975 /* 70 */, 0x94B013AFDF133E14 /* 71 */,
|
||||
0x06A7D1A32823C958 /* 72 */, 0x6F95FE5130F61119 /* 73 */,
|
||||
0xD92AB34E462C06C0 /* 74 */, 0xED7BDE33887C71D2 /* 75 */,
|
||||
0x79746D6E6518393E /* 76 */, 0x5BA419385D713329 /* 77 */,
|
||||
0x7C1BA6B948A97564 /* 78 */, 0x31987C197BFDAC67 /* 79 */,
|
||||
0xDE6C23C44B053D02 /* 80 */, 0x581C49FED002D64D /* 81 */,
|
||||
0xDD474D6338261571 /* 82 */, 0xAA4546C3E473D062 /* 83 */,
|
||||
0x928FCE349455F860 /* 84 */, 0x48161BBACAAB94D9 /* 85 */,
|
||||
0x63912430770E6F68 /* 86 */, 0x6EC8A5E602C6641C /* 87 */,
|
||||
0x87282515337DDD2B /* 88 */, 0x2CDA6B42034B701B /* 89 */,
|
||||
0xB03D37C181CB096D /* 90 */, 0xE108438266C71C6F /* 91 */,
|
||||
0x2B3180C7EB51B255 /* 92 */, 0xDF92B82F96C08BBC /* 93 */,
|
||||
0x5C68C8C0A632F3BA /* 94 */, 0x5504CC861C3D0556 /* 95 */,
|
||||
0xABBFA4E55FB26B8F /* 96 */, 0x41848B0AB3BACEB4 /* 97 */,
|
||||
0xB334A273AA445D32 /* 98 */, 0xBCA696F0A85AD881 /* 99 */,
|
||||
0x24F6EC65B528D56C /* 100 */, 0x0CE1512E90F4524A /* 101 */,
|
||||
0x4E9DD79D5506D35A /* 102 */, 0x258905FAC6CE9779 /* 103 */,
|
||||
0x2019295B3E109B33 /* 104 */, 0xF8A9478B73A054CC /* 105 */,
|
||||
0x2924F2F934417EB0 /* 106 */, 0x3993357D536D1BC4 /* 107 */,
|
||||
0x38A81AC21DB6FF8B /* 108 */, 0x47C4FBF17D6016BF /* 109 */,
|
||||
0x1E0FAADD7667E3F5 /* 110 */, 0x7ABCFF62938BEB96 /* 111 */,
|
||||
0xA78DAD948FC179C9 /* 112 */, 0x8F1F98B72911E50D /* 113 */,
|
||||
0x61E48EAE27121A91 /* 114 */, 0x4D62F7AD31859808 /* 115 */,
|
||||
0xECEBA345EF5CEAEB /* 116 */, 0xF5CEB25EBC9684CE /* 117 */,
|
||||
0xF633E20CB7F76221 /* 118 */, 0xA32CDF06AB8293E4 /* 119 */,
|
||||
0x985A202CA5EE2CA4 /* 120 */, 0xCF0B8447CC8A8FB1 /* 121 */,
|
||||
0x9F765244979859A3 /* 122 */, 0xA8D516B1A1240017 /* 123 */,
|
||||
0x0BD7BA3EBB5DC726 /* 124 */, 0xE54BCA55B86ADB39 /* 125 */,
|
||||
0x1D7A3AFD6C478063 /* 126 */, 0x519EC608E7669EDD /* 127 */,
|
||||
0x0E5715A2D149AA23 /* 128 */, 0x177D4571848FF194 /* 129 */,
|
||||
0xEEB55F3241014C22 /* 130 */, 0x0F5E5CA13A6E2EC2 /* 131 */,
|
||||
0x8029927B75F5C361 /* 132 */, 0xAD139FABC3D6E436 /* 133 */,
|
||||
0x0D5DF1A94CCF402F /* 134 */, 0x3E8BD948BEA5DFC8 /* 135 */,
|
||||
0xA5A0D357BD3FF77E /* 136 */, 0xA2D12E251F74F645 /* 137 */,
|
||||
0x66FD9E525E81A082 /* 138 */, 0x2E0C90CE7F687A49 /* 139 */,
|
||||
0xC2E8BCBEBA973BC5 /* 140 */, 0x000001BCE509745F /* 141 */,
|
||||
0x423777BBE6DAB3D6 /* 142 */, 0xD1661C7EAEF06EB5 /* 143 */,
|
||||
0xA1781F354DAACFD8 /* 144 */, 0x2D11284A2B16AFFC /* 145 */,
|
||||
0xF1FC4F67FA891D1F /* 146 */, 0x73ECC25DCB920ADA /* 147 */,
|
||||
0xAE610C22C2A12651 /* 148 */, 0x96E0A810D356B78A /* 149 */,
|
||||
0x5A9A381F2FE7870F /* 150 */, 0xD5AD62EDE94E5530 /* 151 */,
|
||||
0xD225E5E8368D1427 /* 152 */, 0x65977B70C7AF4631 /* 153 */,
|
||||
0x99F889B2DE39D74F /* 154 */, 0x233F30BF54E1D143 /* 155 */,
|
||||
0x9A9675D3D9A63C97 /* 156 */, 0x5470554FF334F9A8 /* 157 */,
|
||||
0x166ACB744A4F5688 /* 158 */, 0x70C74CAAB2E4AEAD /* 159 */,
|
||||
0xF0D091646F294D12 /* 160 */, 0x57B82A89684031D1 /* 161 */,
|
||||
0xEFD95A5A61BE0B6B /* 162 */, 0x2FBD12E969F2F29A /* 163 */,
|
||||
0x9BD37013FEFF9FE8 /* 164 */, 0x3F9B0404D6085A06 /* 165 */,
|
||||
0x4940C1F3166CFE15 /* 166 */, 0x09542C4DCDF3DEFB /* 167 */,
|
||||
0xB4C5218385CD5CE3 /* 168 */, 0xC935B7DC4462A641 /* 169 */,
|
||||
0x3417F8A68ED3B63F /* 170 */, 0xB80959295B215B40 /* 171 */,
|
||||
0xF99CDAEF3B8C8572 /* 172 */, 0x018C0614F8FCB95D /* 173 */,
|
||||
0x1B14ACCD1A3ACDF3 /* 174 */, 0x84D471F200BB732D /* 175 */,
|
||||
0xC1A3110E95E8DA16 /* 176 */, 0x430A7220BF1A82B8 /* 177 */,
|
||||
0xB77E090D39DF210E /* 178 */, 0x5EF4BD9F3CD05E9D /* 179 */,
|
||||
0x9D4FF6DA7E57A444 /* 180 */, 0xDA1D60E183D4A5F8 /* 181 */,
|
||||
0xB287C38417998E47 /* 182 */, 0xFE3EDC121BB31886 /* 183 */,
|
||||
0xC7FE3CCC980CCBEF /* 184 */, 0xE46FB590189BFD03 /* 185 */,
|
||||
0x3732FD469A4C57DC /* 186 */, 0x7EF700A07CF1AD65 /* 187 */,
|
||||
0x59C64468A31D8859 /* 188 */, 0x762FB0B4D45B61F6 /* 189 */,
|
||||
0x155BAED099047718 /* 190 */, 0x68755E4C3D50BAA6 /* 191 */,
|
||||
0xE9214E7F22D8B4DF /* 192 */, 0x2ADDBF532EAC95F4 /* 193 */,
|
||||
0x32AE3909B4BD0109 /* 194 */, 0x834DF537B08E3450 /* 195 */,
|
||||
0xFA209DA84220728D /* 196 */, 0x9E691D9B9EFE23F7 /* 197 */,
|
||||
0x0446D288C4AE8D7F /* 198 */, 0x7B4CC524E169785B /* 199 */,
|
||||
0x21D87F0135CA1385 /* 200 */, 0xCEBB400F137B8AA5 /* 201 */,
|
||||
0x272E2B66580796BE /* 202 */, 0x3612264125C2B0DE /* 203 */,
|
||||
0x057702BDAD1EFBB2 /* 204 */, 0xD4BABB8EACF84BE9 /* 205 */,
|
||||
0x91583139641BC67B /* 206 */, 0x8BDC2DE08036E024 /* 207 */,
|
||||
0x603C8156F49F68ED /* 208 */, 0xF7D236F7DBEF5111 /* 209 */,
|
||||
0x9727C4598AD21E80 /* 210 */, 0xA08A0896670A5FD7 /* 211 */,
|
||||
0xCB4A8F4309EBA9CB /* 212 */, 0x81AF564B0F7036A1 /* 213 */,
|
||||
0xC0B99AA778199ABD /* 214 */, 0x959F1EC83FC8E952 /* 215 */,
|
||||
0x8C505077794A81B9 /* 216 */, 0x3ACAAF8F056338F0 /* 217 */,
|
||||
0x07B43F50627A6778 /* 218 */, 0x4A44AB49F5ECCC77 /* 219 */,
|
||||
0x3BC3D6E4B679EE98 /* 220 */, 0x9CC0D4D1CF14108C /* 221 */,
|
||||
0x4406C00B206BC8A0 /* 222 */, 0x82A18854C8D72D89 /* 223 */,
|
||||
0x67E366B35C3C432C /* 224 */, 0xB923DD61102B37F2 /* 225 */,
|
||||
0x56AB2779D884271D /* 226 */, 0xBE83E1B0FF1525AF /* 227 */,
|
||||
0xFB7C65D4217E49A9 /* 228 */, 0x6BDBE0E76D48E7D4 /* 229 */,
|
||||
0x08DF828745D9179E /* 230 */, 0x22EA6A9ADD53BD34 /* 231 */,
|
||||
0xE36E141C5622200A /* 232 */, 0x7F805D1B8CB750EE /* 233 */,
|
||||
0xAFE5C7A59F58E837 /* 234 */, 0xE27F996A4FB1C23C /* 235 */,
|
||||
0xD3867DFB0775F0D0 /* 236 */, 0xD0E673DE6E88891A /* 237 */,
|
||||
0x123AEB9EAFB86C25 /* 238 */, 0x30F1D5D5C145B895 /* 239 */,
|
||||
0xBB434A2DEE7269E7 /* 240 */, 0x78CB67ECF931FA38 /* 241 */,
|
||||
0xF33B0372323BBF9C /* 242 */, 0x52D66336FB279C74 /* 243 */,
|
||||
0x505F33AC0AFB4EAA /* 244 */, 0xE8A5CD99A2CCE187 /* 245 */,
|
||||
0x534974801E2D30BB /* 246 */, 0x8D2D5711D5876D90 /* 247 */,
|
||||
0x1F1A412891BC038E /* 248 */, 0xD6E2E71D82E56648 /* 249 */,
|
||||
0x74036C3A497732B7 /* 250 */, 0x89B67ED96361F5AB /* 251 */,
|
||||
0xFFED95D8F1EA02A2 /* 252 */, 0xE72B3BD61464D43D /* 253 */,
|
||||
0xA6300F170BDC4820 /* 254 */, 0xEBC18760ED78A77A /* 255 */,
|
||||
0xE6A6BE5A05A12138 /* 256 */, 0xB5A122A5B4F87C98 /* 257 */,
|
||||
0x563C6089140B6990 /* 258 */, 0x4C46CB2E391F5DD5 /* 259 */,
|
||||
0xD932ADDBC9B79434 /* 260 */, 0x08EA70E42015AFF5 /* 261 */,
|
||||
0xD765A6673E478CF1 /* 262 */, 0xC4FB757EAB278D99 /* 263 */,
|
||||
0xDF11C6862D6E0692 /* 264 */, 0xDDEB84F10D7F3B16 /* 265 */,
|
||||
0x6F2EF604A665EA04 /* 266 */, 0x4A8E0F0FF0E0DFB3 /* 267 */,
|
||||
0xA5EDEEF83DBCBA51 /* 268 */, 0xFC4F0A2A0EA4371E /* 269 */,
|
||||
0xE83E1DA85CB38429 /* 270 */, 0xDC8FF882BA1B1CE2 /* 271 */,
|
||||
0xCD45505E8353E80D /* 272 */, 0x18D19A00D4DB0717 /* 273 */,
|
||||
0x34A0CFEDA5F38101 /* 274 */, 0x0BE77E518887CAF2 /* 275 */,
|
||||
0x1E341438B3C45136 /* 276 */, 0xE05797F49089CCF9 /* 277 */,
|
||||
0xFFD23F9DF2591D14 /* 278 */, 0x543DDA228595C5CD /* 279 */,
|
||||
0x661F81FD99052A33 /* 280 */, 0x8736E641DB0F7B76 /* 281 */,
|
||||
0x15227725418E5307 /* 282 */, 0xE25F7F46162EB2FA /* 283 */,
|
||||
0x48A8B2126C13D9FE /* 284 */, 0xAFDC541792E76EEA /* 285 */,
|
||||
0x03D912BFC6D1898F /* 286 */, 0x31B1AAFA1B83F51B /* 287 */,
|
||||
0xF1AC2796E42AB7D9 /* 288 */, 0x40A3A7D7FCD2EBAC /* 289 */,
|
||||
0x1056136D0AFBBCC5 /* 290 */, 0x7889E1DD9A6D0C85 /* 291 */,
|
||||
0xD33525782A7974AA /* 292 */, 0xA7E25D09078AC09B /* 293 */,
|
||||
0xBD4138B3EAC6EDD0 /* 294 */, 0x920ABFBE71EB9E70 /* 295 */,
|
||||
0xA2A5D0F54FC2625C /* 296 */, 0xC054E36B0B1290A3 /* 297 */,
|
||||
0xF6DD59FF62FE932B /* 298 */, 0x3537354511A8AC7D /* 299 */,
|
||||
0xCA845E9172FADCD4 /* 300 */, 0x84F82B60329D20DC /* 301 */,
|
||||
0x79C62CE1CD672F18 /* 302 */, 0x8B09A2ADD124642C /* 303 */,
|
||||
0xD0C1E96A19D9E726 /* 304 */, 0x5A786A9B4BA9500C /* 305 */,
|
||||
0x0E020336634C43F3 /* 306 */, 0xC17B474AEB66D822 /* 307 */,
|
||||
0x6A731AE3EC9BAAC2 /* 308 */, 0x8226667AE0840258 /* 309 */,
|
||||
0x67D4567691CAECA5 /* 310 */, 0x1D94155C4875ADB5 /* 311 */,
|
||||
0x6D00FD985B813FDF /* 312 */, 0x51286EFCB774CD06 /* 313 */,
|
||||
0x5E8834471FA744AF /* 314 */, 0xF72CA0AEE761AE2E /* 315 */,
|
||||
0xBE40E4CDAEE8E09A /* 316 */, 0xE9970BBB5118F665 /* 317 */,
|
||||
0x726E4BEB33DF1964 /* 318 */, 0x703B000729199762 /* 319 */,
|
||||
0x4631D816F5EF30A7 /* 320 */, 0xB880B5B51504A6BE /* 321 */,
|
||||
0x641793C37ED84B6C /* 322 */, 0x7B21ED77F6E97D96 /* 323 */,
|
||||
0x776306312EF96B73 /* 324 */, 0xAE528948E86FF3F4 /* 325 */,
|
||||
0x53DBD7F286A3F8F8 /* 326 */, 0x16CADCE74CFC1063 /* 327 */,
|
||||
0x005C19BDFA52C6DD /* 328 */, 0x68868F5D64D46AD3 /* 329 */,
|
||||
0x3A9D512CCF1E186A /* 330 */, 0x367E62C2385660AE /* 331 */,
|
||||
0xE359E7EA77DCB1D7 /* 332 */, 0x526C0773749ABE6E /* 333 */,
|
||||
0x735AE5F9D09F734B /* 334 */, 0x493FC7CC8A558BA8 /* 335 */,
|
||||
0xB0B9C1533041AB45 /* 336 */, 0x321958BA470A59BD /* 337 */,
|
||||
0x852DB00B5F46C393 /* 338 */, 0x91209B2BD336B0E5 /* 339 */,
|
||||
0x6E604F7D659EF19F /* 340 */, 0xB99A8AE2782CCB24 /* 341 */,
|
||||
0xCCF52AB6C814C4C7 /* 342 */, 0x4727D9AFBE11727B /* 343 */,
|
||||
0x7E950D0C0121B34D /* 344 */, 0x756F435670AD471F /* 345 */,
|
||||
0xF5ADD442615A6849 /* 346 */, 0x4E87E09980B9957A /* 347 */,
|
||||
0x2ACFA1DF50AEE355 /* 348 */, 0xD898263AFD2FD556 /* 349 */,
|
||||
0xC8F4924DD80C8FD6 /* 350 */, 0xCF99CA3D754A173A /* 351 */,
|
||||
0xFE477BACAF91BF3C /* 352 */, 0xED5371F6D690C12D /* 353 */,
|
||||
0x831A5C285E687094 /* 354 */, 0xC5D3C90A3708A0A4 /* 355 */,
|
||||
0x0F7F903717D06580 /* 356 */, 0x19F9BB13B8FDF27F /* 357 */,
|
||||
0xB1BD6F1B4D502843 /* 358 */, 0x1C761BA38FFF4012 /* 359 */,
|
||||
0x0D1530C4E2E21F3B /* 360 */, 0x8943CE69A7372C8A /* 361 */,
|
||||
0xE5184E11FEB5CE66 /* 362 */, 0x618BDB80BD736621 /* 363 */,
|
||||
0x7D29BAD68B574D0B /* 364 */, 0x81BB613E25E6FE5B /* 365 */,
|
||||
0x071C9C10BC07913F /* 366 */, 0xC7BEEB7909AC2D97 /* 367 */,
|
||||
0xC3E58D353BC5D757 /* 368 */, 0xEB017892F38F61E8 /* 369 */,
|
||||
0xD4EFFB9C9B1CC21A /* 370 */, 0x99727D26F494F7AB /* 371 */,
|
||||
0xA3E063A2956B3E03 /* 372 */, 0x9D4A8B9A4AA09C30 /* 373 */,
|
||||
0x3F6AB7D500090FB4 /* 374 */, 0x9CC0F2A057268AC0 /* 375 */,
|
||||
0x3DEE9D2DEDBF42D1 /* 376 */, 0x330F49C87960A972 /* 377 */,
|
||||
0xC6B2720287421B41 /* 378 */, 0x0AC59EC07C00369C /* 379 */,
|
||||
0xEF4EAC49CB353425 /* 380 */, 0xF450244EEF0129D8 /* 381 */,
|
||||
0x8ACC46E5CAF4DEB6 /* 382 */, 0x2FFEAB63989263F7 /* 383 */,
|
||||
0x8F7CB9FE5D7A4578 /* 384 */, 0x5BD8F7644E634635 /* 385 */,
|
||||
0x427A7315BF2DC900 /* 386 */, 0x17D0C4AA2125261C /* 387 */,
|
||||
0x3992486C93518E50 /* 388 */, 0xB4CBFEE0A2D7D4C3 /* 389 */,
|
||||
0x7C75D6202C5DDD8D /* 390 */, 0xDBC295D8E35B6C61 /* 391 */,
|
||||
0x60B369D302032B19 /* 392 */, 0xCE42685FDCE44132 /* 393 */,
|
||||
0x06F3DDB9DDF65610 /* 394 */, 0x8EA4D21DB5E148F0 /* 395 */,
|
||||
0x20B0FCE62FCD496F /* 396 */, 0x2C1B912358B0EE31 /* 397 */,
|
||||
0xB28317B818F5A308 /* 398 */, 0xA89C1E189CA6D2CF /* 399 */,
|
||||
0x0C6B18576AAADBC8 /* 400 */, 0xB65DEAA91299FAE3 /* 401 */,
|
||||
0xFB2B794B7F1027E7 /* 402 */, 0x04E4317F443B5BEB /* 403 */,
|
||||
0x4B852D325939D0A6 /* 404 */, 0xD5AE6BEEFB207FFC /* 405 */,
|
||||
0x309682B281C7D374 /* 406 */, 0xBAE309A194C3B475 /* 407 */,
|
||||
0x8CC3F97B13B49F05 /* 408 */, 0x98A9422FF8293967 /* 409 */,
|
||||
0x244B16B01076FF7C /* 410 */, 0xF8BF571C663D67EE /* 411 */,
|
||||
0x1F0D6758EEE30DA1 /* 412 */, 0xC9B611D97ADEB9B7 /* 413 */,
|
||||
0xB7AFD5887B6C57A2 /* 414 */, 0x6290AE846B984FE1 /* 415 */,
|
||||
0x94DF4CDEACC1A5FD /* 416 */, 0x058A5BD1C5483AFF /* 417 */,
|
||||
0x63166CC142BA3C37 /* 418 */, 0x8DB8526EB2F76F40 /* 419 */,
|
||||
0xE10880036F0D6D4E /* 420 */, 0x9E0523C9971D311D /* 421 */,
|
||||
0x45EC2824CC7CD691 /* 422 */, 0x575B8359E62382C9 /* 423 */,
|
||||
0xFA9E400DC4889995 /* 424 */, 0xD1823ECB45721568 /* 425 */,
|
||||
0xDAFD983B8206082F /* 426 */, 0xAA7D29082386A8CB /* 427 */,
|
||||
0x269FCD4403B87588 /* 428 */, 0x1B91F5F728BDD1E0 /* 429 */,
|
||||
0xE4669F39040201F6 /* 430 */, 0x7A1D7C218CF04ADE /* 431 */,
|
||||
0x65623C29D79CE5CE /* 432 */, 0x2368449096C00BB1 /* 433 */,
|
||||
0xAB9BF1879DA503BA /* 434 */, 0xBC23ECB1A458058E /* 435 */,
|
||||
0x9A58DF01BB401ECC /* 436 */, 0xA070E868A85F143D /* 437 */,
|
||||
0x4FF188307DF2239E /* 438 */, 0x14D565B41A641183 /* 439 */,
|
||||
0xEE13337452701602 /* 440 */, 0x950E3DCF3F285E09 /* 441 */,
|
||||
0x59930254B9C80953 /* 442 */, 0x3BF299408930DA6D /* 443 */,
|
||||
0xA955943F53691387 /* 444 */, 0xA15EDECAA9CB8784 /* 445 */,
|
||||
0x29142127352BE9A0 /* 446 */, 0x76F0371FFF4E7AFB /* 447 */,
|
||||
0x0239F450274F2228 /* 448 */, 0xBB073AF01D5E868B /* 449 */,
|
||||
0xBFC80571C10E96C1 /* 450 */, 0xD267088568222E23 /* 451 */,
|
||||
0x9671A3D48E80B5B0 /* 452 */, 0x55B5D38AE193BB81 /* 453 */,
|
||||
0x693AE2D0A18B04B8 /* 454 */, 0x5C48B4ECADD5335F /* 455 */,
|
||||
0xFD743B194916A1CA /* 456 */, 0x2577018134BE98C4 /* 457 */,
|
||||
0xE77987E83C54A4AD /* 458 */, 0x28E11014DA33E1B9 /* 459 */,
|
||||
0x270CC59E226AA213 /* 460 */, 0x71495F756D1A5F60 /* 461 */,
|
||||
0x9BE853FB60AFEF77 /* 462 */, 0xADC786A7F7443DBF /* 463 */,
|
||||
0x0904456173B29A82 /* 464 */, 0x58BC7A66C232BD5E /* 465 */,
|
||||
0xF306558C673AC8B2 /* 466 */, 0x41F639C6B6C9772A /* 467 */,
|
||||
0x216DEFE99FDA35DA /* 468 */, 0x11640CC71C7BE615 /* 469 */,
|
||||
0x93C43694565C5527 /* 470 */, 0xEA038E6246777839 /* 471 */,
|
||||
0xF9ABF3CE5A3E2469 /* 472 */, 0x741E768D0FD312D2 /* 473 */,
|
||||
0x0144B883CED652C6 /* 474 */, 0xC20B5A5BA33F8552 /* 475 */,
|
||||
0x1AE69633C3435A9D /* 476 */, 0x97A28CA4088CFDEC /* 477 */,
|
||||
0x8824A43C1E96F420 /* 478 */, 0x37612FA66EEEA746 /* 479 */,
|
||||
0x6B4CB165F9CF0E5A /* 480 */, 0x43AA1C06A0ABFB4A /* 481 */,
|
||||
0x7F4DC26FF162796B /* 482 */, 0x6CBACC8E54ED9B0F /* 483 */,
|
||||
0xA6B7FFEFD2BB253E /* 484 */, 0x2E25BC95B0A29D4F /* 485 */,
|
||||
0x86D6A58BDEF1388C /* 486 */, 0xDED74AC576B6F054 /* 487 */,
|
||||
0x8030BDBC2B45805D /* 488 */, 0x3C81AF70E94D9289 /* 489 */,
|
||||
0x3EFF6DDA9E3100DB /* 490 */, 0xB38DC39FDFCC8847 /* 491 */,
|
||||
0x123885528D17B87E /* 492 */, 0xF2DA0ED240B1B642 /* 493 */,
|
||||
0x44CEFADCD54BF9A9 /* 494 */, 0x1312200E433C7EE6 /* 495 */,
|
||||
0x9FFCC84F3A78C748 /* 496 */, 0xF0CD1F72248576BB /* 497 */,
|
||||
0xEC6974053638CFE4 /* 498 */, 0x2BA7B67C0CEC4E4C /* 499 */,
|
||||
0xAC2F4DF3E5CE32ED /* 500 */, 0xCB33D14326EA4C11 /* 501 */,
|
||||
0xA4E9044CC77E58BC /* 502 */, 0x5F513293D934FCEF /* 503 */,
|
||||
0x5DC9645506E55444 /* 504 */, 0x50DE418F317DE40A /* 505 */,
|
||||
0x388CB31A69DDE259 /* 506 */, 0x2DB4A83455820A86 /* 507 */,
|
||||
0x9010A91E84711AE9 /* 508 */, 0x4DF7F0B7B1498371 /* 509 */,
|
||||
0xD62A2EABC0977179 /* 510 */, 0x22FAC097AA8D5C0E /* 511 */,
|
||||
0xF49FCC2FF1DAF39B /* 512 */, 0x487FD5C66FF29281 /* 513 */,
|
||||
0xE8A30667FCDCA83F /* 514 */, 0x2C9B4BE3D2FCCE63 /* 515 */,
|
||||
0xDA3FF74B93FBBBC2 /* 516 */, 0x2FA165D2FE70BA66 /* 517 */,
|
||||
0xA103E279970E93D4 /* 518 */, 0xBECDEC77B0E45E71 /* 519 */,
|
||||
0xCFB41E723985E497 /* 520 */, 0xB70AAA025EF75017 /* 521 */,
|
||||
0xD42309F03840B8E0 /* 522 */, 0x8EFC1AD035898579 /* 523 */,
|
||||
0x96C6920BE2B2ABC5 /* 524 */, 0x66AF4163375A9172 /* 525 */,
|
||||
0x2174ABDCCA7127FB /* 526 */, 0xB33CCEA64A72FF41 /* 527 */,
|
||||
0xF04A4933083066A5 /* 528 */, 0x8D970ACDD7289AF5 /* 529 */,
|
||||
0x8F96E8E031C8C25E /* 530 */, 0xF3FEC02276875D47 /* 531 */,
|
||||
0xEC7BF310056190DD /* 532 */, 0xF5ADB0AEBB0F1491 /* 533 */,
|
||||
0x9B50F8850FD58892 /* 534 */, 0x4975488358B74DE8 /* 535 */,
|
||||
0xA3354FF691531C61 /* 536 */, 0x0702BBE481D2C6EE /* 537 */,
|
||||
0x89FB24057DEDED98 /* 538 */, 0xAC3075138596E902 /* 539 */,
|
||||
0x1D2D3580172772ED /* 540 */, 0xEB738FC28E6BC30D /* 541 */,
|
||||
0x5854EF8F63044326 /* 542 */, 0x9E5C52325ADD3BBE /* 543 */,
|
||||
0x90AA53CF325C4623 /* 544 */, 0xC1D24D51349DD067 /* 545 */,
|
||||
0x2051CFEEA69EA624 /* 546 */, 0x13220F0A862E7E4F /* 547 */,
|
||||
0xCE39399404E04864 /* 548 */, 0xD9C42CA47086FCB7 /* 549 */,
|
||||
0x685AD2238A03E7CC /* 550 */, 0x066484B2AB2FF1DB /* 551 */,
|
||||
0xFE9D5D70EFBF79EC /* 552 */, 0x5B13B9DD9C481854 /* 553 */,
|
||||
0x15F0D475ED1509AD /* 554 */, 0x0BEBCD060EC79851 /* 555 */,
|
||||
0xD58C6791183AB7F8 /* 556 */, 0xD1187C5052F3EEE4 /* 557 */,
|
||||
0xC95D1192E54E82FF /* 558 */, 0x86EEA14CB9AC6CA2 /* 559 */,
|
||||
0x3485BEB153677D5D /* 560 */, 0xDD191D781F8C492A /* 561 */,
|
||||
0xF60866BAA784EBF9 /* 562 */, 0x518F643BA2D08C74 /* 563 */,
|
||||
0x8852E956E1087C22 /* 564 */, 0xA768CB8DC410AE8D /* 565 */,
|
||||
0x38047726BFEC8E1A /* 566 */, 0xA67738B4CD3B45AA /* 567 */,
|
||||
0xAD16691CEC0DDE19 /* 568 */, 0xC6D4319380462E07 /* 569 */,
|
||||
0xC5A5876D0BA61938 /* 570 */, 0x16B9FA1FA58FD840 /* 571 */,
|
||||
0x188AB1173CA74F18 /* 572 */, 0xABDA2F98C99C021F /* 573 */,
|
||||
0x3E0580AB134AE816 /* 574 */, 0x5F3B05B773645ABB /* 575 */,
|
||||
0x2501A2BE5575F2F6 /* 576 */, 0x1B2F74004E7E8BA9 /* 577 */,
|
||||
0x1CD7580371E8D953 /* 578 */, 0x7F6ED89562764E30 /* 579 */,
|
||||
0xB15926FF596F003D /* 580 */, 0x9F65293DA8C5D6B9 /* 581 */,
|
||||
0x6ECEF04DD690F84C /* 582 */, 0x4782275FFF33AF88 /* 583 */,
|
||||
0xE41433083F820801 /* 584 */, 0xFD0DFE409A1AF9B5 /* 585 */,
|
||||
0x4325A3342CDB396B /* 586 */, 0x8AE77E62B301B252 /* 587 */,
|
||||
0xC36F9E9F6655615A /* 588 */, 0x85455A2D92D32C09 /* 589 */,
|
||||
0xF2C7DEA949477485 /* 590 */, 0x63CFB4C133A39EBA /* 591 */,
|
||||
0x83B040CC6EBC5462 /* 592 */, 0x3B9454C8FDB326B0 /* 593 */,
|
||||
0x56F56A9E87FFD78C /* 594 */, 0x2DC2940D99F42BC6 /* 595 */,
|
||||
0x98F7DF096B096E2D /* 596 */, 0x19A6E01E3AD852BF /* 597 */,
|
||||
0x42A99CCBDBD4B40B /* 598 */, 0xA59998AF45E9C559 /* 599 */,
|
||||
0x366295E807D93186 /* 600 */, 0x6B48181BFAA1F773 /* 601 */,
|
||||
0x1FEC57E2157A0A1D /* 602 */, 0x4667446AF6201AD5 /* 603 */,
|
||||
0xE615EBCACFB0F075 /* 604 */, 0xB8F31F4F68290778 /* 605 */,
|
||||
0x22713ED6CE22D11E /* 606 */, 0x3057C1A72EC3C93B /* 607 */,
|
||||
0xCB46ACC37C3F1F2F /* 608 */, 0xDBB893FD02AAF50E /* 609 */,
|
||||
0x331FD92E600B9FCF /* 610 */, 0xA498F96148EA3AD6 /* 611 */,
|
||||
0xA8D8426E8B6A83EA /* 612 */, 0xA089B274B7735CDC /* 613 */,
|
||||
0x87F6B3731E524A11 /* 614 */, 0x118808E5CBC96749 /* 615 */,
|
||||
0x9906E4C7B19BD394 /* 616 */, 0xAFED7F7E9B24A20C /* 617 */,
|
||||
0x6509EADEEB3644A7 /* 618 */, 0x6C1EF1D3E8EF0EDE /* 619 */,
|
||||
0xB9C97D43E9798FB4 /* 620 */, 0xA2F2D784740C28A3 /* 621 */,
|
||||
0x7B8496476197566F /* 622 */, 0x7A5BE3E6B65F069D /* 623 */,
|
||||
0xF96330ED78BE6F10 /* 624 */, 0xEEE60DE77A076A15 /* 625 */,
|
||||
0x2B4BEE4AA08B9BD0 /* 626 */, 0x6A56A63EC7B8894E /* 627 */,
|
||||
0x02121359BA34FEF4 /* 628 */, 0x4CBF99F8283703FC /* 629 */,
|
||||
0x398071350CAF30C8 /* 630 */, 0xD0A77A89F017687A /* 631 */,
|
||||
0xF1C1A9EB9E423569 /* 632 */, 0x8C7976282DEE8199 /* 633 */,
|
||||
0x5D1737A5DD1F7ABD /* 634 */, 0x4F53433C09A9FA80 /* 635 */,
|
||||
0xFA8B0C53DF7CA1D9 /* 636 */, 0x3FD9DCBC886CCB77 /* 637 */,
|
||||
0xC040917CA91B4720 /* 638 */, 0x7DD00142F9D1DCDF /* 639 */,
|
||||
0x8476FC1D4F387B58 /* 640 */, 0x23F8E7C5F3316503 /* 641 */,
|
||||
0x032A2244E7E37339 /* 642 */, 0x5C87A5D750F5A74B /* 643 */,
|
||||
0x082B4CC43698992E /* 644 */, 0xDF917BECB858F63C /* 645 */,
|
||||
0x3270B8FC5BF86DDA /* 646 */, 0x10AE72BB29B5DD76 /* 647 */,
|
||||
0x576AC94E7700362B /* 648 */, 0x1AD112DAC61EFB8F /* 649 */,
|
||||
0x691BC30EC5FAA427 /* 650 */, 0xFF246311CC327143 /* 651 */,
|
||||
0x3142368E30E53206 /* 652 */, 0x71380E31E02CA396 /* 653 */,
|
||||
0x958D5C960AAD76F1 /* 654 */, 0xF8D6F430C16DA536 /* 655 */,
|
||||
0xC8FFD13F1BE7E1D2 /* 656 */, 0x7578AE66004DDBE1 /* 657 */,
|
||||
0x05833F01067BE646 /* 658 */, 0xBB34B5AD3BFE586D /* 659 */,
|
||||
0x095F34C9A12B97F0 /* 660 */, 0x247AB64525D60CA8 /* 661 */,
|
||||
0xDCDBC6F3017477D1 /* 662 */, 0x4A2E14D4DECAD24D /* 663 */,
|
||||
0xBDB5E6D9BE0A1EEB /* 664 */, 0x2A7E70F7794301AB /* 665 */,
|
||||
0xDEF42D8A270540FD /* 666 */, 0x01078EC0A34C22C1 /* 667 */,
|
||||
0xE5DE511AF4C16387 /* 668 */, 0x7EBB3A52BD9A330A /* 669 */,
|
||||
0x77697857AA7D6435 /* 670 */, 0x004E831603AE4C32 /* 671 */,
|
||||
0xE7A21020AD78E312 /* 672 */, 0x9D41A70C6AB420F2 /* 673 */,
|
||||
0x28E06C18EA1141E6 /* 674 */, 0xD2B28CBD984F6B28 /* 675 */,
|
||||
0x26B75F6C446E9D83 /* 676 */, 0xBA47568C4D418D7F /* 677 */,
|
||||
0xD80BADBFE6183D8E /* 678 */, 0x0E206D7F5F166044 /* 679 */,
|
||||
0xE258A43911CBCA3E /* 680 */, 0x723A1746B21DC0BC /* 681 */,
|
||||
0xC7CAA854F5D7CDD3 /* 682 */, 0x7CAC32883D261D9C /* 683 */,
|
||||
0x7690C26423BA942C /* 684 */, 0x17E55524478042B8 /* 685 */,
|
||||
0xE0BE477656A2389F /* 686 */, 0x4D289B5E67AB2DA0 /* 687 */,
|
||||
0x44862B9C8FBBFD31 /* 688 */, 0xB47CC8049D141365 /* 689 */,
|
||||
0x822C1B362B91C793 /* 690 */, 0x4EB14655FB13DFD8 /* 691 */,
|
||||
0x1ECBBA0714E2A97B /* 692 */, 0x6143459D5CDE5F14 /* 693 */,
|
||||
0x53A8FBF1D5F0AC89 /* 694 */, 0x97EA04D81C5E5B00 /* 695 */,
|
||||
0x622181A8D4FDB3F3 /* 696 */, 0xE9BCD341572A1208 /* 697 */,
|
||||
0x1411258643CCE58A /* 698 */, 0x9144C5FEA4C6E0A4 /* 699 */,
|
||||
0x0D33D06565CF620F /* 700 */, 0x54A48D489F219CA1 /* 701 */,
|
||||
0xC43E5EAC6D63C821 /* 702 */, 0xA9728B3A72770DAF /* 703 */,
|
||||
0xD7934E7B20DF87EF /* 704 */, 0xE35503B61A3E86E5 /* 705 */,
|
||||
0xCAE321FBC819D504 /* 706 */, 0x129A50B3AC60BFA6 /* 707 */,
|
||||
0xCD5E68EA7E9FB6C3 /* 708 */, 0xB01C90199483B1C7 /* 709 */,
|
||||
0x3DE93CD5C295376C /* 710 */, 0xAED52EDF2AB9AD13 /* 711 */,
|
||||
0x2E60F512C0A07884 /* 712 */, 0xBC3D86A3E36210C9 /* 713 */,
|
||||
0x35269D9B163951CE /* 714 */, 0x0C7D6E2AD0CDB5FA /* 715 */,
|
||||
0x59E86297D87F5733 /* 716 */, 0x298EF221898DB0E7 /* 717 */,
|
||||
0x55000029D1A5AA7E /* 718 */, 0x8BC08AE1B5061B45 /* 719 */,
|
||||
0xC2C31C2B6C92703A /* 720 */, 0x94CC596BAF25EF42 /* 721 */,
|
||||
0x0A1D73DB22540456 /* 722 */, 0x04B6A0F9D9C4179A /* 723 */,
|
||||
0xEFFDAFA2AE3D3C60 /* 724 */, 0xF7C8075BB49496C4 /* 725 */,
|
||||
0x9CC5C7141D1CD4E3 /* 726 */, 0x78BD1638218E5534 /* 727 */,
|
||||
0xB2F11568F850246A /* 728 */, 0xEDFABCFA9502BC29 /* 729 */,
|
||||
0x796CE5F2DA23051B /* 730 */, 0xAAE128B0DC93537C /* 731 */,
|
||||
0x3A493DA0EE4B29AE /* 732 */, 0xB5DF6B2C416895D7 /* 733 */,
|
||||
0xFCABBD25122D7F37 /* 734 */, 0x70810B58105DC4B1 /* 735 */,
|
||||
0xE10FDD37F7882A90 /* 736 */, 0x524DCAB5518A3F5C /* 737 */,
|
||||
0x3C9E85878451255B /* 738 */, 0x4029828119BD34E2 /* 739 */,
|
||||
0x74A05B6F5D3CECCB /* 740 */, 0xB610021542E13ECA /* 741 */,
|
||||
0x0FF979D12F59E2AC /* 742 */, 0x6037DA27E4F9CC50 /* 743 */,
|
||||
0x5E92975A0DF1847D /* 744 */, 0xD66DE190D3E623FE /* 745 */,
|
||||
0x5032D6B87B568048 /* 746 */, 0x9A36B7CE8235216E /* 747 */,
|
||||
0x80272A7A24F64B4A /* 748 */, 0x93EFED8B8C6916F7 /* 749 */,
|
||||
0x37DDBFF44CCE1555 /* 750 */, 0x4B95DB5D4B99BD25 /* 751 */,
|
||||
0x92D3FDA169812FC0 /* 752 */, 0xFB1A4A9A90660BB6 /* 753 */,
|
||||
0x730C196946A4B9B2 /* 754 */, 0x81E289AA7F49DA68 /* 755 */,
|
||||
0x64669A0F83B1A05F /* 756 */, 0x27B3FF7D9644F48B /* 757 */,
|
||||
0xCC6B615C8DB675B3 /* 758 */, 0x674F20B9BCEBBE95 /* 759 */,
|
||||
0x6F31238275655982 /* 760 */, 0x5AE488713E45CF05 /* 761 */,
|
||||
0xBF619F9954C21157 /* 762 */, 0xEABAC46040A8EAE9 /* 763 */,
|
||||
0x454C6FE9F2C0C1CD /* 764 */, 0x419CF6496412691C /* 765 */,
|
||||
0xD3DC3BEF265B0F70 /* 766 */, 0x6D0E60F5C3578A9E /* 767 */,
|
||||
0x5B0E608526323C55 /* 768 */, 0x1A46C1A9FA1B59F5 /* 769 */,
|
||||
0xA9E245A17C4C8FFA /* 770 */, 0x65CA5159DB2955D7 /* 771 */,
|
||||
0x05DB0A76CE35AFC2 /* 772 */, 0x81EAC77EA9113D45 /* 773 */,
|
||||
0x528EF88AB6AC0A0D /* 774 */, 0xA09EA253597BE3FF /* 775 */,
|
||||
0x430DDFB3AC48CD56 /* 776 */, 0xC4B3A67AF45CE46F /* 777 */,
|
||||
0x4ECECFD8FBE2D05E /* 778 */, 0x3EF56F10B39935F0 /* 779 */,
|
||||
0x0B22D6829CD619C6 /* 780 */, 0x17FD460A74DF2069 /* 781 */,
|
||||
0x6CF8CC8E8510ED40 /* 782 */, 0xD6C824BF3A6ECAA7 /* 783 */,
|
||||
0x61243D581A817049 /* 784 */, 0x048BACB6BBC163A2 /* 785 */,
|
||||
0xD9A38AC27D44CC32 /* 786 */, 0x7FDDFF5BAAF410AB /* 787 */,
|
||||
0xAD6D495AA804824B /* 788 */, 0xE1A6A74F2D8C9F94 /* 789 */,
|
||||
0xD4F7851235DEE8E3 /* 790 */, 0xFD4B7F886540D893 /* 791 */,
|
||||
0x247C20042AA4BFDA /* 792 */, 0x096EA1C517D1327C /* 793 */,
|
||||
0xD56966B4361A6685 /* 794 */, 0x277DA5C31221057D /* 795 */,
|
||||
0x94D59893A43ACFF7 /* 796 */, 0x64F0C51CCDC02281 /* 797 */,
|
||||
0x3D33BCC4FF6189DB /* 798 */, 0xE005CB184CE66AF1 /* 799 */,
|
||||
0xFF5CCD1D1DB99BEA /* 800 */, 0xB0B854A7FE42980F /* 801 */,
|
||||
0x7BD46A6A718D4B9F /* 802 */, 0xD10FA8CC22A5FD8C /* 803 */,
|
||||
0xD31484952BE4BD31 /* 804 */, 0xC7FA975FCB243847 /* 805 */,
|
||||
0x4886ED1E5846C407 /* 806 */, 0x28CDDB791EB70B04 /* 807 */,
|
||||
0xC2B00BE2F573417F /* 808 */, 0x5C9590452180F877 /* 809 */,
|
||||
0x7A6BDDFFF370EB00 /* 810 */, 0xCE509E38D6D9D6A4 /* 811 */,
|
||||
0xEBEB0F00647FA702 /* 812 */, 0x1DCC06CF76606F06 /* 813 */,
|
||||
0xE4D9F28BA286FF0A /* 814 */, 0xD85A305DC918C262 /* 815 */,
|
||||
0x475B1D8732225F54 /* 816 */, 0x2D4FB51668CCB5FE /* 817 */,
|
||||
0xA679B9D9D72BBA20 /* 818 */, 0x53841C0D912D43A5 /* 819 */,
|
||||
0x3B7EAA48BF12A4E8 /* 820 */, 0x781E0E47F22F1DDF /* 821 */,
|
||||
0xEFF20CE60AB50973 /* 822 */, 0x20D261D19DFFB742 /* 823 */,
|
||||
0x16A12B03062A2E39 /* 824 */, 0x1960EB2239650495 /* 825 */,
|
||||
0x251C16FED50EB8B8 /* 826 */, 0x9AC0C330F826016E /* 827 */,
|
||||
0xED152665953E7671 /* 828 */, 0x02D63194A6369570 /* 829 */,
|
||||
0x5074F08394B1C987 /* 830 */, 0x70BA598C90B25CE1 /* 831 */,
|
||||
0x794A15810B9742F6 /* 832 */, 0x0D5925E9FCAF8C6C /* 833 */,
|
||||
0x3067716CD868744E /* 834 */, 0x910AB077E8D7731B /* 835 */,
|
||||
0x6A61BBDB5AC42F61 /* 836 */, 0x93513EFBF0851567 /* 837 */,
|
||||
0xF494724B9E83E9D5 /* 838 */, 0xE887E1985C09648D /* 839 */,
|
||||
0x34B1D3C675370CFD /* 840 */, 0xDC35E433BC0D255D /* 841 */,
|
||||
0xD0AAB84234131BE0 /* 842 */, 0x08042A50B48B7EAF /* 843 */,
|
||||
0x9997C4EE44A3AB35 /* 844 */, 0x829A7B49201799D0 /* 845 */,
|
||||
0x263B8307B7C54441 /* 846 */, 0x752F95F4FD6A6CA6 /* 847 */,
|
||||
0x927217402C08C6E5 /* 848 */, 0x2A8AB754A795D9EE /* 849 */,
|
||||
0xA442F7552F72943D /* 850 */, 0x2C31334E19781208 /* 851 */,
|
||||
0x4FA98D7CEAEE6291 /* 852 */, 0x55C3862F665DB309 /* 853 */,
|
||||
0xBD0610175D53B1F3 /* 854 */, 0x46FE6CB840413F27 /* 855 */,
|
||||
0x3FE03792DF0CFA59 /* 856 */, 0xCFE700372EB85E8F /* 857 */,
|
||||
0xA7BE29E7ADBCE118 /* 858 */, 0xE544EE5CDE8431DD /* 859 */,
|
||||
0x8A781B1B41F1873E /* 860 */, 0xA5C94C78A0D2F0E7 /* 861 */,
|
||||
0x39412E2877B60728 /* 862 */, 0xA1265EF3AFC9A62C /* 863 */,
|
||||
0xBCC2770C6A2506C5 /* 864 */, 0x3AB66DD5DCE1CE12 /* 865 */,
|
||||
0xE65499D04A675B37 /* 866 */, 0x7D8F523481BFD216 /* 867 */,
|
||||
0x0F6F64FCEC15F389 /* 868 */, 0x74EFBE618B5B13C8 /* 869 */,
|
||||
0xACDC82B714273E1D /* 870 */, 0xDD40BFE003199D17 /* 871 */,
|
||||
0x37E99257E7E061F8 /* 872 */, 0xFA52626904775AAA /* 873 */,
|
||||
0x8BBBF63A463D56F9 /* 874 */, 0xF0013F1543A26E64 /* 875 */,
|
||||
0xA8307E9F879EC898 /* 876 */, 0xCC4C27A4150177CC /* 877 */,
|
||||
0x1B432F2CCA1D3348 /* 878 */, 0xDE1D1F8F9F6FA013 /* 879 */,
|
||||
0x606602A047A7DDD6 /* 880 */, 0xD237AB64CC1CB2C7 /* 881 */,
|
||||
0x9B938E7225FCD1D3 /* 882 */, 0xEC4E03708E0FF476 /* 883 */,
|
||||
0xFEB2FBDA3D03C12D /* 884 */, 0xAE0BCED2EE43889A /* 885 */,
|
||||
0x22CB8923EBFB4F43 /* 886 */, 0x69360D013CF7396D /* 887 */,
|
||||
0x855E3602D2D4E022 /* 888 */, 0x073805BAD01F784C /* 889 */,
|
||||
0x33E17A133852F546 /* 890 */, 0xDF4874058AC7B638 /* 891 */,
|
||||
0xBA92B29C678AA14A /* 892 */, 0x0CE89FC76CFAADCD /* 893 */,
|
||||
0x5F9D4E0908339E34 /* 894 */, 0xF1AFE9291F5923B9 /* 895 */,
|
||||
0x6E3480F60F4A265F /* 896 */, 0xEEBF3A2AB29B841C /* 897 */,
|
||||
0xE21938A88F91B4AD /* 898 */, 0x57DFEFF845C6D3C3 /* 899 */,
|
||||
0x2F006B0BF62CAAF2 /* 900 */, 0x62F479EF6F75EE78 /* 901 */,
|
||||
0x11A55AD41C8916A9 /* 902 */, 0xF229D29084FED453 /* 903 */,
|
||||
0x42F1C27B16B000E6 /* 904 */, 0x2B1F76749823C074 /* 905 */,
|
||||
0x4B76ECA3C2745360 /* 906 */, 0x8C98F463B91691BD /* 907 */,
|
||||
0x14BCC93CF1ADE66A /* 908 */, 0x8885213E6D458397 /* 909 */,
|
||||
0x8E177DF0274D4711 /* 910 */, 0xB49B73B5503F2951 /* 911 */,
|
||||
0x10168168C3F96B6B /* 912 */, 0x0E3D963B63CAB0AE /* 913 */,
|
||||
0x8DFC4B5655A1DB14 /* 914 */, 0xF789F1356E14DE5C /* 915 */,
|
||||
0x683E68AF4E51DAC1 /* 916 */, 0xC9A84F9D8D4B0FD9 /* 917 */,
|
||||
0x3691E03F52A0F9D1 /* 918 */, 0x5ED86E46E1878E80 /* 919 */,
|
||||
0x3C711A0E99D07150 /* 920 */, 0x5A0865B20C4E9310 /* 921 */,
|
||||
0x56FBFC1FE4F0682E /* 922 */, 0xEA8D5DE3105EDF9B /* 923 */,
|
||||
0x71ABFDB12379187A /* 924 */, 0x2EB99DE1BEE77B9C /* 925 */,
|
||||
0x21ECC0EA33CF4523 /* 926 */, 0x59A4D7521805C7A1 /* 927 */,
|
||||
0x3896F5EB56AE7C72 /* 928 */, 0xAA638F3DB18F75DC /* 929 */,
|
||||
0x9F39358DABE9808E /* 930 */, 0xB7DEFA91C00B72AC /* 931 */,
|
||||
0x6B5541FD62492D92 /* 932 */, 0x6DC6DEE8F92E4D5B /* 933 */,
|
||||
0x353F57ABC4BEEA7E /* 934 */, 0x735769D6DA5690CE /* 935 */,
|
||||
0x0A234AA642391484 /* 936 */, 0xF6F9508028F80D9D /* 937 */,
|
||||
0xB8E319A27AB3F215 /* 938 */, 0x31AD9C1151341A4D /* 939 */,
|
||||
0x773C22A57BEF5805 /* 940 */, 0x45C7561A07968633 /* 941 */,
|
||||
0xF913DA9E249DBE36 /* 942 */, 0xDA652D9B78A64C68 /* 943 */,
|
||||
0x4C27A97F3BC334EF /* 944 */, 0x76621220E66B17F4 /* 945 */,
|
||||
0x967743899ACD7D0B /* 946 */, 0xF3EE5BCAE0ED6782 /* 947 */,
|
||||
0x409F753600C879FC /* 948 */, 0x06D09A39B5926DB6 /* 949 */,
|
||||
0x6F83AEB0317AC588 /* 950 */, 0x01E6CA4A86381F21 /* 951 */,
|
||||
0x66FF3462D19F3025 /* 952 */, 0x72207C24DDFD3BFB /* 953 */,
|
||||
0x4AF6B6D3E2ECE2EB /* 954 */, 0x9C994DBEC7EA08DE /* 955 */,
|
||||
0x49ACE597B09A8BC4 /* 956 */, 0xB38C4766CF0797BA /* 957 */,
|
||||
0x131B9373C57C2A75 /* 958 */, 0xB1822CCE61931E58 /* 959 */,
|
||||
0x9D7555B909BA1C0C /* 960 */, 0x127FAFDD937D11D2 /* 961 */,
|
||||
0x29DA3BADC66D92E4 /* 962 */, 0xA2C1D57154C2ECBC /* 963 */,
|
||||
0x58C5134D82F6FE24 /* 964 */, 0x1C3AE3515B62274F /* 965 */,
|
||||
0xE907C82E01CB8126 /* 966 */, 0xF8ED091913E37FCB /* 967 */,
|
||||
0x3249D8F9C80046C9 /* 968 */, 0x80CF9BEDE388FB63 /* 969 */,
|
||||
0x1881539A116CF19E /* 970 */, 0x5103F3F76BD52457 /* 971 */,
|
||||
0x15B7E6F5AE47F7A8 /* 972 */, 0xDBD7C6DED47E9CCF /* 973 */,
|
||||
0x44E55C410228BB1A /* 974 */, 0xB647D4255EDB4E99 /* 975 */,
|
||||
0x5D11882BB8AAFC30 /* 976 */, 0xF5098BBB29D3212A /* 977 */,
|
||||
0x8FB5EA14E90296B3 /* 978 */, 0x677B942157DD025A /* 979 */,
|
||||
0xFB58E7C0A390ACB5 /* 980 */, 0x89D3674C83BD4A01 /* 981 */,
|
||||
0x9E2DA4DF4BF3B93B /* 982 */, 0xFCC41E328CAB4829 /* 983 */,
|
||||
0x03F38C96BA582C52 /* 984 */, 0xCAD1BDBD7FD85DB2 /* 985 */,
|
||||
0xBBB442C16082AE83 /* 986 */, 0xB95FE86BA5DA9AB0 /* 987 */,
|
||||
0xB22E04673771A93F /* 988 */, 0x845358C9493152D8 /* 989 */,
|
||||
0xBE2A488697B4541E /* 990 */, 0x95A2DC2DD38E6966 /* 991 */,
|
||||
0xC02C11AC923C852B /* 992 */, 0x2388B1990DF2A87B /* 993 */,
|
||||
0x7C8008FA1B4F37BE /* 994 */, 0x1F70D0C84D54E503 /* 995 */,
|
||||
0x5490ADEC7ECE57D4 /* 996 */, 0x002B3C27D9063A3A /* 997 */,
|
||||
0x7EAEA3848030A2BF /* 998 */, 0xC602326DED2003C0 /* 999 */,
|
||||
0x83A7287D69A94086 /* 1000 */, 0xC57A5FCB30F57A8A /* 1001 */,
|
||||
0xB56844E479EBE779 /* 1002 */, 0xA373B40F05DCBCE9 /* 1003 */,
|
||||
0xD71A786E88570EE2 /* 1004 */, 0x879CBACDBDE8F6A0 /* 1005 */,
|
||||
0x976AD1BCC164A32F /* 1006 */, 0xAB21E25E9666D78B /* 1007 */,
|
||||
0x901063AAE5E5C33C /* 1008 */, 0x9818B34448698D90 /* 1009 */,
|
||||
0xE36487AE3E1E8ABB /* 1010 */, 0xAFBDF931893BDCB4 /* 1011 */,
|
||||
0x6345A0DC5FBBD519 /* 1012 */, 0x8628FE269B9465CA /* 1013 */,
|
||||
0x1E5D01603F9C51EC /* 1014 */, 0x4DE44006A15049B7 /* 1015 */,
|
||||
0xBF6C70E5F776CBB1 /* 1016 */, 0x411218F2EF552BED /* 1017 */,
|
||||
0xCB0C0708705A36A3 /* 1018 */, 0xE74D14754F986044 /* 1019 */,
|
||||
0xCD56D9430EA8280E /* 1020 */, 0xC12591D7535F5065 /* 1021 */,
|
||||
0xC83223F1720AEF96 /* 1022 */, 0xC3A0396F7363A51F /* 1023 */
|
||||
];
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
170
SabreTools.Hashing/MessageDigest/MD2.cs
Normal file
170
SabreTools.Hashing/MessageDigest/MD2.cs
Normal file
@@ -0,0 +1,170 @@
|
||||
using System;
|
||||
using static SabreTools.Hashing.MessageDigest.Constants;
|
||||
|
||||
namespace SabreTools.Hashing.MessageDigest
|
||||
{
|
||||
/// <see href="https://datatracker.ietf.org/doc/html/rfc1115"/>
|
||||
public class MD2 : MessageDigestBase<uint>
|
||||
{
|
||||
/// <summary>
|
||||
/// Buffer for forming digest in
|
||||
/// </summary>
|
||||
/// <remarks>At the end, D[0...15] form the message digest</remarks>
|
||||
private readonly byte[] _digest = new byte[48];
|
||||
|
||||
/// <summary>
|
||||
/// Checksum register
|
||||
/// </summary>
|
||||
private readonly byte[] _checksum = new byte[16];
|
||||
|
||||
/// <summary>
|
||||
/// Number of bytes handled, modulo 16
|
||||
/// </summary>
|
||||
private byte _byteCount;
|
||||
|
||||
/// <summary>
|
||||
/// Last checksum char saved
|
||||
/// </summary>
|
||||
private byte _lastByte;
|
||||
|
||||
public MD2() : base()
|
||||
{
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
protected override void ResetImpl()
|
||||
{
|
||||
Array.Clear(_digest, 0, _digest.Length);
|
||||
Array.Clear(_checksum, 0, _checksum.Length);
|
||||
_byteCount = 0;
|
||||
_lastByte = 0;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override void TransformBlock(byte[] data, int offset, int length)
|
||||
{
|
||||
// Figure out how much buffer is needed
|
||||
int bufferLen = 16 - _byteCount;
|
||||
|
||||
// If there is buffer to fill and it will meet the limit
|
||||
if (_byteCount > 0 && _byteCount + length >= 16)
|
||||
{
|
||||
// Fill the buffer from the input
|
||||
for (int i = 0; i < bufferLen; i++)
|
||||
{
|
||||
// Add new character to buffer
|
||||
_digest[16 + _byteCount] = data[offset + i];
|
||||
_digest[32 + _byteCount] = (byte)(data[offset + i] ^ _digest[_byteCount]);
|
||||
|
||||
// Update checksum register C and value L
|
||||
_lastByte = _checksum[_byteCount] ^= MD2SBox[0xff & (data[offset + i] ^ _lastByte)];
|
||||
|
||||
// Increment i by one modulo 16
|
||||
_byteCount = (byte)((_byteCount + 1) & 15);
|
||||
}
|
||||
|
||||
// Set the new values
|
||||
offset += bufferLen;
|
||||
length -= bufferLen;
|
||||
|
||||
// Run the update
|
||||
Update();
|
||||
}
|
||||
|
||||
/// Process any standalone blocks
|
||||
while (length >= 16)
|
||||
{
|
||||
// Fill the buffer from the input
|
||||
for (int i = 0; i < 16; i++)
|
||||
{
|
||||
// Add new character to buffer
|
||||
_digest[16 + _byteCount] = data[offset + i];
|
||||
_digest[32 + _byteCount] = (byte)(data[offset + i] ^ _digest[_byteCount]);
|
||||
|
||||
// Update checksum register C and value L
|
||||
_lastByte = _checksum[_byteCount] ^= MD2SBox[0xff & (data[offset + i] ^ _lastByte)];
|
||||
|
||||
// Increment i by one modulo 16
|
||||
_byteCount = (byte)((_byteCount + 1) & 15);
|
||||
}
|
||||
|
||||
// Set the new values
|
||||
offset += 16;
|
||||
length -= 16;
|
||||
|
||||
// Run the update
|
||||
Update();
|
||||
}
|
||||
|
||||
// Save the remainder in the buffer
|
||||
if (length > 0)
|
||||
{
|
||||
// Fill the buffer from the input
|
||||
for (int i = 0; i < length; i++)
|
||||
{
|
||||
// Add new character to buffer
|
||||
_digest[16 + _byteCount] = data[offset + i];
|
||||
_digest[32 + _byteCount] = (byte)(data[offset + i] ^ _digest[_byteCount]);
|
||||
|
||||
// Update checksum register C and value L
|
||||
_lastByte = _checksum[_byteCount] ^= MD2SBox[0xff & (data[offset + i] ^ _lastByte)];
|
||||
|
||||
// Increment i by one modulo 16
|
||||
_byteCount = (byte)((_byteCount + 1) & 15);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override void Terminate()
|
||||
{
|
||||
// Determine the pad length
|
||||
byte padLength = (byte)(16 - _byteCount);
|
||||
|
||||
// Pad the block
|
||||
byte[] padding = new byte[padLength];
|
||||
#if NETFRAMEWORK
|
||||
for (int i = 0; i < padLength; i++)
|
||||
{
|
||||
padding[i] = padLength;
|
||||
}
|
||||
#else
|
||||
Array.Fill(padding, padLength);
|
||||
#endif
|
||||
TransformBlock(padding, 0, padLength);
|
||||
TransformBlock(_checksum, 0, _checksum.Length);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override byte[] GetHash()
|
||||
{
|
||||
var hash = new byte[16];
|
||||
Array.Copy(_digest, hash, 16);
|
||||
|
||||
// Reset the state and return
|
||||
Reset();
|
||||
return hash;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The routine MDUPDATE updates the message digest context buffer to
|
||||
/// account for the presence of the character c in the message whose
|
||||
/// digest is being computed. This routine will be called for each
|
||||
/// message byte in turn.
|
||||
/// </summary>
|
||||
/// <remarks>The following is a more efficient version of the loop</remarks>
|
||||
private void Update()
|
||||
{
|
||||
byte t = 0;
|
||||
for (byte j = 0; j < 18; j++)
|
||||
{
|
||||
for (byte i = 0; i < 48; i++)
|
||||
{
|
||||
t = _digest[i] = (byte)(_digest[i] ^ MD2SBox[t]);
|
||||
}
|
||||
|
||||
t += j;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
216
SabreTools.Hashing/MessageDigest/MD4.cs
Normal file
216
SabreTools.Hashing/MessageDigest/MD4.cs
Normal file
@@ -0,0 +1,216 @@
|
||||
using System;
|
||||
using static SabreTools.Hashing.HashOperations;
|
||||
using static SabreTools.Hashing.MessageDigest.Constants;
|
||||
|
||||
namespace SabreTools.Hashing.MessageDigest
|
||||
{
|
||||
/// <see href="https://datatracker.ietf.org/doc/html/rfc1320"/>
|
||||
public class MD4 : MessageDigestBase<uint>
|
||||
{
|
||||
/// <summary>
|
||||
/// Set of 4 32-bit numbers representing the hash state
|
||||
/// </summary>
|
||||
private readonly uint[] _state = new uint[4];
|
||||
|
||||
public MD4() : base()
|
||||
{
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
protected override void ResetImpl()
|
||||
{
|
||||
_state[0] = MD4SeedA;
|
||||
_state[1] = MD4SeedB;
|
||||
_state[2] = MD4SeedC;
|
||||
_state[3] = MD4SeedD;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override void TransformBlock(byte[] data, int offset, int length)
|
||||
{
|
||||
// Figure out how much buffer is needed
|
||||
int bufferLen = (int)(_totalBytes & 0x3f);
|
||||
|
||||
// Increment the processed byte count
|
||||
_totalBytes += length;
|
||||
|
||||
// If there is buffer to fill and it will meet the limit
|
||||
if (bufferLen > 0 && bufferLen + length >= 64)
|
||||
{
|
||||
// Fill the buffer from the input
|
||||
Array.Copy(data, offset, _buffer, bufferLen, 64 - bufferLen);
|
||||
|
||||
// Set the new values
|
||||
offset += 64 - bufferLen;
|
||||
length -= 64 - bufferLen;
|
||||
|
||||
// Split the buffer for the round
|
||||
for (int i = 0; i < 16; i++)
|
||||
{
|
||||
_block[i] = ReadLE32(_buffer, i * 4);
|
||||
}
|
||||
|
||||
// Run the round
|
||||
Round();
|
||||
bufferLen = 0;
|
||||
}
|
||||
|
||||
/// Process any standalone blocks
|
||||
while (length >= 64)
|
||||
{
|
||||
// Fill the buffer from the input
|
||||
Array.Copy(data, offset, _buffer, 0, 64);
|
||||
|
||||
// Set the new values
|
||||
offset += 64;
|
||||
length -= 64;
|
||||
|
||||
// Split the buffer for the round
|
||||
for (int i = 0; i < 16; i++)
|
||||
{
|
||||
_block[i] = ReadLE32(_buffer, i * 4);
|
||||
}
|
||||
|
||||
// Run the round
|
||||
Round();
|
||||
}
|
||||
|
||||
// Save the remainder in the buffer
|
||||
if (length > 0)
|
||||
Array.Copy(data, offset, _buffer, bufferLen, length);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override void Terminate()
|
||||
{
|
||||
// Determine the pad length
|
||||
int padLength = 64 - (int)(_totalBytes & 0x3f);
|
||||
if (padLength <= 8)
|
||||
padLength += 64;
|
||||
|
||||
// Get the total byte count in bits
|
||||
long totalBitCount = _totalBytes * 8;
|
||||
|
||||
// Prebuild the padding
|
||||
var padding = new byte[padLength];
|
||||
padding[0] = 0x80;
|
||||
padding[padLength - 1] = (byte)((totalBitCount >> 56) & 0xff);
|
||||
padding[padLength - 2] = (byte)((totalBitCount >> 48) & 0xff);
|
||||
padding[padLength - 3] = (byte)((totalBitCount >> 40) & 0xff);
|
||||
padding[padLength - 4] = (byte)((totalBitCount >> 32) & 0xff);
|
||||
padding[padLength - 5] = (byte)((totalBitCount >> 24) & 0xff);
|
||||
padding[padLength - 6] = (byte)((totalBitCount >> 16) & 0xff);
|
||||
padding[padLength - 7] = (byte)((totalBitCount >> 8) & 0xff);
|
||||
padding[padLength - 8] = (byte)((totalBitCount >> 0) & 0xff);
|
||||
|
||||
// Pad the block
|
||||
TransformBlock(padding, 0, padding.Length);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override byte[] GetHash()
|
||||
{
|
||||
var hash = new byte[16];
|
||||
int hashOffset = 0;
|
||||
|
||||
// Assemble the hash array
|
||||
for (int i = 0; i < _state.Length; i++)
|
||||
{
|
||||
byte[] segment = BitConverter.GetBytes(_state[i]);
|
||||
Array.Copy(segment, 0, hash, hashOffset, 4);
|
||||
hashOffset += 4;
|
||||
}
|
||||
|
||||
// Reset the state and return
|
||||
Reset();
|
||||
return hash;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Perform one round of updates on the cached values
|
||||
/// </summary>
|
||||
private void Round()
|
||||
{
|
||||
// Setup values
|
||||
uint a = _state[0];
|
||||
uint b = _state[1];
|
||||
uint c = _state[2];
|
||||
uint d = _state[3];
|
||||
|
||||
// Round 1
|
||||
a = RotateLeft32(a + F(b, c, d) + _block[0] + MD4Round1, 3);
|
||||
d = RotateLeft32(d + F(a, b, c) + _block[1] + MD4Round1, 7);
|
||||
c = RotateLeft32(c + F(d, a, b) + _block[2] + MD4Round1, 11);
|
||||
b = RotateLeft32(b + F(c, d, a) + _block[3] + MD4Round1, 19);
|
||||
a = RotateLeft32(a + F(b, c, d) + _block[4] + MD4Round1, 3);
|
||||
d = RotateLeft32(d + F(a, b, c) + _block[5] + MD4Round1, 7);
|
||||
c = RotateLeft32(c + F(d, a, b) + _block[6] + MD4Round1, 11);
|
||||
b = RotateLeft32(b + F(c, d, a) + _block[7] + MD4Round1, 19);
|
||||
a = RotateLeft32(a + F(b, c, d) + _block[8] + MD4Round1, 3);
|
||||
d = RotateLeft32(d + F(a, b, c) + _block[9] + MD4Round1, 7);
|
||||
c = RotateLeft32(c + F(d, a, b) + _block[10] + MD4Round1, 11);
|
||||
b = RotateLeft32(b + F(c, d, a) + _block[11] + MD4Round1, 19);
|
||||
a = RotateLeft32(a + F(b, c, d) + _block[12] + MD4Round1, 3);
|
||||
d = RotateLeft32(d + F(a, b, c) + _block[13] + MD4Round1, 7);
|
||||
c = RotateLeft32(c + F(d, a, b) + _block[14] + MD4Round1, 11);
|
||||
b = RotateLeft32(b + F(c, d, a) + _block[15] + MD4Round1, 19);
|
||||
|
||||
// Round 2
|
||||
a = RotateLeft32(a + G(b, c, d) + _block[0] + MD4Round2, 3);
|
||||
d = RotateLeft32(d + G(a, b, c) + _block[4] + MD4Round2, 5);
|
||||
c = RotateLeft32(c + G(d, a, b) + _block[8] + MD4Round2, 9);
|
||||
b = RotateLeft32(b + G(c, d, a) + _block[12] + MD4Round2, 13);
|
||||
a = RotateLeft32(a + G(b, c, d) + _block[1] + MD4Round2, 3);
|
||||
d = RotateLeft32(d + G(a, b, c) + _block[5] + MD4Round2, 5);
|
||||
c = RotateLeft32(c + G(d, a, b) + _block[9] + MD4Round2, 9);
|
||||
b = RotateLeft32(b + G(c, d, a) + _block[13] + MD4Round2, 13);
|
||||
a = RotateLeft32(a + G(b, c, d) + _block[2] + MD4Round2, 3);
|
||||
d = RotateLeft32(d + G(a, b, c) + _block[6] + MD4Round2, 5);
|
||||
c = RotateLeft32(c + G(d, a, b) + _block[10] + MD4Round2, 9);
|
||||
b = RotateLeft32(b + G(c, d, a) + _block[14] + MD4Round2, 13);
|
||||
a = RotateLeft32(a + G(b, c, d) + _block[3] + MD4Round2, 3);
|
||||
d = RotateLeft32(d + G(a, b, c) + _block[7] + MD4Round2, 5);
|
||||
c = RotateLeft32(c + G(d, a, b) + _block[11] + MD4Round2, 9);
|
||||
b = RotateLeft32(b + G(c, d, a) + _block[15] + MD4Round2, 13);
|
||||
|
||||
// Round 3
|
||||
a = RotateLeft32(a + H(b, c, d) + _block[0] + MD4Round3, 3);
|
||||
d = RotateLeft32(d + H(a, b, c) + _block[8] + MD4Round3, 9);
|
||||
c = RotateLeft32(c + H(d, a, b) + _block[4] + MD4Round3, 11);
|
||||
b = RotateLeft32(b + H(c, d, a) + _block[12] + MD4Round3, 15);
|
||||
a = RotateLeft32(a + H(b, c, d) + _block[2] + MD4Round3, 3);
|
||||
d = RotateLeft32(d + H(a, b, c) + _block[10] + MD4Round3, 9);
|
||||
c = RotateLeft32(c + H(d, a, b) + _block[6] + MD4Round3, 11);
|
||||
b = RotateLeft32(b + H(c, d, a) + _block[14] + MD4Round3, 15);
|
||||
a = RotateLeft32(a + H(b, c, d) + _block[1] + MD4Round3, 3);
|
||||
d = RotateLeft32(d + H(a, b, c) + _block[9] + MD4Round3, 9);
|
||||
c = RotateLeft32(c + H(d, a, b) + _block[5] + MD4Round3, 11);
|
||||
b = RotateLeft32(b + H(c, d, a) + _block[13] + MD4Round3, 15);
|
||||
a = RotateLeft32(a + H(b, c, d) + _block[3] + MD4Round3, 3);
|
||||
d = RotateLeft32(d + H(a, b, c) + _block[11] + MD4Round3, 9);
|
||||
c = RotateLeft32(c + H(d, a, b) + _block[7] + MD4Round3, 11);
|
||||
b = RotateLeft32(b + H(c, d, a) + _block[15] + MD4Round3, 15);
|
||||
|
||||
// Update stored values
|
||||
_state[0] += a;
|
||||
_state[1] += b;
|
||||
_state[2] += c;
|
||||
_state[3] += d;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Auxiliary function F
|
||||
/// </summary>
|
||||
private static uint F(uint x, uint y, uint z) => (x & y) | (~x & z);
|
||||
|
||||
/// <summary>
|
||||
/// Auxiliary function G
|
||||
/// </summary>
|
||||
private static uint G(uint x, uint y, uint z) => (x & y) | (x & z) | (y & z);
|
||||
|
||||
/// <summary>
|
||||
/// Auxiliary function H
|
||||
/// </summary>
|
||||
private static uint H(uint x, uint y, uint z) => x ^ y ^ z;
|
||||
}
|
||||
}
|
||||
85
SabreTools.Hashing/MessageDigest/MessageDigestBase.cs
Normal file
85
SabreTools.Hashing/MessageDigest/MessageDigestBase.cs
Normal file
@@ -0,0 +1,85 @@
|
||||
using System;
|
||||
|
||||
namespace SabreTools.Hashing.MessageDigest
|
||||
{
|
||||
public abstract class MessageDigestBase
|
||||
{
|
||||
/// <summary>
|
||||
/// Total number of bytes processed
|
||||
/// </summary>
|
||||
protected long _totalBytes;
|
||||
|
||||
/// <summary>
|
||||
/// Internal byte buffer to accumulate before <see cref="_block"/>
|
||||
/// </summary>
|
||||
protected readonly byte[] _buffer = new byte[64];
|
||||
|
||||
/// <summary>
|
||||
/// Reset additional values
|
||||
/// </summary>
|
||||
protected abstract void ResetImpl();
|
||||
|
||||
/// <summary>
|
||||
/// Hash a block of data and append it to the existing hash
|
||||
/// </summary>
|
||||
/// <param name="data">Byte array representing the data</param>
|
||||
/// <param name="offset">Offset in the byte array to include</param>
|
||||
/// <param name="length">Length of the data to hash</param>
|
||||
public abstract void TransformBlock(byte[] data, int offset, int length);
|
||||
|
||||
/// <summary>
|
||||
/// End the hashing process
|
||||
/// </summary>
|
||||
/// TODO: Combine this when the padding byte can be set by implementing classes
|
||||
public abstract void Terminate();
|
||||
|
||||
/// <summary>
|
||||
/// Get the current value of the hash
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// If <see cref="Terminate"/> has not been run, this value
|
||||
/// will not be accurate for the processed bytes so far.
|
||||
/// </remarks>
|
||||
/// TODO: Combine this when there's an easier way of passing the state
|
||||
public abstract byte[] GetHash();
|
||||
}
|
||||
|
||||
public abstract class MessageDigestBase<T> : MessageDigestBase where T : struct
|
||||
{
|
||||
/// <summary>
|
||||
/// Internal buffer for processing
|
||||
/// </summary>
|
||||
protected readonly T[] _block;
|
||||
|
||||
public MessageDigestBase()
|
||||
{
|
||||
if (typeof(T) == typeof(short) || typeof(T) == typeof(ushort))
|
||||
_block = new T[32];
|
||||
else if (typeof(T) == typeof(int) || typeof(T) == typeof(uint))
|
||||
_block = new T[16];
|
||||
else if (typeof(T) == typeof(long) || typeof(T) == typeof(ulong))
|
||||
_block = new T[8];
|
||||
|
||||
else
|
||||
throw new InvalidOperationException();
|
||||
|
||||
Reset();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reset the internal hashing state
|
||||
/// </summary>
|
||||
public void Reset()
|
||||
{
|
||||
// Reset the seed values
|
||||
ResetImpl();
|
||||
|
||||
// Reset the byte count
|
||||
_totalBytes = 0;
|
||||
|
||||
// Reset the buffers
|
||||
Array.Clear(_buffer, 0, _buffer.Length);
|
||||
Array.Clear(_block, 0, _block.Length);
|
||||
}
|
||||
}
|
||||
}
|
||||
449
SabreTools.Hashing/MessageDigest/RipeMD128.cs
Normal file
449
SabreTools.Hashing/MessageDigest/RipeMD128.cs
Normal file
@@ -0,0 +1,449 @@
|
||||
using System;
|
||||
using static SabreTools.Hashing.HashOperations;
|
||||
using static SabreTools.Hashing.MessageDigest.Constants;
|
||||
|
||||
namespace SabreTools.Hashing.MessageDigest
|
||||
{
|
||||
/// <see href="https://cdn.standards.iteh.ai/samples/39876/10f9f9f4bb614eaaaeba7e157e183ca3/ISO-IEC-10118-3-2004.pdf"/>
|
||||
/// <see href="https://homes.esat.kuleuven.be/~bosselae/ripemd160/pdf/AB-9601/AB-9601.pdf"/>
|
||||
public class RipeMD128 : MessageDigestBase<uint>
|
||||
{
|
||||
/// <summary>
|
||||
/// Set of 4 32-bit numbers representing the hash state
|
||||
/// </summary>
|
||||
private readonly uint[] _state = new uint[4];
|
||||
|
||||
public RipeMD128() : base()
|
||||
{
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
protected override void ResetImpl()
|
||||
{
|
||||
_state[0] = RMD128Y0;
|
||||
_state[1] = RMD128Y1;
|
||||
_state[2] = RMD128Y2;
|
||||
_state[3] = RMD128Y3;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override void TransformBlock(byte[] data, int offset, int length)
|
||||
{
|
||||
// Figure out how much buffer is needed
|
||||
int bufferLen = (int)(_totalBytes & 0x3f);
|
||||
|
||||
// Increment the processed byte count
|
||||
_totalBytes += length;
|
||||
|
||||
// If there is buffer to fill and it will meet the limit
|
||||
if (bufferLen > 0 && bufferLen + length >= 64)
|
||||
{
|
||||
// Fill the buffer from the input
|
||||
Array.Copy(data, offset, _buffer, bufferLen, 64 - bufferLen);
|
||||
|
||||
// Set the new values
|
||||
offset += 64 - bufferLen;
|
||||
length -= 64 - bufferLen;
|
||||
|
||||
// Split the buffer for the round
|
||||
for (int i = 0; i < 16; i++)
|
||||
{
|
||||
_block[i] = ReadLE32(_buffer, i * 4);
|
||||
}
|
||||
|
||||
// Run the round
|
||||
Round();
|
||||
bufferLen = 0;
|
||||
}
|
||||
|
||||
/// Process any standalone blocks
|
||||
while (length >= 64)
|
||||
{
|
||||
// Fill the buffer from the input
|
||||
Array.Copy(data, offset, _buffer, 0, 64);
|
||||
|
||||
// Set the new values
|
||||
offset += 64;
|
||||
length -= 64;
|
||||
|
||||
// Split the buffer for the round
|
||||
for (int i = 0; i < 16; i++)
|
||||
{
|
||||
_block[i] = ReadLE32(_buffer, i * 4);
|
||||
}
|
||||
|
||||
// Run the round
|
||||
Round();
|
||||
}
|
||||
|
||||
// Save the remainder in the buffer
|
||||
if (length > 0)
|
||||
Array.Copy(data, offset, _buffer, bufferLen, length);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override void Terminate()
|
||||
{
|
||||
// Determine the pad length
|
||||
int padLength = 64 - (int)(_totalBytes & 0x3f);
|
||||
if (padLength <= 8)
|
||||
padLength += 64;
|
||||
|
||||
// Get the total byte count in bits
|
||||
long totalBitCount = _totalBytes * 8;
|
||||
|
||||
// Prebuild the padding
|
||||
var padding = new byte[padLength];
|
||||
padding[0] = 0x80;
|
||||
padding[padLength - 1] = (byte)((totalBitCount >> 56) & 0xff);
|
||||
padding[padLength - 2] = (byte)((totalBitCount >> 48) & 0xff);
|
||||
padding[padLength - 3] = (byte)((totalBitCount >> 40) & 0xff);
|
||||
padding[padLength - 4] = (byte)((totalBitCount >> 32) & 0xff);
|
||||
padding[padLength - 5] = (byte)((totalBitCount >> 24) & 0xff);
|
||||
padding[padLength - 6] = (byte)((totalBitCount >> 16) & 0xff);
|
||||
padding[padLength - 7] = (byte)((totalBitCount >> 8) & 0xff);
|
||||
padding[padLength - 8] = (byte)((totalBitCount >> 0) & 0xff);
|
||||
|
||||
// Pad the block
|
||||
TransformBlock(padding, 0, padding.Length);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override byte[] GetHash()
|
||||
{
|
||||
var hash = new byte[16];
|
||||
int hashOffset = 0;
|
||||
|
||||
// Assemble the hash array
|
||||
for (int i = 0; i < _state.Length; i++)
|
||||
{
|
||||
byte[] segment = BitConverter.GetBytes(_state[i]);
|
||||
Array.Copy(segment, 0, hash, hashOffset, 4);
|
||||
hashOffset += 4;
|
||||
}
|
||||
|
||||
// Reset the state and return
|
||||
Reset();
|
||||
return hash;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Perform one round of updates on the cached values
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The official specification for RIPEMD-128 includes tables
|
||||
/// and instructions that represent a loop. Most standard implementations
|
||||
/// use the unrolled version of that loop to make it more efficient.
|
||||
///
|
||||
/// The below code started with the looped version but has been converted
|
||||
/// to the more standard implementation instead.
|
||||
/// </remarks>
|
||||
private void Round()
|
||||
{
|
||||
// Setup values
|
||||
uint x0 = _state[0], xp0 = _state[0];
|
||||
uint x1 = _state[1], xp1 = _state[1];
|
||||
uint x2 = _state[2], xp2 = _state[2];
|
||||
uint x3 = _state[3], xp3 = _state[3];
|
||||
|
||||
#region Rounds 0-15
|
||||
|
||||
// Round 0
|
||||
x0 = RotateLeft32(x0 + G00_15(x1, x2, x3) + _block[0] + RMD128Round00To15, 11);
|
||||
xp0 = RotateLeft32(xp0 + G48_63(xp1, xp2, xp3) + _block[5] + RMD128RoundPrime00To15, 8);
|
||||
|
||||
// Round 1
|
||||
x3 = RotateLeft32(x3 + G00_15(x0, x1, x2) + _block[1] + RMD128Round00To15, 14);
|
||||
xp3 = RotateLeft32(xp3 + G48_63(xp0, xp1, xp2) + _block[14] + RMD128RoundPrime00To15, 9);
|
||||
|
||||
// Round 2
|
||||
x2 = RotateLeft32(x2 + G00_15(x3, x0, x1) + _block[2] + RMD128Round00To15, 15);
|
||||
xp2 = RotateLeft32(xp2 + G48_63(xp3, xp0, xp1) + _block[7] + RMD128RoundPrime00To15, 9);
|
||||
|
||||
// Round 3
|
||||
x1 = RotateLeft32(x1 + G00_15(x2, x3, x0) + _block[3] + RMD128Round00To15, 12);
|
||||
xp1 = RotateLeft32(xp1 + G48_63(xp2, xp3, xp0) + _block[0] + RMD128RoundPrime00To15, 11);
|
||||
|
||||
// Round 4
|
||||
x0 = RotateLeft32(x0 + G00_15(x1, x2, x3) + _block[4] + RMD128Round00To15, 5);
|
||||
xp0 = RotateLeft32(xp0 + G48_63(xp1, xp2, xp3) + _block[9] + RMD128RoundPrime00To15, 13);
|
||||
|
||||
// Round 5
|
||||
x3 = RotateLeft32(x3 + G00_15(x0, x1, x2) + _block[5] + RMD128Round00To15, 8);
|
||||
xp3 = RotateLeft32(xp3 + G48_63(xp0, xp1, xp2) + _block[2] + RMD128RoundPrime00To15, 15);
|
||||
|
||||
// Round 6
|
||||
x2 = RotateLeft32(x2 + G00_15(x3, x0, x1) + _block[6] + RMD128Round00To15, 7);
|
||||
xp2 = RotateLeft32(xp2 + G48_63(xp3, xp0, xp1) + _block[11] + RMD128RoundPrime00To15, 15);
|
||||
|
||||
// Round 7
|
||||
x1 = RotateLeft32(x1 + G00_15(x2, x3, x0) + _block[7] + RMD128Round00To15, 9);
|
||||
xp1 = RotateLeft32(xp1 + G48_63(xp2, xp3, xp0) + _block[4] + RMD128RoundPrime00To15, 5);
|
||||
|
||||
// Round 8
|
||||
x0 = RotateLeft32(x0 + G00_15(x1, x2, x3) + _block[8] + RMD128Round00To15, 11);
|
||||
xp0 = RotateLeft32(xp0 + G48_63(xp1, xp2, xp3) + _block[13] + RMD128RoundPrime00To15, 7);
|
||||
|
||||
// Round 9
|
||||
x3 = RotateLeft32(x3 + G00_15(x0, x1, x2) + _block[9] + RMD128Round00To15, 13);
|
||||
xp3 = RotateLeft32(xp3 + G48_63(xp0, xp1, xp2) + _block[6] + RMD128RoundPrime00To15, 7);
|
||||
|
||||
// Round 10
|
||||
x2 = RotateLeft32(x2 + G00_15(x3, x0, x1) + _block[10] + RMD128Round00To15, 14);
|
||||
xp2 = RotateLeft32(xp2 + G48_63(xp3, xp0, xp1) + _block[15] + RMD128RoundPrime00To15, 8);
|
||||
|
||||
// Round 11
|
||||
x1 = RotateLeft32(x1 + G00_15(x2, x3, x0) + _block[11] + RMD128Round00To15, 15);
|
||||
xp1 = RotateLeft32(xp1 + G48_63(xp2, xp3, xp0) + _block[8] + RMD128RoundPrime00To15, 11);
|
||||
|
||||
// Round 12
|
||||
x0 = RotateLeft32(x0 + G00_15(x1, x2, x3) + _block[12] + RMD128Round00To15, 6);
|
||||
xp0 = RotateLeft32(xp0 + G48_63(xp1, xp2, xp3) + _block[1] + RMD128RoundPrime00To15, 14);
|
||||
|
||||
// Round 13
|
||||
x3 = RotateLeft32(x3 + G00_15(x0, x1, x2) + _block[13] + RMD128Round00To15, 7);
|
||||
xp3 = RotateLeft32(xp3 + G48_63(xp0, xp1, xp2) + _block[10] + RMD128RoundPrime00To15, 14);
|
||||
|
||||
// Round 14
|
||||
x2 = RotateLeft32(x2 + G00_15(x3, x0, x1) + _block[14] + RMD128Round00To15, 9);
|
||||
xp2 = RotateLeft32(xp2 + G48_63(xp3, xp0, xp1) + _block[3] + RMD128RoundPrime00To15, 12);
|
||||
|
||||
// Round 15
|
||||
x1 = RotateLeft32(x1 + G00_15(x2, x3, x0) + _block[15] + RMD128Round00To15, 8);
|
||||
xp1 = RotateLeft32(xp1 + G48_63(xp2, xp3, xp0) + _block[12] + RMD128RoundPrime00To15, 6);
|
||||
|
||||
#endregion
|
||||
|
||||
#region Rounds 16-31
|
||||
|
||||
// Round 16
|
||||
x0 = RotateLeft32(x0 + G16_31(x1, x2, x3) + _block[7] + RMD128Round16To31, 7);
|
||||
xp0 = RotateLeft32(xp0 + G32_47(xp1, xp2, xp3) + _block[6] + RMD128RoundPrime16To31, 9);
|
||||
|
||||
// Round 17
|
||||
x3 = RotateLeft32(x3 + G16_31(x0, x1, x2) + _block[4] + RMD128Round16To31, 6);
|
||||
xp3 = RotateLeft32(xp3 + G32_47(xp0, xp1, xp2) + _block[11] + RMD128RoundPrime16To31, 13);
|
||||
|
||||
// Round 18
|
||||
x2 = RotateLeft32(x2 + G16_31(x3, x0, x1) + _block[13] + RMD128Round16To31, 8);
|
||||
xp2 = RotateLeft32(xp2 + G32_47(xp3, xp0, xp1) + _block[3] + RMD128RoundPrime16To31, 15);
|
||||
|
||||
// Round 19
|
||||
x1 = RotateLeft32(x1 + G16_31(x2, x3, x0) + _block[1] + RMD128Round16To31, 13);
|
||||
xp1 = RotateLeft32(xp1 + G32_47(xp2, xp3, xp0) + _block[7] + RMD128RoundPrime16To31, 7);
|
||||
|
||||
// Round 20
|
||||
x0 = RotateLeft32(x0 + G16_31(x1, x2, x3) + _block[10] + RMD128Round16To31, 11);
|
||||
xp0 = RotateLeft32(xp0 + G32_47(xp1, xp2, xp3) + _block[0] + RMD128RoundPrime16To31, 12);
|
||||
|
||||
// Round 21
|
||||
x3 = RotateLeft32(x3 + G16_31(x0, x1, x2) + _block[6] + RMD128Round16To31, 9);
|
||||
xp3 = RotateLeft32(xp3 + G32_47(xp0, xp1, xp2) + _block[13] + RMD128RoundPrime16To31, 8);
|
||||
|
||||
// Round 22
|
||||
x2 = RotateLeft32(x2 + G16_31(x3, x0, x1) + _block[15] + RMD128Round16To31, 7);
|
||||
xp2 = RotateLeft32(xp2 + G32_47(xp3, xp0, xp1) + _block[5] + RMD128RoundPrime16To31, 9);
|
||||
|
||||
// Round 23
|
||||
x1 = RotateLeft32(x1 + G16_31(x2, x3, x0) + _block[3] + RMD128Round16To31, 15);
|
||||
xp1 = RotateLeft32(xp1 + G32_47(xp2, xp3, xp0) + _block[10] + RMD128RoundPrime16To31, 11);
|
||||
|
||||
// Round 24
|
||||
x0 = RotateLeft32(x0 + G16_31(x1, x2, x3) + _block[12] + RMD128Round16To31, 7);
|
||||
xp0 = RotateLeft32(xp0 + G32_47(xp1, xp2, xp3) + _block[14] + RMD128RoundPrime16To31, 7);
|
||||
|
||||
// Round 25
|
||||
x3 = RotateLeft32(x3 + G16_31(x0, x1, x2) + _block[0] + RMD128Round16To31, 12);
|
||||
xp3 = RotateLeft32(xp3 + G32_47(xp0, xp1, xp2) + _block[15] + RMD128RoundPrime16To31, 7);
|
||||
|
||||
// Round 26
|
||||
x2 = RotateLeft32(x2 + G16_31(x3, x0, x1) + _block[9] + RMD128Round16To31, 15);
|
||||
xp2 = RotateLeft32(xp2 + G32_47(xp3, xp0, xp1) + _block[8] + RMD128RoundPrime16To31, 12);
|
||||
|
||||
// Round 27
|
||||
x1 = RotateLeft32(x1 + G16_31(x2, x3, x0) + _block[5] + RMD128Round16To31, 9);
|
||||
xp1 = RotateLeft32(xp1 + G32_47(xp2, xp3, xp0) + _block[12] + RMD128RoundPrime16To31, 7);
|
||||
|
||||
// Round 28
|
||||
x0 = RotateLeft32(x0 + G16_31(x1, x2, x3) + _block[2] + RMD128Round16To31, 11);
|
||||
xp0 = RotateLeft32(xp0 + G32_47(xp1, xp2, xp3) + _block[4] + RMD128RoundPrime16To31, 6);
|
||||
|
||||
// Round 29
|
||||
x3 = RotateLeft32(x3 + G16_31(x0, x1, x2) + _block[14] + RMD128Round16To31, 7);
|
||||
xp3 = RotateLeft32(xp3 + G32_47(xp0, xp1, xp2) + _block[9] + RMD128RoundPrime16To31, 15);
|
||||
|
||||
// Round 30
|
||||
x2 = RotateLeft32(x2 + G16_31(x3, x0, x1) + _block[11] + RMD128Round16To31, 13);
|
||||
xp2 = RotateLeft32(xp2 + G32_47(xp3, xp0, xp1) + _block[1] + RMD128RoundPrime16To31, 13);
|
||||
|
||||
// Round 31
|
||||
x1 = RotateLeft32(x1 + G16_31(x2, x3, x0) + _block[8] + RMD128Round16To31, 12);
|
||||
xp1 = RotateLeft32(xp1 + G32_47(xp2, xp3, xp0) + _block[2] + RMD128RoundPrime16To31, 11);
|
||||
|
||||
#endregion
|
||||
|
||||
#region Rounds 32-47
|
||||
|
||||
// Round 32
|
||||
x0 = RotateLeft32(x0 + G32_47(x1, x2, x3) + _block[3] + RMD128Round32To47, 11);
|
||||
xp0 = RotateLeft32(xp0 + G16_31(xp1, xp2, xp3) + _block[15] + RMD128RoundPrime32To47, 9);
|
||||
|
||||
// Round 33
|
||||
x3 = RotateLeft32(x3 + G32_47(x0, x1, x2) + _block[10] + RMD128Round32To47, 13);
|
||||
xp3 = RotateLeft32(xp3 + G16_31(xp0, xp1, xp2) + _block[5] + RMD128RoundPrime32To47, 7);
|
||||
|
||||
// Round 34
|
||||
x2 = RotateLeft32(x2 + G32_47(x3, x0, x1) + _block[14] + RMD128Round32To47, 6);
|
||||
xp2 = RotateLeft32(xp2 + G16_31(xp3, xp0, xp1) + _block[1] + RMD128RoundPrime32To47, 15);
|
||||
|
||||
// Round 35
|
||||
x1 = RotateLeft32(x1 + G32_47(x2, x3, x0) + _block[4] + RMD128Round32To47, 7);
|
||||
xp1 = RotateLeft32(xp1 + G16_31(xp2, xp3, xp0) + _block[3] + RMD128RoundPrime32To47, 11);
|
||||
|
||||
// Round 36
|
||||
x0 = RotateLeft32(x0 + G32_47(x1, x2, x3) + _block[9] + RMD128Round32To47, 14);
|
||||
xp0 = RotateLeft32(xp0 + G16_31(xp1, xp2, xp3) + _block[7] + RMD128RoundPrime32To47, 8);
|
||||
|
||||
// Round 37
|
||||
x3 = RotateLeft32(x3 + G32_47(x0, x1, x2) + _block[15] + RMD128Round32To47, 9);
|
||||
xp3 = RotateLeft32(xp3 + G16_31(xp0, xp1, xp2) + _block[14] + RMD128RoundPrime32To47, 6);
|
||||
|
||||
// Round 38
|
||||
x2 = RotateLeft32(x2 + G32_47(x3, x0, x1) + _block[8] + RMD128Round32To47, 13);
|
||||
xp2 = RotateLeft32(xp2 + G16_31(xp3, xp0, xp1) + _block[6] + RMD128RoundPrime32To47, 6);
|
||||
|
||||
// Round 39
|
||||
x1 = RotateLeft32(x1 + G32_47(x2, x3, x0) + _block[1] + RMD128Round32To47, 15);
|
||||
xp1 = RotateLeft32(xp1 + G16_31(xp2, xp3, xp0) + _block[9] + RMD128RoundPrime32To47, 14);
|
||||
|
||||
// Round 40
|
||||
x0 = RotateLeft32(x0 + G32_47(x1, x2, x3) + _block[2] + RMD128Round32To47, 14);
|
||||
xp0 = RotateLeft32(xp0 + G16_31(xp1, xp2, xp3) + _block[11] + RMD128RoundPrime32To47, 12);
|
||||
|
||||
// Round 41
|
||||
x3 = RotateLeft32(x3 + G32_47(x0, x1, x2) + _block[7] + RMD128Round32To47, 8);
|
||||
xp3 = RotateLeft32(xp3 + G16_31(xp0, xp1, xp2) + _block[8] + RMD128RoundPrime32To47, 13);
|
||||
|
||||
// Round 42
|
||||
x2 = RotateLeft32(x2 + G32_47(x3, x0, x1) + _block[0] + RMD128Round32To47, 13);
|
||||
xp2 = RotateLeft32(xp2 + G16_31(xp3, xp0, xp1) + _block[12] + RMD128RoundPrime32To47, 5);
|
||||
|
||||
// Round 43
|
||||
x1 = RotateLeft32(x1 + G32_47(x2, x3, x0) + _block[6] + RMD128Round32To47, 6);
|
||||
xp1 = RotateLeft32(xp1 + G16_31(xp2, xp3, xp0) + _block[2] + RMD128RoundPrime32To47, 14);
|
||||
|
||||
// Round 44
|
||||
x0 = RotateLeft32(x0 + G32_47(x1, x2, x3) + _block[13] + RMD128Round32To47, 5);
|
||||
xp0 = RotateLeft32(xp0 + G16_31(xp1, xp2, xp3) + _block[10] + RMD128RoundPrime32To47, 13);
|
||||
|
||||
// Round 45
|
||||
x3 = RotateLeft32(x3 + G32_47(x0, x1, x2) + _block[11] + RMD128Round32To47, 12);
|
||||
xp3 = RotateLeft32(xp3 + G16_31(xp0, xp1, xp2) + _block[0] + RMD128RoundPrime32To47, 13);
|
||||
|
||||
// Round 46
|
||||
x2 = RotateLeft32(x2 + G32_47(x3, x0, x1) + _block[5] + RMD128Round32To47, 7);
|
||||
xp2 = RotateLeft32(xp2 + G16_31(xp3, xp0, xp1) + _block[4] + RMD128RoundPrime32To47, 7);
|
||||
|
||||
// Round 47
|
||||
x1 = RotateLeft32(x1 + G32_47(x2, x3, x0) + _block[12] + RMD128Round32To47, 5);
|
||||
xp1 = RotateLeft32(xp1 + G16_31(xp2, xp3, xp0) + _block[13] + RMD128RoundPrime32To47, 5);
|
||||
|
||||
#endregion
|
||||
|
||||
#region Rounds 48-63
|
||||
|
||||
// Round 48
|
||||
x0 = RotateLeft32(x0 + G48_63(x1, x2, x3) + _block[1] + RMD128Round48To63, 11);
|
||||
xp0 = RotateLeft32(xp0 + G00_15(xp1, xp2, xp3) + _block[8] + RMD128RoundPrime48To63, 15);
|
||||
|
||||
// Round 49
|
||||
x3 = RotateLeft32(x3 + G48_63(x0, x1, x2) + _block[9] + RMD128Round48To63, 12);
|
||||
xp3 = RotateLeft32(xp3 + G00_15(xp0, xp1, xp2) + _block[6] + RMD128RoundPrime48To63, 5);
|
||||
|
||||
// Round 50
|
||||
x2 = RotateLeft32(x2 + G48_63(x3, x0, x1) + _block[11] + RMD128Round48To63, 14);
|
||||
xp2 = RotateLeft32(xp2 + G00_15(xp3, xp0, xp1) + _block[4] + RMD128RoundPrime48To63, 8);
|
||||
|
||||
// Round 51
|
||||
x1 = RotateLeft32(x1 + G48_63(x2, x3, x0) + _block[10] + RMD128Round48To63, 15);
|
||||
xp1 = RotateLeft32(xp1 + G00_15(xp2, xp3, xp0) + _block[1] + RMD128RoundPrime48To63, 11);
|
||||
|
||||
// Round 52
|
||||
x0 = RotateLeft32(x0 + G48_63(x1, x2, x3) + _block[0] + RMD128Round48To63, 14);
|
||||
xp0 = RotateLeft32(xp0 + G00_15(xp1, xp2, xp3) + _block[3] + RMD128RoundPrime48To63, 14);
|
||||
|
||||
// Round 53
|
||||
x3 = RotateLeft32(x3 + G48_63(x0, x1, x2) + _block[8] + RMD128Round48To63, 15);
|
||||
xp3 = RotateLeft32(xp3 + G00_15(xp0, xp1, xp2) + _block[11] + RMD128RoundPrime48To63, 14);
|
||||
|
||||
// Round 54
|
||||
x2 = RotateLeft32(x2 + G48_63(x3, x0, x1) + _block[12] + RMD128Round48To63, 9);
|
||||
xp2 = RotateLeft32(xp2 + G00_15(xp3, xp0, xp1) + _block[15] + RMD128RoundPrime48To63, 6);
|
||||
|
||||
// Round 55
|
||||
x1 = RotateLeft32(x1 + G48_63(x2, x3, x0) + _block[4] + RMD128Round48To63, 8);
|
||||
xp1 = RotateLeft32(xp1 + G00_15(xp2, xp3, xp0) + _block[0] + RMD128RoundPrime48To63, 14);
|
||||
|
||||
// Round 56
|
||||
x0 = RotateLeft32(x0 + G48_63(x1, x2, x3) + _block[13] + RMD128Round48To63, 9);
|
||||
xp0 = RotateLeft32(xp0 + G00_15(xp1, xp2, xp3) + _block[5] + RMD128RoundPrime48To63, 6);
|
||||
|
||||
// Round 57
|
||||
x3 = RotateLeft32(x3 + G48_63(x0, x1, x2) + _block[3] + RMD128Round48To63, 14);
|
||||
xp3 = RotateLeft32(xp3 + G00_15(xp0, xp1, xp2) + _block[12] + RMD128RoundPrime48To63, 9);
|
||||
|
||||
// Round 58
|
||||
x2 = RotateLeft32(x2 + G48_63(x3, x0, x1) + _block[7] + RMD128Round48To63, 5);
|
||||
xp2 = RotateLeft32(xp2 + G00_15(xp3, xp0, xp1) + _block[2] + RMD128RoundPrime48To63, 12);
|
||||
|
||||
// Round 59
|
||||
x1 = RotateLeft32(x1 + G48_63(x2, x3, x0) + _block[15] + RMD128Round48To63, 6);
|
||||
xp1 = RotateLeft32(xp1 + G00_15(xp2, xp3, xp0) + _block[13] + RMD128RoundPrime48To63, 9);
|
||||
|
||||
// Round 60
|
||||
x0 = RotateLeft32(x0 + G48_63(x1, x2, x3) + _block[14] + RMD128Round48To63, 8);
|
||||
xp0 = RotateLeft32(xp0 + G00_15(xp1, xp2, xp3) + _block[9] + RMD128RoundPrime48To63, 12);
|
||||
|
||||
// Round 61
|
||||
x3 = RotateLeft32(x3 + G48_63(x0, x1, x2) + _block[5] + RMD128Round48To63, 6);
|
||||
xp3 = RotateLeft32(xp3 + G00_15(xp0, xp1, xp2) + _block[7] + RMD128RoundPrime48To63, 5);
|
||||
|
||||
// Round 62
|
||||
x2 = RotateLeft32(x2 + G48_63(x3, x0, x1) + _block[6] + RMD128Round48To63, 5);
|
||||
xp2 = RotateLeft32(xp2 + G00_15(xp3, xp0, xp1) + _block[10] + RMD128RoundPrime48To63, 15);
|
||||
|
||||
// Round 63
|
||||
x1 = RotateLeft32(x1 + G48_63(x2, x3, x0) + _block[2] + RMD128Round48To63, 12);
|
||||
xp1 = RotateLeft32(xp1 + G00_15(xp2, xp3, xp0) + _block[14] + RMD128RoundPrime48To63, 8);
|
||||
|
||||
#endregion
|
||||
|
||||
// Avalanche values
|
||||
xp3 += x2 + _state[1];
|
||||
_state[1] = _state[2] + x3 + xp0;
|
||||
_state[2] = _state[3] + x0 + xp1;
|
||||
_state[3] = _state[0] + x1 + xp2;
|
||||
_state[0] = xp3;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Round operation [0, 15]
|
||||
/// </summary>
|
||||
private static uint G00_15(uint x, uint y, uint z) => x ^ y ^ z;
|
||||
|
||||
/// <summary>
|
||||
/// Round operation [16, 31]
|
||||
/// </summary>
|
||||
private static uint G16_31(uint x, uint y, uint z) => (x & y) | (~x & z);
|
||||
|
||||
/// <summary>
|
||||
/// Round operation [32, 47]
|
||||
/// </summary>
|
||||
private static uint G32_47(uint x, uint y, uint z) => (x | ~y) ^ z;
|
||||
|
||||
/// <summary>
|
||||
/// Round operation [48, 63]
|
||||
/// </summary>
|
||||
private static uint G48_63(uint x, uint y, uint z) => (x & z) | (y & ~z);
|
||||
}
|
||||
}
|
||||
685
SabreTools.Hashing/MessageDigest/RipeMD160.cs
Normal file
685
SabreTools.Hashing/MessageDigest/RipeMD160.cs
Normal file
@@ -0,0 +1,685 @@
|
||||
using System;
|
||||
using static SabreTools.Hashing.HashOperations;
|
||||
using static SabreTools.Hashing.MessageDigest.Constants;
|
||||
|
||||
namespace SabreTools.Hashing.MessageDigest
|
||||
{
|
||||
/// <see href="https://cdn.standards.iteh.ai/samples/39876/10f9f9f4bb614eaaaeba7e157e183ca3/ISO-IEC-10118-3-2004.pdf"/>
|
||||
/// <see href="https://homes.esat.kuleuven.be/~bosselae/ripemd160/pdf/AB-9601/AB-9601.pdf"/>
|
||||
public class RipeMD160 : MessageDigestBase<uint>
|
||||
{
|
||||
/// <summary>
|
||||
/// Set of 5 32-bit numbers representing the hash state
|
||||
/// </summary>
|
||||
private readonly uint[] _state = new uint[5];
|
||||
|
||||
public RipeMD160() : base()
|
||||
{
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
protected override void ResetImpl()
|
||||
{
|
||||
_state[0] = RMD160Y0;
|
||||
_state[1] = RMD160Y1;
|
||||
_state[2] = RMD160Y2;
|
||||
_state[3] = RMD160Y3;
|
||||
_state[4] = RMD160Y4;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override void TransformBlock(byte[] data, int offset, int length)
|
||||
{
|
||||
// Figure out how much buffer is needed
|
||||
int bufferLen = (int)(_totalBytes & 0x3f);
|
||||
|
||||
// Increment the processed byte count
|
||||
_totalBytes += length;
|
||||
|
||||
// If there is buffer to fill and it will meet the limit
|
||||
if (bufferLen > 0 && bufferLen + length >= 64)
|
||||
{
|
||||
// Fill the buffer from the input
|
||||
Array.Copy(data, offset, _buffer, bufferLen, 64 - bufferLen);
|
||||
|
||||
// Set the new values
|
||||
offset += 64 - bufferLen;
|
||||
length -= 64 - bufferLen;
|
||||
|
||||
// Split the buffer for the round
|
||||
for (int i = 0; i < 16; i++)
|
||||
{
|
||||
_block[i] = ReadLE32(_buffer, i * 4);
|
||||
}
|
||||
|
||||
// Run the round
|
||||
Round();
|
||||
bufferLen = 0;
|
||||
}
|
||||
|
||||
/// Process any standalone blocks
|
||||
while (length >= 64)
|
||||
{
|
||||
// Fill the buffer from the input
|
||||
Array.Copy(data, offset, _buffer, 0, 64);
|
||||
|
||||
// Set the new values
|
||||
offset += 64;
|
||||
length -= 64;
|
||||
|
||||
// Split the buffer for the round
|
||||
for (int i = 0; i < 16; i++)
|
||||
{
|
||||
_block[i] = ReadLE32(_buffer, i * 4);
|
||||
}
|
||||
|
||||
// Run the round
|
||||
Round();
|
||||
}
|
||||
|
||||
// Save the remainder in the buffer
|
||||
if (length > 0)
|
||||
Array.Copy(data, offset, _buffer, bufferLen, length);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override void Terminate()
|
||||
{
|
||||
// Determine the pad length
|
||||
int padLength = 64 - (int)(_totalBytes & 0x3f);
|
||||
if (padLength <= 8)
|
||||
padLength += 64;
|
||||
|
||||
// Get the total byte count in bits
|
||||
long totalBitCount = _totalBytes * 8;
|
||||
|
||||
// Prebuild the padding
|
||||
var padding = new byte[padLength];
|
||||
padding[0] = 0x80;
|
||||
padding[padLength - 1] = (byte)((totalBitCount >> 56) & 0xff);
|
||||
padding[padLength - 2] = (byte)((totalBitCount >> 48) & 0xff);
|
||||
padding[padLength - 3] = (byte)((totalBitCount >> 40) & 0xff);
|
||||
padding[padLength - 4] = (byte)((totalBitCount >> 32) & 0xff);
|
||||
padding[padLength - 5] = (byte)((totalBitCount >> 24) & 0xff);
|
||||
padding[padLength - 6] = (byte)((totalBitCount >> 16) & 0xff);
|
||||
padding[padLength - 7] = (byte)((totalBitCount >> 8 ) & 0xff);
|
||||
padding[padLength - 8] = (byte)((totalBitCount >> 0 ) & 0xff);
|
||||
|
||||
// Pad the block
|
||||
TransformBlock(padding, 0, padding.Length);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override byte[] GetHash()
|
||||
{
|
||||
var hash = new byte[20];
|
||||
int hashOffset = 0;
|
||||
|
||||
// Assemble the hash array
|
||||
for (int i = 0; i < _state.Length; i++)
|
||||
{
|
||||
byte[] segment = BitConverter.GetBytes(_state[i]);
|
||||
Array.Copy(segment, 0, hash, hashOffset, 4);
|
||||
hashOffset += 4;
|
||||
}
|
||||
|
||||
// Reset the state and return
|
||||
Reset();
|
||||
return hash;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Perform one round of updates on the cached values
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The official specification for RIPEMD-160 includes tables
|
||||
/// and instructions that represent a loop. Most standard implementations
|
||||
/// use the unrolled version of that loop to make it more efficient.
|
||||
///
|
||||
/// The below code started with the looped version but has been converted
|
||||
/// to the more standard implementation instead.
|
||||
/// </remarks>
|
||||
private void Round()
|
||||
{
|
||||
// Setup values
|
||||
uint x0 = _state[0], xp0 = _state[0];
|
||||
uint x1 = _state[1], xp1 = _state[1];
|
||||
uint x2 = _state[2], xp2 = _state[2];
|
||||
uint x3 = _state[3], xp3 = _state[3];
|
||||
uint x4 = _state[4], xp4 = _state[4];
|
||||
|
||||
#region Rounds 0-15
|
||||
|
||||
// Round 0
|
||||
x0 = RotateLeft32(x0 + G00_15(x1, x2, x3) + _block[0] + RMD160Round00To15, 11) + x4;
|
||||
x2 = RotateLeft32(x2, 10);
|
||||
xp0 = RotateLeft32(xp0 + G64_79(xp1, xp2, xp3) + _block[5] + RMD160RoundPrime00To15, 8) + xp4;
|
||||
xp2 = RotateLeft32(xp2, 10);
|
||||
|
||||
// Round 1
|
||||
x4 = RotateLeft32(x4 + G00_15(x0, x1, x2) + _block[1] + RMD160Round00To15, 14) + x3;
|
||||
x1 = RotateLeft32(x1, 10);
|
||||
xp4 = RotateLeft32(xp4 + G64_79(xp0, xp1, xp2) + _block[14] + RMD160RoundPrime00To15, 9) + xp3;
|
||||
xp1 = RotateLeft32(xp1, 10);
|
||||
|
||||
// Round 2
|
||||
x3 = RotateLeft32(x3 + G00_15(x4, x0, x1) + _block[2] + RMD160Round00To15, 15) + x2;
|
||||
x0 = RotateLeft32(x0, 10);
|
||||
xp3 = RotateLeft32(xp3 + G64_79(xp4, xp0, xp1) + _block[7] + RMD160RoundPrime00To15, 9) + xp2;
|
||||
xp0 = RotateLeft32(xp0, 10);
|
||||
|
||||
// Round 3
|
||||
x2 = RotateLeft32(x2 + G00_15(x3, x4, x0) + _block[3] + RMD160Round00To15, 12) + x1;
|
||||
x4 = RotateLeft32(x4, 10);
|
||||
xp2 = RotateLeft32(xp2 + G64_79(xp3, xp4, xp0) + _block[0] + RMD160RoundPrime00To15, 11) + xp1;
|
||||
xp4 = RotateLeft32(xp4, 10);
|
||||
|
||||
// Round 4
|
||||
x1 = RotateLeft32(x1 + G00_15(x2, x3, x4) + _block[4] + RMD160Round00To15, 5) + x0;
|
||||
x3 = RotateLeft32(x3, 10);
|
||||
xp1 = RotateLeft32(xp1 + G64_79(xp2, xp3, xp4) + _block[9] + RMD160RoundPrime00To15, 13) + xp0;
|
||||
xp3 = RotateLeft32(xp3, 10);
|
||||
|
||||
// Round 5
|
||||
x0 = RotateLeft32(x0 + G00_15(x1, x2, x3) + _block[5] + RMD160Round00To15, 8) + x4;
|
||||
x2 = RotateLeft32(x2, 10);
|
||||
xp0 = RotateLeft32(xp0 + G64_79(xp1, xp2, xp3) + _block[2] + RMD160RoundPrime00To15, 15) + xp4;
|
||||
xp2 = RotateLeft32(xp2, 10);
|
||||
|
||||
// Round 6
|
||||
x4 = RotateLeft32(x4 + G00_15(x0, x1, x2) + _block[6] + RMD160Round00To15, 7) + x3;
|
||||
x1 = RotateLeft32(x1, 10);
|
||||
xp4 = RotateLeft32(xp4 + G64_79(xp0, xp1, xp2) + _block[11] + RMD160RoundPrime00To15, 15) + xp3;
|
||||
xp1 = RotateLeft32(xp1, 10);
|
||||
|
||||
// Round 7
|
||||
x3 = RotateLeft32(x3 + G00_15(x4, x0, x1) + _block[7] + RMD160Round00To15, 9) + x2;
|
||||
x0 = RotateLeft32(x0, 10);
|
||||
xp3 = RotateLeft32(xp3 + G64_79(xp4, xp0, xp1) + _block[4] + RMD160RoundPrime00To15, 5) + xp2;
|
||||
xp0 = RotateLeft32(xp0, 10);
|
||||
|
||||
// Round 8
|
||||
x2 = RotateLeft32(x2 + G00_15(x3, x4, x0) + _block[8] + RMD160Round00To15, 11) + x1;
|
||||
x4 = RotateLeft32(x4, 10);
|
||||
xp2 = RotateLeft32(xp2 + G64_79(xp3, xp4, xp0) + _block[13] + RMD160RoundPrime00To15, 7) + xp1;
|
||||
xp4 = RotateLeft32(xp4, 10);
|
||||
|
||||
// Round 9
|
||||
x1 = RotateLeft32(x1 + G00_15(x2, x3, x4) + _block[9] + RMD160Round00To15, 13) + x0;
|
||||
x3 = RotateLeft32(x3, 10);
|
||||
xp1 = RotateLeft32(xp1 + G64_79(xp2, xp3, xp4) + _block[6] + RMD160RoundPrime00To15, 7) + xp0;
|
||||
xp3 = RotateLeft32(xp3, 10);
|
||||
|
||||
// Round 10
|
||||
x0 = RotateLeft32(x0 + G00_15(x1, x2, x3) + _block[10] + RMD160Round00To15, 14) + x4;
|
||||
x2 = RotateLeft32(x2, 10);
|
||||
xp0 = RotateLeft32(xp0 + G64_79(xp1, xp2, xp3) + _block[15] + RMD160RoundPrime00To15, 8) + xp4;
|
||||
xp2 = RotateLeft32(xp2, 10);
|
||||
|
||||
// Round 11
|
||||
x4 = RotateLeft32(x4 + G00_15(x0, x1, x2) + _block[11] + RMD160Round00To15, 15) + x3;
|
||||
x1 = RotateLeft32(x1, 10);
|
||||
xp4 = RotateLeft32(xp4 + G64_79(xp0, xp1, xp2) + _block[8] + RMD160RoundPrime00To15, 11) + xp3;
|
||||
xp1 = RotateLeft32(xp1, 10);
|
||||
|
||||
// Round 12
|
||||
x3 = RotateLeft32(x3 + G00_15(x4, x0, x1) + _block[12] + RMD160Round00To15, 6) + x2;
|
||||
x0 = RotateLeft32(x0, 10);
|
||||
xp3 = RotateLeft32(xp3 + G64_79(xp4, xp0, xp1) + _block[1] + RMD160RoundPrime00To15, 14) + xp2;
|
||||
xp0 = RotateLeft32(xp0, 10);
|
||||
|
||||
// Round 13
|
||||
x2 = RotateLeft32(x2 + G00_15(x3, x4, x0) + _block[13] + RMD160Round00To15, 7) + x1;
|
||||
x4 = RotateLeft32(x4, 10);
|
||||
xp2 = RotateLeft32(xp2 + G64_79(xp3, xp4, xp0) + _block[10] + RMD160RoundPrime00To15, 14) + xp1;
|
||||
xp4 = RotateLeft32(xp4, 10);
|
||||
|
||||
// Round 14
|
||||
x1 = RotateLeft32(x1 + G00_15(x2, x3, x4) + _block[14] + RMD160Round00To15, 9) + x0;
|
||||
x3 = RotateLeft32(x3, 10);
|
||||
xp1 = RotateLeft32(xp1 + G64_79(xp2, xp3, xp4) + _block[3] + RMD160RoundPrime00To15, 12) + xp0;
|
||||
xp3 = RotateLeft32(xp3, 10);
|
||||
|
||||
// Round 15
|
||||
x0 = RotateLeft32(x0 + G00_15(x1, x2, x3) + _block[15] + RMD160Round00To15, 8) + x4;
|
||||
x2 = RotateLeft32(x2, 10);
|
||||
xp0 = RotateLeft32(xp0 + G64_79(xp1, xp2, xp3) + _block[12] + RMD160RoundPrime00To15, 6) + xp4;
|
||||
xp2 = RotateLeft32(xp2, 10);
|
||||
|
||||
#endregion
|
||||
|
||||
#region Rounds 16-31
|
||||
|
||||
// Round 16
|
||||
x4 = RotateLeft32(x4 + G16_31(x0, x1, x2) + _block[7] + RMD160Round16To31, 7) + x3;
|
||||
x1 = RotateLeft32(x1, 10);
|
||||
xp4 = RotateLeft32(xp4 + G48_63(xp0, xp1, xp2) + _block[6] + RMD160RoundPrime16To31, 9) + xp3;
|
||||
xp1 = RotateLeft32(xp1, 10);
|
||||
|
||||
// Round 17
|
||||
x3 = RotateLeft32(x3 + G16_31(x4, x0, x1) + _block[4] + RMD160Round16To31, 6) + x2;
|
||||
x0 = RotateLeft32(x0, 10);
|
||||
xp3 = RotateLeft32(xp3 + G48_63(xp4, xp0, xp1) + _block[11] + RMD160RoundPrime16To31, 13) + xp2;
|
||||
xp0 = RotateLeft32(xp0, 10);
|
||||
|
||||
// Round 18
|
||||
x2 = RotateLeft32(x2 + G16_31(x3, x4, x0) + _block[13] + RMD160Round16To31, 8) + x1;
|
||||
x4 = RotateLeft32(x4, 10);
|
||||
xp2 = RotateLeft32(xp2 + G48_63(xp3, xp4, xp0) + _block[3] + RMD160RoundPrime16To31, 15) + xp1;
|
||||
xp4 = RotateLeft32(xp4, 10);
|
||||
|
||||
// Round 19
|
||||
x1 = RotateLeft32(x1 + G16_31(x2, x3, x4) + _block[1] + RMD160Round16To31, 13) + x0;
|
||||
x3 = RotateLeft32(x3, 10);
|
||||
xp1 = RotateLeft32(xp1 + G48_63(xp2, xp3, xp4) + _block[7] + RMD160RoundPrime16To31, 7) + xp0;
|
||||
xp3 = RotateLeft32(xp3, 10);
|
||||
|
||||
// Round 20
|
||||
x0 = RotateLeft32(x0 + G16_31(x1, x2, x3) + _block[10] + RMD160Round16To31, 11) + x4;
|
||||
x2 = RotateLeft32(x2, 10);
|
||||
xp0 = RotateLeft32(xp0 + G48_63(xp1, xp2, xp3) + _block[0] + RMD160RoundPrime16To31, 12) + xp4;
|
||||
xp2 = RotateLeft32(xp2, 10);
|
||||
|
||||
// Round 21
|
||||
x4 = RotateLeft32(x4 + G16_31(x0, x1, x2) + _block[6] + RMD160Round16To31, 9) + x3;
|
||||
x1 = RotateLeft32(x1, 10);
|
||||
xp4 = RotateLeft32(xp4 + G48_63(xp0, xp1, xp2) + _block[13] + RMD160RoundPrime16To31, 8) + xp3;
|
||||
xp1 = RotateLeft32(xp1, 10);
|
||||
|
||||
// Round 22
|
||||
x3 = RotateLeft32(x3 + G16_31(x4, x0, x1) + _block[15] + RMD160Round16To31, 7) + x2;
|
||||
x0 = RotateLeft32(x0, 10);
|
||||
xp3 = RotateLeft32(xp3 + G48_63(xp4, xp0, xp1) + _block[5] + RMD160RoundPrime16To31, 9) + xp2;
|
||||
xp0 = RotateLeft32(xp0, 10);
|
||||
|
||||
// Round 23
|
||||
x2 = RotateLeft32(x2 + G16_31(x3, x4, x0) + _block[3] + RMD160Round16To31, 15) + x1;
|
||||
x4 = RotateLeft32(x4, 10);
|
||||
xp2 = RotateLeft32(xp2 + G48_63(xp3, xp4, xp0) + _block[10] + RMD160RoundPrime16To31, 11) + xp1;
|
||||
xp4 = RotateLeft32(xp4, 10);
|
||||
|
||||
// Round 24
|
||||
x1 = RotateLeft32(x1 + G16_31(x2, x3, x4) + _block[12] + RMD160Round16To31, 7) + x0;
|
||||
x3 = RotateLeft32(x3, 10);
|
||||
xp1 = RotateLeft32(xp1 + G48_63(xp2, xp3, xp4) + _block[14] + RMD160RoundPrime16To31, 7) + xp0;
|
||||
xp3 = RotateLeft32(xp3, 10);
|
||||
|
||||
// Round 25
|
||||
x0 = RotateLeft32(x0 + G16_31(x1, x2, x3) + _block[0] + RMD160Round16To31, 12) + x4;
|
||||
x2 = RotateLeft32(x2, 10);
|
||||
xp0 = RotateLeft32(xp0 + G48_63(xp1, xp2, xp3) + _block[15] + RMD160RoundPrime16To31, 7) + xp4;
|
||||
xp2 = RotateLeft32(xp2, 10);
|
||||
|
||||
// Round 26
|
||||
x4 = RotateLeft32(x4 + G16_31(x0, x1, x2) + _block[9] + RMD160Round16To31, 15) + x3;
|
||||
x1 = RotateLeft32(x1, 10);
|
||||
xp4 = RotateLeft32(xp4 + G48_63(xp0, xp1, xp2) + _block[8] + RMD160RoundPrime16To31, 12) + xp3;
|
||||
xp1 = RotateLeft32(xp1, 10);
|
||||
|
||||
// Round 27
|
||||
x3 = RotateLeft32(x3 + G16_31(x4, x0, x1) + _block[5] + RMD160Round16To31, 9) + x2;
|
||||
x0 = RotateLeft32(x0, 10);
|
||||
xp3 = RotateLeft32(xp3 + G48_63(xp4, xp0, xp1) + _block[12] + RMD160RoundPrime16To31, 7) + xp2;
|
||||
xp0 = RotateLeft32(xp0, 10);
|
||||
|
||||
// Round 28
|
||||
x2 = RotateLeft32(x2 + G16_31(x3, x4, x0) + _block[2] + RMD160Round16To31, 11) + x1;
|
||||
x4 = RotateLeft32(x4, 10);
|
||||
xp2 = RotateLeft32(xp2 + G48_63(xp3, xp4, xp0) + _block[4] + RMD160RoundPrime16To31, 6) + xp1;
|
||||
xp4 = RotateLeft32(xp4, 10);
|
||||
|
||||
// Round 29
|
||||
x1 = RotateLeft32(x1 + G16_31(x2, x3, x4) + _block[14] + RMD160Round16To31, 7) + x0;
|
||||
x3 = RotateLeft32(x3, 10);
|
||||
xp1 = RotateLeft32(xp1 + G48_63(xp2, xp3, xp4) + _block[9] + RMD160RoundPrime16To31, 15) + xp0;
|
||||
xp3 = RotateLeft32(xp3, 10);
|
||||
|
||||
// Round 30
|
||||
x0 = RotateLeft32(x0 + G16_31(x1, x2, x3) + _block[11] + RMD160Round16To31, 13) + x4;
|
||||
x2 = RotateLeft32(x2, 10);
|
||||
xp0 = RotateLeft32(xp0 + G48_63(xp1, xp2, xp3) + _block[1] + RMD160RoundPrime16To31, 13) + xp4;
|
||||
xp2 = RotateLeft32(xp2, 10);
|
||||
|
||||
// Round 31
|
||||
x4 = RotateLeft32(x4 + G16_31(x0, x1, x2) + _block[8] + RMD160Round16To31, 12) + x3;
|
||||
x1 = RotateLeft32(x1, 10);
|
||||
xp4 = RotateLeft32(xp4 + G48_63(xp0, xp1, xp2) + _block[2] + RMD160RoundPrime16To31, 11) + xp3;
|
||||
xp1 = RotateLeft32(xp1, 10);
|
||||
|
||||
#endregion
|
||||
|
||||
#region Rounds 32-47
|
||||
|
||||
// Round 32
|
||||
x3 = RotateLeft32(x3 + G32_47(x4, x0, x1) + _block[3] + RMD160Round32To47, 11) + x2;
|
||||
x0 = RotateLeft32(x0, 10);
|
||||
xp3 = RotateLeft32(xp3 + G32_47(xp4, xp0, xp1) + _block[15] + RMD160RoundPrime32To47, 9) + xp2;
|
||||
xp0 = RotateLeft32(xp0, 10);
|
||||
|
||||
// Round 33
|
||||
x2 = RotateLeft32(x2 + G32_47(x3, x4, x0) + _block[10] + RMD160Round32To47, 13) + x1;
|
||||
x4 = RotateLeft32(x4, 10);
|
||||
xp2 = RotateLeft32(xp2 + G32_47(xp3, xp4, xp0) + _block[5] + RMD160RoundPrime32To47, 7) + xp1;
|
||||
xp4 = RotateLeft32(xp4, 10);
|
||||
|
||||
// Round 34
|
||||
x1 = RotateLeft32(x1 + G32_47(x2, x3, x4) + _block[14] + RMD160Round32To47, 6) + x0;
|
||||
x3 = RotateLeft32(x3, 10);
|
||||
xp1 = RotateLeft32(xp1 + G32_47(xp2, xp3, xp4) + _block[1] + RMD160RoundPrime32To47, 15) + xp0;
|
||||
xp3 = RotateLeft32(xp3, 10);
|
||||
|
||||
// Round 35
|
||||
x0 = RotateLeft32(x0 + G32_47(x1, x2, x3) + _block[4] + RMD160Round32To47, 7) + x4;
|
||||
x2 = RotateLeft32(x2, 10);
|
||||
xp0 = RotateLeft32(xp0 + G32_47(xp1, xp2, xp3) + _block[3] + RMD160RoundPrime32To47, 11) + xp4;
|
||||
xp2 = RotateLeft32(xp2, 10);
|
||||
|
||||
// Round 36
|
||||
x4 = RotateLeft32(x4 + G32_47(x0, x1, x2) + _block[9] + RMD160Round32To47, 14) + x3;
|
||||
x1 = RotateLeft32(x1, 10);
|
||||
xp4 = RotateLeft32(xp4 + G32_47(xp0, xp1, xp2) + _block[7] + RMD160RoundPrime32To47, 8) + xp3;
|
||||
xp1 = RotateLeft32(xp1, 10);
|
||||
|
||||
// Round 37
|
||||
x3 = RotateLeft32(x3 + G32_47(x4, x0, x1) + _block[15] + RMD160Round32To47, 9) + x2;
|
||||
x0 = RotateLeft32(x0, 10);
|
||||
xp3 = RotateLeft32(xp3 + G32_47(xp4, xp0, xp1) + _block[14] + RMD160RoundPrime32To47, 6) + xp2;
|
||||
xp0 = RotateLeft32(xp0, 10);
|
||||
|
||||
// Round 38
|
||||
x2 = RotateLeft32(x2 + G32_47(x3, x4, x0) + _block[8] + RMD160Round32To47, 13) + x1;
|
||||
x4 = RotateLeft32(x4, 10);
|
||||
xp2 = RotateLeft32(xp2 + G32_47(xp3, xp4, xp0) + _block[6] + RMD160RoundPrime32To47, 6) + xp1;
|
||||
xp4 = RotateLeft32(xp4, 10);
|
||||
|
||||
// Round 39
|
||||
x1 = RotateLeft32(x1 + G32_47(x2, x3, x4) + _block[1] + RMD160Round32To47, 15) + x0;
|
||||
x3 = RotateLeft32(x3, 10);
|
||||
xp1 = RotateLeft32(xp1 + G32_47(xp2, xp3, xp4) + _block[9] + RMD160RoundPrime32To47, 14) + xp0;
|
||||
xp3 = RotateLeft32(xp3, 10);
|
||||
|
||||
// Round 40
|
||||
x0 = RotateLeft32(x0 + G32_47(x1, x2, x3) + _block[2] + RMD160Round32To47, 14) + x4;
|
||||
x2 = RotateLeft32(x2, 10);
|
||||
xp0 = RotateLeft32(xp0 + G32_47(xp1, xp2, xp3) + _block[11] + RMD160RoundPrime32To47, 12) + xp4;
|
||||
xp2 = RotateLeft32(xp2, 10);
|
||||
|
||||
// Round 41
|
||||
x4 = RotateLeft32(x4 + G32_47(x0, x1, x2) + _block[7] + RMD160Round32To47, 8) + x3;
|
||||
x1 = RotateLeft32(x1, 10);
|
||||
xp4 = RotateLeft32(xp4 + G32_47(xp0, xp1, xp2) + _block[8] + RMD160RoundPrime32To47, 13) + xp3;
|
||||
xp1 = RotateLeft32(xp1, 10);
|
||||
|
||||
// Round 42
|
||||
x3 = RotateLeft32(x3 + G32_47(x4, x0, x1) + _block[0] + RMD160Round32To47, 13) + x2;
|
||||
x0 = RotateLeft32(x0, 10);
|
||||
xp3 = RotateLeft32(xp3 + G32_47(xp4, xp0, xp1) + _block[12] + RMD160RoundPrime32To47, 5) + xp2;
|
||||
xp0 = RotateLeft32(xp0, 10);
|
||||
|
||||
// Round 43
|
||||
x2 = RotateLeft32(x2 + G32_47(x3, x4, x0) + _block[6] + RMD160Round32To47, 6) + x1;
|
||||
x4 = RotateLeft32(x4, 10);
|
||||
xp2 = RotateLeft32(xp2 + G32_47(xp3, xp4, xp0) + _block[2] + RMD160RoundPrime32To47, 14) + xp1;
|
||||
xp4 = RotateLeft32(xp4, 10);
|
||||
|
||||
// Round 44
|
||||
x1 = RotateLeft32(x1 + G32_47(x2, x3, x4) + _block[13] + RMD160Round32To47, 5) + x0;
|
||||
x3 = RotateLeft32(x3, 10);
|
||||
xp1 = RotateLeft32(xp1 + G32_47(xp2, xp3, xp4) + _block[10] + RMD160RoundPrime32To47, 13) + xp0;
|
||||
xp3 = RotateLeft32(xp3, 10);
|
||||
|
||||
// Round 45
|
||||
x0 = RotateLeft32(x0 + G32_47(x1, x2, x3) + _block[11] + RMD160Round32To47, 12) + x4;
|
||||
x2 = RotateLeft32(x2, 10);
|
||||
xp0 = RotateLeft32(xp0 + G32_47(xp1, xp2, xp3) + _block[0] + RMD160RoundPrime32To47, 13) + xp4;
|
||||
xp2 = RotateLeft32(xp2, 10);
|
||||
|
||||
// Round 46
|
||||
x4 = RotateLeft32(x4 + G32_47(x0, x1, x2) + _block[5] + RMD160Round32To47, 7) + x3;
|
||||
x1 = RotateLeft32(x1, 10);
|
||||
xp4 = RotateLeft32(xp4 + G32_47(xp0, xp1, xp2) + _block[4] + RMD160RoundPrime32To47, 7) + xp3;
|
||||
xp1 = RotateLeft32(xp1, 10);
|
||||
|
||||
// Round 47
|
||||
x3 = RotateLeft32(x3 + G32_47(x4, x0, x1) + _block[12] + RMD160Round32To47, 5) + x2;
|
||||
x0 = RotateLeft32(x0, 10);
|
||||
xp3 = RotateLeft32(xp3 + G32_47(xp4, xp0, xp1) + _block[13] + RMD160RoundPrime32To47, 5) + xp2;
|
||||
xp0 = RotateLeft32(xp0, 10);
|
||||
|
||||
#endregion
|
||||
|
||||
#region Rounds 48-63
|
||||
|
||||
// Round 48
|
||||
x2 = RotateLeft32(x2 + G48_63(x3, x4, x0) + _block[1] + RMD160Round48To63, 11) + x1;
|
||||
x4 = RotateLeft32(x4, 10);
|
||||
xp2 = RotateLeft32(xp2 + G16_31(xp3, xp4, xp0) + _block[8] + RMD160RoundPrime48To63, 15) + xp1;
|
||||
xp4 = RotateLeft32(xp4, 10);
|
||||
|
||||
// Round 49
|
||||
x1 = RotateLeft32(x1 + G48_63(x2, x3, x4) + _block[9] + RMD160Round48To63, 12) + x0;
|
||||
x3 = RotateLeft32(x3, 10);
|
||||
xp1 = RotateLeft32(xp1 + G16_31(xp2, xp3, xp4) + _block[6] + RMD160RoundPrime48To63, 5) + xp0;
|
||||
xp3 = RotateLeft32(xp3, 10);
|
||||
|
||||
// Round 50
|
||||
x0 = RotateLeft32(x0 + G48_63(x1, x2, x3) + _block[11] + RMD160Round48To63, 14) + x4;
|
||||
x2 = RotateLeft32(x2, 10);
|
||||
xp0 = RotateLeft32(xp0 + G16_31(xp1, xp2, xp3) + _block[4] + RMD160RoundPrime48To63, 8) + xp4;
|
||||
xp2 = RotateLeft32(xp2, 10);
|
||||
|
||||
// Round 51
|
||||
x4 = RotateLeft32(x4 + G48_63(x0, x1, x2) + _block[10] + RMD160Round48To63, 15) + x3;
|
||||
x1 = RotateLeft32(x1, 10);
|
||||
xp4 = RotateLeft32(xp4 + G16_31(xp0, xp1, xp2) + _block[1] + RMD160RoundPrime48To63, 11) + xp3;
|
||||
xp1 = RotateLeft32(xp1, 10);
|
||||
|
||||
// Round 52
|
||||
x3 = RotateLeft32(x3 + G48_63(x4, x0, x1) + _block[0] + RMD160Round48To63, 14) + x2;
|
||||
x0 = RotateLeft32(x0, 10);
|
||||
xp3 = RotateLeft32(xp3 + G16_31(xp4, xp0, xp1) + _block[3] + RMD160RoundPrime48To63, 14) + xp2;
|
||||
xp0 = RotateLeft32(xp0, 10);
|
||||
|
||||
// Round 53
|
||||
x2 = RotateLeft32(x2 + G48_63(x3, x4, x0) + _block[8] + RMD160Round48To63, 15) + x1;
|
||||
x4 = RotateLeft32(x4, 10);
|
||||
xp2 = RotateLeft32(xp2 + G16_31(xp3, xp4, xp0) + _block[11] + RMD160RoundPrime48To63, 14) + xp1;
|
||||
xp4 = RotateLeft32(xp4, 10);
|
||||
|
||||
// Round 54
|
||||
x1 = RotateLeft32(x1 + G48_63(x2, x3, x4) + _block[12] + RMD160Round48To63, 9) + x0;
|
||||
x3 = RotateLeft32(x3, 10);
|
||||
xp1 = RotateLeft32(xp1 + G16_31(xp2, xp3, xp4) + _block[15] + RMD160RoundPrime48To63, 6) + xp0;
|
||||
xp3 = RotateLeft32(xp3, 10);
|
||||
|
||||
// Round 55
|
||||
x0 = RotateLeft32(x0 + G48_63(x1, x2, x3) + _block[4] + RMD160Round48To63, 8) + x4;
|
||||
x2 = RotateLeft32(x2, 10);
|
||||
xp0 = RotateLeft32(xp0 + G16_31(xp1, xp2, xp3) + _block[0] + RMD160RoundPrime48To63, 14) + xp4;
|
||||
xp2 = RotateLeft32(xp2, 10);
|
||||
|
||||
// Round 56
|
||||
x4 = RotateLeft32(x4 + G48_63(x0, x1, x2) + _block[13] + RMD160Round48To63, 9) + x3;
|
||||
x1 = RotateLeft32(x1, 10);
|
||||
xp4 = RotateLeft32(xp4 + G16_31(xp0, xp1, xp2) + _block[5] + RMD160RoundPrime48To63, 6) + xp3;
|
||||
xp1 = RotateLeft32(xp1, 10);
|
||||
|
||||
// Round 57
|
||||
x3 = RotateLeft32(x3 + G48_63(x4, x0, x1) + _block[3] + RMD160Round48To63, 14) + x2;
|
||||
x0 = RotateLeft32(x0, 10);
|
||||
xp3 = RotateLeft32(xp3 + G16_31(xp4, xp0, xp1) + _block[12] + RMD160RoundPrime48To63, 9) + xp2;
|
||||
xp0 = RotateLeft32(xp0, 10);
|
||||
|
||||
// Round 58
|
||||
x2 = RotateLeft32(x2 + G48_63(x3, x4, x0) + _block[7] + RMD160Round48To63, 5) + x1;
|
||||
x4 = RotateLeft32(x4, 10);
|
||||
xp2 = RotateLeft32(xp2 + G16_31(xp3, xp4, xp0) + _block[2] + RMD160RoundPrime48To63, 12) + xp1;
|
||||
xp4 = RotateLeft32(xp4, 10);
|
||||
|
||||
// Round 59
|
||||
x1 = RotateLeft32(x1 + G48_63(x2, x3, x4) + _block[15] + RMD160Round48To63, 6) + x0;
|
||||
x3 = RotateLeft32(x3, 10);
|
||||
xp1 = RotateLeft32(xp1 + G16_31(xp2, xp3, xp4) + _block[13] + RMD160RoundPrime48To63, 9) + xp0;
|
||||
xp3 = RotateLeft32(xp3, 10);
|
||||
|
||||
// Round 60
|
||||
x0 = RotateLeft32(x0 + G48_63(x1, x2, x3) + _block[14] + RMD160Round48To63, 8) + x4;
|
||||
x2 = RotateLeft32(x2, 10);
|
||||
xp0 = RotateLeft32(xp0 + G16_31(xp1, xp2, xp3) + _block[9] + RMD160RoundPrime48To63, 12) + xp4;
|
||||
xp2 = RotateLeft32(xp2, 10);
|
||||
|
||||
// Round 61
|
||||
x4 = RotateLeft32(x4 + G48_63(x0, x1, x2) + _block[5] + RMD160Round48To63, 6) + x3;
|
||||
x1 = RotateLeft32(x1, 10);
|
||||
xp4 = RotateLeft32(xp4 + G16_31(xp0, xp1, xp2) + _block[7] + RMD160RoundPrime48To63, 5) + xp3;
|
||||
xp1 = RotateLeft32(xp1, 10);
|
||||
|
||||
// Round 62
|
||||
x3 = RotateLeft32(x3 + G48_63(x4, x0, x1) + _block[6] + RMD160Round48To63, 5) + x2;
|
||||
x0 = RotateLeft32(x0, 10);
|
||||
xp3 = RotateLeft32(xp3 + G16_31(xp4, xp0, xp1) + _block[10] + RMD160RoundPrime48To63, 15) + xp2;
|
||||
xp0 = RotateLeft32(xp0, 10);
|
||||
|
||||
// Round 63
|
||||
x2 = RotateLeft32(x2 + G48_63(x3, x4, x0) + _block[2] + RMD160Round48To63, 12) + x1;
|
||||
x4 = RotateLeft32(x4, 10);
|
||||
xp2 = RotateLeft32(xp2 + G16_31(xp3, xp4, xp0) + _block[14] + RMD160RoundPrime48To63, 8) + xp1;
|
||||
xp4 = RotateLeft32(xp4, 10);
|
||||
|
||||
#endregion
|
||||
|
||||
#region Rounds 64-79
|
||||
|
||||
// Round 64
|
||||
x1 = RotateLeft32(x1 + G64_79(x2, x3, x4) + _block[4] + RMD160Round64To79, 9) + x0;
|
||||
x3 = RotateLeft32(x3, 10);
|
||||
xp1 = RotateLeft32(xp1 + G00_15(xp2, xp3, xp4) + _block[12] + RMD160RoundPrime64To79, 8) + xp0;
|
||||
xp3 = RotateLeft32(xp3, 10);
|
||||
|
||||
// Round 65
|
||||
x0 = RotateLeft32(x0 + G64_79(x1, x2, x3) + _block[0] + RMD160Round64To79, 15) + x4;
|
||||
x2 = RotateLeft32(x2, 10);
|
||||
xp0 = RotateLeft32(xp0 + G00_15(xp1, xp2, xp3) + _block[15] + RMD160RoundPrime64To79, 5) + xp4;
|
||||
xp2 = RotateLeft32(xp2, 10);
|
||||
|
||||
// Round 66
|
||||
x4 = RotateLeft32(x4 + G64_79(x0, x1, x2) + _block[5] + RMD160Round64To79, 5) + x3;
|
||||
x1 = RotateLeft32(x1, 10);
|
||||
xp4 = RotateLeft32(xp4 + G00_15(xp0, xp1, xp2) + _block[10] + RMD160RoundPrime64To79, 12) + xp3;
|
||||
xp1 = RotateLeft32(xp1, 10);
|
||||
|
||||
// Round 67
|
||||
x3 = RotateLeft32(x3 + G64_79(x4, x0, x1) + _block[9] + RMD160Round64To79, 11) + x2;
|
||||
x0 = RotateLeft32(x0, 10);
|
||||
xp3 = RotateLeft32(xp3 + G00_15(xp4, xp0, xp1) + _block[4] + RMD160RoundPrime64To79, 9) + xp2;
|
||||
xp0 = RotateLeft32(xp0, 10);
|
||||
|
||||
// Round 68
|
||||
x2 = RotateLeft32(x2 + G64_79(x3, x4, x0) + _block[7] + RMD160Round64To79, 6) + x1;
|
||||
x4 = RotateLeft32(x4, 10);
|
||||
xp2 = RotateLeft32(xp2 + G00_15(xp3, xp4, xp0) + _block[1] + RMD160RoundPrime64To79, 12) + xp1;
|
||||
xp4 = RotateLeft32(xp4, 10);
|
||||
|
||||
// Round 69
|
||||
x1 = RotateLeft32(x1 + G64_79(x2, x3, x4) + _block[12] + RMD160Round64To79, 8) + x0;
|
||||
x3 = RotateLeft32(x3, 10);
|
||||
xp1 = RotateLeft32(xp1 + G00_15(xp2, xp3, xp4) + _block[5] + RMD160RoundPrime64To79, 5) + xp0;
|
||||
xp3 = RotateLeft32(xp3, 10);
|
||||
|
||||
// Round 70
|
||||
x0 = RotateLeft32(x0 + G64_79(x1, x2, x3) + _block[2] + RMD160Round64To79, 13) + x4;
|
||||
x2 = RotateLeft32(x2, 10);
|
||||
xp0 = RotateLeft32(xp0 + G00_15(xp1, xp2, xp3) + _block[8] + RMD160RoundPrime64To79, 14) + xp4;
|
||||
xp2 = RotateLeft32(xp2, 10);
|
||||
|
||||
// Round 71
|
||||
x4 = RotateLeft32(x4 + G64_79(x0, x1, x2) + _block[10] + RMD160Round64To79, 12) + x3;
|
||||
x1 = RotateLeft32(x1, 10);
|
||||
xp4 = RotateLeft32(xp4 + G00_15(xp0, xp1, xp2) + _block[7] + RMD160RoundPrime64To79, 6) + xp3;
|
||||
xp1 = RotateLeft32(xp1, 10);
|
||||
|
||||
// Round 72
|
||||
x3 = RotateLeft32(x3 + G64_79(x4, x0, x1) + _block[14] + RMD160Round64To79, 5) + x2;
|
||||
x0 = RotateLeft32(x0, 10);
|
||||
xp3 = RotateLeft32(xp3 + G00_15(xp4, xp0, xp1) + _block[6] + RMD160RoundPrime64To79, 8) + xp2;
|
||||
xp0 = RotateLeft32(xp0, 10);
|
||||
|
||||
// Round 73
|
||||
x2 = RotateLeft32(x2 + G64_79(x3, x4, x0) + _block[1] + RMD160Round64To79, 12) + x1;
|
||||
x4 = RotateLeft32(x4, 10);
|
||||
xp2 = RotateLeft32(xp2 + G00_15(xp3, xp4, xp0) + _block[2] + RMD160RoundPrime64To79, 13) + xp1;
|
||||
xp4 = RotateLeft32(xp4, 10);
|
||||
|
||||
// Round 74
|
||||
x1 = RotateLeft32(x1 + G64_79(x2, x3, x4) + _block[3] + RMD160Round64To79, 13) + x0;
|
||||
x3 = RotateLeft32(x3, 10);
|
||||
xp1 = RotateLeft32(xp1 + G00_15(xp2, xp3, xp4) + _block[13] + RMD160RoundPrime64To79, 6) + xp0;
|
||||
xp3 = RotateLeft32(xp3, 10);
|
||||
|
||||
// Round 75
|
||||
x0 = RotateLeft32(x0 + G64_79(x1, x2, x3) + _block[8] + RMD160Round64To79, 14) + x4;
|
||||
x2 = RotateLeft32(x2, 10);
|
||||
xp0 = RotateLeft32(xp0 + G00_15(xp1, xp2, xp3) + _block[14] + RMD160RoundPrime64To79, 5) + xp4;
|
||||
xp2 = RotateLeft32(xp2, 10);
|
||||
|
||||
// Round 76
|
||||
x4 = RotateLeft32(x4 + G64_79(x0, x1, x2) + _block[11] + RMD160Round64To79, 11) + x3;
|
||||
x1 = RotateLeft32(x1, 10);
|
||||
xp4 = RotateLeft32(xp4 + G00_15(xp0, xp1, xp2) + _block[0] + RMD160RoundPrime64To79, 15) + xp3;
|
||||
xp1 = RotateLeft32(xp1, 10);
|
||||
|
||||
// Round 77
|
||||
x3 = RotateLeft32(x3 + G64_79(x4, x0, x1) + _block[6] + RMD160Round64To79, 8) + x2;
|
||||
x0 = RotateLeft32(x0, 10);
|
||||
xp3 = RotateLeft32(xp3 + G00_15(xp4, xp0, xp1) + _block[3] + RMD160RoundPrime64To79, 13) + xp2;
|
||||
xp0 = RotateLeft32(xp0, 10);
|
||||
|
||||
// Round 78
|
||||
x2 = RotateLeft32(x2 + G64_79(x3, x4, x0) + _block[15] + RMD160Round64To79, 5) + x1;
|
||||
x4 = RotateLeft32(x4, 10);
|
||||
xp2 = RotateLeft32(xp2 + G00_15(xp3, xp4, xp0) + _block[9] + RMD160RoundPrime64To79, 11) + xp1;
|
||||
xp4 = RotateLeft32(xp4, 10);
|
||||
|
||||
// Round 79
|
||||
x1 = RotateLeft32(x1 + G64_79(x2, x3, x4) + _block[13] + RMD160Round64To79, 6) + x0;
|
||||
x3 = RotateLeft32(x3, 10);
|
||||
xp1 = RotateLeft32(xp1 + G00_15(xp2, xp3, xp4) + _block[11] + RMD160RoundPrime64To79, 11) + xp0;
|
||||
xp3 = RotateLeft32(xp3, 10);
|
||||
|
||||
#endregion
|
||||
|
||||
// Avalanche values
|
||||
xp3 += x2 + _state[1];
|
||||
_state[1] = _state[2] + x3 + xp4;
|
||||
_state[2] = _state[3] + x4 + xp0;
|
||||
_state[3] = _state[4] + x0 + xp1;
|
||||
_state[4] = _state[0] + x1 + xp2;
|
||||
_state[0] = xp3;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Round operation [0, 15]
|
||||
/// </summary>
|
||||
private static uint G00_15(uint x, uint y, uint z) => x ^ y ^ z;
|
||||
|
||||
/// <summary>
|
||||
/// Round operation [16, 31]
|
||||
/// </summary>
|
||||
private static uint G16_31(uint x, uint y, uint z) => (x & y) | (~x & z);
|
||||
|
||||
/// <summary>
|
||||
/// Round operation [32, 47]
|
||||
/// </summary>
|
||||
private static uint G32_47(uint x, uint y, uint z) => (x | ~y) ^ z;
|
||||
|
||||
/// <summary>
|
||||
/// Round operation [48, 63]
|
||||
/// </summary>
|
||||
private static uint G48_63(uint x, uint y, uint z) => (x & z) | (y & ~z);
|
||||
|
||||
/// <summary>
|
||||
/// Round operation [64, 79]
|
||||
/// </summary>
|
||||
private static uint G64_79(uint x, uint y, uint z) => x ^ (y | ~z);
|
||||
}
|
||||
}
|
||||
469
SabreTools.Hashing/MessageDigest/RipeMD256.cs
Normal file
469
SabreTools.Hashing/MessageDigest/RipeMD256.cs
Normal file
@@ -0,0 +1,469 @@
|
||||
using System;
|
||||
using static SabreTools.Hashing.HashOperations;
|
||||
using static SabreTools.Hashing.MessageDigest.Constants;
|
||||
|
||||
namespace SabreTools.Hashing.MessageDigest
|
||||
{
|
||||
/// <see href="https://cdn.standards.iteh.ai/samples/39876/10f9f9f4bb614eaaaeba7e157e183ca3/ISO-IEC-10118-3-2004.pdf"/>
|
||||
/// <see href="https://homes.esat.kuleuven.be/~bosselae/ripemd160/pdf/AB-9601/AB-9601.pdf"/>
|
||||
public class RipeMD256 : MessageDigestBase<uint>
|
||||
{
|
||||
/// <summary>
|
||||
/// Set of 4 32-bit numbers representing the hash state
|
||||
/// </summary>
|
||||
private readonly uint[] _state = new uint[8];
|
||||
|
||||
public RipeMD256() : base()
|
||||
{
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
protected override void ResetImpl()
|
||||
{
|
||||
_state[0] = RMD128Y0;
|
||||
_state[1] = RMD128Y1;
|
||||
_state[2] = RMD128Y2;
|
||||
_state[3] = RMD128Y3;
|
||||
_state[4] = RMD256Y4;
|
||||
_state[5] = RMD256Y5;
|
||||
_state[6] = RMD256Y6;
|
||||
_state[7] = RMD256Y7;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override void TransformBlock(byte[] data, int offset, int length)
|
||||
{
|
||||
// Figure out how much buffer is needed
|
||||
int bufferLen = (int)(_totalBytes & 0x3f);
|
||||
|
||||
// Increment the processed byte count
|
||||
_totalBytes += length;
|
||||
|
||||
// If there is buffer to fill and it will meet the limit
|
||||
if (bufferLen > 0 && bufferLen + length >= 64)
|
||||
{
|
||||
// Fill the buffer from the input
|
||||
Array.Copy(data, offset, _buffer, bufferLen, 64 - bufferLen);
|
||||
|
||||
// Set the new values
|
||||
offset += 64 - bufferLen;
|
||||
length -= 64 - bufferLen;
|
||||
|
||||
// Split the buffer for the round
|
||||
for (int i = 0; i < 16; i++)
|
||||
{
|
||||
_block[i] = ReadLE32(_buffer, i * 4);
|
||||
}
|
||||
|
||||
// Run the round
|
||||
Round();
|
||||
bufferLen = 0;
|
||||
}
|
||||
|
||||
/// Process any standalone blocks
|
||||
while (length >= 64)
|
||||
{
|
||||
// Fill the buffer from the input
|
||||
Array.Copy(data, offset, _buffer, 0, 64);
|
||||
|
||||
// Set the new values
|
||||
offset += 64;
|
||||
length -= 64;
|
||||
|
||||
// Split the buffer for the round
|
||||
for (int i = 0; i < 16; i++)
|
||||
{
|
||||
_block[i] = ReadLE32(_buffer, i * 4);
|
||||
}
|
||||
|
||||
// Run the round
|
||||
Round();
|
||||
}
|
||||
|
||||
// Save the remainder in the buffer
|
||||
if (length > 0)
|
||||
Array.Copy(data, offset, _buffer, bufferLen, length);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override void Terminate()
|
||||
{
|
||||
// Determine the pad length
|
||||
int padLength = 64 - (int)(_totalBytes & 0x3f);
|
||||
if (padLength <= 8)
|
||||
padLength += 64;
|
||||
|
||||
// Get the total byte count in bits
|
||||
long totalBitCount = _totalBytes * 8;
|
||||
|
||||
// Prebuild the padding
|
||||
var padding = new byte[padLength];
|
||||
padding[0] = 0x80;
|
||||
padding[padLength - 1] = (byte)((totalBitCount >> 56) & 0xff);
|
||||
padding[padLength - 2] = (byte)((totalBitCount >> 48) & 0xff);
|
||||
padding[padLength - 3] = (byte)((totalBitCount >> 40) & 0xff);
|
||||
padding[padLength - 4] = (byte)((totalBitCount >> 32) & 0xff);
|
||||
padding[padLength - 5] = (byte)((totalBitCount >> 24) & 0xff);
|
||||
padding[padLength - 6] = (byte)((totalBitCount >> 16) & 0xff);
|
||||
padding[padLength - 7] = (byte)((totalBitCount >> 8) & 0xff);
|
||||
padding[padLength - 8] = (byte)((totalBitCount >> 0) & 0xff);
|
||||
|
||||
// Pad the block
|
||||
TransformBlock(padding, 0, padding.Length);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override byte[] GetHash()
|
||||
{
|
||||
var hash = new byte[32];
|
||||
int hashOffset = 0;
|
||||
|
||||
// Assemble the hash array
|
||||
for (int i = 0; i < _state.Length; i++)
|
||||
{
|
||||
byte[] segment = BitConverter.GetBytes(_state[i]);
|
||||
Array.Copy(segment, 0, hash, hashOffset, 4);
|
||||
hashOffset += 4;
|
||||
}
|
||||
|
||||
// Reset the state and return
|
||||
Reset();
|
||||
return hash;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Perform one round of updates on the cached values
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The official specification for RIPEMD-128 includes tables
|
||||
/// and instructions that represent a loop. Most standard implementations
|
||||
/// use the unrolled version of that loop to make it more efficient.
|
||||
///
|
||||
/// The below code started with the looped version but has been converted
|
||||
/// to the more standard implementation instead.
|
||||
/// </remarks>
|
||||
private void Round()
|
||||
{
|
||||
// Setup values
|
||||
uint x0 = _state[0], xp0 = _state[4];
|
||||
uint x1 = _state[1], xp1 = _state[5];
|
||||
uint x2 = _state[2], xp2 = _state[6];
|
||||
uint x3 = _state[3], xp3 = _state[7];
|
||||
uint t;
|
||||
|
||||
#region Rounds 0-15
|
||||
|
||||
// Round 0
|
||||
x0 = RotateLeft32(x0 + G00_15(x1, x2, x3) + _block[0] + RMD128Round00To15, 11);
|
||||
xp0 = RotateLeft32(xp0 + G48_63(xp1, xp2, xp3) + _block[5] + RMD128RoundPrime00To15, 8);
|
||||
|
||||
// Round 1
|
||||
x3 = RotateLeft32(x3 + G00_15(x0, x1, x2) + _block[1] + RMD128Round00To15, 14);
|
||||
xp3 = RotateLeft32(xp3 + G48_63(xp0, xp1, xp2) + _block[14] + RMD128RoundPrime00To15, 9);
|
||||
|
||||
// Round 2
|
||||
x2 = RotateLeft32(x2 + G00_15(x3, x0, x1) + _block[2] + RMD128Round00To15, 15);
|
||||
xp2 = RotateLeft32(xp2 + G48_63(xp3, xp0, xp1) + _block[7] + RMD128RoundPrime00To15, 9);
|
||||
|
||||
// Round 3
|
||||
x1 = RotateLeft32(x1 + G00_15(x2, x3, x0) + _block[3] + RMD128Round00To15, 12);
|
||||
xp1 = RotateLeft32(xp1 + G48_63(xp2, xp3, xp0) + _block[0] + RMD128RoundPrime00To15, 11);
|
||||
|
||||
// Round 4
|
||||
x0 = RotateLeft32(x0 + G00_15(x1, x2, x3) + _block[4] + RMD128Round00To15, 5);
|
||||
xp0 = RotateLeft32(xp0 + G48_63(xp1, xp2, xp3) + _block[9] + RMD128RoundPrime00To15, 13);
|
||||
|
||||
// Round 5
|
||||
x3 = RotateLeft32(x3 + G00_15(x0, x1, x2) + _block[5] + RMD128Round00To15, 8);
|
||||
xp3 = RotateLeft32(xp3 + G48_63(xp0, xp1, xp2) + _block[2] + RMD128RoundPrime00To15, 15);
|
||||
|
||||
// Round 6
|
||||
x2 = RotateLeft32(x2 + G00_15(x3, x0, x1) + _block[6] + RMD128Round00To15, 7);
|
||||
xp2 = RotateLeft32(xp2 + G48_63(xp3, xp0, xp1) + _block[11] + RMD128RoundPrime00To15, 15);
|
||||
|
||||
// Round 7
|
||||
x1 = RotateLeft32(x1 + G00_15(x2, x3, x0) + _block[7] + RMD128Round00To15, 9);
|
||||
xp1 = RotateLeft32(xp1 + G48_63(xp2, xp3, xp0) + _block[4] + RMD128RoundPrime00To15, 5);
|
||||
|
||||
// Round 8
|
||||
x0 = RotateLeft32(x0 + G00_15(x1, x2, x3) + _block[8] + RMD128Round00To15, 11);
|
||||
xp0 = RotateLeft32(xp0 + G48_63(xp1, xp2, xp3) + _block[13] + RMD128RoundPrime00To15, 7);
|
||||
|
||||
// Round 9
|
||||
x3 = RotateLeft32(x3 + G00_15(x0, x1, x2) + _block[9] + RMD128Round00To15, 13);
|
||||
xp3 = RotateLeft32(xp3 + G48_63(xp0, xp1, xp2) + _block[6] + RMD128RoundPrime00To15, 7);
|
||||
|
||||
// Round 10
|
||||
x2 = RotateLeft32(x2 + G00_15(x3, x0, x1) + _block[10] + RMD128Round00To15, 14);
|
||||
xp2 = RotateLeft32(xp2 + G48_63(xp3, xp0, xp1) + _block[15] + RMD128RoundPrime00To15, 8);
|
||||
|
||||
// Round 11
|
||||
x1 = RotateLeft32(x1 + G00_15(x2, x3, x0) + _block[11] + RMD128Round00To15, 15);
|
||||
xp1 = RotateLeft32(xp1 + G48_63(xp2, xp3, xp0) + _block[8] + RMD128RoundPrime00To15, 11);
|
||||
|
||||
// Round 12
|
||||
x0 = RotateLeft32(x0 + G00_15(x1, x2, x3) + _block[12] + RMD128Round00To15, 6);
|
||||
xp0 = RotateLeft32(xp0 + G48_63(xp1, xp2, xp3) + _block[1] + RMD128RoundPrime00To15, 14);
|
||||
|
||||
// Round 13
|
||||
x3 = RotateLeft32(x3 + G00_15(x0, x1, x2) + _block[13] + RMD128Round00To15, 7);
|
||||
xp3 = RotateLeft32(xp3 + G48_63(xp0, xp1, xp2) + _block[10] + RMD128RoundPrime00To15, 14);
|
||||
|
||||
// Round 14
|
||||
x2 = RotateLeft32(x2 + G00_15(x3, x0, x1) + _block[14] + RMD128Round00To15, 9);
|
||||
xp2 = RotateLeft32(xp2 + G48_63(xp3, xp0, xp1) + _block[3] + RMD128RoundPrime00To15, 12);
|
||||
|
||||
// Round 15
|
||||
x1 = RotateLeft32(x1 + G00_15(x2, x3, x0) + _block[15] + RMD128Round00To15, 8);
|
||||
xp1 = RotateLeft32(xp1 + G48_63(xp2, xp3, xp0) + _block[12] + RMD128RoundPrime00To15, 6);
|
||||
|
||||
// Swap set 1
|
||||
t = x0; x0 = xp0; xp0 = t;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Rounds 16-31
|
||||
|
||||
// Round 16
|
||||
x0 = RotateLeft32(x0 + G16_31(x1, x2, x3) + _block[7] + RMD128Round16To31, 7);
|
||||
xp0 = RotateLeft32(xp0 + G32_47(xp1, xp2, xp3) + _block[6] + RMD128RoundPrime16To31, 9);
|
||||
|
||||
// Round 17
|
||||
x3 = RotateLeft32(x3 + G16_31(x0, x1, x2) + _block[4] + RMD128Round16To31, 6);
|
||||
xp3 = RotateLeft32(xp3 + G32_47(xp0, xp1, xp2) + _block[11] + RMD128RoundPrime16To31, 13);
|
||||
|
||||
// Round 18
|
||||
x2 = RotateLeft32(x2 + G16_31(x3, x0, x1) + _block[13] + RMD128Round16To31, 8);
|
||||
xp2 = RotateLeft32(xp2 + G32_47(xp3, xp0, xp1) + _block[3] + RMD128RoundPrime16To31, 15);
|
||||
|
||||
// Round 19
|
||||
x1 = RotateLeft32(x1 + G16_31(x2, x3, x0) + _block[1] + RMD128Round16To31, 13);
|
||||
xp1 = RotateLeft32(xp1 + G32_47(xp2, xp3, xp0) + _block[7] + RMD128RoundPrime16To31, 7);
|
||||
|
||||
// Round 20
|
||||
x0 = RotateLeft32(x0 + G16_31(x1, x2, x3) + _block[10] + RMD128Round16To31, 11);
|
||||
xp0 = RotateLeft32(xp0 + G32_47(xp1, xp2, xp3) + _block[0] + RMD128RoundPrime16To31, 12);
|
||||
|
||||
// Round 21
|
||||
x3 = RotateLeft32(x3 + G16_31(x0, x1, x2) + _block[6] + RMD128Round16To31, 9);
|
||||
xp3 = RotateLeft32(xp3 + G32_47(xp0, xp1, xp2) + _block[13] + RMD128RoundPrime16To31, 8);
|
||||
|
||||
// Round 22
|
||||
x2 = RotateLeft32(x2 + G16_31(x3, x0, x1) + _block[15] + RMD128Round16To31, 7);
|
||||
xp2 = RotateLeft32(xp2 + G32_47(xp3, xp0, xp1) + _block[5] + RMD128RoundPrime16To31, 9);
|
||||
|
||||
// Round 23
|
||||
x1 = RotateLeft32(x1 + G16_31(x2, x3, x0) + _block[3] + RMD128Round16To31, 15);
|
||||
xp1 = RotateLeft32(xp1 + G32_47(xp2, xp3, xp0) + _block[10] + RMD128RoundPrime16To31, 11);
|
||||
|
||||
// Round 24
|
||||
x0 = RotateLeft32(x0 + G16_31(x1, x2, x3) + _block[12] + RMD128Round16To31, 7);
|
||||
xp0 = RotateLeft32(xp0 + G32_47(xp1, xp2, xp3) + _block[14] + RMD128RoundPrime16To31, 7);
|
||||
|
||||
// Round 25
|
||||
x3 = RotateLeft32(x3 + G16_31(x0, x1, x2) + _block[0] + RMD128Round16To31, 12);
|
||||
xp3 = RotateLeft32(xp3 + G32_47(xp0, xp1, xp2) + _block[15] + RMD128RoundPrime16To31, 7);
|
||||
|
||||
// Round 26
|
||||
x2 = RotateLeft32(x2 + G16_31(x3, x0, x1) + _block[9] + RMD128Round16To31, 15);
|
||||
xp2 = RotateLeft32(xp2 + G32_47(xp3, xp0, xp1) + _block[8] + RMD128RoundPrime16To31, 12);
|
||||
|
||||
// Round 27
|
||||
x1 = RotateLeft32(x1 + G16_31(x2, x3, x0) + _block[5] + RMD128Round16To31, 9);
|
||||
xp1 = RotateLeft32(xp1 + G32_47(xp2, xp3, xp0) + _block[12] + RMD128RoundPrime16To31, 7);
|
||||
|
||||
// Round 28
|
||||
x0 = RotateLeft32(x0 + G16_31(x1, x2, x3) + _block[2] + RMD128Round16To31, 11);
|
||||
xp0 = RotateLeft32(xp0 + G32_47(xp1, xp2, xp3) + _block[4] + RMD128RoundPrime16To31, 6);
|
||||
|
||||
// Round 29
|
||||
x3 = RotateLeft32(x3 + G16_31(x0, x1, x2) + _block[14] + RMD128Round16To31, 7);
|
||||
xp3 = RotateLeft32(xp3 + G32_47(xp0, xp1, xp2) + _block[9] + RMD128RoundPrime16To31, 15);
|
||||
|
||||
// Round 30
|
||||
x2 = RotateLeft32(x2 + G16_31(x3, x0, x1) + _block[11] + RMD128Round16To31, 13);
|
||||
xp2 = RotateLeft32(xp2 + G32_47(xp3, xp0, xp1) + _block[1] + RMD128RoundPrime16To31, 13);
|
||||
|
||||
// Round 31
|
||||
x1 = RotateLeft32(x1 + G16_31(x2, x3, x0) + _block[8] + RMD128Round16To31, 12);
|
||||
xp1 = RotateLeft32(xp1 + G32_47(xp2, xp3, xp0) + _block[2] + RMD128RoundPrime16To31, 11);
|
||||
|
||||
// Swap set 2
|
||||
t = x1; x1 = xp1; xp1 = t;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Rounds 32-47
|
||||
|
||||
// Round 32
|
||||
x0 = RotateLeft32(x0 + G32_47(x1, x2, x3) + _block[3] + RMD128Round32To47, 11);
|
||||
xp0 = RotateLeft32(xp0 + G16_31(xp1, xp2, xp3) + _block[15] + RMD128RoundPrime32To47, 9);
|
||||
|
||||
// Round 33
|
||||
x3 = RotateLeft32(x3 + G32_47(x0, x1, x2) + _block[10] + RMD128Round32To47, 13);
|
||||
xp3 = RotateLeft32(xp3 + G16_31(xp0, xp1, xp2) + _block[5] + RMD128RoundPrime32To47, 7);
|
||||
|
||||
// Round 34
|
||||
x2 = RotateLeft32(x2 + G32_47(x3, x0, x1) + _block[14] + RMD128Round32To47, 6);
|
||||
xp2 = RotateLeft32(xp2 + G16_31(xp3, xp0, xp1) + _block[1] + RMD128RoundPrime32To47, 15);
|
||||
|
||||
// Round 35
|
||||
x1 = RotateLeft32(x1 + G32_47(x2, x3, x0) + _block[4] + RMD128Round32To47, 7);
|
||||
xp1 = RotateLeft32(xp1 + G16_31(xp2, xp3, xp0) + _block[3] + RMD128RoundPrime32To47, 11);
|
||||
|
||||
// Round 36
|
||||
x0 = RotateLeft32(x0 + G32_47(x1, x2, x3) + _block[9] + RMD128Round32To47, 14);
|
||||
xp0 = RotateLeft32(xp0 + G16_31(xp1, xp2, xp3) + _block[7] + RMD128RoundPrime32To47, 8);
|
||||
|
||||
// Round 37
|
||||
x3 = RotateLeft32(x3 + G32_47(x0, x1, x2) + _block[15] + RMD128Round32To47, 9);
|
||||
xp3 = RotateLeft32(xp3 + G16_31(xp0, xp1, xp2) + _block[14] + RMD128RoundPrime32To47, 6);
|
||||
|
||||
// Round 38
|
||||
x2 = RotateLeft32(x2 + G32_47(x3, x0, x1) + _block[8] + RMD128Round32To47, 13);
|
||||
xp2 = RotateLeft32(xp2 + G16_31(xp3, xp0, xp1) + _block[6] + RMD128RoundPrime32To47, 6);
|
||||
|
||||
// Round 39
|
||||
x1 = RotateLeft32(x1 + G32_47(x2, x3, x0) + _block[1] + RMD128Round32To47, 15);
|
||||
xp1 = RotateLeft32(xp1 + G16_31(xp2, xp3, xp0) + _block[9] + RMD128RoundPrime32To47, 14);
|
||||
|
||||
// Round 40
|
||||
x0 = RotateLeft32(x0 + G32_47(x1, x2, x3) + _block[2] + RMD128Round32To47, 14);
|
||||
xp0 = RotateLeft32(xp0 + G16_31(xp1, xp2, xp3) + _block[11] + RMD128RoundPrime32To47, 12);
|
||||
|
||||
// Round 41
|
||||
x3 = RotateLeft32(x3 + G32_47(x0, x1, x2) + _block[7] + RMD128Round32To47, 8);
|
||||
xp3 = RotateLeft32(xp3 + G16_31(xp0, xp1, xp2) + _block[8] + RMD128RoundPrime32To47, 13);
|
||||
|
||||
// Round 42
|
||||
x2 = RotateLeft32(x2 + G32_47(x3, x0, x1) + _block[0] + RMD128Round32To47, 13);
|
||||
xp2 = RotateLeft32(xp2 + G16_31(xp3, xp0, xp1) + _block[12] + RMD128RoundPrime32To47, 5);
|
||||
|
||||
// Round 43
|
||||
x1 = RotateLeft32(x1 + G32_47(x2, x3, x0) + _block[6] + RMD128Round32To47, 6);
|
||||
xp1 = RotateLeft32(xp1 + G16_31(xp2, xp3, xp0) + _block[2] + RMD128RoundPrime32To47, 14);
|
||||
|
||||
// Round 44
|
||||
x0 = RotateLeft32(x0 + G32_47(x1, x2, x3) + _block[13] + RMD128Round32To47, 5);
|
||||
xp0 = RotateLeft32(xp0 + G16_31(xp1, xp2, xp3) + _block[10] + RMD128RoundPrime32To47, 13);
|
||||
|
||||
// Round 45
|
||||
x3 = RotateLeft32(x3 + G32_47(x0, x1, x2) + _block[11] + RMD128Round32To47, 12);
|
||||
xp3 = RotateLeft32(xp3 + G16_31(xp0, xp1, xp2) + _block[0] + RMD128RoundPrime32To47, 13);
|
||||
|
||||
// Round 46
|
||||
x2 = RotateLeft32(x2 + G32_47(x3, x0, x1) + _block[5] + RMD128Round32To47, 7);
|
||||
xp2 = RotateLeft32(xp2 + G16_31(xp3, xp0, xp1) + _block[4] + RMD128RoundPrime32To47, 7);
|
||||
|
||||
// Round 47
|
||||
x1 = RotateLeft32(x1 + G32_47(x2, x3, x0) + _block[12] + RMD128Round32To47, 5);
|
||||
xp1 = RotateLeft32(xp1 + G16_31(xp2, xp3, xp0) + _block[13] + RMD128RoundPrime32To47, 5);
|
||||
|
||||
// Swap set 3
|
||||
t = x2; x2 = xp2; xp2 = t;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Rounds 48-63
|
||||
|
||||
// Round 48
|
||||
x0 = RotateLeft32(x0 + G48_63(x1, x2, x3) + _block[1] + RMD128Round48To63, 11);
|
||||
xp0 = RotateLeft32(xp0 + G00_15(xp1, xp2, xp3) + _block[8] + RMD128RoundPrime48To63, 15);
|
||||
|
||||
// Round 49
|
||||
x3 = RotateLeft32(x3 + G48_63(x0, x1, x2) + _block[9] + RMD128Round48To63, 12);
|
||||
xp3 = RotateLeft32(xp3 + G00_15(xp0, xp1, xp2) + _block[6] + RMD128RoundPrime48To63, 5);
|
||||
|
||||
// Round 50
|
||||
x2 = RotateLeft32(x2 + G48_63(x3, x0, x1) + _block[11] + RMD128Round48To63, 14);
|
||||
xp2 = RotateLeft32(xp2 + G00_15(xp3, xp0, xp1) + _block[4] + RMD128RoundPrime48To63, 8);
|
||||
|
||||
// Round 51
|
||||
x1 = RotateLeft32(x1 + G48_63(x2, x3, x0) + _block[10] + RMD128Round48To63, 15);
|
||||
xp1 = RotateLeft32(xp1 + G00_15(xp2, xp3, xp0) + _block[1] + RMD128RoundPrime48To63, 11);
|
||||
|
||||
// Round 52
|
||||
x0 = RotateLeft32(x0 + G48_63(x1, x2, x3) + _block[0] + RMD128Round48To63, 14);
|
||||
xp0 = RotateLeft32(xp0 + G00_15(xp1, xp2, xp3) + _block[3] + RMD128RoundPrime48To63, 14);
|
||||
|
||||
// Round 53
|
||||
x3 = RotateLeft32(x3 + G48_63(x0, x1, x2) + _block[8] + RMD128Round48To63, 15);
|
||||
xp3 = RotateLeft32(xp3 + G00_15(xp0, xp1, xp2) + _block[11] + RMD128RoundPrime48To63, 14);
|
||||
|
||||
// Round 54
|
||||
x2 = RotateLeft32(x2 + G48_63(x3, x0, x1) + _block[12] + RMD128Round48To63, 9);
|
||||
xp2 = RotateLeft32(xp2 + G00_15(xp3, xp0, xp1) + _block[15] + RMD128RoundPrime48To63, 6);
|
||||
|
||||
// Round 55
|
||||
x1 = RotateLeft32(x1 + G48_63(x2, x3, x0) + _block[4] + RMD128Round48To63, 8);
|
||||
xp1 = RotateLeft32(xp1 + G00_15(xp2, xp3, xp0) + _block[0] + RMD128RoundPrime48To63, 14);
|
||||
|
||||
// Round 56
|
||||
x0 = RotateLeft32(x0 + G48_63(x1, x2, x3) + _block[13] + RMD128Round48To63, 9);
|
||||
xp0 = RotateLeft32(xp0 + G00_15(xp1, xp2, xp3) + _block[5] + RMD128RoundPrime48To63, 6);
|
||||
|
||||
// Round 57
|
||||
x3 = RotateLeft32(x3 + G48_63(x0, x1, x2) + _block[3] + RMD128Round48To63, 14);
|
||||
xp3 = RotateLeft32(xp3 + G00_15(xp0, xp1, xp2) + _block[12] + RMD128RoundPrime48To63, 9);
|
||||
|
||||
// Round 58
|
||||
x2 = RotateLeft32(x2 + G48_63(x3, x0, x1) + _block[7] + RMD128Round48To63, 5);
|
||||
xp2 = RotateLeft32(xp2 + G00_15(xp3, xp0, xp1) + _block[2] + RMD128RoundPrime48To63, 12);
|
||||
|
||||
// Round 59
|
||||
x1 = RotateLeft32(x1 + G48_63(x2, x3, x0) + _block[15] + RMD128Round48To63, 6);
|
||||
xp1 = RotateLeft32(xp1 + G00_15(xp2, xp3, xp0) + _block[13] + RMD128RoundPrime48To63, 9);
|
||||
|
||||
// Round 60
|
||||
x0 = RotateLeft32(x0 + G48_63(x1, x2, x3) + _block[14] + RMD128Round48To63, 8);
|
||||
xp0 = RotateLeft32(xp0 + G00_15(xp1, xp2, xp3) + _block[9] + RMD128RoundPrime48To63, 12);
|
||||
|
||||
// Round 61
|
||||
x3 = RotateLeft32(x3 + G48_63(x0, x1, x2) + _block[5] + RMD128Round48To63, 6);
|
||||
xp3 = RotateLeft32(xp3 + G00_15(xp0, xp1, xp2) + _block[7] + RMD128RoundPrime48To63, 5);
|
||||
|
||||
// Round 62
|
||||
x2 = RotateLeft32(x2 + G48_63(x3, x0, x1) + _block[6] + RMD128Round48To63, 5);
|
||||
xp2 = RotateLeft32(xp2 + G00_15(xp3, xp0, xp1) + _block[10] + RMD128RoundPrime48To63, 15);
|
||||
|
||||
// Round 63
|
||||
x1 = RotateLeft32(x1 + G48_63(x2, x3, x0) + _block[2] + RMD128Round48To63, 12);
|
||||
xp1 = RotateLeft32(xp1 + G00_15(xp2, xp3, xp0) + _block[14] + RMD128RoundPrime48To63, 8);
|
||||
|
||||
// Swap set 4
|
||||
t = x3; x3 = xp3; xp3 = t;
|
||||
|
||||
#endregion
|
||||
|
||||
// Avalanche values
|
||||
_state[0] += x0;
|
||||
_state[1] += x1;
|
||||
_state[2] += x2;
|
||||
_state[3] += x3;
|
||||
_state[4] += xp0;
|
||||
_state[5] += xp1;
|
||||
_state[6] += xp2;
|
||||
_state[7] += xp3;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Round operation [0, 15]
|
||||
/// </summary>
|
||||
private static uint G00_15(uint x, uint y, uint z) => x ^ y ^ z;
|
||||
|
||||
/// <summary>
|
||||
/// Round operation [16, 31]
|
||||
/// </summary>
|
||||
private static uint G16_31(uint x, uint y, uint z) => (x & y) | (~x & z);
|
||||
|
||||
/// <summary>
|
||||
/// Round operation [32, 47]
|
||||
/// </summary>
|
||||
private static uint G32_47(uint x, uint y, uint z) => (x | ~y) ^ z;
|
||||
|
||||
/// <summary>
|
||||
/// Round operation [48, 63]
|
||||
/// </summary>
|
||||
private static uint G48_63(uint x, uint y, uint z) => (x & z) | (y & ~z);
|
||||
}
|
||||
}
|
||||
710
SabreTools.Hashing/MessageDigest/RipeMD320.cs
Normal file
710
SabreTools.Hashing/MessageDigest/RipeMD320.cs
Normal file
@@ -0,0 +1,710 @@
|
||||
using System;
|
||||
using static SabreTools.Hashing.HashOperations;
|
||||
using static SabreTools.Hashing.MessageDigest.Constants;
|
||||
|
||||
namespace SabreTools.Hashing.MessageDigest
|
||||
{
|
||||
/// <see href="https://cdn.standards.iteh.ai/samples/39876/10f9f9f4bb614eaaaeba7e157e183ca3/ISO-IEC-10118-3-2004.pdf"/>
|
||||
/// <see href="https://homes.esat.kuleuven.be/~bosselae/ripemd160/pdf/AB-9601/AB-9601.pdf"/>
|
||||
public class RipeMD320 : MessageDigestBase<uint>
|
||||
{
|
||||
/// <summary>
|
||||
/// Set of 10 32-bit numbers representing the hash state
|
||||
/// </summary>
|
||||
private readonly uint[] _state = new uint[10];
|
||||
|
||||
public RipeMD320() : base()
|
||||
{
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
protected override void ResetImpl()
|
||||
{
|
||||
_state[0] = RMD160Y0;
|
||||
_state[1] = RMD160Y1;
|
||||
_state[2] = RMD160Y2;
|
||||
_state[3] = RMD160Y3;
|
||||
_state[4] = RMD160Y4;
|
||||
_state[5] = RMD320Y5;
|
||||
_state[6] = RMD320Y6;
|
||||
_state[7] = RMD320Y7;
|
||||
_state[8] = RMD320Y8;
|
||||
_state[9] = RMD320Y9;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override void TransformBlock(byte[] data, int offset, int length)
|
||||
{
|
||||
// Figure out how much buffer is needed
|
||||
int bufferLen = (int)(_totalBytes & 0x3f);
|
||||
|
||||
// Increment the processed byte count
|
||||
_totalBytes += length;
|
||||
|
||||
// If there is buffer to fill and it will meet the limit
|
||||
if (bufferLen > 0 && bufferLen + length >= 64)
|
||||
{
|
||||
// Fill the buffer from the input
|
||||
Array.Copy(data, offset, _buffer, bufferLen, 64 - bufferLen);
|
||||
|
||||
// Set the new values
|
||||
offset += 64 - bufferLen;
|
||||
length -= 64 - bufferLen;
|
||||
|
||||
// Split the buffer for the round
|
||||
for (int i = 0; i < 16; i++)
|
||||
{
|
||||
_block[i] = ReadLE32(_buffer, i * 4);
|
||||
}
|
||||
|
||||
// Run the round
|
||||
Round();
|
||||
bufferLen = 0;
|
||||
}
|
||||
|
||||
/// Process any standalone blocks
|
||||
while (length >= 64)
|
||||
{
|
||||
// Fill the buffer from the input
|
||||
Array.Copy(data, offset, _buffer, 0, 64);
|
||||
|
||||
// Set the new values
|
||||
offset += 64;
|
||||
length -= 64;
|
||||
|
||||
// Split the buffer for the round
|
||||
for (int i = 0; i < 16; i++)
|
||||
{
|
||||
_block[i] = ReadLE32(_buffer, i * 4);
|
||||
}
|
||||
|
||||
// Run the round
|
||||
Round();
|
||||
}
|
||||
|
||||
// Save the remainder in the buffer
|
||||
if (length > 0)
|
||||
Array.Copy(data, offset, _buffer, bufferLen, length);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override void Terminate()
|
||||
{
|
||||
// Determine the pad length
|
||||
int padLength = 64 - (int)(_totalBytes & 0x3f);
|
||||
if (padLength <= 8)
|
||||
padLength += 64;
|
||||
|
||||
// Get the total byte count in bits
|
||||
long totalBitCount = _totalBytes * 8;
|
||||
|
||||
// Prebuild the padding
|
||||
var padding = new byte[padLength];
|
||||
padding[0] = 0x80;
|
||||
padding[padLength - 1] = (byte)((totalBitCount >> 56) & 0xff);
|
||||
padding[padLength - 2] = (byte)((totalBitCount >> 48) & 0xff);
|
||||
padding[padLength - 3] = (byte)((totalBitCount >> 40) & 0xff);
|
||||
padding[padLength - 4] = (byte)((totalBitCount >> 32) & 0xff);
|
||||
padding[padLength - 5] = (byte)((totalBitCount >> 24) & 0xff);
|
||||
padding[padLength - 6] = (byte)((totalBitCount >> 16) & 0xff);
|
||||
padding[padLength - 7] = (byte)((totalBitCount >> 8 ) & 0xff);
|
||||
padding[padLength - 8] = (byte)((totalBitCount >> 0 ) & 0xff);
|
||||
|
||||
// Pad the block
|
||||
TransformBlock(padding, 0, padding.Length);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override byte[] GetHash()
|
||||
{
|
||||
var hash = new byte[40];
|
||||
int hashOffset = 0;
|
||||
|
||||
// Assemble the hash array
|
||||
for (int i = 0; i < _state.Length; i++)
|
||||
{
|
||||
byte[] segment = BitConverter.GetBytes(_state[i]);
|
||||
Array.Copy(segment, 0, hash, hashOffset, 4);
|
||||
hashOffset += 4;
|
||||
}
|
||||
|
||||
// Reset the state and return
|
||||
Reset();
|
||||
return hash;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Perform one round of updates on the cached values
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The official specification for RIPEMD-160 includes tables
|
||||
/// and instructions that represent a loop. Most standard implementations
|
||||
/// use the unrolled version of that loop to make it more efficient.
|
||||
///
|
||||
/// The below code started with the looped version but has been converted
|
||||
/// to the more standard implementation instead.
|
||||
/// </remarks>
|
||||
private void Round()
|
||||
{
|
||||
// Setup values
|
||||
uint x0 = _state[0], xp0 = _state[5];
|
||||
uint x1 = _state[1], xp1 = _state[6];
|
||||
uint x2 = _state[2], xp2 = _state[7];
|
||||
uint x3 = _state[3], xp3 = _state[8];
|
||||
uint x4 = _state[4], xp4 = _state[9];
|
||||
uint t;
|
||||
|
||||
#region Rounds 0-15
|
||||
|
||||
// Round 0
|
||||
x0 = RotateLeft32(x0 + G00_15(x1, x2, x3) + _block[0] + RMD160Round00To15, 11) + x4;
|
||||
x2 = RotateLeft32(x2, 10);
|
||||
xp0 = RotateLeft32(xp0 + G64_79(xp1, xp2, xp3) + _block[5] + RMD160RoundPrime00To15, 8) + xp4;
|
||||
xp2 = RotateLeft32(xp2, 10);
|
||||
|
||||
// Round 1
|
||||
x4 = RotateLeft32(x4 + G00_15(x0, x1, x2) + _block[1] + RMD160Round00To15, 14) + x3;
|
||||
x1 = RotateLeft32(x1, 10);
|
||||
xp4 = RotateLeft32(xp4 + G64_79(xp0, xp1, xp2) + _block[14] + RMD160RoundPrime00To15, 9) + xp3;
|
||||
xp1 = RotateLeft32(xp1, 10);
|
||||
|
||||
// Round 2
|
||||
x3 = RotateLeft32(x3 + G00_15(x4, x0, x1) + _block[2] + RMD160Round00To15, 15) + x2;
|
||||
x0 = RotateLeft32(x0, 10);
|
||||
xp3 = RotateLeft32(xp3 + G64_79(xp4, xp0, xp1) + _block[7] + RMD160RoundPrime00To15, 9) + xp2;
|
||||
xp0 = RotateLeft32(xp0, 10);
|
||||
|
||||
// Round 3
|
||||
x2 = RotateLeft32(x2 + G00_15(x3, x4, x0) + _block[3] + RMD160Round00To15, 12) + x1;
|
||||
x4 = RotateLeft32(x4, 10);
|
||||
xp2 = RotateLeft32(xp2 + G64_79(xp3, xp4, xp0) + _block[0] + RMD160RoundPrime00To15, 11) + xp1;
|
||||
xp4 = RotateLeft32(xp4, 10);
|
||||
|
||||
// Round 4
|
||||
x1 = RotateLeft32(x1 + G00_15(x2, x3, x4) + _block[4] + RMD160Round00To15, 5) + x0;
|
||||
x3 = RotateLeft32(x3, 10);
|
||||
xp1 = RotateLeft32(xp1 + G64_79(xp2, xp3, xp4) + _block[9] + RMD160RoundPrime00To15, 13) + xp0;
|
||||
xp3 = RotateLeft32(xp3, 10);
|
||||
|
||||
// Round 5
|
||||
x0 = RotateLeft32(x0 + G00_15(x1, x2, x3) + _block[5] + RMD160Round00To15, 8) + x4;
|
||||
x2 = RotateLeft32(x2, 10);
|
||||
xp0 = RotateLeft32(xp0 + G64_79(xp1, xp2, xp3) + _block[2] + RMD160RoundPrime00To15, 15) + xp4;
|
||||
xp2 = RotateLeft32(xp2, 10);
|
||||
|
||||
// Round 6
|
||||
x4 = RotateLeft32(x4 + G00_15(x0, x1, x2) + _block[6] + RMD160Round00To15, 7) + x3;
|
||||
x1 = RotateLeft32(x1, 10);
|
||||
xp4 = RotateLeft32(xp4 + G64_79(xp0, xp1, xp2) + _block[11] + RMD160RoundPrime00To15, 15) + xp3;
|
||||
xp1 = RotateLeft32(xp1, 10);
|
||||
|
||||
// Round 7
|
||||
x3 = RotateLeft32(x3 + G00_15(x4, x0, x1) + _block[7] + RMD160Round00To15, 9) + x2;
|
||||
x0 = RotateLeft32(x0, 10);
|
||||
xp3 = RotateLeft32(xp3 + G64_79(xp4, xp0, xp1) + _block[4] + RMD160RoundPrime00To15, 5) + xp2;
|
||||
xp0 = RotateLeft32(xp0, 10);
|
||||
|
||||
// Round 8
|
||||
x2 = RotateLeft32(x2 + G00_15(x3, x4, x0) + _block[8] + RMD160Round00To15, 11) + x1;
|
||||
x4 = RotateLeft32(x4, 10);
|
||||
xp2 = RotateLeft32(xp2 + G64_79(xp3, xp4, xp0) + _block[13] + RMD160RoundPrime00To15, 7) + xp1;
|
||||
xp4 = RotateLeft32(xp4, 10);
|
||||
|
||||
// Round 9
|
||||
x1 = RotateLeft32(x1 + G00_15(x2, x3, x4) + _block[9] + RMD160Round00To15, 13) + x0;
|
||||
x3 = RotateLeft32(x3, 10);
|
||||
xp1 = RotateLeft32(xp1 + G64_79(xp2, xp3, xp4) + _block[6] + RMD160RoundPrime00To15, 7) + xp0;
|
||||
xp3 = RotateLeft32(xp3, 10);
|
||||
|
||||
// Round 10
|
||||
x0 = RotateLeft32(x0 + G00_15(x1, x2, x3) + _block[10] + RMD160Round00To15, 14) + x4;
|
||||
x2 = RotateLeft32(x2, 10);
|
||||
xp0 = RotateLeft32(xp0 + G64_79(xp1, xp2, xp3) + _block[15] + RMD160RoundPrime00To15, 8) + xp4;
|
||||
xp2 = RotateLeft32(xp2, 10);
|
||||
|
||||
// Round 11
|
||||
x4 = RotateLeft32(x4 + G00_15(x0, x1, x2) + _block[11] + RMD160Round00To15, 15) + x3;
|
||||
x1 = RotateLeft32(x1, 10);
|
||||
xp4 = RotateLeft32(xp4 + G64_79(xp0, xp1, xp2) + _block[8] + RMD160RoundPrime00To15, 11) + xp3;
|
||||
xp1 = RotateLeft32(xp1, 10);
|
||||
|
||||
// Round 12
|
||||
x3 = RotateLeft32(x3 + G00_15(x4, x0, x1) + _block[12] + RMD160Round00To15, 6) + x2;
|
||||
x0 = RotateLeft32(x0, 10);
|
||||
xp3 = RotateLeft32(xp3 + G64_79(xp4, xp0, xp1) + _block[1] + RMD160RoundPrime00To15, 14) + xp2;
|
||||
xp0 = RotateLeft32(xp0, 10);
|
||||
|
||||
// Round 13
|
||||
x2 = RotateLeft32(x2 + G00_15(x3, x4, x0) + _block[13] + RMD160Round00To15, 7) + x1;
|
||||
x4 = RotateLeft32(x4, 10);
|
||||
xp2 = RotateLeft32(xp2 + G64_79(xp3, xp4, xp0) + _block[10] + RMD160RoundPrime00To15, 14) + xp1;
|
||||
xp4 = RotateLeft32(xp4, 10);
|
||||
|
||||
// Round 14
|
||||
x1 = RotateLeft32(x1 + G00_15(x2, x3, x4) + _block[14] + RMD160Round00To15, 9) + x0;
|
||||
x3 = RotateLeft32(x3, 10);
|
||||
xp1 = RotateLeft32(xp1 + G64_79(xp2, xp3, xp4) + _block[3] + RMD160RoundPrime00To15, 12) + xp0;
|
||||
xp3 = RotateLeft32(xp3, 10);
|
||||
|
||||
// Round 15
|
||||
x0 = RotateLeft32(x0 + G00_15(x1, x2, x3) + _block[15] + RMD160Round00To15, 8) + x4;
|
||||
x2 = RotateLeft32(x2, 10);
|
||||
xp0 = RotateLeft32(xp0 + G64_79(xp1, xp2, xp3) + _block[12] + RMD160RoundPrime00To15, 6) + xp4;
|
||||
xp2 = RotateLeft32(xp2, 10);
|
||||
|
||||
// Swap set 1
|
||||
t = x0; x0 = xp0; xp0 = t;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Rounds 16-31
|
||||
|
||||
// Round 16
|
||||
x4 = RotateLeft32(x4 + G16_31(x0, x1, x2) + _block[7] + RMD160Round16To31, 7) + x3;
|
||||
x1 = RotateLeft32(x1, 10);
|
||||
xp4 = RotateLeft32(xp4 + G48_63(xp0, xp1, xp2) + _block[6] + RMD160RoundPrime16To31, 9) + xp3;
|
||||
xp1 = RotateLeft32(xp1, 10);
|
||||
|
||||
// Round 17
|
||||
x3 = RotateLeft32(x3 + G16_31(x4, x0, x1) + _block[4] + RMD160Round16To31, 6) + x2;
|
||||
x0 = RotateLeft32(x0, 10);
|
||||
xp3 = RotateLeft32(xp3 + G48_63(xp4, xp0, xp1) + _block[11] + RMD160RoundPrime16To31, 13) + xp2;
|
||||
xp0 = RotateLeft32(xp0, 10);
|
||||
|
||||
// Round 18
|
||||
x2 = RotateLeft32(x2 + G16_31(x3, x4, x0) + _block[13] + RMD160Round16To31, 8) + x1;
|
||||
x4 = RotateLeft32(x4, 10);
|
||||
xp2 = RotateLeft32(xp2 + G48_63(xp3, xp4, xp0) + _block[3] + RMD160RoundPrime16To31, 15) + xp1;
|
||||
xp4 = RotateLeft32(xp4, 10);
|
||||
|
||||
// Round 19
|
||||
x1 = RotateLeft32(x1 + G16_31(x2, x3, x4) + _block[1] + RMD160Round16To31, 13) + x0;
|
||||
x3 = RotateLeft32(x3, 10);
|
||||
xp1 = RotateLeft32(xp1 + G48_63(xp2, xp3, xp4) + _block[7] + RMD160RoundPrime16To31, 7) + xp0;
|
||||
xp3 = RotateLeft32(xp3, 10);
|
||||
|
||||
// Round 20
|
||||
x0 = RotateLeft32(x0 + G16_31(x1, x2, x3) + _block[10] + RMD160Round16To31, 11) + x4;
|
||||
x2 = RotateLeft32(x2, 10);
|
||||
xp0 = RotateLeft32(xp0 + G48_63(xp1, xp2, xp3) + _block[0] + RMD160RoundPrime16To31, 12) + xp4;
|
||||
xp2 = RotateLeft32(xp2, 10);
|
||||
|
||||
// Round 21
|
||||
x4 = RotateLeft32(x4 + G16_31(x0, x1, x2) + _block[6] + RMD160Round16To31, 9) + x3;
|
||||
x1 = RotateLeft32(x1, 10);
|
||||
xp4 = RotateLeft32(xp4 + G48_63(xp0, xp1, xp2) + _block[13] + RMD160RoundPrime16To31, 8) + xp3;
|
||||
xp1 = RotateLeft32(xp1, 10);
|
||||
|
||||
// Round 22
|
||||
x3 = RotateLeft32(x3 + G16_31(x4, x0, x1) + _block[15] + RMD160Round16To31, 7) + x2;
|
||||
x0 = RotateLeft32(x0, 10);
|
||||
xp3 = RotateLeft32(xp3 + G48_63(xp4, xp0, xp1) + _block[5] + RMD160RoundPrime16To31, 9) + xp2;
|
||||
xp0 = RotateLeft32(xp0, 10);
|
||||
|
||||
// Round 23
|
||||
x2 = RotateLeft32(x2 + G16_31(x3, x4, x0) + _block[3] + RMD160Round16To31, 15) + x1;
|
||||
x4 = RotateLeft32(x4, 10);
|
||||
xp2 = RotateLeft32(xp2 + G48_63(xp3, xp4, xp0) + _block[10] + RMD160RoundPrime16To31, 11) + xp1;
|
||||
xp4 = RotateLeft32(xp4, 10);
|
||||
|
||||
// Round 24
|
||||
x1 = RotateLeft32(x1 + G16_31(x2, x3, x4) + _block[12] + RMD160Round16To31, 7) + x0;
|
||||
x3 = RotateLeft32(x3, 10);
|
||||
xp1 = RotateLeft32(xp1 + G48_63(xp2, xp3, xp4) + _block[14] + RMD160RoundPrime16To31, 7) + xp0;
|
||||
xp3 = RotateLeft32(xp3, 10);
|
||||
|
||||
// Round 25
|
||||
x0 = RotateLeft32(x0 + G16_31(x1, x2, x3) + _block[0] + RMD160Round16To31, 12) + x4;
|
||||
x2 = RotateLeft32(x2, 10);
|
||||
xp0 = RotateLeft32(xp0 + G48_63(xp1, xp2, xp3) + _block[15] + RMD160RoundPrime16To31, 7) + xp4;
|
||||
xp2 = RotateLeft32(xp2, 10);
|
||||
|
||||
// Round 26
|
||||
x4 = RotateLeft32(x4 + G16_31(x0, x1, x2) + _block[9] + RMD160Round16To31, 15) + x3;
|
||||
x1 = RotateLeft32(x1, 10);
|
||||
xp4 = RotateLeft32(xp4 + G48_63(xp0, xp1, xp2) + _block[8] + RMD160RoundPrime16To31, 12) + xp3;
|
||||
xp1 = RotateLeft32(xp1, 10);
|
||||
|
||||
// Round 27
|
||||
x3 = RotateLeft32(x3 + G16_31(x4, x0, x1) + _block[5] + RMD160Round16To31, 9) + x2;
|
||||
x0 = RotateLeft32(x0, 10);
|
||||
xp3 = RotateLeft32(xp3 + G48_63(xp4, xp0, xp1) + _block[12] + RMD160RoundPrime16To31, 7) + xp2;
|
||||
xp0 = RotateLeft32(xp0, 10);
|
||||
|
||||
// Round 28
|
||||
x2 = RotateLeft32(x2 + G16_31(x3, x4, x0) + _block[2] + RMD160Round16To31, 11) + x1;
|
||||
x4 = RotateLeft32(x4, 10);
|
||||
xp2 = RotateLeft32(xp2 + G48_63(xp3, xp4, xp0) + _block[4] + RMD160RoundPrime16To31, 6) + xp1;
|
||||
xp4 = RotateLeft32(xp4, 10);
|
||||
|
||||
// Round 29
|
||||
x1 = RotateLeft32(x1 + G16_31(x2, x3, x4) + _block[14] + RMD160Round16To31, 7) + x0;
|
||||
x3 = RotateLeft32(x3, 10);
|
||||
xp1 = RotateLeft32(xp1 + G48_63(xp2, xp3, xp4) + _block[9] + RMD160RoundPrime16To31, 15) + xp0;
|
||||
xp3 = RotateLeft32(xp3, 10);
|
||||
|
||||
// Round 30
|
||||
x0 = RotateLeft32(x0 + G16_31(x1, x2, x3) + _block[11] + RMD160Round16To31, 13) + x4;
|
||||
x2 = RotateLeft32(x2, 10);
|
||||
xp0 = RotateLeft32(xp0 + G48_63(xp1, xp2, xp3) + _block[1] + RMD160RoundPrime16To31, 13) + xp4;
|
||||
xp2 = RotateLeft32(xp2, 10);
|
||||
|
||||
// Round 31
|
||||
x4 = RotateLeft32(x4 + G16_31(x0, x1, x2) + _block[8] + RMD160Round16To31, 12) + x3;
|
||||
x1 = RotateLeft32(x1, 10);
|
||||
xp4 = RotateLeft32(xp4 + G48_63(xp0, xp1, xp2) + _block[2] + RMD160RoundPrime16To31, 11) + xp3;
|
||||
xp1 = RotateLeft32(xp1, 10);
|
||||
|
||||
// Swap set 2
|
||||
t = x1; x1 = xp1; xp1 = t;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Rounds 32-47
|
||||
|
||||
// Round 32
|
||||
x3 = RotateLeft32(x3 + G32_47(x4, x0, x1) + _block[3] + RMD160Round32To47, 11) + x2;
|
||||
x0 = RotateLeft32(x0, 10);
|
||||
xp3 = RotateLeft32(xp3 + G32_47(xp4, xp0, xp1) + _block[15] + RMD160RoundPrime32To47, 9) + xp2;
|
||||
xp0 = RotateLeft32(xp0, 10);
|
||||
|
||||
// Round 33
|
||||
x2 = RotateLeft32(x2 + G32_47(x3, x4, x0) + _block[10] + RMD160Round32To47, 13) + x1;
|
||||
x4 = RotateLeft32(x4, 10);
|
||||
xp2 = RotateLeft32(xp2 + G32_47(xp3, xp4, xp0) + _block[5] + RMD160RoundPrime32To47, 7) + xp1;
|
||||
xp4 = RotateLeft32(xp4, 10);
|
||||
|
||||
// Round 34
|
||||
x1 = RotateLeft32(x1 + G32_47(x2, x3, x4) + _block[14] + RMD160Round32To47, 6) + x0;
|
||||
x3 = RotateLeft32(x3, 10);
|
||||
xp1 = RotateLeft32(xp1 + G32_47(xp2, xp3, xp4) + _block[1] + RMD160RoundPrime32To47, 15) + xp0;
|
||||
xp3 = RotateLeft32(xp3, 10);
|
||||
|
||||
// Round 35
|
||||
x0 = RotateLeft32(x0 + G32_47(x1, x2, x3) + _block[4] + RMD160Round32To47, 7) + x4;
|
||||
x2 = RotateLeft32(x2, 10);
|
||||
xp0 = RotateLeft32(xp0 + G32_47(xp1, xp2, xp3) + _block[3] + RMD160RoundPrime32To47, 11) + xp4;
|
||||
xp2 = RotateLeft32(xp2, 10);
|
||||
|
||||
// Round 36
|
||||
x4 = RotateLeft32(x4 + G32_47(x0, x1, x2) + _block[9] + RMD160Round32To47, 14) + x3;
|
||||
x1 = RotateLeft32(x1, 10);
|
||||
xp4 = RotateLeft32(xp4 + G32_47(xp0, xp1, xp2) + _block[7] + RMD160RoundPrime32To47, 8) + xp3;
|
||||
xp1 = RotateLeft32(xp1, 10);
|
||||
|
||||
// Round 37
|
||||
x3 = RotateLeft32(x3 + G32_47(x4, x0, x1) + _block[15] + RMD160Round32To47, 9) + x2;
|
||||
x0 = RotateLeft32(x0, 10);
|
||||
xp3 = RotateLeft32(xp3 + G32_47(xp4, xp0, xp1) + _block[14] + RMD160RoundPrime32To47, 6) + xp2;
|
||||
xp0 = RotateLeft32(xp0, 10);
|
||||
|
||||
// Round 38
|
||||
x2 = RotateLeft32(x2 + G32_47(x3, x4, x0) + _block[8] + RMD160Round32To47, 13) + x1;
|
||||
x4 = RotateLeft32(x4, 10);
|
||||
xp2 = RotateLeft32(xp2 + G32_47(xp3, xp4, xp0) + _block[6] + RMD160RoundPrime32To47, 6) + xp1;
|
||||
xp4 = RotateLeft32(xp4, 10);
|
||||
|
||||
// Round 39
|
||||
x1 = RotateLeft32(x1 + G32_47(x2, x3, x4) + _block[1] + RMD160Round32To47, 15) + x0;
|
||||
x3 = RotateLeft32(x3, 10);
|
||||
xp1 = RotateLeft32(xp1 + G32_47(xp2, xp3, xp4) + _block[9] + RMD160RoundPrime32To47, 14) + xp0;
|
||||
xp3 = RotateLeft32(xp3, 10);
|
||||
|
||||
// Round 40
|
||||
x0 = RotateLeft32(x0 + G32_47(x1, x2, x3) + _block[2] + RMD160Round32To47, 14) + x4;
|
||||
x2 = RotateLeft32(x2, 10);
|
||||
xp0 = RotateLeft32(xp0 + G32_47(xp1, xp2, xp3) + _block[11] + RMD160RoundPrime32To47, 12) + xp4;
|
||||
xp2 = RotateLeft32(xp2, 10);
|
||||
|
||||
// Round 41
|
||||
x4 = RotateLeft32(x4 + G32_47(x0, x1, x2) + _block[7] + RMD160Round32To47, 8) + x3;
|
||||
x1 = RotateLeft32(x1, 10);
|
||||
xp4 = RotateLeft32(xp4 + G32_47(xp0, xp1, xp2) + _block[8] + RMD160RoundPrime32To47, 13) + xp3;
|
||||
xp1 = RotateLeft32(xp1, 10);
|
||||
|
||||
// Round 42
|
||||
x3 = RotateLeft32(x3 + G32_47(x4, x0, x1) + _block[0] + RMD160Round32To47, 13) + x2;
|
||||
x0 = RotateLeft32(x0, 10);
|
||||
xp3 = RotateLeft32(xp3 + G32_47(xp4, xp0, xp1) + _block[12] + RMD160RoundPrime32To47, 5) + xp2;
|
||||
xp0 = RotateLeft32(xp0, 10);
|
||||
|
||||
// Round 43
|
||||
x2 = RotateLeft32(x2 + G32_47(x3, x4, x0) + _block[6] + RMD160Round32To47, 6) + x1;
|
||||
x4 = RotateLeft32(x4, 10);
|
||||
xp2 = RotateLeft32(xp2 + G32_47(xp3, xp4, xp0) + _block[2] + RMD160RoundPrime32To47, 14) + xp1;
|
||||
xp4 = RotateLeft32(xp4, 10);
|
||||
|
||||
// Round 44
|
||||
x1 = RotateLeft32(x1 + G32_47(x2, x3, x4) + _block[13] + RMD160Round32To47, 5) + x0;
|
||||
x3 = RotateLeft32(x3, 10);
|
||||
xp1 = RotateLeft32(xp1 + G32_47(xp2, xp3, xp4) + _block[10] + RMD160RoundPrime32To47, 13) + xp0;
|
||||
xp3 = RotateLeft32(xp3, 10);
|
||||
|
||||
// Round 45
|
||||
x0 = RotateLeft32(x0 + G32_47(x1, x2, x3) + _block[11] + RMD160Round32To47, 12) + x4;
|
||||
x2 = RotateLeft32(x2, 10);
|
||||
xp0 = RotateLeft32(xp0 + G32_47(xp1, xp2, xp3) + _block[0] + RMD160RoundPrime32To47, 13) + xp4;
|
||||
xp2 = RotateLeft32(xp2, 10);
|
||||
|
||||
// Round 46
|
||||
x4 = RotateLeft32(x4 + G32_47(x0, x1, x2) + _block[5] + RMD160Round32To47, 7) + x3;
|
||||
x1 = RotateLeft32(x1, 10);
|
||||
xp4 = RotateLeft32(xp4 + G32_47(xp0, xp1, xp2) + _block[4] + RMD160RoundPrime32To47, 7) + xp3;
|
||||
xp1 = RotateLeft32(xp1, 10);
|
||||
|
||||
// Round 47
|
||||
x3 = RotateLeft32(x3 + G32_47(x4, x0, x1) + _block[12] + RMD160Round32To47, 5) + x2;
|
||||
x0 = RotateLeft32(x0, 10);
|
||||
xp3 = RotateLeft32(xp3 + G32_47(xp4, xp0, xp1) + _block[13] + RMD160RoundPrime32To47, 5) + xp2;
|
||||
xp0 = RotateLeft32(xp0, 10);
|
||||
|
||||
// Swap set 3
|
||||
t = x2; x2 = xp2; xp2 = t;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Rounds 48-63
|
||||
|
||||
// Round 48
|
||||
x2 = RotateLeft32(x2 + G48_63(x3, x4, x0) + _block[1] + RMD160Round48To63, 11) + x1;
|
||||
x4 = RotateLeft32(x4, 10);
|
||||
xp2 = RotateLeft32(xp2 + G16_31(xp3, xp4, xp0) + _block[8] + RMD160RoundPrime48To63, 15) + xp1;
|
||||
xp4 = RotateLeft32(xp4, 10);
|
||||
|
||||
// Round 49
|
||||
x1 = RotateLeft32(x1 + G48_63(x2, x3, x4) + _block[9] + RMD160Round48To63, 12) + x0;
|
||||
x3 = RotateLeft32(x3, 10);
|
||||
xp1 = RotateLeft32(xp1 + G16_31(xp2, xp3, xp4) + _block[6] + RMD160RoundPrime48To63, 5) + xp0;
|
||||
xp3 = RotateLeft32(xp3, 10);
|
||||
|
||||
// Round 50
|
||||
x0 = RotateLeft32(x0 + G48_63(x1, x2, x3) + _block[11] + RMD160Round48To63, 14) + x4;
|
||||
x2 = RotateLeft32(x2, 10);
|
||||
xp0 = RotateLeft32(xp0 + G16_31(xp1, xp2, xp3) + _block[4] + RMD160RoundPrime48To63, 8) + xp4;
|
||||
xp2 = RotateLeft32(xp2, 10);
|
||||
|
||||
// Round 51
|
||||
x4 = RotateLeft32(x4 + G48_63(x0, x1, x2) + _block[10] + RMD160Round48To63, 15) + x3;
|
||||
x1 = RotateLeft32(x1, 10);
|
||||
xp4 = RotateLeft32(xp4 + G16_31(xp0, xp1, xp2) + _block[1] + RMD160RoundPrime48To63, 11) + xp3;
|
||||
xp1 = RotateLeft32(xp1, 10);
|
||||
|
||||
// Round 52
|
||||
x3 = RotateLeft32(x3 + G48_63(x4, x0, x1) + _block[0] + RMD160Round48To63, 14) + x2;
|
||||
x0 = RotateLeft32(x0, 10);
|
||||
xp3 = RotateLeft32(xp3 + G16_31(xp4, xp0, xp1) + _block[3] + RMD160RoundPrime48To63, 14) + xp2;
|
||||
xp0 = RotateLeft32(xp0, 10);
|
||||
|
||||
// Round 53
|
||||
x2 = RotateLeft32(x2 + G48_63(x3, x4, x0) + _block[8] + RMD160Round48To63, 15) + x1;
|
||||
x4 = RotateLeft32(x4, 10);
|
||||
xp2 = RotateLeft32(xp2 + G16_31(xp3, xp4, xp0) + _block[11] + RMD160RoundPrime48To63, 14) + xp1;
|
||||
xp4 = RotateLeft32(xp4, 10);
|
||||
|
||||
// Round 54
|
||||
x1 = RotateLeft32(x1 + G48_63(x2, x3, x4) + _block[12] + RMD160Round48To63, 9) + x0;
|
||||
x3 = RotateLeft32(x3, 10);
|
||||
xp1 = RotateLeft32(xp1 + G16_31(xp2, xp3, xp4) + _block[15] + RMD160RoundPrime48To63, 6) + xp0;
|
||||
xp3 = RotateLeft32(xp3, 10);
|
||||
|
||||
// Round 55
|
||||
x0 = RotateLeft32(x0 + G48_63(x1, x2, x3) + _block[4] + RMD160Round48To63, 8) + x4;
|
||||
x2 = RotateLeft32(x2, 10);
|
||||
xp0 = RotateLeft32(xp0 + G16_31(xp1, xp2, xp3) + _block[0] + RMD160RoundPrime48To63, 14) + xp4;
|
||||
xp2 = RotateLeft32(xp2, 10);
|
||||
|
||||
// Round 56
|
||||
x4 = RotateLeft32(x4 + G48_63(x0, x1, x2) + _block[13] + RMD160Round48To63, 9) + x3;
|
||||
x1 = RotateLeft32(x1, 10);
|
||||
xp4 = RotateLeft32(xp4 + G16_31(xp0, xp1, xp2) + _block[5] + RMD160RoundPrime48To63, 6) + xp3;
|
||||
xp1 = RotateLeft32(xp1, 10);
|
||||
|
||||
// Round 57
|
||||
x3 = RotateLeft32(x3 + G48_63(x4, x0, x1) + _block[3] + RMD160Round48To63, 14) + x2;
|
||||
x0 = RotateLeft32(x0, 10);
|
||||
xp3 = RotateLeft32(xp3 + G16_31(xp4, xp0, xp1) + _block[12] + RMD160RoundPrime48To63, 9) + xp2;
|
||||
xp0 = RotateLeft32(xp0, 10);
|
||||
|
||||
// Round 58
|
||||
x2 = RotateLeft32(x2 + G48_63(x3, x4, x0) + _block[7] + RMD160Round48To63, 5) + x1;
|
||||
x4 = RotateLeft32(x4, 10);
|
||||
xp2 = RotateLeft32(xp2 + G16_31(xp3, xp4, xp0) + _block[2] + RMD160RoundPrime48To63, 12) + xp1;
|
||||
xp4 = RotateLeft32(xp4, 10);
|
||||
|
||||
// Round 59
|
||||
x1 = RotateLeft32(x1 + G48_63(x2, x3, x4) + _block[15] + RMD160Round48To63, 6) + x0;
|
||||
x3 = RotateLeft32(x3, 10);
|
||||
xp1 = RotateLeft32(xp1 + G16_31(xp2, xp3, xp4) + _block[13] + RMD160RoundPrime48To63, 9) + xp0;
|
||||
xp3 = RotateLeft32(xp3, 10);
|
||||
|
||||
// Round 60
|
||||
x0 = RotateLeft32(x0 + G48_63(x1, x2, x3) + _block[14] + RMD160Round48To63, 8) + x4;
|
||||
x2 = RotateLeft32(x2, 10);
|
||||
xp0 = RotateLeft32(xp0 + G16_31(xp1, xp2, xp3) + _block[9] + RMD160RoundPrime48To63, 12) + xp4;
|
||||
xp2 = RotateLeft32(xp2, 10);
|
||||
|
||||
// Round 61
|
||||
x4 = RotateLeft32(x4 + G48_63(x0, x1, x2) + _block[5] + RMD160Round48To63, 6) + x3;
|
||||
x1 = RotateLeft32(x1, 10);
|
||||
xp4 = RotateLeft32(xp4 + G16_31(xp0, xp1, xp2) + _block[7] + RMD160RoundPrime48To63, 5) + xp3;
|
||||
xp1 = RotateLeft32(xp1, 10);
|
||||
|
||||
// Round 62
|
||||
x3 = RotateLeft32(x3 + G48_63(x4, x0, x1) + _block[6] + RMD160Round48To63, 5) + x2;
|
||||
x0 = RotateLeft32(x0, 10);
|
||||
xp3 = RotateLeft32(xp3 + G16_31(xp4, xp0, xp1) + _block[10] + RMD160RoundPrime48To63, 15) + xp2;
|
||||
xp0 = RotateLeft32(xp0, 10);
|
||||
|
||||
// Round 63
|
||||
x2 = RotateLeft32(x2 + G48_63(x3, x4, x0) + _block[2] + RMD160Round48To63, 12) + x1;
|
||||
x4 = RotateLeft32(x4, 10);
|
||||
xp2 = RotateLeft32(xp2 + G16_31(xp3, xp4, xp0) + _block[14] + RMD160RoundPrime48To63, 8) + xp1;
|
||||
xp4 = RotateLeft32(xp4, 10);
|
||||
|
||||
// Swap set 4
|
||||
t = x3; x3 = xp3; xp3 = t;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Rounds 64-79
|
||||
|
||||
// Round 64
|
||||
x1 = RotateLeft32(x1 + G64_79(x2, x3, x4) + _block[4] + RMD160Round64To79, 9) + x0;
|
||||
x3 = RotateLeft32(x3, 10);
|
||||
xp1 = RotateLeft32(xp1 + G00_15(xp2, xp3, xp4) + _block[12] + RMD160RoundPrime64To79, 8) + xp0;
|
||||
xp3 = RotateLeft32(xp3, 10);
|
||||
|
||||
// Round 65
|
||||
x0 = RotateLeft32(x0 + G64_79(x1, x2, x3) + _block[0] + RMD160Round64To79, 15) + x4;
|
||||
x2 = RotateLeft32(x2, 10);
|
||||
xp0 = RotateLeft32(xp0 + G00_15(xp1, xp2, xp3) + _block[15] + RMD160RoundPrime64To79, 5) + xp4;
|
||||
xp2 = RotateLeft32(xp2, 10);
|
||||
|
||||
// Round 66
|
||||
x4 = RotateLeft32(x4 + G64_79(x0, x1, x2) + _block[5] + RMD160Round64To79, 5) + x3;
|
||||
x1 = RotateLeft32(x1, 10);
|
||||
xp4 = RotateLeft32(xp4 + G00_15(xp0, xp1, xp2) + _block[10] + RMD160RoundPrime64To79, 12) + xp3;
|
||||
xp1 = RotateLeft32(xp1, 10);
|
||||
|
||||
// Round 67
|
||||
x3 = RotateLeft32(x3 + G64_79(x4, x0, x1) + _block[9] + RMD160Round64To79, 11) + x2;
|
||||
x0 = RotateLeft32(x0, 10);
|
||||
xp3 = RotateLeft32(xp3 + G00_15(xp4, xp0, xp1) + _block[4] + RMD160RoundPrime64To79, 9) + xp2;
|
||||
xp0 = RotateLeft32(xp0, 10);
|
||||
|
||||
// Round 68
|
||||
x2 = RotateLeft32(x2 + G64_79(x3, x4, x0) + _block[7] + RMD160Round64To79, 6) + x1;
|
||||
x4 = RotateLeft32(x4, 10);
|
||||
xp2 = RotateLeft32(xp2 + G00_15(xp3, xp4, xp0) + _block[1] + RMD160RoundPrime64To79, 12) + xp1;
|
||||
xp4 = RotateLeft32(xp4, 10);
|
||||
|
||||
// Round 69
|
||||
x1 = RotateLeft32(x1 + G64_79(x2, x3, x4) + _block[12] + RMD160Round64To79, 8) + x0;
|
||||
x3 = RotateLeft32(x3, 10);
|
||||
xp1 = RotateLeft32(xp1 + G00_15(xp2, xp3, xp4) + _block[5] + RMD160RoundPrime64To79, 5) + xp0;
|
||||
xp3 = RotateLeft32(xp3, 10);
|
||||
|
||||
// Round 70
|
||||
x0 = RotateLeft32(x0 + G64_79(x1, x2, x3) + _block[2] + RMD160Round64To79, 13) + x4;
|
||||
x2 = RotateLeft32(x2, 10);
|
||||
xp0 = RotateLeft32(xp0 + G00_15(xp1, xp2, xp3) + _block[8] + RMD160RoundPrime64To79, 14) + xp4;
|
||||
xp2 = RotateLeft32(xp2, 10);
|
||||
|
||||
// Round 71
|
||||
x4 = RotateLeft32(x4 + G64_79(x0, x1, x2) + _block[10] + RMD160Round64To79, 12) + x3;
|
||||
x1 = RotateLeft32(x1, 10);
|
||||
xp4 = RotateLeft32(xp4 + G00_15(xp0, xp1, xp2) + _block[7] + RMD160RoundPrime64To79, 6) + xp3;
|
||||
xp1 = RotateLeft32(xp1, 10);
|
||||
|
||||
// Round 72
|
||||
x3 = RotateLeft32(x3 + G64_79(x4, x0, x1) + _block[14] + RMD160Round64To79, 5) + x2;
|
||||
x0 = RotateLeft32(x0, 10);
|
||||
xp3 = RotateLeft32(xp3 + G00_15(xp4, xp0, xp1) + _block[6] + RMD160RoundPrime64To79, 8) + xp2;
|
||||
xp0 = RotateLeft32(xp0, 10);
|
||||
|
||||
// Round 73
|
||||
x2 = RotateLeft32(x2 + G64_79(x3, x4, x0) + _block[1] + RMD160Round64To79, 12) + x1;
|
||||
x4 = RotateLeft32(x4, 10);
|
||||
xp2 = RotateLeft32(xp2 + G00_15(xp3, xp4, xp0) + _block[2] + RMD160RoundPrime64To79, 13) + xp1;
|
||||
xp4 = RotateLeft32(xp4, 10);
|
||||
|
||||
// Round 74
|
||||
x1 = RotateLeft32(x1 + G64_79(x2, x3, x4) + _block[3] + RMD160Round64To79, 13) + x0;
|
||||
x3 = RotateLeft32(x3, 10);
|
||||
xp1 = RotateLeft32(xp1 + G00_15(xp2, xp3, xp4) + _block[13] + RMD160RoundPrime64To79, 6) + xp0;
|
||||
xp3 = RotateLeft32(xp3, 10);
|
||||
|
||||
// Round 75
|
||||
x0 = RotateLeft32(x0 + G64_79(x1, x2, x3) + _block[8] + RMD160Round64To79, 14) + x4;
|
||||
x2 = RotateLeft32(x2, 10);
|
||||
xp0 = RotateLeft32(xp0 + G00_15(xp1, xp2, xp3) + _block[14] + RMD160RoundPrime64To79, 5) + xp4;
|
||||
xp2 = RotateLeft32(xp2, 10);
|
||||
|
||||
// Round 76
|
||||
x4 = RotateLeft32(x4 + G64_79(x0, x1, x2) + _block[11] + RMD160Round64To79, 11) + x3;
|
||||
x1 = RotateLeft32(x1, 10);
|
||||
xp4 = RotateLeft32(xp4 + G00_15(xp0, xp1, xp2) + _block[0] + RMD160RoundPrime64To79, 15) + xp3;
|
||||
xp1 = RotateLeft32(xp1, 10);
|
||||
|
||||
// Round 77
|
||||
x3 = RotateLeft32(x3 + G64_79(x4, x0, x1) + _block[6] + RMD160Round64To79, 8) + x2;
|
||||
x0 = RotateLeft32(x0, 10);
|
||||
xp3 = RotateLeft32(xp3 + G00_15(xp4, xp0, xp1) + _block[3] + RMD160RoundPrime64To79, 13) + xp2;
|
||||
xp0 = RotateLeft32(xp0, 10);
|
||||
|
||||
// Round 78
|
||||
x2 = RotateLeft32(x2 + G64_79(x3, x4, x0) + _block[15] + RMD160Round64To79, 5) + x1;
|
||||
x4 = RotateLeft32(x4, 10);
|
||||
xp2 = RotateLeft32(xp2 + G00_15(xp3, xp4, xp0) + _block[9] + RMD160RoundPrime64To79, 11) + xp1;
|
||||
xp4 = RotateLeft32(xp4, 10);
|
||||
|
||||
// Round 79
|
||||
x1 = RotateLeft32(x1 + G64_79(x2, x3, x4) + _block[13] + RMD160Round64To79, 6) + x0;
|
||||
x3 = RotateLeft32(x3, 10);
|
||||
xp1 = RotateLeft32(xp1 + G00_15(xp2, xp3, xp4) + _block[11] + RMD160RoundPrime64To79, 11) + xp0;
|
||||
xp3 = RotateLeft32(xp3, 10);
|
||||
|
||||
// Swap set 5
|
||||
t = x4; x4 = xp4; xp4 = t;
|
||||
|
||||
#endregion
|
||||
|
||||
// Avalanche values
|
||||
_state[0] += x0;
|
||||
_state[1] += x1;
|
||||
_state[2] += x2;
|
||||
_state[3] += x3;
|
||||
_state[4] += x4;
|
||||
_state[5] += xp0;
|
||||
_state[6] += xp1;
|
||||
_state[7] += xp2;
|
||||
_state[8] += xp3;
|
||||
_state[9] += xp4;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Round operation [0, 15]
|
||||
/// </summary>
|
||||
private static uint G00_15(uint x, uint y, uint z) => x ^ y ^ z;
|
||||
|
||||
/// <summary>
|
||||
/// Round operation [16, 31]
|
||||
/// </summary>
|
||||
private static uint G16_31(uint x, uint y, uint z) => (x & y) | (~x & z);
|
||||
|
||||
/// <summary>
|
||||
/// Round operation [32, 47]
|
||||
/// </summary>
|
||||
private static uint G32_47(uint x, uint y, uint z) => (x | ~y) ^ z;
|
||||
|
||||
/// <summary>
|
||||
/// Round operation [48, 63]
|
||||
/// </summary>
|
||||
private static uint G48_63(uint x, uint y, uint z) => (x & z) | (y & ~z);
|
||||
|
||||
/// <summary>
|
||||
/// Round operation [64, 79]
|
||||
/// </summary>
|
||||
private static uint G64_79(uint x, uint y, uint z) => x ^ (y | ~z);
|
||||
}
|
||||
}
|
||||
25
SabreTools.Hashing/MessageDigest/Tiger128_3.cs
Normal file
25
SabreTools.Hashing/MessageDigest/Tiger128_3.cs
Normal file
@@ -0,0 +1,25 @@
|
||||
using System;
|
||||
|
||||
namespace SabreTools.Hashing.MessageDigest
|
||||
{
|
||||
/// <summary>
|
||||
/// 3-pass variant of Tiger-128
|
||||
/// </summary>
|
||||
public class Tiger128_3 : TigerHashBase
|
||||
{
|
||||
public Tiger128_3() : base()
|
||||
{
|
||||
_passes = 3;
|
||||
_padStart = 0x01;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override byte[] GetHash()
|
||||
{
|
||||
byte[] hash = base.GetHash();
|
||||
byte[] trimmedHash = new byte[16];
|
||||
Array.Copy(hash, trimmedHash, 16);
|
||||
return trimmedHash;
|
||||
}
|
||||
}
|
||||
}
|
||||
25
SabreTools.Hashing/MessageDigest/Tiger128_4.cs
Normal file
25
SabreTools.Hashing/MessageDigest/Tiger128_4.cs
Normal file
@@ -0,0 +1,25 @@
|
||||
using System;
|
||||
|
||||
namespace SabreTools.Hashing.MessageDigest
|
||||
{
|
||||
/// <summary>
|
||||
/// 4-pass variant of Tiger-128
|
||||
/// </summary>
|
||||
public class Tiger128_4 : TigerHashBase
|
||||
{
|
||||
public Tiger128_4() : base()
|
||||
{
|
||||
_passes = 4;
|
||||
_padStart = 0x01;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override byte[] GetHash()
|
||||
{
|
||||
byte[] hash = base.GetHash();
|
||||
byte[] trimmedHash = new byte[16];
|
||||
Array.Copy(hash, trimmedHash, 16);
|
||||
return trimmedHash;
|
||||
}
|
||||
}
|
||||
}
|
||||
25
SabreTools.Hashing/MessageDigest/Tiger160_3.cs
Normal file
25
SabreTools.Hashing/MessageDigest/Tiger160_3.cs
Normal file
@@ -0,0 +1,25 @@
|
||||
using System;
|
||||
|
||||
namespace SabreTools.Hashing.MessageDigest
|
||||
{
|
||||
/// <summary>
|
||||
/// 3-pass variant of Tiger-160
|
||||
/// </summary>
|
||||
public class Tiger160_3 : TigerHashBase
|
||||
{
|
||||
public Tiger160_3() : base()
|
||||
{
|
||||
_passes = 3;
|
||||
_padStart = 0x01;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override byte[] GetHash()
|
||||
{
|
||||
byte[] hash = base.GetHash();
|
||||
byte[] trimmedHash = new byte[20];
|
||||
Array.Copy(hash, trimmedHash, 20);
|
||||
return trimmedHash;
|
||||
}
|
||||
}
|
||||
}
|
||||
25
SabreTools.Hashing/MessageDigest/Tiger160_4.cs
Normal file
25
SabreTools.Hashing/MessageDigest/Tiger160_4.cs
Normal file
@@ -0,0 +1,25 @@
|
||||
using System;
|
||||
|
||||
namespace SabreTools.Hashing.MessageDigest
|
||||
{
|
||||
/// <summary>
|
||||
/// 4-pass variant of Tiger-160
|
||||
/// </summary>
|
||||
public class Tiger160_4 : TigerHashBase
|
||||
{
|
||||
public Tiger160_4() : base()
|
||||
{
|
||||
_passes = 4;
|
||||
_padStart = 0x01;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override byte[] GetHash()
|
||||
{
|
||||
byte[] hash = base.GetHash();
|
||||
byte[] trimmedHash = new byte[20];
|
||||
Array.Copy(hash, trimmedHash, 20);
|
||||
return trimmedHash;
|
||||
}
|
||||
}
|
||||
}
|
||||
14
SabreTools.Hashing/MessageDigest/Tiger192_3.cs
Normal file
14
SabreTools.Hashing/MessageDigest/Tiger192_3.cs
Normal file
@@ -0,0 +1,14 @@
|
||||
namespace SabreTools.Hashing.MessageDigest
|
||||
{
|
||||
/// <summary>
|
||||
/// 3-pass variant of Tiger-192
|
||||
/// </summary>
|
||||
public class Tiger192_3 : TigerHashBase
|
||||
{
|
||||
public Tiger192_3() : base()
|
||||
{
|
||||
_passes = 3;
|
||||
_padStart = 0x01;
|
||||
}
|
||||
}
|
||||
}
|
||||
14
SabreTools.Hashing/MessageDigest/Tiger192_4.cs
Normal file
14
SabreTools.Hashing/MessageDigest/Tiger192_4.cs
Normal file
@@ -0,0 +1,14 @@
|
||||
namespace SabreTools.Hashing.MessageDigest
|
||||
{
|
||||
/// <summary>
|
||||
/// 4-pass variant of Tiger-192
|
||||
/// </summary>
|
||||
public class Tiger192_4 : TigerHashBase
|
||||
{
|
||||
public Tiger192_4() : base()
|
||||
{
|
||||
_passes = 4;
|
||||
_padStart = 0x01;
|
||||
}
|
||||
}
|
||||
}
|
||||
25
SabreTools.Hashing/MessageDigest/Tiger2_128_3.cs
Normal file
25
SabreTools.Hashing/MessageDigest/Tiger2_128_3.cs
Normal file
@@ -0,0 +1,25 @@
|
||||
using System;
|
||||
|
||||
namespace SabreTools.Hashing.MessageDigest
|
||||
{
|
||||
/// <summary>
|
||||
/// 3-pass variant of Tiger2-128
|
||||
/// </summary>
|
||||
public class Tiger2_128_3 : TigerHashBase
|
||||
{
|
||||
public Tiger2_128_3() : base()
|
||||
{
|
||||
_passes = 3;
|
||||
_padStart = 0x80;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override byte[] GetHash()
|
||||
{
|
||||
byte[] hash = base.GetHash();
|
||||
byte[] trimmedHash = new byte[16];
|
||||
Array.Copy(hash, trimmedHash, 16);
|
||||
return trimmedHash;
|
||||
}
|
||||
}
|
||||
}
|
||||
25
SabreTools.Hashing/MessageDigest/Tiger2_128_4.cs
Normal file
25
SabreTools.Hashing/MessageDigest/Tiger2_128_4.cs
Normal file
@@ -0,0 +1,25 @@
|
||||
using System;
|
||||
|
||||
namespace SabreTools.Hashing.MessageDigest
|
||||
{
|
||||
/// <summary>
|
||||
/// 4-pass variant of Tiger2-128
|
||||
/// </summary>
|
||||
public class Tiger2_128_4 : TigerHashBase
|
||||
{
|
||||
public Tiger2_128_4() : base()
|
||||
{
|
||||
_passes = 4;
|
||||
_padStart = 0x80;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override byte[] GetHash()
|
||||
{
|
||||
byte[] hash = base.GetHash();
|
||||
byte[] trimmedHash = new byte[16];
|
||||
Array.Copy(hash, trimmedHash, 16);
|
||||
return trimmedHash;
|
||||
}
|
||||
}
|
||||
}
|
||||
25
SabreTools.Hashing/MessageDigest/Tiger2_160_3.cs
Normal file
25
SabreTools.Hashing/MessageDigest/Tiger2_160_3.cs
Normal file
@@ -0,0 +1,25 @@
|
||||
using System;
|
||||
|
||||
namespace SabreTools.Hashing.MessageDigest
|
||||
{
|
||||
/// <summary>
|
||||
/// 3-pass variant of Tiger2-160
|
||||
/// </summary>
|
||||
public class Tiger2_160_3 : TigerHashBase
|
||||
{
|
||||
public Tiger2_160_3() : base()
|
||||
{
|
||||
_passes = 3;
|
||||
_padStart = 0x80;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override byte[] GetHash()
|
||||
{
|
||||
byte[] hash = base.GetHash();
|
||||
byte[] trimmedHash = new byte[20];
|
||||
Array.Copy(hash, trimmedHash, 20);
|
||||
return trimmedHash;
|
||||
}
|
||||
}
|
||||
}
|
||||
25
SabreTools.Hashing/MessageDigest/Tiger2_160_4.cs
Normal file
25
SabreTools.Hashing/MessageDigest/Tiger2_160_4.cs
Normal file
@@ -0,0 +1,25 @@
|
||||
using System;
|
||||
|
||||
namespace SabreTools.Hashing.MessageDigest
|
||||
{
|
||||
/// <summary>
|
||||
/// 4-pass variant of Tiger2-160
|
||||
/// </summary>
|
||||
public class Tiger2_160_4 : TigerHashBase
|
||||
{
|
||||
public Tiger2_160_4() : base()
|
||||
{
|
||||
_passes = 4;
|
||||
_padStart = 0x80;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override byte[] GetHash()
|
||||
{
|
||||
byte[] hash = base.GetHash();
|
||||
byte[] trimmedHash = new byte[20];
|
||||
Array.Copy(hash, trimmedHash, 20);
|
||||
return trimmedHash;
|
||||
}
|
||||
}
|
||||
}
|
||||
14
SabreTools.Hashing/MessageDigest/Tiger2_192_3.cs
Normal file
14
SabreTools.Hashing/MessageDigest/Tiger2_192_3.cs
Normal file
@@ -0,0 +1,14 @@
|
||||
namespace SabreTools.Hashing.MessageDigest
|
||||
{
|
||||
/// <summary>
|
||||
/// 3-pass variant of Tiger2-192
|
||||
/// </summary>
|
||||
public class Tiger2_192_3 : TigerHashBase
|
||||
{
|
||||
public Tiger2_192_3() : base()
|
||||
{
|
||||
_passes = 3;
|
||||
_padStart = 0x80;
|
||||
}
|
||||
}
|
||||
}
|
||||
14
SabreTools.Hashing/MessageDigest/Tiger2_192_4.cs
Normal file
14
SabreTools.Hashing/MessageDigest/Tiger2_192_4.cs
Normal file
@@ -0,0 +1,14 @@
|
||||
namespace SabreTools.Hashing.MessageDigest
|
||||
{
|
||||
/// <summary>
|
||||
/// 4-pass variant of Tiger2-192
|
||||
/// </summary>
|
||||
public class Tiger2_192_4 : TigerHashBase
|
||||
{
|
||||
public Tiger2_192_4() : base()
|
||||
{
|
||||
_passes = 4;
|
||||
_padStart = 0x80;
|
||||
}
|
||||
}
|
||||
}
|
||||
242
SabreTools.Hashing/MessageDigest/TigerHashBase.cs
Normal file
242
SabreTools.Hashing/MessageDigest/TigerHashBase.cs
Normal file
@@ -0,0 +1,242 @@
|
||||
using System;
|
||||
using static SabreTools.Hashing.HashOperations;
|
||||
using static SabreTools.Hashing.MessageDigest.Constants;
|
||||
|
||||
namespace SabreTools.Hashing.MessageDigest
|
||||
{
|
||||
/// <see href="https://biham.cs.technion.ac.il/Reports/Tiger//>
|
||||
public abstract class TigerHashBase : MessageDigestBase<ulong>
|
||||
{
|
||||
/// <summary>
|
||||
/// Number of passes (minimum 3)
|
||||
/// </summary>
|
||||
protected int _passes;
|
||||
|
||||
/// <summary>
|
||||
/// Byte to start padding with
|
||||
/// </summary>
|
||||
protected byte _padStart;
|
||||
|
||||
/// <summary>
|
||||
/// Set of 3 64-bit numbers representing the hash state
|
||||
/// </summary>
|
||||
private readonly ulong[] _state = new ulong[3];
|
||||
|
||||
public TigerHashBase() : base()
|
||||
{
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
protected override void ResetImpl()
|
||||
{
|
||||
_state[0] = TigerSeedA;
|
||||
_state[1] = TigerSeedB;
|
||||
_state[2] = TigerSeedC;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override void TransformBlock(byte[] data, int offset, int length)
|
||||
{
|
||||
// Figure out how much buffer is needed
|
||||
int bufferLen = (int)(_totalBytes & 0x3f);
|
||||
|
||||
// Increment the processed byte count
|
||||
_totalBytes += length;
|
||||
|
||||
// If there is buffer to fill and it will meet the limit
|
||||
if (bufferLen > 0 && bufferLen + length >= 64)
|
||||
{
|
||||
// Fill the buffer from the input
|
||||
Array.Copy(data, offset, _buffer, bufferLen, 64 - bufferLen);
|
||||
|
||||
// Set the new values
|
||||
offset += 64 - bufferLen;
|
||||
length -= 64 - bufferLen;
|
||||
|
||||
// Split the buffer for the round
|
||||
for (int i = 0; i < 8; i++)
|
||||
{
|
||||
_block[i] = ReadLE64(_buffer, i * 8);
|
||||
}
|
||||
|
||||
// Run the round
|
||||
Compress();
|
||||
bufferLen = 0;
|
||||
}
|
||||
|
||||
/// Process any standalone blocks
|
||||
while (length >= 64)
|
||||
{
|
||||
// Fill the buffer from the input
|
||||
Array.Copy(data, offset, _buffer, 0, 64);
|
||||
|
||||
// Set the new values
|
||||
offset += 64;
|
||||
length -= 64;
|
||||
|
||||
// Split the buffer for the round
|
||||
for (int i = 0; i < 8; i++)
|
||||
{
|
||||
_block[i] = ReadLE64(_buffer, i * 8);
|
||||
}
|
||||
|
||||
// Run the round
|
||||
Compress();
|
||||
}
|
||||
|
||||
// Save the remainder in the buffer
|
||||
if (length > 0)
|
||||
Array.Copy(data, offset, _buffer, bufferLen, length);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override void Terminate()
|
||||
{
|
||||
// Determine the pad length
|
||||
int padLength = 64 - (int)(_totalBytes & 0x3f);
|
||||
if (padLength <= 8)
|
||||
padLength += 64;
|
||||
|
||||
// Get the total byte count in bits
|
||||
long totalBitCount = _totalBytes * 8;
|
||||
|
||||
// Prebuild the padding
|
||||
var padding = new byte[padLength];
|
||||
padding[0] = _padStart;
|
||||
padding[padLength - 1] = (byte)((totalBitCount >> 56) & 0xff);
|
||||
padding[padLength - 2] = (byte)((totalBitCount >> 48) & 0xff);
|
||||
padding[padLength - 3] = (byte)((totalBitCount >> 40) & 0xff);
|
||||
padding[padLength - 4] = (byte)((totalBitCount >> 32) & 0xff);
|
||||
padding[padLength - 5] = (byte)((totalBitCount >> 24) & 0xff);
|
||||
padding[padLength - 6] = (byte)((totalBitCount >> 16) & 0xff);
|
||||
padding[padLength - 7] = (byte)((totalBitCount >> 8) & 0xff);
|
||||
padding[padLength - 8] = (byte)((totalBitCount >> 0) & 0xff);
|
||||
|
||||
// Pad the block
|
||||
TransformBlock(padding, 0, padding.Length);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override byte[] GetHash()
|
||||
{
|
||||
var hash = new byte[24];
|
||||
int hashOffset = 0;
|
||||
|
||||
// Assemble the hash array
|
||||
for (int i = 0; i < _state.Length; i++)
|
||||
{
|
||||
byte[] segment = BitConverter.GetBytes(_state[i]);
|
||||
Array.Copy(segment, 0, hash, hashOffset, 8);
|
||||
hashOffset += 8;
|
||||
}
|
||||
|
||||
// Reset the state and return
|
||||
Reset();
|
||||
return hash;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Perform one round of updates on the cached values
|
||||
/// </summary>
|
||||
private void Compress()
|
||||
{
|
||||
// Save current values [save_abc]
|
||||
ulong aa = _state[0];
|
||||
ulong bb = _state[1];
|
||||
ulong cc = _state[2];
|
||||
|
||||
// Pass 1 [pass(a, b, c, 5)]
|
||||
Pass(ref _state[0], ref _state[1], ref _state[2], 5);
|
||||
|
||||
// Avalanche [key_schedule]
|
||||
KeySchedule();
|
||||
|
||||
// Pass 2 [pass(c, a, b, 7)]
|
||||
Pass(ref _state[2], ref _state[0], ref _state[1], 7);
|
||||
|
||||
// Avalanche [key_schedule]
|
||||
KeySchedule();
|
||||
|
||||
// Pass 3 [pass(b, c, a, 9)]
|
||||
Pass(ref _state[1], ref _state[2], ref _state[0], 9);
|
||||
|
||||
// Perform correct set of extra passes
|
||||
for (int pass_no = 3; pass_no < _passes; pass_no++)
|
||||
{
|
||||
// Avalanche [key_schedule]
|
||||
KeySchedule();
|
||||
|
||||
// Pass N [pass(a, b, c, 9)]
|
||||
Pass(ref _state[0], ref _state[1], ref _state[2], 9);
|
||||
|
||||
// Rotate
|
||||
ulong tmpa = _state[0];
|
||||
_state[0] = _state[2];
|
||||
_state[2] = _state[1];
|
||||
_state[1] = tmpa;
|
||||
}
|
||||
|
||||
// Update stored values [feedforward]
|
||||
_state[0] ^= aa;
|
||||
_state[1] -= bb;
|
||||
_state[2] += cc;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// pass(a,b,c,mul)
|
||||
/// </summary>
|
||||
private void Pass(ref ulong a, ref ulong b, ref ulong c, int mul)
|
||||
{
|
||||
Round(ref a, ref b, ref c, _block[0], mul);
|
||||
Round(ref b, ref c, ref a, _block[1], mul);
|
||||
Round(ref c, ref a, ref b, _block[2], mul);
|
||||
Round(ref a, ref b, ref c, _block[3], mul);
|
||||
Round(ref b, ref c, ref a, _block[4], mul);
|
||||
Round(ref c, ref a, ref b, _block[5], mul);
|
||||
Round(ref a, ref b, ref c, _block[6], mul);
|
||||
Round(ref b, ref c, ref a, _block[7], mul);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// round(a,b,c,x,mul)
|
||||
/// </summary>
|
||||
private static void Round(ref ulong a, ref ulong b, ref ulong c, ulong x, int mul)
|
||||
{
|
||||
c ^= x;
|
||||
|
||||
a -= TigerSBox[((c >> (0 * 8)) & 0xFF) + (0 * 256)]
|
||||
^ TigerSBox[((c >> (2 * 8)) & 0xFF) + (1 * 256)]
|
||||
^ TigerSBox[((c >> (4 * 8)) & 0xFF) + (2 * 256)]
|
||||
^ TigerSBox[((c >> (6 * 8)) & 0xFF) + (3 * 256)];
|
||||
b += TigerSBox[((c >> (1 * 8)) & 0xFF) + (3 * 256)]
|
||||
^ TigerSBox[((c >> (3 * 8)) & 0xFF) + (2 * 256)]
|
||||
^ TigerSBox[((c >> (5 * 8)) & 0xFF) + (1 * 256)]
|
||||
^ TigerSBox[((c >> (7 * 8)) & 0xFF) + (0 * 256)];
|
||||
|
||||
unchecked { b *= (ulong)mul; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// key_schedule
|
||||
/// </summary>
|
||||
private void KeySchedule()
|
||||
{
|
||||
_block[0] -= _block[7] ^ 0xA5A5A5A5A5A5A5A5;
|
||||
_block[1] ^= _block[0];
|
||||
_block[2] += _block[1];
|
||||
_block[3] -= _block[2] ^ ((~_block[1]) << 19);
|
||||
_block[4] ^= _block[3];
|
||||
_block[5] += _block[4];
|
||||
_block[6] -= _block[5] ^ ((~_block[4]) >> 23);
|
||||
_block[7] ^= _block[6];
|
||||
_block[0] += _block[7];
|
||||
_block[1] -= _block[0] ^ ((~_block[7]) << 19);
|
||||
_block[2] ^= _block[1];
|
||||
_block[3] += _block[2];
|
||||
_block[4] -= _block[3] ^ ((~_block[2]) >> 23);
|
||||
_block[5] ^= _block[4];
|
||||
_block[6] += _block[5];
|
||||
_block[7] -= _block[6] ^ 0x0123456789ABCDEF;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,153 +0,0 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2012-2015 Eugene Larchenko (spct@mail.ru)
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
|
||||
*/
|
||||
|
||||
using System;
|
||||
|
||||
namespace OptimizedCRC
|
||||
{
|
||||
internal class OptimizedCRC : IDisposable
|
||||
{
|
||||
private const uint kCrcPoly = 0xEDB88320;
|
||||
private const uint kInitial = 0xFFFFFFFF;
|
||||
private const int CRC_NUM_TABLES = 8;
|
||||
private static readonly uint[] Table;
|
||||
|
||||
static OptimizedCRC()
|
||||
{
|
||||
unchecked
|
||||
{
|
||||
Table = new uint[256 * CRC_NUM_TABLES];
|
||||
int i;
|
||||
for (i = 0; i < 256; i++)
|
||||
{
|
||||
uint r = (uint)i;
|
||||
for (int j = 0; j < 8; j++)
|
||||
{
|
||||
r = (r >> 1) ^ (kCrcPoly & ~((r & 1) - 1));
|
||||
}
|
||||
Table[i] = r;
|
||||
}
|
||||
for (; i < 256 * CRC_NUM_TABLES; i++)
|
||||
{
|
||||
uint r = Table[i - 256];
|
||||
Table[i] = Table[r & 0xFF] ^ (r >> 8);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public uint UnsignedValue;
|
||||
|
||||
public OptimizedCRC()
|
||||
{
|
||||
Init();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reset CRC
|
||||
/// </summary>
|
||||
public void Init()
|
||||
{
|
||||
UnsignedValue = kInitial;
|
||||
}
|
||||
|
||||
public int Value
|
||||
{
|
||||
get { return (int)~UnsignedValue; }
|
||||
}
|
||||
|
||||
public void Update(byte[] data, int offset, int count)
|
||||
{
|
||||
new ArraySegment<byte>(data, offset, count); // check arguments
|
||||
if (count == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var table = OptimizedCRC.Table;
|
||||
|
||||
uint crc = UnsignedValue;
|
||||
|
||||
for (; (offset & 7) != 0 && count != 0; count--)
|
||||
{
|
||||
crc = (crc >> 8) ^ table[(byte)crc ^ data[offset++]];
|
||||
}
|
||||
|
||||
if (count >= 8)
|
||||
{
|
||||
/*
|
||||
* Idea from 7-zip project sources (http://7-zip.org/sdk.html)
|
||||
*/
|
||||
|
||||
int end = (count - 8) & ~7;
|
||||
count -= end;
|
||||
end += offset;
|
||||
|
||||
while (offset != end)
|
||||
{
|
||||
crc ^= (uint)(data[offset] + (data[offset + 1] << 8) + (data[offset + 2] << 16) + (data[offset + 3] << 24));
|
||||
uint high = (uint)(data[offset + 4] + (data[offset + 5] << 8) + (data[offset + 6] << 16) + (data[offset + 7] << 24));
|
||||
offset += 8;
|
||||
|
||||
crc = table[(byte)crc + 0x700]
|
||||
^ table[(byte)(crc >>= 8) + 0x600]
|
||||
^ table[(byte)(crc >>= 8) + 0x500]
|
||||
^ table[/*(byte)*/(crc >> 8) + 0x400]
|
||||
^ table[(byte)(high) + 0x300]
|
||||
^ table[(byte)(high >>= 8) + 0x200]
|
||||
^ table[(byte)(high >>= 8) + 0x100]
|
||||
^ table[/*(byte)*/(high >> 8) + 0x000];
|
||||
}
|
||||
}
|
||||
|
||||
while (count-- != 0)
|
||||
{
|
||||
crc = (crc >> 8) ^ table[(byte)crc ^ data[offset++]];
|
||||
}
|
||||
|
||||
UnsignedValue = crc;
|
||||
}
|
||||
|
||||
static public int Compute(byte[] data, int offset, int count)
|
||||
{
|
||||
var crc = new OptimizedCRC();
|
||||
crc.Update(data, offset, count);
|
||||
return crc.Value;
|
||||
}
|
||||
|
||||
static public int Compute(byte[] data)
|
||||
{
|
||||
return Compute(data, 0, data.Length);
|
||||
}
|
||||
|
||||
static public int Compute(ArraySegment<byte> block)
|
||||
{
|
||||
return Compute(block.Array!, block.Offset, block.Count);
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
UnsignedValue = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,46 +1,51 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<!-- Assembly Properties -->
|
||||
<TargetFrameworks>net20;net35;net40;net452;net462;net472;net48;netcoreapp3.1;net5.0;net6.0;net7.0;net8.0</TargetFrameworks>
|
||||
<RuntimeIdentifiers>win-x86;win-x64;win-arm64;linux-x64;linux-arm64;osx-x64</RuntimeIdentifiers>
|
||||
<CheckEolTargetFramework>false</CheckEolTargetFramework>
|
||||
<IncludeSourceRevisionInInformationalVersion>false</IncludeSourceRevisionInInformationalVersion>
|
||||
<LangVersion>latest</LangVersion>
|
||||
<Nullable>enable</Nullable>
|
||||
<SuppressTfmSupportBuildWarnings>true</SuppressTfmSupportBuildWarnings>
|
||||
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
|
||||
<Version>1.1.4</Version>
|
||||
<PropertyGroup>
|
||||
<!-- Assembly Properties -->
|
||||
<TargetFrameworks>net20;net35;net40;net452;net462;net472;net48;netcoreapp3.1;net5.0;net6.0;net7.0;net8.0;net9.0</TargetFrameworks>
|
||||
<CheckEolTargetFramework>false</CheckEolTargetFramework>
|
||||
<IncludeSourceRevisionInInformationalVersion>false</IncludeSourceRevisionInInformationalVersion>
|
||||
<LangVersion>latest</LangVersion>
|
||||
<Nullable>enable</Nullable>
|
||||
<SuppressTfmSupportBuildWarnings>true</SuppressTfmSupportBuildWarnings>
|
||||
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
|
||||
<Version>1.4.0</Version>
|
||||
|
||||
<!-- Package Properties -->
|
||||
<Authors>Matt Nadareski</Authors>
|
||||
<Copyright>Copyright (c)2016-2024 Matt Nadareski</Copyright>
|
||||
<PackageProjectUrl>https://github.com/SabreTools/</PackageProjectUrl>
|
||||
<PackageReadmeFile>README.md</PackageReadmeFile>
|
||||
<RepositoryUrl>https://github.com/SabreTools/SabreTools.Hashing</RepositoryUrl>
|
||||
<RepositoryType>git</RepositoryType>
|
||||
<PackageTags>hash hashing checksum checksumming crc md5 sha1</PackageTags>
|
||||
<PackageLicenseExpression>MIT</PackageLicenseExpression>
|
||||
</PropertyGroup>
|
||||
<!-- Package Properties -->
|
||||
<Authors>Matt Nadareski</Authors>
|
||||
<Copyright>Copyright (c)2016-2024 Matt Nadareski</Copyright>
|
||||
<PackageProjectUrl>https://github.com/SabreTools/</PackageProjectUrl>
|
||||
<PackageReadmeFile>README.md</PackageReadmeFile>
|
||||
<RepositoryUrl>https://github.com/SabreTools/SabreTools.Hashing</RepositoryUrl>
|
||||
<RepositoryType>git</RepositoryType>
|
||||
<PackageTags>hash hashing checksum checksumming crc md5 sha1</PackageTags>
|
||||
<PackageLicenseExpression>MIT</PackageLicenseExpression>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<None Include="../README.md" Pack="true" PackagePath="" />
|
||||
</ItemGroup>
|
||||
<!-- Support All Frameworks -->
|
||||
<PropertyGroup Condition="$(TargetFramework.StartsWith(`net2`)) OR $(TargetFramework.StartsWith(`net3`)) OR $(TargetFramework.StartsWith(`net4`))">
|
||||
<RuntimeIdentifiers>win-x86;win-x64</RuntimeIdentifiers>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="$(TargetFramework.StartsWith(`netcoreapp`)) OR $(TargetFramework.StartsWith(`net5`))">
|
||||
<RuntimeIdentifiers>win-x86;win-x64;win-arm64;linux-x64;linux-arm64;osx-x64</RuntimeIdentifiers>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="$(TargetFramework.StartsWith(`net6`)) OR $(TargetFramework.StartsWith(`net7`)) OR $(TargetFramework.StartsWith(`net8`)) OR $(TargetFramework.StartsWith(`net9`))">
|
||||
<RuntimeIdentifiers>win-x86;win-x64;win-arm64;linux-x64;linux-arm64;osx-x64;osx-arm64</RuntimeIdentifiers>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="$(RuntimeIdentifier.StartsWith(`osx-arm`))">
|
||||
<TargetFrameworks>net6.0;net7.0;net8.0;net9.0</TargetFrameworks>
|
||||
</PropertyGroup>
|
||||
|
||||
<!-- Support for old .NET versions -->
|
||||
<ItemGroup Condition="$(TargetFramework.StartsWith(`net2`)) OR $(TargetFramework.StartsWith(`net3`))">
|
||||
<PackageReference Include="Net30.LinqBridge" Version="1.3.0" />
|
||||
</ItemGroup>
|
||||
<ItemGroup Condition="$(TargetFramework.StartsWith(`net2`)) OR $(TargetFramework.StartsWith(`net3`)) OR $(TargetFramework.StartsWith(`net40`))">
|
||||
<PackageReference Include="MinAsyncBridge" Version="0.12.4" />
|
||||
<PackageReference Include="MinTasksExtensionsBridge" Version="0.3.4" />
|
||||
<PackageReference Include="MinThreadingBridge" Version="0.11.4" />
|
||||
</ItemGroup>
|
||||
<ItemGroup Condition="$(TargetFramework.StartsWith(`net45`)) OR $(TargetFramework.StartsWith(`net46`)) OR $(TargetFramework.StartsWith(`net47`)) OR $(TargetFramework.StartsWith(`net48`))">
|
||||
<PackageReference Include="System.Memory" Version="4.5.5" />
|
||||
</ItemGroup>
|
||||
<ItemGroup Condition="!$(TargetFramework.StartsWith(`net2`)) AND !$(TargetFramework.StartsWith(`net3`)) AND !$(TargetFramework.StartsWith(`net40`)) AND !$(TargetFramework.StartsWith(`net45`))">
|
||||
<PackageReference Include="System.IO.Hashing" Version="8.0.0" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="../README.md" Pack="true" PackagePath="" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
<!-- Support for old .NET versions -->
|
||||
<ItemGroup Condition="!$(TargetFramework.StartsWith(`net2`)) AND !$(TargetFramework.StartsWith(`net3`)) AND !$(TargetFramework.StartsWith(`net40`)) AND !$(TargetFramework.StartsWith(`net45`))">
|
||||
<PackageReference Include="System.IO.Hashing" Version="8.0.0" />
|
||||
</ItemGroup>
|
||||
<ItemGroup Condition="$(TargetFramework.StartsWith(`net7`)) OR $(TargetFramework.StartsWith(`net8`)) OR $(TargetFramework.StartsWith(`net9`))">
|
||||
<PackageReference Include="Blake3" Version="1.1.0" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
98
SabreTools.Hashing/XxHash/Constants.cs
Normal file
98
SabreTools.Hashing/XxHash/Constants.cs
Normal file
@@ -0,0 +1,98 @@
|
||||
namespace SabreTools.Hashing.XxHash
|
||||
{
|
||||
// https://github.com/Cyan4973/xxHash/blob/dev/xxhash.h
|
||||
internal static class Constants
|
||||
{
|
||||
#region Version
|
||||
|
||||
public const int XXH_VERSION_MAJOR = 0;
|
||||
|
||||
public const int XXH_VERSION_MINOR = 8;
|
||||
|
||||
public const int XXH_VERSION_RELEASE = 3;
|
||||
|
||||
#endregion
|
||||
|
||||
#region XXH32
|
||||
|
||||
public const uint XXH_PRIME32_1 = 0x9E3779B1;
|
||||
|
||||
public const uint XXH_PRIME32_2 = 0x85EBCA77;
|
||||
|
||||
public const uint XXH_PRIME32_3 = 0xC2B2AE3D;
|
||||
|
||||
public const uint XXH_PRIME32_4 = 0x27D4EB2F;
|
||||
|
||||
public const uint XXH_PRIME32_5 = 0x165667B1;
|
||||
|
||||
#endregion
|
||||
|
||||
#region XXH64
|
||||
|
||||
public const ulong XXH_PRIME64_1 = 0x9E3779B185EBCA87;
|
||||
|
||||
public const ulong XXH_PRIME64_2 = 0xC2B2AE3D27D4EB4F;
|
||||
|
||||
public const ulong XXH_PRIME64_3 = 0x165667B19E3779F9;
|
||||
|
||||
public const ulong XXH_PRIME64_4 = 0x85EBCA77C2B2AE63;
|
||||
|
||||
public const ulong XXH_PRIME64_5 = 0x27D4EB2F165667C5;
|
||||
|
||||
#endregion
|
||||
|
||||
#region XXH3
|
||||
|
||||
/// <summary>
|
||||
/// Pseudorandom secret taken directly from FARSH.
|
||||
/// </summary>
|
||||
public static readonly byte[] XXH3_kSecret =
|
||||
[
|
||||
0xb8, 0xfe, 0x6c, 0x39, 0x23, 0xa4, 0x4b, 0xbe, 0x7c, 0x01, 0x81, 0x2c, 0xf7, 0x21, 0xad, 0x1c,
|
||||
0xde, 0xd4, 0x6d, 0xe9, 0x83, 0x90, 0x97, 0xdb, 0x72, 0x40, 0xa4, 0xa4, 0xb7, 0xb3, 0x67, 0x1f,
|
||||
0xcb, 0x79, 0xe6, 0x4e, 0xcc, 0xc0, 0xe5, 0x78, 0x82, 0x5a, 0xd0, 0x7d, 0xcc, 0xff, 0x72, 0x21,
|
||||
0xb8, 0x08, 0x46, 0x74, 0xf7, 0x43, 0x24, 0x8e, 0xe0, 0x35, 0x90, 0xe6, 0x81, 0x3a, 0x26, 0x4c,
|
||||
0x3c, 0x28, 0x52, 0xbb, 0x91, 0xc3, 0x00, 0xcb, 0x88, 0xd0, 0x65, 0x8b, 0x1b, 0x53, 0x2e, 0xa3,
|
||||
0x71, 0x64, 0x48, 0x97, 0xa2, 0x0d, 0xf9, 0x4e, 0x38, 0x19, 0xef, 0x46, 0xa9, 0xde, 0xac, 0xd8,
|
||||
0xa8, 0xfa, 0x76, 0x3f, 0xe3, 0x9c, 0x34, 0x3f, 0xf9, 0xdc, 0xbb, 0xc7, 0xc7, 0x0b, 0x4f, 0x1d,
|
||||
0x8a, 0x51, 0xe0, 0x4b, 0xcd, 0xb4, 0x59, 0x31, 0xc8, 0x9f, 0x7e, 0xc9, 0xd9, 0x78, 0x73, 0x64,
|
||||
0xea, 0xc5, 0xac, 0x83, 0x34, 0xd3, 0xeb, 0xc3, 0xc5, 0x81, 0xa0, 0xff, 0xfa, 0x13, 0x63, 0xeb,
|
||||
0x17, 0x0d, 0xdd, 0x51, 0xb7, 0xf0, 0xda, 0x49, 0xd3, 0x16, 0x55, 0x26, 0x29, 0xd4, 0x68, 0x9e,
|
||||
0x2b, 0x16, 0xbe, 0x58, 0x7d, 0x47, 0xa1, 0xfc, 0x8f, 0xf8, 0xb8, 0xd1, 0x7a, 0xd0, 0x31, 0xce,
|
||||
0x45, 0xcb, 0x3a, 0x8f, 0x95, 0x16, 0x04, 0x28, 0xaf, 0xd7, 0xfb, 0xca, 0xbb, 0x4b, 0x40, 0x7e,
|
||||
];
|
||||
|
||||
public const ulong PRIME_MX1 = 0x165667919E3779F9;
|
||||
|
||||
public const ulong PRIME_MX2 = 0x9FB21C651E98DF25;
|
||||
|
||||
/// <summary>
|
||||
/// The size of the internal XXH3 buffer.
|
||||
/// This is the optimal update size for incremental hashing.
|
||||
/// </summary>
|
||||
public const int XXH3_INTERNALBUFFER_SIZE = 256;
|
||||
|
||||
/// <summary>
|
||||
/// The bare minimum size for a custom secret.
|
||||
/// </summary>
|
||||
public const int XXH3_SECRET_SIZE_MIN = 136;
|
||||
|
||||
/// <summary>
|
||||
/// Default size of the secret buffer (and <see cref="XXH3_kSecret"/>).
|
||||
/// This is the size used in <see cref="XXH3_kSecret"/> and the seeded functions.
|
||||
/// Not to be confused with @ref XXH3_SECRET_SIZE_MIN.
|
||||
/// </summary>
|
||||
public const int XXH3_SECRET_DEFAULT_SIZE = 192;
|
||||
|
||||
public const int XXH_STRIPE_LEN = 64;
|
||||
|
||||
/// <summary>
|
||||
/// Number of secret bytes consumed at each accumulation
|
||||
/// </summary>
|
||||
public const int XXH_SECRET_CONSUME_RATE = 8;
|
||||
|
||||
private const int XXH_ACC_NB = XXH_STRIPE_LEN / sizeof(ulong);
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
74
SabreTools.Hashing/XxHash/Enums.cs
Normal file
74
SabreTools.Hashing/XxHash/Enums.cs
Normal file
@@ -0,0 +1,74 @@
|
||||
namespace SabreTools.Hashing.XxHash
|
||||
{
|
||||
// https://github.com/Cyan4973/xxHash/blob/dev/xxhash.h
|
||||
internal enum ErrorCode
|
||||
{
|
||||
/// <summary>
|
||||
/// OK
|
||||
/// </summary>
|
||||
XXH_OK = 0,
|
||||
|
||||
/// <summary>
|
||||
/// Error
|
||||
/// </summary>
|
||||
XXH_ERROR,
|
||||
}
|
||||
|
||||
// https://github.com/Cyan4973/xxHash/blob/dev/xxhash.h
|
||||
internal enum Alignment
|
||||
{
|
||||
/// <summary>
|
||||
/// Aligned
|
||||
/// </summary>
|
||||
XXH_aligned,
|
||||
|
||||
/// <summary>
|
||||
/// Possibly unaligned
|
||||
/// </summary>
|
||||
XXH_unaligned,
|
||||
}
|
||||
|
||||
// https://github.com/Cyan4973/xxHash/blob/dev/xxhash.h
|
||||
internal enum VectorType
|
||||
{
|
||||
/// <summary>
|
||||
/// Portable scalar version
|
||||
/// </summary>
|
||||
XXH_SCALAR = 0,
|
||||
|
||||
/// <summary>
|
||||
/// SSE2 for Pentium 4, Opteron, all x86_64.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// SSE2 is also guaranteed on Windows 10, macOS, and Android x86.
|
||||
/// </remarks>
|
||||
XXH_SSE2 = 1,
|
||||
|
||||
/// <summary>
|
||||
/// AVX2 for Haswell and Bulldozer
|
||||
/// </summary>
|
||||
XXH_AVX2 = 2,
|
||||
|
||||
/// <summary>
|
||||
/// AVX512 for Skylake and Icelake
|
||||
/// </summary>
|
||||
XXH_AVX512 = 3,
|
||||
|
||||
/// <summary>
|
||||
/// NEON for most ARMv7-A, all AArch64, and WASM SIMD128
|
||||
/// via the SIMDeverywhere polyfill provided with the
|
||||
/// Emscripten SDK.
|
||||
/// </summary>
|
||||
XXH_NEON = 4,
|
||||
|
||||
/// <summary>
|
||||
/// VSX and ZVector for POWER8/z13 (64-bit)
|
||||
/// </summary>
|
||||
XXH_VSX = 5,
|
||||
|
||||
/// <summary>
|
||||
/// SVE for some ARMv8-A and ARMv9-A
|
||||
/// </summary>
|
||||
XXH_SVE = 6,
|
||||
}
|
||||
}
|
||||
251
SabreTools.Hashing/XxHash/Utility.cs
Normal file
251
SabreTools.Hashing/XxHash/Utility.cs
Normal file
@@ -0,0 +1,251 @@
|
||||
using static SabreTools.Hashing.HashOperations;
|
||||
using static SabreTools.Hashing.XxHash.Constants;
|
||||
|
||||
namespace SabreTools.Hashing.XxHash
|
||||
{
|
||||
internal static class Utility
|
||||
{
|
||||
#region Multiply and Fold
|
||||
|
||||
/// <summary>
|
||||
/// Calculates a 64-bit to 128-bit multiply, then XOR folds it.
|
||||
/// </summary>
|
||||
public static ulong MultiplyTo128Fold64(ulong lhs, ulong rhs)
|
||||
{
|
||||
var product = MultiplyTo128(lhs, rhs);
|
||||
return product.Low ^ product.High;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Calculates a 32-bit to 64-bit long multiply.
|
||||
/// </summary>
|
||||
public static ulong MultiplyTo64(ulong x, ulong y)
|
||||
{
|
||||
return (x & 0xFFFFFFFF) * (y & 0xFFFFFFFF);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Calculates a 64->128-bit long multiply.
|
||||
/// </summary>
|
||||
public static XXH3_128Hash MultiplyTo128(ulong lhs, ulong rhs)
|
||||
{
|
||||
// First calculate all of the cross products.
|
||||
ulong lo_lo = MultiplyTo64(lhs & 0xFFFFFFFF, rhs & 0xFFFFFFFF);
|
||||
ulong hi_lo = MultiplyTo64(lhs >> 32, rhs & 0xFFFFFFFF);
|
||||
ulong lo_hi = MultiplyTo64(lhs & 0xFFFFFFFF, rhs >> 32);
|
||||
ulong hi_hi = MultiplyTo64(lhs >> 32, rhs >> 32);
|
||||
|
||||
// Now add the products together. These will never overflow.
|
||||
ulong cross = (lo_lo >> 32) + (hi_lo & 0xFFFFFFFF) + lo_hi;
|
||||
ulong upper = (hi_lo >> 32) + (cross >> 32) + hi_hi;
|
||||
ulong lower = (cross << 32) | (lo_lo & 0xFFFFFFFF);
|
||||
|
||||
return new XXH3_128Hash
|
||||
{
|
||||
Low = lower,
|
||||
High = upper,
|
||||
};
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Shift
|
||||
|
||||
public static ulong XorShift64(ulong v64, int shift)
|
||||
{
|
||||
return v64 ^ (v64 >> shift);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region XXH64 Common
|
||||
|
||||
/// <summary>
|
||||
/// Mixes all bits to finalize the hash.
|
||||
///
|
||||
/// The final mix ensures that all input bits have a chance to impact any bit in
|
||||
/// the output digest, resulting in an unbiased distribution.
|
||||
/// </summary>
|
||||
public static ulong XXH64Avalanche(ulong hash)
|
||||
{
|
||||
hash ^= hash >> 33;
|
||||
hash *= XXH_PRIME64_2;
|
||||
hash ^= hash >> 29;
|
||||
hash *= XXH_PRIME64_3;
|
||||
hash ^= hash >> 32;
|
||||
return hash;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region XXH3 Common
|
||||
|
||||
/// <summary>
|
||||
/// This is a fast avalanche stage,
|
||||
/// suitable when input bits are already partially mixed
|
||||
/// </summary>
|
||||
public static ulong XXH3Avalanche(ulong hash)
|
||||
{
|
||||
hash = XorShift64(hash, 37);
|
||||
hash *= PRIME_MX1;
|
||||
hash = XorShift64(hash, 32);
|
||||
return hash;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This is a stronger avalanche,
|
||||
/// inspired by Pelle Evensen's rrmxmx
|
||||
/// preferable when input has not been previously mixed
|
||||
/// </summary>
|
||||
public static ulong XXH3Rrmxmx(ulong hash, ulong length)
|
||||
{
|
||||
// This mix is inspired by Pelle Evensen's rrmxmx
|
||||
hash ^= RotateLeft64(hash, 49) ^ RotateLeft64(hash, 24);
|
||||
hash *= PRIME_MX2;
|
||||
hash ^= (hash >> 35) + length;
|
||||
hash *= PRIME_MX2;
|
||||
return XorShift64(hash, 28);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Handle length 1 to 3 values
|
||||
/// </summary>
|
||||
public static ulong Len1To3Out64(byte[] data, int offset, int length, byte[] secret, ulong seed)
|
||||
{
|
||||
byte c1 = data[offset + 0];
|
||||
byte c2 = data[offset + (length >> 1)];
|
||||
byte c3 = data[offset + (length - 1)];
|
||||
|
||||
uint combined = ((uint)c1 << 16)
|
||||
| ((uint)c2 << 24)
|
||||
| ((uint)c3 << 0)
|
||||
| ((uint)length << 8);
|
||||
ulong bitflip = (ReadLE32(secret, 0) ^ ReadLE32(secret, 4)) + seed;
|
||||
ulong keyed = combined ^ bitflip;
|
||||
|
||||
return XXH64Avalanche(keyed);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Handle length 4 to 8 values
|
||||
/// </summary>
|
||||
public static ulong Len4To8Out64(byte[] data, int offset, int length, byte[] secret, ulong seed)
|
||||
{
|
||||
seed ^= (ulong)Swap32((uint)seed) << 32;
|
||||
|
||||
uint input1 = ReadLE32(data, offset);
|
||||
uint input2 = ReadLE32(data, offset + length - 4);
|
||||
ulong bitflip = (ReadLE64(secret, 8) ^ ReadLE64(secret, 16)) - seed;
|
||||
ulong input64 = input2 + (((ulong)input1) << 32);
|
||||
ulong keyed = input64 ^ bitflip;
|
||||
|
||||
return XXH3Rrmxmx(keyed, (ulong)length);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Handle length 9 to 16 values
|
||||
/// </summary>
|
||||
public static ulong Len9To16Out64(byte[] data, int offset, int length, byte[] secret, ulong seed)
|
||||
{
|
||||
ulong bitflip1 = (ReadLE64(secret, 24) ^ ReadLE64(secret, 32)) + seed;
|
||||
ulong bitflip2 = (ReadLE64(secret, 40) ^ ReadLE64(secret, 48)) - seed;
|
||||
ulong input_lo = ReadLE64(data, offset) ^ bitflip1;
|
||||
ulong input_hi = ReadLE64(data, offset + length - 8) ^ bitflip2;
|
||||
|
||||
ulong acc = (ulong)length
|
||||
+ Swap64(input_lo) + input_hi
|
||||
+ MultiplyTo128Fold64(input_lo, input_hi);
|
||||
|
||||
return XXH3Avalanche(acc);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Handle length 0 to 16 values
|
||||
/// </summary>
|
||||
public static ulong Len0To16Out64(byte[] data, int offset, int length, byte[] secret, ulong seed)
|
||||
{
|
||||
if (length > 8)
|
||||
return Len9To16Out64(data, offset, length, secret, seed);
|
||||
if (length >= 4)
|
||||
return Len4To8Out64(data, offset, length, secret, seed);
|
||||
if (length > 0)
|
||||
return Len1To3Out64(data, offset, length, secret, seed);
|
||||
|
||||
return XXH64Avalanche(seed ^ (ReadLE64(secret, 56) ^ ReadLE64(secret, 64)));
|
||||
}
|
||||
|
||||
public static ulong Mix16B(byte[] data, int offset, byte[] secret, int secretOffset, ulong seed)
|
||||
{
|
||||
ulong input_lo = ReadLE64(data, offset + 0);
|
||||
ulong input_hi = ReadLE64(data, offset + 8);
|
||||
|
||||
return MultiplyTo128Fold64(
|
||||
input_lo ^ (ReadLE64(secret, secretOffset + 0) + seed),
|
||||
input_hi ^ (ReadLE64(secret, secretOffset + 8) - seed)
|
||||
);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Handle length 7 to 128 values
|
||||
/// </summary>
|
||||
public static ulong Len17To128Out64(byte[] data, int offset, int length, byte[] secret, ulong seed)
|
||||
{
|
||||
ulong acc = (ulong)length * XXH_PRIME64_1;
|
||||
|
||||
if (length > 32)
|
||||
{
|
||||
if (length > 64)
|
||||
{
|
||||
if (length > 96)
|
||||
{
|
||||
acc += Mix16B(data, offset + 48, secret, 96, seed);
|
||||
acc += Mix16B(data, offset + length - 64, secret, 112, seed);
|
||||
}
|
||||
|
||||
acc += Mix16B(data, offset + 32, secret, 64, seed);
|
||||
acc += Mix16B(data, offset + length - 48, secret, 80, seed);
|
||||
}
|
||||
|
||||
acc += Mix16B(data, offset + 16, secret, 32, seed);
|
||||
acc += Mix16B(data, offset + length - 32, secret, 48, seed);
|
||||
}
|
||||
|
||||
acc += Mix16B(data, offset + 0, secret, 0, seed);
|
||||
acc += Mix16B(data, offset + length - 16, secret, 16, seed);
|
||||
|
||||
return XXH3Avalanche(acc);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Handle length 129 to 240 values
|
||||
/// </summary>
|
||||
public static ulong Len129To240Out64(byte[] data, int offset, int length, byte[] secret, ulong seed)
|
||||
{
|
||||
const int XXH3_MIDSIZE_STARTOFFSET = 3;
|
||||
const int XXH3_MIDSIZE_LASTOFFSET = 17;
|
||||
|
||||
ulong acc = (ulong)length * XXH_PRIME64_1;
|
||||
ulong acc_end;
|
||||
uint nbRounds = (uint)length / 16;
|
||||
|
||||
uint i;
|
||||
for (i = 0; i < 8; i++)
|
||||
{
|
||||
acc += Mix16B(data, offset + (int)(16 * i), secret, (int)(16 * i), seed);
|
||||
}
|
||||
|
||||
// Last bytes
|
||||
acc_end = Mix16B(data, offset + length - 16, secret, XXH3_SECRET_SIZE_MIN - XXH3_MIDSIZE_LASTOFFSET, seed);
|
||||
acc = XXH3Avalanche(acc);
|
||||
|
||||
for (i = 8; i < nbRounds; i++)
|
||||
{
|
||||
acc_end += Mix16B(data, offset + (int)(16 * i), secret, (int)(16 * (i - 8)) + XXH3_MIDSIZE_STARTOFFSET, seed);
|
||||
}
|
||||
|
||||
return XXH3Avalanche(acc + acc_end);
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
204
SabreTools.Hashing/XxHash/XXH32State.cs
Normal file
204
SabreTools.Hashing/XxHash/XXH32State.cs
Normal file
@@ -0,0 +1,204 @@
|
||||
using System;
|
||||
using static SabreTools.Hashing.HashOperations;
|
||||
using static SabreTools.Hashing.XxHash.Constants;
|
||||
|
||||
namespace SabreTools.Hashing.XxHash
|
||||
{
|
||||
/// <summary>
|
||||
/// Structure for XXH32 streaming API.
|
||||
/// </summary>
|
||||
/// <see href="https://github.com/Cyan4973/xxHash/blob/dev/xxhash.h"/>
|
||||
internal class XXH32State
|
||||
{
|
||||
/// <summary>
|
||||
/// Total length hashed, modulo 2^32
|
||||
/// </summary>
|
||||
private uint _totalLen32;
|
||||
|
||||
/// <summary>
|
||||
/// Whether the hash is >= 16 (handles <see cref="_totalLen32"/> overflow)
|
||||
/// </summary>
|
||||
private bool _largeLen;
|
||||
|
||||
/// <summary>
|
||||
/// Accumulator lanes
|
||||
/// </summary>
|
||||
private readonly uint[] _acc = new uint[4];
|
||||
|
||||
/// <summary>
|
||||
/// Internal buffer for partial reads. Treated as unsigned char[16].
|
||||
/// </summary>
|
||||
private readonly byte[] _mem32 = new byte[16];
|
||||
|
||||
/// <summary>
|
||||
/// Amount of data in <see cref="_mem32">
|
||||
/// </summary>
|
||||
private int _memsize;
|
||||
|
||||
/// <summary>
|
||||
/// Resets to begin a new hash
|
||||
/// </summary>
|
||||
/// <param name="seed">The 32-bit seed to alter the hash result predictably.</param>
|
||||
public void Reset(uint seed)
|
||||
{
|
||||
_totalLen32 = 0;
|
||||
_largeLen = false;
|
||||
|
||||
unchecked
|
||||
{
|
||||
_acc[0] = seed + XXH_PRIME32_1 + XXH_PRIME32_2;
|
||||
_acc[1] = seed + XXH_PRIME32_2;
|
||||
_acc[2] = seed + 0;
|
||||
_acc[3] = seed - XXH_PRIME32_1;
|
||||
}
|
||||
|
||||
Array.Clear(_mem32, 0, _mem32.Length);
|
||||
_memsize = 0;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Consumes a block of input
|
||||
/// </summary>
|
||||
/// <param name="data">Byte array representing the data</param>
|
||||
/// <param name="offset">Offset in the byte array to include</param>
|
||||
/// <param name="length">Length of the data to hash</param>
|
||||
public void Update(byte[] data, int offset, int length)
|
||||
{
|
||||
int bEnd = offset + length;
|
||||
|
||||
_totalLen32 += (uint)length;
|
||||
_largeLen |= (length >= 16) | (_totalLen32 >= 16);
|
||||
|
||||
// Fill in tmp buffer
|
||||
if (_memsize + length < 16)
|
||||
{
|
||||
Array.Copy(data, offset, _mem32, _memsize, length);
|
||||
_memsize += length;
|
||||
return;
|
||||
}
|
||||
|
||||
// Some data left from previous update
|
||||
if (_memsize > 0)
|
||||
{
|
||||
Array.Copy(data, offset, _mem32, _memsize, 16 - _memsize);
|
||||
|
||||
int p32 = 0;
|
||||
_acc[0] = Round(_acc[0], ReadLE32(_mem32, p32)); p32 += 4;
|
||||
_acc[1] = Round(_acc[1], ReadLE32(_mem32, p32)); p32 += 4;
|
||||
_acc[2] = Round(_acc[2], ReadLE32(_mem32, p32)); p32 += 4;
|
||||
_acc[3] = Round(_acc[3], ReadLE32(_mem32, p32));
|
||||
|
||||
offset += 16 - _memsize;
|
||||
_memsize = 0;
|
||||
}
|
||||
|
||||
if (offset <= bEnd - 16)
|
||||
{
|
||||
int limit = bEnd - 16;
|
||||
do
|
||||
{
|
||||
_acc[0] = Round(_acc[0], ReadLE32(data, offset)); offset += 4;
|
||||
_acc[1] = Round(_acc[1], ReadLE32(data, offset)); offset += 4;
|
||||
_acc[2] = Round(_acc[2], ReadLE32(data, offset)); offset += 4;
|
||||
_acc[3] = Round(_acc[3], ReadLE32(data, offset)); offset += 4;
|
||||
} while (offset <= limit);
|
||||
}
|
||||
|
||||
if (offset < bEnd)
|
||||
{
|
||||
Array.Copy(data, offset, _mem32, 0, bEnd - offset);
|
||||
_memsize = bEnd - offset;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the calculated hash value
|
||||
/// </summary>
|
||||
/// <returns>The calculated 32-bit xxHash32 value from that state.</returns>
|
||||
public uint Digest()
|
||||
{
|
||||
uint hash;
|
||||
|
||||
if (_largeLen)
|
||||
{
|
||||
hash = RotateLeft32(_acc[0], 1)
|
||||
+ RotateLeft32(_acc[1], 7)
|
||||
+ RotateLeft32(_acc[2], 12)
|
||||
+ RotateLeft32(_acc[3], 18);
|
||||
}
|
||||
else
|
||||
{
|
||||
hash = _acc[2] /* == seed */ + XXH_PRIME32_5;
|
||||
}
|
||||
|
||||
hash += _totalLen32;
|
||||
return Finalize(hash, _mem32, 0, _memsize);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Normal stripe processing routine.
|
||||
///
|
||||
/// This shuffles the bits so that any bit from <paramref name="input"/> impacts
|
||||
/// several bits in <paramref name="acc"/>.
|
||||
/// </summary>
|
||||
/// <param name="acc">The accumulator lane.</param>
|
||||
/// <param name="input">The stripe of input to mix.</param>
|
||||
/// <returns>The mixed accumulator lane.</returns>
|
||||
private static uint Round(uint acc, uint input)
|
||||
{
|
||||
acc += input * XXH_PRIME32_2;
|
||||
acc = RotateLeft32(acc, 13);
|
||||
acc *= XXH_PRIME32_1;
|
||||
return acc;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Mixes all bits to finalize the hash.
|
||||
///
|
||||
/// The final mix ensures that all input bits have a chance to impact any bit in
|
||||
/// the output digest, resulting in an unbiased distribution.
|
||||
/// </summary>
|
||||
private static uint Avalanche(uint hash)
|
||||
{
|
||||
hash ^= hash >> 15;
|
||||
hash *= XXH_PRIME32_2;
|
||||
hash ^= hash >> 13;
|
||||
hash *= XXH_PRIME32_3;
|
||||
hash ^= hash >> 16;
|
||||
return hash;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Processes the last 0-15 bytes of @p ptr.
|
||||
///
|
||||
/// There may be up to 15 bytes remaining to consume from the input.
|
||||
/// This final stage will digest them to ensure that all input bytes are present
|
||||
/// in the final mix.
|
||||
/// </summary>
|
||||
/// <param name="hash">The hash to finalize.</param>
|
||||
/// <param name="data">The remaining input.</param>
|
||||
/// <param name="offset">The pointer to the remaining input.</param>
|
||||
/// <param name="length">The remaining length, modulo 16.</param>
|
||||
/// <returns>The finalized hash.</returns>
|
||||
private static uint Finalize(uint hash, byte[] data, int offset, int length)
|
||||
{
|
||||
length &= 15;
|
||||
while (length >= 4)
|
||||
{
|
||||
hash += ReadLE32(data, offset) * XXH_PRIME32_3;
|
||||
offset += 4;
|
||||
hash = RotateLeft32(hash, 17) * XXH_PRIME32_4;
|
||||
length -= 4;
|
||||
}
|
||||
|
||||
while (length > 0)
|
||||
{
|
||||
hash += data[offset++] * XXH_PRIME32_5;
|
||||
hash = RotateLeft32(hash, 11) * XXH_PRIME32_1;
|
||||
--length;
|
||||
}
|
||||
|
||||
return Avalanche(hash);
|
||||
}
|
||||
}
|
||||
}
|
||||
9
SabreTools.Hashing/XxHash/XXH3_128Hash.cs
Normal file
9
SabreTools.Hashing/XxHash/XXH3_128Hash.cs
Normal file
@@ -0,0 +1,9 @@
|
||||
namespace SabreTools.Hashing.XxHash
|
||||
{
|
||||
internal class XXH3_128Hash
|
||||
{
|
||||
public ulong Low { get; set; }
|
||||
|
||||
public ulong High { get; set; }
|
||||
}
|
||||
}
|
||||
131
SabreTools.Hashing/XxHash/XXH3_128State.cs
Normal file
131
SabreTools.Hashing/XxHash/XXH3_128State.cs
Normal file
@@ -0,0 +1,131 @@
|
||||
namespace SabreTools.Hashing.XxHash
|
||||
{
|
||||
// Handle unused private fields
|
||||
#pragma warning disable CS0169
|
||||
#pragma warning disable CS0414
|
||||
#pragma warning disable CS0649
|
||||
|
||||
/// <summary>
|
||||
/// Structure for XXH3 streaming API.
|
||||
/// </summary>
|
||||
/// <see href="https://github.com/Cyan4973/xxHash/blob/dev/xxhash.h"/>
|
||||
internal class XXH3_128State
|
||||
{
|
||||
/// <summary>
|
||||
/// Accumulator lanes
|
||||
/// </summary>
|
||||
private readonly ulong[] _acc = new ulong[8];
|
||||
|
||||
/// <summary>
|
||||
/// Used to store a custom secret generated from a seed.
|
||||
/// </summary>
|
||||
private readonly byte[] _customSecret = new byte[Constants.XXH3_SECRET_DEFAULT_SIZE];
|
||||
|
||||
/// <summary>
|
||||
/// The internal buffer. <see cref="XXH32State._mem32"/>
|
||||
/// </summary>
|
||||
private readonly byte[] _buffer = new byte[Constants.XXH3_INTERNALBUFFER_SIZE];
|
||||
|
||||
/// <summary>
|
||||
/// The amount of memory in <see cref="_buffer"/>, <see cref="XXH32State._memsize"/>
|
||||
/// </summary>
|
||||
private uint _bufferedSize;
|
||||
|
||||
/// <summary>
|
||||
/// Reserved field. Needed for padding on 64-bit.
|
||||
/// </summary>
|
||||
private uint _useSeed;
|
||||
|
||||
/// <summary>
|
||||
/// Number or stripes processed.
|
||||
/// </summary>
|
||||
private ulong _stripesSoFar;
|
||||
|
||||
/// <summary>
|
||||
/// Total length hashed. 64-bit even on 32-bit targets.
|
||||
/// </summary>
|
||||
private ulong _totalLength;
|
||||
|
||||
/// <summary>
|
||||
/// Number of stripes per block.
|
||||
/// </summary>
|
||||
private ulong _stripesPerBlock;
|
||||
|
||||
/// <summary>
|
||||
/// Size of <see cref="_customSecret"/> or <see cref="_extSecret">
|
||||
/// </summary>
|
||||
private ulong _secretLimit;
|
||||
|
||||
/// <summary>
|
||||
/// Seed for _withSeed variants. Must be zero otherwise, @see XXH3_INITSTATE()
|
||||
/// </summary>
|
||||
private ulong _seed;
|
||||
|
||||
/// <summary>
|
||||
/// Reference to an external secret for the _withSecret variants, NULL
|
||||
/// for other variants.
|
||||
/// </summary>
|
||||
/// <remarks>There may be some padding at the end due to alignment on 64 bytes</remarks>
|
||||
private byte[]? _extSecret = null;
|
||||
|
||||
/// <param name="seed">The 64-bit seed to alter the hash result predictably.</param>
|
||||
public XXH3_128State(ulong seed = 0)
|
||||
{
|
||||
// TODO: XXH3_128bits_withSeed
|
||||
}
|
||||
|
||||
/// <param name="secret">The secret data.</param>
|
||||
public XXH3_128State(byte[] secret)
|
||||
{
|
||||
// TODO: XXH3_128bits_withSecret
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Resets to begin a new hash
|
||||
/// </summary>
|
||||
/// <param name="seed">The 64-bit seed to alter the hash result predictably.</param>
|
||||
public void Reset()
|
||||
{
|
||||
// TODO: XXH3_128bits_reset
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Resets to begin a new hash
|
||||
/// </summary>
|
||||
/// <param name="seed">The 64-bit seed to alter the hash result predictably.</param>
|
||||
public void Reset(ulong seed)
|
||||
{
|
||||
// TODO: XXH3_128bits_reset_withSeed
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Resets to begin a new hash
|
||||
/// </summary>
|
||||
/// <param name="secret">The secret data.</param>
|
||||
public void Reset(byte[] secret)
|
||||
{
|
||||
// TODO: XXH3_128bits_reset_withSecret
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Hash a block of data and append it to the existing hash
|
||||
/// </summary>
|
||||
/// <param name="data">Byte array representing the data</param>
|
||||
/// <param name="offset">Offset in the byte array to include</param>
|
||||
/// <param name="length">Length of the data to hash</param>
|
||||
public void TransformBlock(byte[] data, int offset, int length)
|
||||
{
|
||||
// TODO: XXH3_128bits_update
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the calculated hash value
|
||||
/// </summary>
|
||||
/// <returns>The calculated 64-bit xxHash64 value from that state.</returns>
|
||||
public ulong Digest()
|
||||
{
|
||||
// TODO: XXH3_128bits_digest
|
||||
return ulong.MaxValue;
|
||||
}
|
||||
}
|
||||
}
|
||||
136
SabreTools.Hashing/XxHash/XXH3_64State.cs
Normal file
136
SabreTools.Hashing/XxHash/XXH3_64State.cs
Normal file
@@ -0,0 +1,136 @@
|
||||
namespace SabreTools.Hashing.XxHash
|
||||
{
|
||||
// Handle unused private fields
|
||||
#pragma warning disable CS0169
|
||||
#pragma warning disable CS0414
|
||||
#pragma warning disable CS0649
|
||||
|
||||
/// <summary>
|
||||
/// Structure for XXH3 streaming API.
|
||||
/// </summary>
|
||||
/// <see href="https://github.com/Cyan4973/xxHash/blob/dev/xxhash.h"/>
|
||||
internal class XXH3_64State
|
||||
{
|
||||
/// <summary>
|
||||
/// Accumulator lanes
|
||||
/// </summary>
|
||||
private readonly ulong[] _acc = new ulong[8];
|
||||
|
||||
/// <summary>
|
||||
/// Used to store a custom secret generated from a seed.
|
||||
/// </summary>
|
||||
private readonly byte[] _customSecret = new byte[Constants.XXH3_SECRET_DEFAULT_SIZE];
|
||||
|
||||
/// <summary>
|
||||
/// The internal buffer. <see cref="XXH32State._mem32"/>
|
||||
/// </summary>
|
||||
private readonly byte[] _buffer = new byte[Constants.XXH3_INTERNALBUFFER_SIZE];
|
||||
|
||||
/// <summary>
|
||||
/// The amount of memory in <see cref="_buffer"/>, <see cref="XXH32State._memsize"/>
|
||||
/// </summary>
|
||||
private uint _bufferedSize;
|
||||
|
||||
/// <summary>
|
||||
/// Reserved field. Needed for padding on 64-bit.
|
||||
/// </summary>
|
||||
private uint _useSeed;
|
||||
|
||||
/// <summary>
|
||||
/// Number or stripes processed.
|
||||
/// </summary>
|
||||
private ulong _stripesSoFar;
|
||||
|
||||
/// <summary>
|
||||
/// Total length hashed. 64-bit even on 32-bit targets.
|
||||
/// </summary>
|
||||
private ulong _totalLength;
|
||||
|
||||
/// <summary>
|
||||
/// Number of stripes per block.
|
||||
/// </summary>
|
||||
private ulong _stripesPerBlock;
|
||||
|
||||
/// <summary>
|
||||
/// Size of <see cref="_customSecret"/> or <see cref="_extSecret">
|
||||
/// </summary>
|
||||
private ulong _secretLimit;
|
||||
|
||||
/// <summary>
|
||||
/// Seed for _withSeed variants. Must be zero otherwise, @see XXH3_INITSTATE()
|
||||
/// </summary>
|
||||
private ulong _seed;
|
||||
|
||||
/// <summary>
|
||||
/// Reference to an external secret for the _withSecret variants, NULL
|
||||
/// for other variants.
|
||||
/// </summary>
|
||||
/// <remarks>There may be some padding at the end due to alignment on 64 bytes</remarks>
|
||||
private byte[]? _extSecret = null;
|
||||
|
||||
public XXH3_64State()
|
||||
{
|
||||
// TODO: XXH3_64bits
|
||||
}
|
||||
|
||||
/// <param name="seed">The 64-bit seed to alter the hash result predictably.</param>
|
||||
public XXH3_64State(ulong seed)
|
||||
{
|
||||
// TODO: XXH3_64bits_withSeed
|
||||
}
|
||||
|
||||
/// <param name="secret">The secret data.</param>
|
||||
public XXH3_64State(byte[] secret)
|
||||
{
|
||||
// TODO: XXH3_64bits_withSecret
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Resets to begin a new hash
|
||||
/// </summary>
|
||||
/// <param name="seed">The 64-bit seed to alter the hash result predictably.</param>
|
||||
public void Reset()
|
||||
{
|
||||
// TODO: XXH3_64bits_reset
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Resets to begin a new hash
|
||||
/// </summary>
|
||||
/// <param name="seed">The 64-bit seed to alter the hash result predictably.</param>
|
||||
public void Reset(ulong seed)
|
||||
{
|
||||
// TODO: XXH3_64bits_reset_withSeed
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Resets to begin a new hash
|
||||
/// </summary>
|
||||
/// <param name="secret">The secret data.</param>
|
||||
public void Reset(byte[] secret)
|
||||
{
|
||||
// TODO: XXH3_64bits_reset_withSecret
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Hash a block of data and append it to the existing hash
|
||||
/// </summary>
|
||||
/// <param name="data">Byte array representing the data</param>
|
||||
/// <param name="offset">Offset in the byte array to include</param>
|
||||
/// <param name="length">Length of the data to hash</param>
|
||||
public void TransformBlock(byte[] data, int offset, int length)
|
||||
{
|
||||
// TODO: XXH3_64bits_update
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the calculated hash value
|
||||
/// </summary>
|
||||
/// <returns>The calculated 64-bit xxHash64 value from that state.</returns>
|
||||
public ulong Digest()
|
||||
{
|
||||
// TODO: XXH3_64bits_digest
|
||||
return ulong.MaxValue;
|
||||
}
|
||||
}
|
||||
}
|
||||
204
SabreTools.Hashing/XxHash/XXH64State.cs
Normal file
204
SabreTools.Hashing/XxHash/XXH64State.cs
Normal file
@@ -0,0 +1,204 @@
|
||||
using System;
|
||||
using static SabreTools.Hashing.HashOperations;
|
||||
using static SabreTools.Hashing.XxHash.Constants;
|
||||
using static SabreTools.Hashing.XxHash.Utility;
|
||||
|
||||
namespace SabreTools.Hashing.XxHash
|
||||
{
|
||||
/// <summary>
|
||||
/// Structure for XXH64 streaming API.
|
||||
/// </summary>
|
||||
/// <see href="https://github.com/Cyan4973/xxHash/blob/dev/xxhash.h"/>
|
||||
internal class XXH64State
|
||||
{
|
||||
/// <summary>
|
||||
/// Total length hashed. This is always 64-bit.
|
||||
/// </summary>
|
||||
private ulong _totalLen;
|
||||
|
||||
/// <summary>
|
||||
/// Accumulator lanes
|
||||
/// </summary>
|
||||
private readonly ulong[] _acc = new ulong[4];
|
||||
|
||||
/// <summary>
|
||||
/// Internal buffer for partial reads. Treated as unsigned char[32].
|
||||
/// </summary>
|
||||
private readonly byte[] _mem64 = new byte[32];
|
||||
|
||||
/// <summary>
|
||||
/// Amount of data in <see cref="_mem64">
|
||||
/// </summary>
|
||||
private int _memsize;
|
||||
|
||||
/// <summary>
|
||||
/// Resets to begin a new hash
|
||||
/// </summary>
|
||||
/// <param name="seed">The 64-bit seed to alter the hash result predictably.</param>
|
||||
public void Reset(ulong seed)
|
||||
{
|
||||
_totalLen = 0;
|
||||
|
||||
unchecked
|
||||
{
|
||||
_acc[0] = seed + XXH_PRIME64_1 + XXH_PRIME64_2;
|
||||
_acc[1] = seed + XXH_PRIME64_2;
|
||||
_acc[2] = seed + 0;
|
||||
_acc[3] = seed - XXH_PRIME64_1;
|
||||
}
|
||||
|
||||
Array.Clear(_mem64, 0, _mem64.Length);
|
||||
_memsize = 0;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Consumes a block of input
|
||||
/// </summary>
|
||||
/// <param name="data">Byte array representing the data</param>
|
||||
/// <param name="offset">Offset in the byte array to include</param>
|
||||
/// <param name="length">Length of the data to hash</param>
|
||||
public void Update(byte[] data, int offset, int length)
|
||||
{
|
||||
int bEnd = offset + length;
|
||||
|
||||
_totalLen += (ulong)length;
|
||||
|
||||
// Fill in tmp buffer
|
||||
if (_memsize + length < 32)
|
||||
{
|
||||
Array.Copy(data, offset, _mem64, _memsize, length);
|
||||
_memsize += length;
|
||||
return;
|
||||
}
|
||||
|
||||
// Some data left from previous update
|
||||
if (_memsize > 0)
|
||||
{
|
||||
Array.Copy(data, offset, _mem64, _memsize, 32 - _memsize);
|
||||
|
||||
int p64 = 0;
|
||||
_acc[0] = Round(_acc[0], ReadLE64(_mem64, p64)); p64 += 8;
|
||||
_acc[1] = Round(_acc[1], ReadLE64(_mem64, p64)); p64 += 8;
|
||||
_acc[2] = Round(_acc[2], ReadLE64(_mem64, p64)); p64 += 8;
|
||||
_acc[3] = Round(_acc[3], ReadLE64(_mem64, p64));
|
||||
|
||||
offset += 32 - _memsize;
|
||||
_memsize = 0;
|
||||
}
|
||||
|
||||
if (offset <= bEnd - 32)
|
||||
{
|
||||
int limit = bEnd - 32;
|
||||
do
|
||||
{
|
||||
_acc[0] = Round(_acc[0], ReadLE64(data, offset)); offset += 8;
|
||||
_acc[1] = Round(_acc[1], ReadLE64(data, offset)); offset += 8;
|
||||
_acc[2] = Round(_acc[2], ReadLE64(data, offset)); offset += 8;
|
||||
_acc[3] = Round(_acc[3], ReadLE64(data, offset)); offset += 8;
|
||||
} while (offset <= limit);
|
||||
}
|
||||
|
||||
if (offset < bEnd)
|
||||
{
|
||||
Array.Copy(data, offset, _mem64, 0, bEnd - offset);
|
||||
_memsize = bEnd - offset;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the calculated hash value
|
||||
/// </summary>
|
||||
/// <returns>The calculated 64-bit xxHash64 value from that state.</returns>
|
||||
public ulong Digest()
|
||||
{
|
||||
ulong h64;
|
||||
|
||||
if (_totalLen >= 32)
|
||||
{
|
||||
h64 = RotateLeft64(_acc[0], 1)
|
||||
+ RotateLeft64(_acc[1], 7)
|
||||
+ RotateLeft64(_acc[2], 12)
|
||||
+ RotateLeft64(_acc[3], 18);
|
||||
h64 = MergeRound(h64, _acc[0]);
|
||||
h64 = MergeRound(h64, _acc[1]);
|
||||
h64 = MergeRound(h64, _acc[2]);
|
||||
h64 = MergeRound(h64, _acc[3]);
|
||||
}
|
||||
else
|
||||
{
|
||||
h64 = _acc[2] /*seed*/ + XXH_PRIME64_5;
|
||||
}
|
||||
|
||||
h64 += _totalLen;
|
||||
return Finalize(h64, _mem64, 0, (int)_totalLen);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Normal stripe processing routine.
|
||||
///
|
||||
/// This shuffles the bits so that any bit from @p input impacts
|
||||
/// several bits in @p acc.
|
||||
/// </summary>
|
||||
/// <param name="acc">The accumulator lane.</param>
|
||||
/// <param name="input">The stripe of input to mix.</param>
|
||||
/// <returns>The mixed accumulator lane.</returns>
|
||||
private static ulong Round(ulong acc, ulong input)
|
||||
{
|
||||
acc += unchecked(input * XXH_PRIME64_2);
|
||||
acc = RotateLeft64(acc, 31);
|
||||
acc *= XXH_PRIME64_1;
|
||||
return acc;
|
||||
}
|
||||
|
||||
private static ulong MergeRound(ulong acc, ulong val)
|
||||
{
|
||||
val = Round(0, val);
|
||||
acc ^= val;
|
||||
acc = acc * XXH_PRIME64_1 + XXH_PRIME64_4;
|
||||
return acc;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Processes the last 0-31 bytes of @p ptr.
|
||||
///
|
||||
/// There may be up to 31 bytes remaining to consume from the input.
|
||||
/// This final stage will digest them to ensure that all input bytes are present
|
||||
/// in the final mix.
|
||||
/// </summary>
|
||||
/// <param name="hash">The hash to finalize.</param>
|
||||
/// <param name="data">The pointer to the remaining input.</param>
|
||||
/// <param name="offset">The pointer to the remaining input.</param>
|
||||
/// <param name="length">The remaining length, modulo 32.</param>
|
||||
/// <param name="align">Whether @p ptr is aligned.</param>
|
||||
/// <returns>The finalized hash</returns>
|
||||
private static ulong Finalize(ulong hash, byte[] data, int offset, int length)
|
||||
{
|
||||
length &= 31;
|
||||
while (length >= 8)
|
||||
{
|
||||
ulong k1 = Round(0, ReadLE64(data, offset));
|
||||
offset += 8;
|
||||
hash ^= k1;
|
||||
hash = RotateLeft64(hash, 27) * XXH_PRIME64_1 + XXH_PRIME64_4;
|
||||
length -= 8;
|
||||
}
|
||||
|
||||
if (length >= 4)
|
||||
{
|
||||
hash ^= ReadLE32(data, offset) * XXH_PRIME64_1;
|
||||
offset += 4;
|
||||
hash = RotateLeft64(hash, 23) * XXH_PRIME64_2 + XXH_PRIME64_3;
|
||||
length -= 4;
|
||||
}
|
||||
|
||||
while (length > 0)
|
||||
{
|
||||
hash ^= data[offset++] * XXH_PRIME64_5;
|
||||
hash = RotateLeft64(hash, 11) * XXH_PRIME64_1;
|
||||
--length;
|
||||
}
|
||||
|
||||
return XXH64Avalanche(hash);
|
||||
}
|
||||
}
|
||||
}
|
||||
50
SabreTools.Hashing/XxHash/XxHash32.cs
Normal file
50
SabreTools.Hashing/XxHash/XxHash32.cs
Normal file
@@ -0,0 +1,50 @@
|
||||
using System;
|
||||
|
||||
namespace SabreTools.Hashing.XxHash
|
||||
{
|
||||
public class XxHash32
|
||||
{
|
||||
/// <summary>
|
||||
/// The 32-bit seed to alter the hash result predictably.
|
||||
/// </summary>
|
||||
private readonly uint _seed;
|
||||
|
||||
/// <summary>
|
||||
/// Internal xxHash32 state
|
||||
/// </summary>
|
||||
private readonly XXH32State _state;
|
||||
|
||||
public XxHash32(uint seed = 0)
|
||||
{
|
||||
_seed = seed;
|
||||
_state = new XXH32State();
|
||||
_state.Reset(seed);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reset the internal hashing state
|
||||
/// </summary>
|
||||
public void Reset()
|
||||
{
|
||||
_state.Reset(_seed);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Hash a block of data and append it to the existing hash
|
||||
/// </summary>
|
||||
/// <param name="data">Byte array representing the data</param>
|
||||
/// <param name="offset">Offset in the byte array to include</param>
|
||||
/// <param name="length">Length of the data to hash</param>
|
||||
public void TransformBlock(byte[] data, int offset, int length)
|
||||
=> _state.Update(data, offset, length);
|
||||
|
||||
/// <summary>
|
||||
/// Finalize the hash and return as a byte array
|
||||
/// </summary>
|
||||
public byte[] Finalize()
|
||||
{
|
||||
uint hash = _state.Digest();
|
||||
return BitConverter.GetBytes(hash);
|
||||
}
|
||||
}
|
||||
}
|
||||
50
SabreTools.Hashing/XxHash/XxHash64.cs
Normal file
50
SabreTools.Hashing/XxHash/XxHash64.cs
Normal file
@@ -0,0 +1,50 @@
|
||||
using System;
|
||||
|
||||
namespace SabreTools.Hashing.XxHash
|
||||
{
|
||||
public class XxHash64
|
||||
{
|
||||
/// <summary>
|
||||
/// The 64-bit seed to alter the hash result predictably.
|
||||
/// </summary>
|
||||
private readonly uint _seed;
|
||||
|
||||
/// <summary>
|
||||
/// Internal xxHash64 state
|
||||
/// </summary>
|
||||
private readonly XXH64State _state;
|
||||
|
||||
public XxHash64(uint seed = 0)
|
||||
{
|
||||
_seed = seed;
|
||||
_state = new XXH64State();
|
||||
_state.Reset(seed);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reset the internal hashing state
|
||||
/// </summary>
|
||||
public void Reset()
|
||||
{
|
||||
_state.Reset(_seed);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Hash a block of data and append it to the existing hash
|
||||
/// </summary>
|
||||
/// <param name="data">Byte array representing the data</param>
|
||||
/// <param name="offset">Offset in the byte array to include</param>
|
||||
/// <param name="length">Length of the data to hash</param>
|
||||
public void TransformBlock(byte[] data, int offset, int length)
|
||||
=> _state.Update(data, offset, length);
|
||||
|
||||
/// <summary>
|
||||
/// Finalize the hash and return as a byte array
|
||||
/// </summary>
|
||||
public byte[] Finalize()
|
||||
{
|
||||
ulong hash = _state.Digest();
|
||||
return BitConverter.GetBytes(hash);
|
||||
}
|
||||
}
|
||||
}
|
||||
623
SabreTools.Hashing/ZeroHash.cs
Normal file
623
SabreTools.Hashing/ZeroHash.cs
Normal file
@@ -0,0 +1,623 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace SabreTools.Hashing
|
||||
{
|
||||
/// <summary>
|
||||
/// Zero-byte / empty hash
|
||||
/// </summary>
|
||||
public static class ZeroHash
|
||||
{
|
||||
#region Shortcuts for Common Hash Arrays
|
||||
|
||||
/// <summary>
|
||||
/// Zero-byte CRC-32 checksum
|
||||
/// </summary>
|
||||
public static byte[] CRC32Arr => _bytes[HashType.CRC32];
|
||||
|
||||
/// <summary>
|
||||
/// Zero-byte MD5 hash
|
||||
/// </summary>
|
||||
public static byte[] MD5Arr => _bytes[HashType.MD5];
|
||||
|
||||
/// <summary>
|
||||
/// Zero-byte SHA-1 hash
|
||||
/// </summary>
|
||||
public static byte[] SHA1Arr => _bytes[HashType.SHA1];
|
||||
|
||||
/// <summary>
|
||||
/// Zero-byte SHA-256 hash
|
||||
/// </summary>
|
||||
public static byte[] SHA256Arr => _bytes[HashType.SHA256];
|
||||
|
||||
/// <summary>
|
||||
/// Zero-byte SHA-384 hash
|
||||
/// </summary>
|
||||
public static byte[] SHA384Arr => _bytes[HashType.SHA384];
|
||||
|
||||
/// <summary>
|
||||
/// Zero-byte SHA-512 hash
|
||||
/// </summary>
|
||||
public static byte[] SHA512Arr => _bytes[HashType.SHA512];
|
||||
|
||||
/// <summary>
|
||||
/// Zero-byte SpamSum fuzzy hash
|
||||
/// </summary>
|
||||
public static byte[] SpamSumArr => _bytes[HashType.SpamSum];
|
||||
|
||||
#endregion
|
||||
|
||||
#region Shortcuts for Common Hash Strings
|
||||
|
||||
/// <summary>
|
||||
/// Zero-byte CRC-32 checksum
|
||||
/// </summary>
|
||||
public static string CRC32Str => _strings[HashType.CRC32];
|
||||
|
||||
/// <summary>
|
||||
/// Zero-byte MD5 hash
|
||||
/// </summary>
|
||||
public static string MD5Str => _strings[HashType.MD5];
|
||||
|
||||
/// <summary>
|
||||
/// Zero-byte SHA-1 hash
|
||||
/// </summary>
|
||||
public static string SHA1Str => _strings[HashType.SHA1];
|
||||
|
||||
/// <summary>
|
||||
/// Zero-byte SHA-256 hash
|
||||
/// </summary>
|
||||
public static string SHA256Str => _strings[HashType.SHA256];
|
||||
|
||||
/// <summary>
|
||||
/// Zero-byte SHA-384 hash
|
||||
/// </summary>
|
||||
public static string SHA384Str => _strings[HashType.SHA384];
|
||||
|
||||
/// <summary>
|
||||
/// Zero-byte SHA-512 hash
|
||||
/// </summary>
|
||||
public static string SHA512Str => _strings[HashType.SHA512];
|
||||
|
||||
/// <summary>
|
||||
/// Zero-byte SpamSum fuzzy hash
|
||||
/// </summary>
|
||||
public static string SpamSumStr => _strings[HashType.SpamSum];
|
||||
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// Set of all known 0-byte outputs as strings
|
||||
/// </summary>
|
||||
private static readonly Dictionary<HashType, byte[]> _bytes = new()
|
||||
{
|
||||
{HashType.Adler32, [0x00, 0x00, 0x00, 0x01]},
|
||||
|
||||
#if NET7_0_OR_GREATER
|
||||
{HashType.BLAKE3, [0xaf, 0x13, 0x49, 0xb9, 0xf5, 0xf9, 0xa1, 0xa6,
|
||||
0xa0, 0x40, 0x4d, 0xea, 0x36, 0xdc, 0xc9, 0x49,
|
||||
0x9b, 0xcb, 0x25, 0xc9, 0xad, 0xc1, 0x12, 0xb7,
|
||||
0xcc, 0x9a, 0x93, 0xca, 0xe4, 0x1f, 0x32, 0x62]},
|
||||
#endif
|
||||
|
||||
{HashType.CRC1_ZERO, [0x00]},
|
||||
{HashType.CRC1_ONE, [0x01]},
|
||||
|
||||
{HashType.CRC3_GSM, [0x07]},
|
||||
{HashType.CRC3_ROHC, [0x07]},
|
||||
|
||||
{HashType.CRC4_G704, [0x00]},
|
||||
{HashType.CRC4_INTERLAKEN, [0x00]},
|
||||
|
||||
{HashType.CRC5_EPCC1G2, [0x09]},
|
||||
{HashType.CRC5_G704, [0x00]},
|
||||
{HashType.CRC5_USB, [0x00]},
|
||||
|
||||
{HashType.CRC6_CDMA2000A, [0x3f]},
|
||||
{HashType.CRC6_CDMA2000B, [0x3f]},
|
||||
{HashType.CRC6_DARC, [0x00]},
|
||||
{HashType.CRC6_G704, [0x00]},
|
||||
{HashType.CRC6_GSM, [0x3f]},
|
||||
|
||||
{HashType.CRC7_MMC, [0x00]},
|
||||
{HashType.CRC7_ROHC, [0x7f]},
|
||||
{HashType.CRC7_UMTS, [0x00]},
|
||||
|
||||
{HashType.CRC8, [0x00]},
|
||||
{HashType.CRC8_AUTOSAR, [0x00]},
|
||||
{HashType.CRC8_BLUETOOTH, [0x00]},
|
||||
{HashType.CRC8_CDMA2000, [0xff]},
|
||||
{HashType.CRC8_DARC, [0x00]},
|
||||
{HashType.CRC8_DVBS2, [0x00]},
|
||||
{HashType.CRC8_GSMA, [0x00]},
|
||||
{HashType.CRC8_GSMB, [0xff]},
|
||||
{HashType.CRC8_HITAG, [0xff]},
|
||||
{HashType.CRC8_I4321, [0x55]},
|
||||
{HashType.CRC8_ICODE, [0xfd]},
|
||||
{HashType.CRC8_LTE, [0x00]},
|
||||
{HashType.CRC8_MAXIMDOW, [0x00]},
|
||||
{HashType.CRC8_MIFAREMAD, [0xc7]},
|
||||
{HashType.CRC8_NRSC5, [0xff]},
|
||||
{HashType.CRC8_OPENSAFETY, [0x00]},
|
||||
{HashType.CRC8_ROHC, [0xff]},
|
||||
{HashType.CRC8_SAEJ1850, [0x00]},
|
||||
{HashType.CRC8_SMBUS, [0x00]},
|
||||
{HashType.CRC8_TECH3250, [0xff]},
|
||||
{HashType.CRC8_WCDMA, [0x00]},
|
||||
|
||||
{HashType.CRC10_ATM, [0x00, 0x00]},
|
||||
{HashType.CRC10_CDMA2000, [0x03, 0xff]},
|
||||
{HashType.CRC10_GSM, [0x03, 0xff]},
|
||||
|
||||
{HashType.CRC11_FLEXRAY, [0x00, 0x1a]},
|
||||
{HashType.CRC11_UMTS, [0x00, 0x00]},
|
||||
|
||||
{HashType.CRC12_CDMA2000, [0x0f, 0xff]},
|
||||
{HashType.CRC12_DECT, [0x00, 0x00]},
|
||||
{HashType.CRC12_GSM, [0x0f, 0xff]},
|
||||
{HashType.CRC12_UMTS, [0x00, 0x00]},
|
||||
|
||||
{HashType.CRC13_BBC, [0x00, 0x00]},
|
||||
|
||||
{HashType.CRC14_DARC, [0x00, 0x00]},
|
||||
{HashType.CRC14_GSM, [0x3f, 0xff]},
|
||||
|
||||
{HashType.CRC15_CAN, [0x00, 0x00]},
|
||||
{HashType.CRC15_MPT1327, [0x00, 0x01]},
|
||||
|
||||
{HashType.CRC16, [0x00, 0x00]},
|
||||
{HashType.CRC16_ARC, [0x00, 0x00]},
|
||||
{HashType.CRC16_CDMA2000, [0xff, 0xff]},
|
||||
{HashType.CRC16_CMS, [0xff, 0xff]},
|
||||
{HashType.CRC16_DDS110, [0x80, 0x0d]},
|
||||
{HashType.CRC16_DECTR, [0x00, 0x01]},
|
||||
{HashType.CRC16_DECTX, [0x00, 0x00]},
|
||||
{HashType.CRC16_DNP, [0xff, 0xff]},
|
||||
{HashType.CRC16_EN13757, [0xff, 0xff]},
|
||||
{HashType.CRC16_GENIBUS, [0x00, 0x00]},
|
||||
{HashType.CRC16_GSM, [0xff, 0xff]},
|
||||
{HashType.CRC16_IBM3740, [0xff, 0xff]},
|
||||
{HashType.CRC16_IBMSDLC, [0x00, 0x00]},
|
||||
{HashType.CRC16_ISOIEC144433A, [0x63, 0x63]},
|
||||
{HashType.CRC16_KERMIT, [0x00, 0x00]},
|
||||
{HashType.CRC16_LJ1200, [0x00, 0x00]},
|
||||
{HashType.CRC16_M17, [0xff, 0xff]},
|
||||
{HashType.CRC16_MAXIMDOW, [0xff, 0xff]},
|
||||
{HashType.CRC16_MCRF4XX, [0xff, 0xff]},
|
||||
{HashType.CRC16_MODBUS, [0xff, 0xff]},
|
||||
{HashType.CRC16_NRSC5, [0xff, 0xff]},
|
||||
{HashType.CRC16_OPENSAFETYA, [0x00, 0x00]},
|
||||
{HashType.CRC16_OPENSAFETYB, [0x00, 0x00]},
|
||||
{HashType.CRC16_PROFIBUS, [0x00, 0x00]},
|
||||
{HashType.CRC16_RIELLO, [0x55, 0x4d]},
|
||||
{HashType.CRC16_SPIFUJITSU, [0x1d, 0x0f]},
|
||||
{HashType.CRC16_T10DIF, [0x00, 0x00]},
|
||||
{HashType.CRC16_TELEDISK, [0x00, 0x00]},
|
||||
{HashType.CRC16_TMS37157, [0x37, 0x91]},
|
||||
{HashType.CRC16_UMTS, [0x00, 0x00]},
|
||||
{HashType.CRC16_USB, [0x00, 0x00]},
|
||||
{HashType.CRC16_XMODEM, [0x00, 0x00]},
|
||||
|
||||
{HashType.CRC17_CANFD, [0x00, 0x00, 0x00]},
|
||||
|
||||
{HashType.CRC21_CANFD, [0x00, 0x00, 0x00]},
|
||||
|
||||
{HashType.CRC24_BLE, [0xaa, 0xaa, 0xaa]},
|
||||
{HashType.CRC24_FLEXRAYA, [0xfe, 0xdc, 0xba]},
|
||||
{HashType.CRC24_FLEXRAYB, [0xab, 0xcd, 0xef]},
|
||||
{HashType.CRC24_INTERLAKEN, [0x00, 0x00, 0x00]},
|
||||
{HashType.CRC24_LTEA, [0x00, 0x00, 0x00]},
|
||||
{HashType.CRC24_LTEB, [0x00, 0x00, 0x00]},
|
||||
{HashType.CRC24_OPENPGP, [0xb7, 0x04, 0xce]},
|
||||
{HashType.CRC24_OS9, [0x00, 0x00, 0x00]},
|
||||
|
||||
{HashType.CRC30_CDMA, [0x00, 0x00, 0x00, 0x00]},
|
||||
|
||||
{HashType.CRC31_PHILIPS, [0x00, 0x00, 0x00, 0x00]},
|
||||
|
||||
{HashType.CRC32, [0x00, 0x00, 0x00, 0x00]},
|
||||
{HashType.CRC32_AIXM, [0x00, 0x00, 0x00, 0x00]},
|
||||
{HashType.CRC32_AUTOSAR, [0x00, 0x00, 0x00, 0x00]},
|
||||
{HashType.CRC32_BASE91D, [0x00, 0x00, 0x00, 0x00]},
|
||||
{HashType.CRC32_BZIP2, [0x00, 0x00, 0x00, 0x00]},
|
||||
{HashType.CRC32_CDROMEDC, [0x00, 0x00, 0x00, 0x00]},
|
||||
{HashType.CRC32_CKSUM, [0xff, 0xff, 0xff, 0xff]},
|
||||
{HashType.CRC32_ISCSI, [0x00, 0x00, 0x00, 0x00]},
|
||||
{HashType.CRC32_ISOHDLC, [0x00, 0x00, 0x00, 0x00]},
|
||||
{HashType.CRC32_JAMCRC, [0xff, 0xff, 0xff, 0xff]},
|
||||
{HashType.CRC32_MEF, [0xff, 0xff, 0xff, 0xff]},
|
||||
{HashType.CRC32_MPEG2, [0xff, 0xff, 0xff, 0xff]},
|
||||
{HashType.CRC32_XFER, [0x00, 0x00, 0x00, 0x00]},
|
||||
|
||||
{HashType.CRC40_GSM, [0xff, 0xff, 0xff, 0xff, 0xff]},
|
||||
|
||||
{HashType.CRC64, [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]},
|
||||
{HashType.CRC64_ECMA182, [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]},
|
||||
{HashType.CRC64_GOISO, [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]},
|
||||
{HashType.CRC64_MS, [0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff]},
|
||||
{HashType.CRC64_NVME, [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]},
|
||||
{HashType.CRC64_REDIS, [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]},
|
||||
{HashType.CRC64_WE, [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]},
|
||||
{HashType.CRC64_XZ, [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]},
|
||||
|
||||
{HashType.Fletcher16, [0x00, 0x00]},
|
||||
{HashType.Fletcher32, [0x00, 0x00, 0x00, 0x00]},
|
||||
{HashType.Fletcher64, [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]},
|
||||
|
||||
{HashType.FNV0_32, [0x00, 0x00, 0x00, 0x00]},
|
||||
{HashType.FNV0_64, [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]},
|
||||
{HashType.FNV1_32, [0x81, 0x1c, 0x9d, 0xc5]},
|
||||
{HashType.FNV1_64, [0xcb, 0xf2, 0x9c, 0xe4, 0x84, 0x22, 0x23, 0x25]},
|
||||
{HashType.FNV1a_32, [0x81, 0x1c, 0x9d, 0xc5]},
|
||||
{HashType.FNV1a_64, [0xcb, 0xf2, 0x9c, 0xe4, 0x84, 0x22, 0x23, 0x25]},
|
||||
|
||||
{HashType.MD2, [0x83, 0x50, 0xe5, 0xa3, 0xe2, 0x4c, 0x15, 0x3d,
|
||||
0xf2, 0x27, 0x5c, 0x9f, 0x80, 0x69, 0x27, 0x73]},
|
||||
{HashType.MD4, [0x31, 0xd6, 0xcf, 0xe0, 0xd1, 0x6a, 0xe9, 0x31,
|
||||
0xb7, 0x3c, 0x59, 0xd7, 0xe0, 0xc0, 0x89, 0xc0]},
|
||||
{HashType.MD5, [0xd4, 0x1d, 0x8c, 0xd9, 0x8f, 0x00, 0xb2, 0x04,
|
||||
0xe9, 0x80, 0x09, 0x98, 0xec, 0xf8, 0x42, 0x7e]},
|
||||
|
||||
{HashType.RIPEMD128, [0xcd, 0xf2, 0x62, 0x13, 0xa1, 0x50, 0xdc, 0x3e,
|
||||
0xcb, 0x61, 0x0f, 0x18, 0xf6, 0xb3, 0x8b, 0x46]},
|
||||
{HashType.RIPEMD160, [0x9c, 0x11, 0x85, 0xa5, 0xc5, 0xe9, 0xfc, 0x54,
|
||||
0x61, 0x28, 0x08, 0x97, 0x7e, 0xe8, 0xf5, 0x48,
|
||||
0xb2, 0x25, 0x8d, 0x31]},
|
||||
{HashType.RIPEMD256, [0x02, 0xba, 0x4c, 0x4e, 0x5f, 0x8e, 0xcd, 0x18,
|
||||
0x77, 0xfc, 0x52, 0xd6, 0x4d, 0x30, 0xe3, 0x7a,
|
||||
0x2d, 0x97, 0x74, 0xfb, 0x1e, 0x5d, 0x02, 0x63,
|
||||
0x80, 0xae, 0x01, 0x68, 0xe3, 0xc5, 0x52, 0x2d]},
|
||||
{HashType.RIPEMD320, [0x22, 0xd6, 0x5d, 0x56, 0x61, 0x53, 0x6c, 0xdc,
|
||||
0x75, 0xc1, 0xfd, 0xf5, 0xc6, 0xde, 0x7b, 0x41,
|
||||
0xb9, 0xf2, 0x73, 0x25, 0xeb, 0xc6, 0x1e, 0x85,
|
||||
0x57, 0x17, 0x7d, 0x70, 0x5a, 0x0e, 0xc8, 0x80,
|
||||
0x15, 0x1c, 0x3a, 0x32, 0xa0, 0x08, 0x99, 0xb8]},
|
||||
|
||||
{HashType.SHA1, [0xda, 0x39, 0xa3, 0xee, 0x5e, 0x6b, 0x4b, 0x0d,
|
||||
0x32, 0x55, 0xbf, 0xef, 0x95, 0x60, 0x18, 0x90,
|
||||
0xaf, 0xd8, 0x07, 0x09]},
|
||||
{HashType.SHA256, [0xe3, 0xb0, 0xc4, 0x42, 0x98, 0xfc, 0x1c, 0x14,
|
||||
0x9a, 0xfb, 0xf4, 0xc8, 0x99, 0x6f, 0xb9, 0x24,
|
||||
0x27, 0xae, 0x41, 0xe4, 0x64, 0x9b, 0x93, 0x4c,
|
||||
0xa4, 0x95, 0x99, 0x1b, 0x78, 0x52, 0xb8, 0x55]},
|
||||
{HashType.SHA384, [0x38, 0xb0, 0x60, 0xa7, 0x51, 0xac, 0x96, 0x38,
|
||||
0x4c, 0xd9, 0x32, 0x7e, 0xb1, 0xb1, 0xe3, 0x6a,
|
||||
0x21, 0xfd, 0xb7, 0x11, 0x14, 0xbe, 0x07, 0x43,
|
||||
0x4c, 0x0c, 0xc7, 0xbf, 0x63, 0xf6, 0xe1, 0xda,
|
||||
0x27, 0x4e, 0xde, 0xbf, 0xe7, 0x6f, 0x65, 0xfb,
|
||||
0xd5, 0x1a, 0xd2, 0xf1, 0x48, 0x98, 0xb9, 0x5b]},
|
||||
{HashType.SHA512, [0xcf, 0x83, 0xe1, 0x35, 0x7e, 0xef, 0xb8, 0xbd,
|
||||
0xf1, 0x54, 0x28, 0x50, 0xd6, 0x6d, 0x80, 0x07,
|
||||
0xd6, 0x20, 0xe4, 0x05, 0x0b, 0x57, 0x15, 0xdc,
|
||||
0x83, 0xf4, 0xa9, 0x21, 0xd3, 0x6c, 0xe9, 0xce,
|
||||
0x47, 0xd0, 0xd1, 0x3c, 0x5d, 0x85, 0xf2, 0xb0,
|
||||
0xff, 0x83, 0x18, 0xd2, 0x87, 0x7e, 0xec, 0x2f,
|
||||
0x63, 0xb9, 0x31, 0xbd, 0x47, 0x41, 0x7a, 0x81,
|
||||
0xa5, 0x38, 0x32, 0x7a, 0xf9, 0x27, 0xda, 0x3e]},
|
||||
#if NET8_0_OR_GREATER
|
||||
{HashType.SHA3_256, [0xa7, 0xff, 0xc6, 0xf8, 0xbf, 0x1e, 0xd7, 0x66,
|
||||
0x51, 0xc1, 0x47, 0x56, 0xa0, 0x61, 0xd6, 0x62,
|
||||
0xf5, 0x80, 0xff, 0x4d, 0xe4, 0x3b, 0x49, 0xfa,
|
||||
0x82, 0xd8, 0x0a, 0x4b, 0x80, 0xf8, 0x43, 0x4a]},
|
||||
{HashType.SHA3_384, [0x0c, 0x63, 0xa7, 0x5b, 0x84, 0x5e, 0x4f, 0x7d,
|
||||
0x01, 0x10, 0x7d, 0x85, 0x2e, 0x4c, 0x24, 0x85,
|
||||
0xc5, 0x1a, 0x50, 0xaa, 0xaa, 0x94, 0xfc, 0x61,
|
||||
0x99, 0x5e, 0x71, 0xbb, 0xee, 0x98, 0x3a, 0x2a,
|
||||
0xc3, 0x71, 0x38, 0x31, 0x26, 0x4a, 0xdb, 0x47,
|
||||
0xfb, 0x6b, 0xd1, 0xe0, 0x58, 0xd5, 0xf0, 0x04]},
|
||||
{HashType.SHA3_512, [0xa6, 0x9f, 0x73, 0xcc, 0xa2, 0x3a, 0x9a, 0xc5,
|
||||
0xc8, 0xb5, 0x67, 0xdc, 0x18, 0x5a, 0x75, 0x6e,
|
||||
0x97, 0xc9, 0x82, 0x16, 0x4f, 0xe2, 0x58, 0x59,
|
||||
0xe0, 0xd1, 0xdc, 0xc1, 0x47, 0x5c, 0x80, 0xa6,
|
||||
0x15, 0xb2, 0x12, 0x3a, 0xf1, 0xf5, 0xf9, 0x4c,
|
||||
0x11, 0xe3, 0xe9, 0x40, 0x2c, 0x3a, 0xc5, 0x58,
|
||||
0xf5, 0x00, 0x19, 0x9d, 0x95, 0xb6, 0xd3, 0xe3,
|
||||
0x01, 0x75, 0x85, 0x86, 0x28, 0x1d, 0xcd, 0x26]},
|
||||
{HashType.SHAKE128, [0x7f, 0x9c, 0x2b, 0xa4, 0xe8, 0x8f, 0x82, 0x7d,
|
||||
0x61, 0x60, 0x45, 0x50, 0x76, 0x05, 0x85, 0x3e,
|
||||
0xd7, 0x3b, 0x80, 0x93, 0xf6, 0xef, 0xbc, 0x88,
|
||||
0xeb, 0x1a, 0x6e, 0xac, 0xfa, 0x66, 0xef, 0x26]},
|
||||
{HashType.SHAKE256, [0x46, 0xb9, 0xdd, 0x2b, 0x0b, 0xa8, 0x8d, 0x13,
|
||||
0x23, 0x3b, 0x3f, 0xeb, 0x74, 0x3e, 0xeb, 0x24,
|
||||
0x3f, 0xcd, 0x52, 0xea, 0x62, 0xb8, 0x1b, 0x82,
|
||||
0xb5, 0x0c, 0x27, 0x64, 0x6e, 0xd5, 0x76, 0x2f,
|
||||
0xd7, 0x5d, 0xc4, 0xdd, 0xd8, 0xc0, 0xf2, 0x00,
|
||||
0xcb, 0x05, 0x01, 0x9d, 0x67, 0xb5, 0x92, 0xf6,
|
||||
0xfc, 0x82, 0x1c, 0x49, 0x47, 0x9a, 0xb4, 0x86,
|
||||
0x40, 0x29, 0x2e, 0xac, 0xb3, 0xb7, 0xc4, 0xbe]},
|
||||
#endif
|
||||
|
||||
{HashType.SpamSum, [0x33, 0x3a, 0x3a, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00]},
|
||||
|
||||
{HashType.Tiger128_3, [0x32, 0x93, 0xac, 0x63, 0x0c, 0x13, 0xf0, 0x24,
|
||||
0x5f, 0x92, 0xbb, 0xb1, 0x76, 0x6e, 0x16, 0x16]},
|
||||
{HashType.Tiger128_4, [0x24, 0xcc, 0x78, 0xa7, 0xf6, 0xff, 0x35, 0x46,
|
||||
0xe7, 0x98, 0x4e, 0x59, 0x69, 0x5c, 0xa1, 0x3d]},
|
||||
{HashType.Tiger160_3, [0x32, 0x93, 0xac, 0x63, 0x0c, 0x13, 0xf0, 0x24,
|
||||
0x5f, 0x92, 0xbb, 0xb1, 0x76, 0x6e, 0x16, 0x16,
|
||||
0x7a, 0x4e, 0x58, 0x49]},
|
||||
{HashType.Tiger160_4, [0x24, 0xcc, 0x78, 0xa7, 0xf6, 0xff, 0x35, 0x46,
|
||||
0xe7, 0x98, 0x4e, 0x59, 0x69, 0x5c, 0xa1, 0x3d,
|
||||
0x80, 0x4e, 0x0b, 0x68]},
|
||||
{HashType.Tiger192_3, [0x32, 0x93, 0xac, 0x63, 0x0c, 0x13, 0xf0, 0x24,
|
||||
0x5f, 0x92, 0xbb, 0xb1, 0x76, 0x6e, 0x16, 0x16,
|
||||
0x7a, 0x4e, 0x58, 0x49, 0x2d, 0xde, 0x73, 0xf3]},
|
||||
{HashType.Tiger192_4, [0x24, 0xcc, 0x78, 0xa7, 0xf6, 0xff, 0x35, 0x46,
|
||||
0xe7, 0x98, 0x4e, 0x59, 0x69, 0x5c, 0xa1, 0x3d,
|
||||
0x80, 0x4e, 0x0b, 0x68, 0x6e, 0x25, 0x51, 0x94]},
|
||||
{HashType.Tiger2_128_3, [0x44, 0x41, 0xbe, 0x75, 0xf6, 0x01, 0x87, 0x73,
|
||||
0xc2, 0x06, 0xc2, 0x27, 0x45, 0x37, 0x4b, 0x92]},
|
||||
{HashType.Tiger2_128_4, [0x6a, 0x72, 0x01, 0xa4, 0x7a, 0xac, 0x20, 0x65,
|
||||
0x91, 0x38, 0x11, 0x17, 0x55, 0x53, 0x48, 0x9a]},
|
||||
{HashType.Tiger2_160_3, [0x44, 0x41, 0xbe, 0x75, 0xf6, 0x01, 0x87, 0x73,
|
||||
0xc2, 0x06, 0xc2, 0x27, 0x45, 0x37, 0x4b, 0x92,
|
||||
0x4a, 0xa8, 0x31, 0x3f]},
|
||||
{HashType.Tiger2_160_4, [0x6a, 0x72, 0x01, 0xa4, 0x7a, 0xac, 0x20, 0x65,
|
||||
0x91, 0x38, 0x11, 0x17, 0x55, 0x53, 0x48, 0x9a,
|
||||
0xdd, 0x0f, 0x8b, 0x99]},
|
||||
{HashType.Tiger2_192_3, [0x44, 0x41, 0xbe, 0x75, 0xf6, 0x01, 0x87, 0x73,
|
||||
0xc2, 0x06, 0xc2, 0x27, 0x45, 0x37, 0x4b, 0x92,
|
||||
0x4a, 0xa8, 0x31, 0x3f, 0xef, 0x91, 0x9f, 0x41]},
|
||||
{HashType.Tiger2_192_4, [0x6a, 0x72, 0x01, 0xa4, 0x7a, 0xac, 0x20, 0x65,
|
||||
0x91, 0x38, 0x11, 0x17, 0x55, 0x53, 0x48, 0x9a,
|
||||
0xdd, 0x0f, 0x8b, 0x99, 0xe6, 0x5a, 0x09, 0x55]},
|
||||
|
||||
{HashType.XxHash32, [0x02, 0xcc, 0x5d, 0x05]},
|
||||
{HashType.XxHash64, [0xef, 0x46, 0xdb, 0x37, 0x51, 0xd8, 0xe9, 0x99]},
|
||||
#if NET462_OR_GREATER || NETCOREAPP
|
||||
{HashType.XxHash3, [0x2d, 0x06, 0x80, 0x05, 0x38, 0xd3, 0x94, 0xc2]},
|
||||
{HashType.XxHash128, [0x99, 0xaa, 0x06, 0xd3, 0x01, 0x47, 0x98, 0xd8,
|
||||
0x60, 0x01, 0xc3, 0x24, 0x46, 0x8d, 0x49, 0x7f]},
|
||||
#endif
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Set of all known 0-byte outputs as strings
|
||||
/// </summary>
|
||||
private static readonly Dictionary<HashType, string> _strings = new()
|
||||
{
|
||||
{HashType.Adler32, "00000001"},
|
||||
|
||||
#if NET7_0_OR_GREATER
|
||||
{HashType.BLAKE3, "af1349b9f5f9a1a6a0404dea36dcc9499bcb25c9adc112b7cc9a93cae41f3262"},
|
||||
#endif
|
||||
|
||||
{HashType.CRC1_ZERO, "0"},
|
||||
{HashType.CRC1_ONE, "1"},
|
||||
|
||||
{HashType.CRC3_GSM, "7"},
|
||||
{HashType.CRC3_ROHC, "7"},
|
||||
|
||||
{HashType.CRC4_G704, "0"},
|
||||
{HashType.CRC4_INTERLAKEN, "0"},
|
||||
|
||||
{HashType.CRC5_EPCC1G2, "09"},
|
||||
{HashType.CRC5_G704, "00"},
|
||||
{HashType.CRC5_USB, "00"},
|
||||
|
||||
{HashType.CRC6_CDMA2000A, "3f"},
|
||||
{HashType.CRC6_CDMA2000B, "3f"},
|
||||
{HashType.CRC6_DARC, "00"},
|
||||
{HashType.CRC6_G704, "00"},
|
||||
{HashType.CRC6_GSM, "3f"},
|
||||
|
||||
{HashType.CRC7_MMC, "00"},
|
||||
{HashType.CRC7_ROHC, "7f"},
|
||||
{HashType.CRC7_UMTS, "00"},
|
||||
|
||||
{HashType.CRC8, "00"},
|
||||
{HashType.CRC8_AUTOSAR, "00"},
|
||||
{HashType.CRC8_BLUETOOTH, "00"},
|
||||
{HashType.CRC8_CDMA2000, "ff"},
|
||||
{HashType.CRC8_DARC, "00"},
|
||||
{HashType.CRC8_DVBS2, "00"},
|
||||
{HashType.CRC8_GSMA, "00"},
|
||||
{HashType.CRC8_GSMB, "ff"},
|
||||
{HashType.CRC8_HITAG, "ff"},
|
||||
{HashType.CRC8_I4321, "55"},
|
||||
{HashType.CRC8_ICODE, "fd"},
|
||||
{HashType.CRC8_LTE, "00"},
|
||||
{HashType.CRC8_MAXIMDOW, "00"},
|
||||
{HashType.CRC8_MIFAREMAD, "c7"},
|
||||
{HashType.CRC8_NRSC5, "ff"},
|
||||
{HashType.CRC8_OPENSAFETY, "00"},
|
||||
{HashType.CRC8_ROHC, "ff"},
|
||||
{HashType.CRC8_SAEJ1850, "00"},
|
||||
{HashType.CRC8_SMBUS, "00"},
|
||||
{HashType.CRC8_TECH3250, "ff"},
|
||||
{HashType.CRC8_WCDMA, "00"},
|
||||
|
||||
{HashType.CRC10_ATM, "000"},
|
||||
{HashType.CRC10_CDMA2000, "3ff"},
|
||||
{HashType.CRC10_GSM, "3ff"},
|
||||
|
||||
{HashType.CRC11_FLEXRAY, "01a"},
|
||||
{HashType.CRC11_UMTS, "000"},
|
||||
|
||||
{HashType.CRC12_CDMA2000, "fff"},
|
||||
{HashType.CRC12_DECT, "000"},
|
||||
{HashType.CRC12_GSM, "fff"},
|
||||
{HashType.CRC12_UMTS, "000"},
|
||||
|
||||
{HashType.CRC13_BBC, "0000"},
|
||||
|
||||
{HashType.CRC14_DARC, "0000"},
|
||||
{HashType.CRC14_GSM, "3fff"},
|
||||
|
||||
{HashType.CRC15_CAN, "0000"},
|
||||
{HashType.CRC15_MPT1327, "0001"},
|
||||
|
||||
{HashType.CRC16, "0000"},
|
||||
{HashType.CRC16_ARC, "0000"},
|
||||
{HashType.CRC16_CDMA2000, "ffff"},
|
||||
{HashType.CRC16_CMS, "ffff"},
|
||||
{HashType.CRC16_DDS110, "800d"},
|
||||
{HashType.CRC16_DECTR, "0001"},
|
||||
{HashType.CRC16_DECTX, "0000"},
|
||||
{HashType.CRC16_DNP, "ffff"},
|
||||
{HashType.CRC16_EN13757, "ffff"},
|
||||
{HashType.CRC16_GENIBUS, "0000"},
|
||||
{HashType.CRC16_GSM, "ffff"},
|
||||
{HashType.CRC16_IBM3740, "ffff"},
|
||||
{HashType.CRC16_IBMSDLC, "0000"},
|
||||
{HashType.CRC16_ISOIEC144433A, "6363"},
|
||||
{HashType.CRC16_KERMIT, "0000"},
|
||||
{HashType.CRC16_LJ1200, "0000"},
|
||||
{HashType.CRC16_M17, "ffff"},
|
||||
{HashType.CRC16_MAXIMDOW, "ffff"},
|
||||
{HashType.CRC16_MCRF4XX, "ffff"},
|
||||
{HashType.CRC16_MODBUS, "ffff"},
|
||||
{HashType.CRC16_NRSC5, "ffff"},
|
||||
{HashType.CRC16_OPENSAFETYA, "0000"},
|
||||
{HashType.CRC16_OPENSAFETYB, "0000"},
|
||||
{HashType.CRC16_PROFIBUS, "0000"},
|
||||
{HashType.CRC16_RIELLO, "554d"},
|
||||
{HashType.CRC16_SPIFUJITSU, "1d0f"},
|
||||
{HashType.CRC16_T10DIF, "0000"},
|
||||
{HashType.CRC16_TELEDISK, "0000"},
|
||||
{HashType.CRC16_TMS37157, "3791"},
|
||||
{HashType.CRC16_UMTS, "0000"},
|
||||
{HashType.CRC16_USB, "0000"},
|
||||
{HashType.CRC16_XMODEM, "0000"},
|
||||
|
||||
{HashType.CRC17_CANFD, "00000"},
|
||||
|
||||
{HashType.CRC21_CANFD, "000000"},
|
||||
|
||||
{HashType.CRC24_BLE, "aaaaaa"},
|
||||
{HashType.CRC24_FLEXRAYA, "fedcba"},
|
||||
{HashType.CRC24_FLEXRAYB, "abcdef"},
|
||||
{HashType.CRC24_INTERLAKEN, "000000"},
|
||||
{HashType.CRC24_LTEA, "000000"},
|
||||
{HashType.CRC24_LTEB, "000000"},
|
||||
{HashType.CRC24_OPENPGP, "b704ce"},
|
||||
{HashType.CRC24_OS9, "000000"},
|
||||
|
||||
{HashType.CRC30_CDMA, "00000000"},
|
||||
|
||||
{HashType.CRC31_PHILIPS, "00000000"},
|
||||
|
||||
{HashType.CRC32, "00000000"},
|
||||
{HashType.CRC32_AIXM, "00000000"},
|
||||
{HashType.CRC32_AUTOSAR, "00000000"},
|
||||
{HashType.CRC32_BASE91D, "00000000"},
|
||||
{HashType.CRC32_BZIP2, "00000000"},
|
||||
{HashType.CRC32_CDROMEDC, "00000000"},
|
||||
{HashType.CRC32_CKSUM, "ffffffff"},
|
||||
{HashType.CRC32_ISCSI, "00000000"},
|
||||
{HashType.CRC32_ISOHDLC, "00000000"},
|
||||
{HashType.CRC32_JAMCRC, "ffffffff"},
|
||||
{HashType.CRC32_MEF, "ffffffff"},
|
||||
{HashType.CRC32_MPEG2, "ffffffff"},
|
||||
{HashType.CRC32_XFER, "00000000"},
|
||||
|
||||
{HashType.CRC40_GSM, "ffffffffff"},
|
||||
|
||||
{HashType.CRC64, "0000000000000000"},
|
||||
{HashType.CRC64_ECMA182, "0000000000000000"},
|
||||
{HashType.CRC64_GOISO, "0000000000000000"},
|
||||
{HashType.CRC64_MS, "ffffffffffffffff"},
|
||||
{HashType.CRC64_NVME, "0000000000000000"},
|
||||
{HashType.CRC64_REDIS, "0000000000000000"},
|
||||
{HashType.CRC64_WE, "0000000000000000"},
|
||||
{HashType.CRC64_XZ, "0000000000000000"},
|
||||
|
||||
{HashType.Fletcher16, "0000"},
|
||||
{HashType.Fletcher32, "00000000"},
|
||||
{HashType.Fletcher64, "0000000000000000"},
|
||||
|
||||
{HashType.FNV0_32, "00000000"},
|
||||
{HashType.FNV0_64, "0000000000000000"},
|
||||
{HashType.FNV1_32, "811c9dc5"},
|
||||
{HashType.FNV1_64, "cbf29ce484222325"},
|
||||
{HashType.FNV1a_32, "811c9dc5"},
|
||||
{HashType.FNV1a_64, "cbf29ce484222325"},
|
||||
|
||||
{HashType.MD2, "8350e5a3e24c153df2275c9f80692773"},
|
||||
{HashType.MD4, "31d6cfe0d16ae931b73c59d7e0c089c0"},
|
||||
{HashType.MD5, "d41d8cd98f00b204e9800998ecf8427e"},
|
||||
|
||||
{HashType.RIPEMD128, "cdf26213a150dc3ecb610f18f6b38b46"},
|
||||
{HashType.RIPEMD160, "9c1185a5c5e9fc54612808977ee8f548b2258d31"},
|
||||
{HashType.RIPEMD256, "02ba4c4e5f8ecd1877fc52d64d30e37a2d9774fb1e5d026380ae0168e3c5522d"},
|
||||
{HashType.RIPEMD320, "22d65d5661536cdc75c1fdf5c6de7b41b9f27325ebc61e8557177d705a0ec880151c3a32a00899b8"},
|
||||
|
||||
{HashType.SHA1, "da39a3ee5e6b4b0d3255bfef95601890afd80709"},
|
||||
{HashType.SHA256, "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"},
|
||||
{HashType.SHA384, "38b060a751ac96384cd9327eb1b1e36a21fdb71114be07434c0cc7bf63f6e1da274edebfe76f65fbd51ad2f14898b95b"},
|
||||
{HashType.SHA512, "cf83e1357eefb8bdf1542850d66d8007d620e4050b5715dc83f4a921d36ce9ce47d0d13c5d85f2b0ff8318d2877eec2f63b931bd47417a81a538327af927da3e"},
|
||||
#if NET8_0_OR_GREATER
|
||||
{HashType.SHA3_256, "a7ffc6f8bf1ed76651c14756a061d662f580ff4de43b49fa82d80a4b80f8434a"},
|
||||
{HashType.SHA3_384, "0c63a75b845e4f7d01107d852e4c2485c51a50aaaa94fc61995e71bbee983a2ac3713831264adb47fb6bd1e058d5f004"},
|
||||
{HashType.SHA3_512, "a69f73cca23a9ac5c8b567dc185a756e97c982164fe25859e0d1dcc1475c80a615b2123af1f5f94c11e3e9402c3ac558f500199d95b6d3e301758586281dcd26"},
|
||||
{HashType.SHAKE128, "7f9c2ba4e88f827d616045507605853ed73b8093f6efbc88eb1a6eacfa66ef26"},
|
||||
{HashType.SHAKE256, "46b9dd2b0ba88d13233b3feb743eeb243fcd52ea62b81b82b50c27646ed5762fd75dc4ddd8c0f200cb05019d67b592f6fc821c49479ab48640292eacb3b7c4be"},
|
||||
#endif
|
||||
|
||||
{HashType.SpamSum, "3::"},
|
||||
|
||||
{HashType.Tiger128_3, "3293ac630c13f0245f92bbb1766e1616"},
|
||||
{HashType.Tiger128_4, "24cc78a7f6ff3546e7984e59695ca13d"},
|
||||
{HashType.Tiger160_3, "3293ac630c13f0245f92bbb1766e16167a4e5849"},
|
||||
{HashType.Tiger160_4, "24cc78a7f6ff3546e7984e59695ca13d804e0b68"},
|
||||
{HashType.Tiger192_3, "3293ac630c13f0245f92bbb1766e16167a4e58492dde73f3"},
|
||||
{HashType.Tiger192_4, "24cc78a7f6ff3546e7984e59695ca13d804e0b686e255194"},
|
||||
{HashType.Tiger2_128_3, "4441be75f6018773c206c22745374b92"},
|
||||
{HashType.Tiger2_128_4, "6a7201a47aac2065913811175553489a"},
|
||||
{HashType.Tiger2_160_3, "4441be75f6018773c206c22745374b924aa8313f"},
|
||||
{HashType.Tiger2_160_4, "6a7201a47aac2065913811175553489add0f8b99"},
|
||||
{HashType.Tiger2_192_3, "4441be75f6018773c206c22745374b924aa8313fef919f41"},
|
||||
{HashType.Tiger2_192_4, "6a7201a47aac2065913811175553489add0f8b99e65a0955"},
|
||||
|
||||
{HashType.XxHash32, "02cc5d05"},
|
||||
{HashType.XxHash64, "ef46db3751d8e999"},
|
||||
#if NET462_OR_GREATER || NETCOREAPP
|
||||
{HashType.XxHash3, "2d06800538d394c2"},
|
||||
{HashType.XxHash128, "99aa06d3014798d86001c324468d497f"},
|
||||
#endif
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Get the 0-byte value for <paramref name="hashType"/> as a byte array
|
||||
/// </summary>
|
||||
/// <param name="hashType">Hash type to get the value for</param>
|
||||
/// <returns>Non-empty array containing the value on success, empty array on failure</returns>
|
||||
public static byte[] GetBytes(HashType hashType)
|
||||
{
|
||||
if (!_strings.ContainsKey(hashType))
|
||||
return [];
|
||||
|
||||
return _bytes[hashType];
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the 0-byte value for <paramref name="hashType"/> as a string
|
||||
/// </summary>
|
||||
/// <param name="hashType">Hash type to get the value for</param>
|
||||
/// <returns>Non-empty string containing the value on success, empty string on failure</returns>
|
||||
public static string GetString(HashType hashType)
|
||||
{
|
||||
if (!_strings.ContainsKey(hashType))
|
||||
return string.Empty;
|
||||
|
||||
return _strings[hashType];
|
||||
}
|
||||
}
|
||||
}
|
||||
36
publish-nix.sh
Normal file
36
publish-nix.sh
Normal file
@@ -0,0 +1,36 @@
|
||||
#! /bin/bash
|
||||
|
||||
# This batch file assumes the following:
|
||||
# - .NET 9.0 (or newer) SDK is installed and in PATH
|
||||
#
|
||||
# If any of these are not satisfied, the operation may fail
|
||||
# in an unpredictable way and result in an incomplete output.
|
||||
|
||||
# Optional parameters
|
||||
NO_BUILD=false
|
||||
while getopts "b" OPTION
|
||||
do
|
||||
case $OPTION in
|
||||
b)
|
||||
NO_BUILD=true
|
||||
;;
|
||||
*)
|
||||
echo "Invalid option provided"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
# Set the current directory as a variable
|
||||
BUILD_FOLDER=$PWD
|
||||
|
||||
# Only build if requested
|
||||
if [ $NO_BUILD = false ]
|
||||
then
|
||||
# Restore Nuget packages for all builds
|
||||
echo "Restoring Nuget packages"
|
||||
dotnet restore
|
||||
|
||||
# Create Nuget Package
|
||||
dotnet pack SabreTools.Hashing/SabreTools.Hashing.csproj --output $BUILD_FOLDER
|
||||
fi
|
||||
26
publish-win.ps1
Normal file
26
publish-win.ps1
Normal file
@@ -0,0 +1,26 @@
|
||||
# This batch file assumes the following:
|
||||
# - .NET 9.0 (or newer) SDK is installed and in PATH
|
||||
#
|
||||
# If any of these are not satisfied, the operation may fail
|
||||
# in an unpredictable way and result in an incomplete output.
|
||||
|
||||
# Optional parameters
|
||||
param(
|
||||
[Parameter(Mandatory = $false)]
|
||||
[Alias("NoBuild")]
|
||||
[switch]$NO_BUILD
|
||||
)
|
||||
|
||||
# Set the current directory as a variable
|
||||
$BUILD_FOLDER = $PSScriptRoot
|
||||
|
||||
# Only build if requested
|
||||
if (!$NO_BUILD.IsPresent)
|
||||
{
|
||||
# Restore Nuget packages for all builds
|
||||
Write-Host "Restoring Nuget packages"
|
||||
dotnet restore
|
||||
|
||||
# Create Nuget Package
|
||||
dotnet pack SabreTools.Hashing\SabreTools.Hashing.csproj --output $BUILD_FOLDER
|
||||
}
|
||||
Reference in New Issue
Block a user