47 Commits
1.1.2 ... 1.2.2

Author SHA1 Message Date
Matt Nadareski
7eeb11261b Bump version 2024-10-24 17:22:24 -04:00
Matt Nadareski
a0fc83b617 Add publish scripts 2024-10-24 17:21:55 -04:00
Matt Nadareski
fbc81459ee Reduce framework-dependent code 2024-10-24 17:17:39 -04:00
Matt Nadareski
7d53e07e90 Simplify internal hashing method
This may fix a bug with some compressed streams that, if no bytes were read, may cause odd issues when passed to the hashers, leading to inconsistent values.
2024-10-24 16:45:02 -04:00
Matt Nadareski
e83c31b89c Increase to 50 files in zip 2024-07-19 11:03:27 -04:00
Matt Nadareski
ca08f97336 Increase to 20 files in zip 2024-07-19 10:59:36 -04:00
Matt Nadareski
bd1e23dad4 Add gzip stream test, just in case 2024-07-19 10:54:54 -04:00
Matt Nadareski
b22f3d2743 Better documentation in tests 2024-07-19 10:50:46 -04:00
Matt Nadareski
23ed4e9849 Ensure multiple files hash correctly from archives 2024-07-19 10:47:42 -04:00
Matt Nadareski
4bc26b824f Bump version 2024-07-16 00:05:33 -04:00
Matt Nadareski
d5b0b2ad02 Don't rely on stream size; read until nothing left 2024-07-16 00:02:49 -04:00
Matt Nadareski
3fa3ece655 All unsafe setting of length in hashing 2024-07-15 23:38:12 -04:00
Matt Nadareski
87fb62d772 Start adding Tiger hash (nw) 2024-06-25 13:54:07 -04:00
Matt Nadareski
ce9887ef19 Bump version 2024-03-25 14:21:26 -04:00
Matt Nadareski
dcd4555027 Link to documentation around SHA3 family hashes 2024-03-24 20:15:32 -04:00
Matt Nadareski
b11ded8756 Fix errant build issue 2024-03-24 20:09:05 -04:00
Matt Nadareski
28b33b67f8 Enable SHAKE128 and SHAKE256 processing 2024-03-24 20:07:03 -04:00
Matt Nadareski
cb7c84293d Fix copy-paste issue in tests 2024-03-24 19:59:06 -04:00
Matt Nadareski
83c6346114 Disable verbose test output 2024-03-24 19:57:16 -04:00
Matt Nadareski
eef5fdc29b Use verbose output for tests temporarily 2024-03-24 19:50:52 -04:00
Matt Nadareski
84d319867c Add SHA3 implementations for supported platforms 2024-03-24 19:45:27 -04:00
Matt Nadareski
83c69f895c Add SHAKE128 and SHAKE256 for supported platforms 2024-03-24 19:38:48 -04:00
Matt Nadareski
826d629d98 Update README for CRC-32 changes 2024-03-24 18:46:44 -04:00
Matt Nadareski
6e8f13089e Update README for CRC-64 changes 2024-03-24 18:45:34 -04:00
Matt Nadareski
632b11ef2b Correctly label CRC64 implementations, extend to old .NET 2024-03-24 18:35:04 -04:00
Matt Nadareski
c8f7497bf3 Suppress Nuget warning as error 2024-03-24 02:34:17 -04:00
Matt Nadareski
7dc19b8127 Add CRC-32 implementation from Aaru.Checksums 2024-03-24 02:30:10 -04:00
Matt Nadareski
a3bca2abb4 Add CRC64 from Aaru.Checksums 2024-03-24 02:22:28 -04:00
Matt Nadareski
c19509944b Add CRC-16 variants from Aaru.Checksums 2024-03-24 02:09:32 -04:00
Matt Nadareski
076686bc04 Version gate some constants for consistency 2024-03-24 01:59:52 -04:00
Matt Nadareski
1aea60880a Add Adler-32, Fletcher-16, and Fletcher-32 from Aaru.Checksums 2024-03-24 01:58:23 -04:00
Matt Nadareski
9e5cadd8d2 Add BLAKE3 for net7.0 and above 2024-03-24 00:15:56 -04:00
Matt Nadareski
11c03d8a08 Update summaries in HashType 2024-03-08 12:50:25 -05:00
Matt Nadareski
ff113dfcad Hook up all 3 implementations for choice 2024-03-08 12:48:30 -05:00
Matt Nadareski
fe9fe268c9 Add other CRC32 implementations (unused) 2024-03-08 12:41:22 -05:00
Matt Nadareski
71a45e5cd9 Update README 2024-03-08 10:26:00 -05:00
Matt Nadareski
f0c42d3707 Add optimized CRC for newer .NET versions 2024-03-08 10:22:35 -05:00
Matt Nadareski
3c31839ee2 Remove some needless version gating 2024-03-08 09:36:18 -05:00
Matt Nadareski
3ddc4397de Remove net452 from tests for GHA 2024-03-08 09:34:00 -05:00
Matt Nadareski
bf0cc50ded Update README 2024-03-08 09:26:48 -05:00
Matt Nadareski
99d4b5d62f Add RIPEMD160 for .NET Framework 2024-03-08 09:20:28 -05:00
Matt Nadareski
45adf3a8cd Bump version 2024-03-06 10:55:44 -05:00
Matt Nadareski
b5fc196018 Fix OptimizedCRC, extend tests 2024-03-06 01:33:00 -05:00
Matt Nadareski
fac3a5ab43 Add constants from SabreTools 2024-03-05 14:47:16 -05:00
Matt Nadareski
8face3e4ed Bump version 2024-03-05 13:09:38 -05:00
Matt Nadareski
047463f726 Add byte array variants (fixes #1) 2024-03-05 13:05:42 -05:00
Matt Nadareski
7ab41ce096 Add leave open parameter for stream hashing (fixes #2) 2024-03-05 12:58:06 -05:00
39 changed files with 7301 additions and 305 deletions

View File

@@ -4,10 +4,11 @@ This library comprises of methods and helpers to simplify the process of getting
| Source | Hash / Checksum Types | Notes |
| --- | --- | --- |
| [Aaru.Checksums](https://github.com/aaru-dps/Aaru.Checksums) | SpamSum | Some code tweaks made to support older .NET versions |
| [Aaru.Checksums](https://github.com/aaru-dps/Aaru.Checksums) | Adler-32, CRC-16 (CCITT and IBM polynomials), CRC-32, CRC-64 (Normal and Reversed Polynomials), Fletcher-16, Fletcher-32, SpamSum | Some code tweaks made to support older .NET versions, CRC-32 implementation used in `net20`, `net35`, `net40`, and `net452` |
| [Blake3.NET](https://github.com/xoofx/Blake3.NET) | BLAKE3 | Used in `net7.0` and above |
| [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 |
| [CRC32](https://gitlab.com/eugene77/CRC32) | CRC-32 (Multiple implementations) | |
| [System.IO.Hashing](https://www.nuget.org/packages/System.IO.Hashing) | CRC-32, CRC-64 (Normal Polynomial), xxHash32, xxHash64, XXH3, XXH128 | Used in `net462` and above |
| [System.Security.Cryptography](https://learn.microsoft.com/en-us/dotnet/api/system.security.cryptography) | MD5, RIPEMD160 (.NET Framework only), 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) |
Find the link to the Nuget package [here](https://www.nuget.org/packages/SabreTools.Hashing).

View 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);
}
}
}
}

View File

@@ -6,23 +6,18 @@ 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
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
@@ -42,63 +37,23 @@ namespace SabreTools.Hashing.Test
public void GetFileHashesTest()
{
var hashDict = HashTool.GetFileHashes(_hashFilePath);
Assert.NotNull(hashDict);
Assert.Equal(_crc32, hashDict[HashType.CRC32]);
Assert.Equal(_crc64, hashDict[HashType.CRC64]);
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]);
Assert.Equal(_xxhash32, hashDict[HashType.XxHash32]);
Assert.Equal(_xxhash64, hashDict[HashType.XxHash64]);
Assert.Equal(_xxhash3, hashDict[HashType.XxHash3]);
Assert.Equal(_xxhash128, hashDict[HashType.XxHash128]);
TestHelper.ValidateHashes(hashDict);
}
[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]);
Assert.Equal(_crc32, hashDict[HashType.CRC32]);
Assert.Equal(_crc64, hashDict[HashType.CRC64]);
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]);
Assert.Equal(_xxhash32, hashDict[HashType.XxHash32]);
Assert.Equal(_xxhash64, hashDict[HashType.XxHash64]);
Assert.Equal(_xxhash3, hashDict[HashType.XxHash3]);
Assert.Equal(_xxhash128, hashDict[HashType.XxHash128]);
TestHelper.ValidateHashes(hashDict);
}
[Fact]
public void GetByteArrayHashesTest()
{
byte[] fileBytes = File.ReadAllBytes(_hashFilePath);
var hashDict = HashTool.GetByteArrayHashes(fileBytes);
Assert.NotNull(hashDict);
Assert.Equal(_crc32, hashDict[HashType.CRC32]);
Assert.Equal(_crc64, hashDict[HashType.CRC64]);
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]);
Assert.Equal(_xxhash32, hashDict[HashType.XxHash32]);
Assert.Equal(_xxhash64, hashDict[HashType.XxHash64]);
Assert.Equal(_xxhash3, hashDict[HashType.XxHash3]);
Assert.Equal(_xxhash128, hashDict[HashType.XxHash128]);
TestHelper.ValidateHashes(hashDict);
}
[Fact]
@@ -106,20 +61,7 @@ namespace SabreTools.Hashing.Test
{
var fileStream = File.OpenRead(_hashFilePath);
var hashDict = HashTool.GetStreamHashes(fileStream);
Assert.NotNull(hashDict);
Assert.Equal(_crc32, hashDict[HashType.CRC32]);
Assert.Equal(_crc64, hashDict[HashType.CRC64]);
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]);
Assert.Equal(_xxhash32, hashDict[HashType.XxHash32]);
Assert.Equal(_xxhash64, hashDict[HashType.XxHash64]);
Assert.Equal(_xxhash3, hashDict[HashType.XxHash3]);
Assert.Equal(_xxhash128, hashDict[HashType.XxHash128]);
TestHelper.ValidateHashes(hashDict);
}
}
}

View File

@@ -1,9 +1,12 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>net6.0;net8.0</TargetFrameworks>
<TargetFrameworks>net462;net6.0;net7.0;net8.0</TargetFrameworks>
<CheckEolTargetFramework>false</CheckEolTargetFramework>
<IsPackable>false</IsPackable>
<LangVersion>latest</LangVersion>
<Nullable>enable</Nullable>
<SuppressTfmSupportBuildWarnings>true</SuppressTfmSupportBuildWarnings>
</PropertyGroup>
<ItemGroup>
@@ -16,12 +19,9 @@
</Content>
</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" />
<!-- Support for old .NET versions -->
<ItemGroup Condition="$(TargetFramework.StartsWith(`net462`)) OR $(TargetFramework.StartsWith(`net6`)) OR $(TargetFramework.StartsWith(`net7`)) OR $(TargetFramework.StartsWith(`net8`))">
<PackageReference Include="System.IO.Compression" Version="4.3.0" />
<PackageReference Include="xunit" Version="2.6.2" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.5.4">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
@@ -29,6 +29,14 @@
</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>

Binary file not shown.

Binary file not shown.

View File

@@ -0,0 +1,97 @@
using System.Collections.Generic;
using Xunit;
namespace SabreTools.Hashing.Test
{
/// <summary>
/// Helper class for tests
/// </summary>
internal static class TestHelper
{
#region Known File Information
private const long _hashFileSize = 125;
private const string _adler32 = "08562d95";
#if NET7_0_OR_GREATER
private const string _blake3 = "d4bd7ca6f1ebea9580d9381106b248eb5b6069170d0bfd00b17d659fcd10dcdc";
#endif
private const string _crc16_ccitt = "482d";
private const string _crc16_ibm = "7573";
private const string _crc32 = "ba02a660";
private const string _crc64 = "a0e0009c18b5338d";
private const string _crc64_reversed = "fb49044e8331f6e5";
private const string _fletcher16 = "46c1";
private const string _fletcher32 = "073f2d94";
private const string _md5 = "b722871eaa950016296184d026c5dec9";
#if NETFRAMEWORK
private const string _ripemd160 = "346361e1d7fdb836650cecdb842b0dbe660eed66";
#endif
private const string _sha1 = "eea1ee2d801d830c4bdad4df3c8da6f9f52d1a9f";
private const string _sha256 = "fdb02dee8c319c52087382c45f099c90d0b6cc824850aff28c1bfb2884b7b855";
private const string _sha384 = "e276c49618fff25bc1fe2e0659cd0ef0e7c1186563b063e07c52323b9899f3ce9b091be04d6208444b3ef1265e879074";
private const string _sha512 = "15d69514eb628c2403e945a7cafd1d27e557f6e336c69b63ea17e7ed9d256cc374ee662f09305836d6de37fdae59d83883b982aa8446e4ff26346b6b6b50b240";
#if NET8_0_OR_GREATER
private const string _sha3_256 = "1d76459e68c865b5911ada5104067cc604c5c60b345c4e81b3905e916a43c868";
private const string _sha3_384 = "1bcbed87b73f25c0adf486c3afbf0ea3105763c387af3f8b2bd79b0a1964d42832b1d7c6a2225f9153ead26f442e8b67";
private const string _sha3_512 = "89852144df37c58d01f5912124f1942dd00bac0346eb3971943416699c3094cff087fb42c356019c3d91f8e8f55b9254c8caec48e9414af6817297d06725ffeb";
private const string _shake128 = "e5f88d0db79a71c39490beb9ebac21eaf4a5d6368438fca20f5e4ce77cfee9aa";
private const string _shake256 = "24d9e83198bbc7baf4dcd293bfc35ae3fff05399786c37318f1b1ef85f41970c66926f8a2a1f912d96e2d8e45535af88a301a1c200697437c1a65d7e980344bc";
#endif
private const string _spamsum = "3:hMCPQCE6AFQxWyENFACBE+rW6Tj7SMQmKozr9MVERkL:hZRdxZENFs+rPSromekL";
#if NET462_OR_GREATER || NETCOREAPP
private const string _xxhash32 = "8e331daa";
private const string _xxhash64 = "082bf6f0a49e1e18";
private const string _xxhash3 = "040474eb0eda9ff2";
private const string _xxhash128 = "d934b4b4a5e1e11baeef8012fbcd11e8";
#endif
#endregion
/// <summary>
/// Validate the hashes in a hash dictionary
/// </summary>
public static void ValidateHashes(Dictionary<HashType, string?>? hashDict)
{
Assert.NotNull(hashDict);
Assert.Equal(_adler32, hashDict![HashType.Adler32]);
#if NET7_0_OR_GREATER
Assert.Equal(_blake3, hashDict[HashType.BLAKE3]);
#endif
Assert.Equal(_crc16_ccitt, hashDict[HashType.CRC16_CCITT]);
Assert.Equal(_crc16_ibm, hashDict[HashType.CRC16_IBM]);
Assert.Equal(_crc32, hashDict[HashType.CRC32]);
Assert.Equal(_crc32, hashDict[HashType.CRC32_ISO]);
Assert.Equal(_crc32, hashDict[HashType.CRC32_Naive]);
Assert.Equal(_crc32, hashDict[HashType.CRC32_Optimized]);
Assert.Equal(_crc32, hashDict[HashType.CRC32_Parallel]);
Assert.Equal(_crc64, hashDict[HashType.CRC64]);
Assert.Equal(_crc64_reversed, hashDict[HashType.CRC64_Reversed]);
Assert.Equal(_fletcher16, hashDict[HashType.Fletcher16]);
Assert.Equal(_fletcher32, hashDict[HashType.Fletcher32]);
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]);
#if NET8_0_OR_GREATER
if (System.Security.Cryptography.SHA3_256.IsSupported)
Assert.Equal(_sha3_256, hashDict[HashType.SHA3_256]);
if (System.Security.Cryptography.SHA3_384.IsSupported)
Assert.Equal(_sha3_384, hashDict[HashType.SHA3_384]);
if (System.Security.Cryptography.SHA3_512.IsSupported)
Assert.Equal(_sha3_512, hashDict[HashType.SHA3_512]);
if (System.Security.Cryptography.Shake128.IsSupported)
Assert.Equal(_shake128, hashDict[HashType.SHAKE128]);
if (System.Security.Cryptography.Shake256.IsSupported)
Assert.Equal(_shake256, hashDict[HashType.SHAKE256]);
#endif
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
}
}
}

View File

@@ -0,0 +1,217 @@
// /***************************************************************************
// Aaru Data Preservation Suite
// ----------------------------------------------------------------------------
//
// Filename : neon.cs
// Author(s) : Natalia Portillo <claunia@claunia.com>
// The Chromium Authors
//
// Component : Checksums.
//
// --[ Description ] ----------------------------------------------------------
//
// Compute Adler32 checksum using NEON vectorization.
//
// --[ License ] --------------------------------------------------------------
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// ----------------------------------------------------------------------------
// Copyright © 2011-2023 Natalia Portillo
// Copyright 2017 The Chromium Authors. All rights reserved.
// ****************************************************************************/
#if NET5_0_OR_GREATER
using System.Runtime.Intrinsics;
using System.Runtime.Intrinsics.Arm;
namespace Aaru.Checksums.Adler32;
static class Neon
{
internal static void Step(ref ushort preSum1, ref ushort preSum2, byte[] buf, uint len)
{
/*
* Split Adler-32 into component sums.
*/
uint s1 = preSum1;
uint s2 = preSum2;
var bufPos = 0;
/*
* Process the data in blocks.
*/
const uint blockSize = 1 << 5;
uint blocks = len / blockSize;
len -= blocks * blockSize;
while(blocks != 0)
{
uint n = Adler32Context.NMAX / blockSize; /* The NMAX constraint. */
if(n > blocks)
n = blocks;
blocks -= n;
/*
* Process n blocks of data. At most NMAX data bytes can be
* processed before s2 must be reduced modulo ADLER_MODULE.
*/
var vS2 = Vector128.Create(s1 * n, 0, 0, 0);
var vS1 = Vector128.Create(0u, 0, 0, 0);
Vector128<ushort> vColumnSum1 = AdvSimd.DuplicateToVector128((ushort)0);
Vector128<ushort> vColumnSum2 = AdvSimd.DuplicateToVector128((ushort)0);
Vector128<ushort> vColumnSum3 = AdvSimd.DuplicateToVector128((ushort)0);
Vector128<ushort> vColumnSum4 = AdvSimd.DuplicateToVector128((ushort)0);
do
{
/*
* Load 32 input bytes.
*/
var bytes1 = Vector128.Create(buf[bufPos], buf[bufPos + 1], buf[bufPos + 2], buf[bufPos + 3],
buf[bufPos + 4], buf[bufPos + 5], buf[bufPos + 6], buf[bufPos + 7],
buf[bufPos + 8], buf[bufPos + 9], buf[bufPos + 10], buf[bufPos + 11],
buf[bufPos + 12], buf[bufPos + 13], buf[bufPos + 14], buf[bufPos + 15]);
bufPos += 16;
var bytes2 = Vector128.Create(buf[bufPos], buf[bufPos + 1], buf[bufPos + 2], buf[bufPos + 3],
buf[bufPos + 4], buf[bufPos + 5], buf[bufPos + 6], buf[bufPos + 7],
buf[bufPos + 8], buf[bufPos + 9], buf[bufPos + 10], buf[bufPos + 11],
buf[bufPos + 12], buf[bufPos + 13], buf[bufPos + 14], buf[bufPos + 15]);
bufPos += 16;
/*
* Add previous block byte sum to v_s2.
*/
vS2 = AdvSimd.Add(vS2, vS1);
/*
* Horizontally add the bytes for s1.
*/
vS1 =
AdvSimd.AddPairwiseWideningAndAdd(vS1,
AdvSimd.
AddPairwiseWideningAndAdd(AdvSimd.AddPairwiseWidening(bytes1),
bytes2));
/*
* Vertically add the bytes for s2.
*/
vColumnSum1 = AdvSimd.AddWideningLower(vColumnSum1, bytes1.GetLower());
vColumnSum2 = AdvSimd.AddWideningLower(vColumnSum2, bytes1.GetUpper());
vColumnSum3 = AdvSimd.AddWideningLower(vColumnSum3, bytes2.GetLower());
vColumnSum4 = AdvSimd.AddWideningLower(vColumnSum4, bytes2.GetUpper());
} while(--n != 0);
vS2 = AdvSimd.ShiftLeftLogical(vS2, 5);
/*
* Multiply-add bytes by [ 32, 31, 30, ... ] for s2.
*/
vS2 = AdvSimd.MultiplyWideningLowerAndAdd(vS2, vColumnSum1.GetLower(),
Vector64.Create((ushort)32, 31, 30, 29));
vS2 = AdvSimd.MultiplyWideningLowerAndAdd(vS2, vColumnSum1.GetUpper(),
Vector64.Create((ushort)28, 27, 26, 25));
vS2 = AdvSimd.MultiplyWideningLowerAndAdd(vS2, vColumnSum2.GetLower(),
Vector64.Create((ushort)24, 23, 22, 21));
vS2 = AdvSimd.MultiplyWideningLowerAndAdd(vS2, vColumnSum2.GetUpper(),
Vector64.Create((ushort)20, 19, 18, 17));
vS2 = AdvSimd.MultiplyWideningLowerAndAdd(vS2, vColumnSum3.GetLower(),
Vector64.Create((ushort)16, 15, 14, 13));
vS2 = AdvSimd.MultiplyWideningLowerAndAdd(vS2, vColumnSum3.GetUpper(),
Vector64.Create((ushort)12, 11, 10, 9));
vS2 = AdvSimd.MultiplyWideningLowerAndAdd(vS2, vColumnSum4.GetLower(), Vector64.Create((ushort)8, 7, 6, 5));
vS2 = AdvSimd.MultiplyWideningLowerAndAdd(vS2, vColumnSum4.GetUpper(), Vector64.Create((ushort)4, 3, 2, 1));
/*
* Sum epi32 ints v_s1(s2) and accumulate in s1(s2).
*/
Vector64<uint> sum1 = AdvSimd.AddPairwise(vS1.GetLower(), vS1.GetUpper());
Vector64<uint> sum2 = AdvSimd.AddPairwise(vS2.GetLower(), vS2.GetUpper());
Vector64<uint> s1S2 = AdvSimd.AddPairwise(sum1, sum2);
s1 += AdvSimd.Extract(s1S2, 0);
s2 += AdvSimd.Extract(s1S2, 1);
/*
* Reduce.
*/
s1 %= Adler32Context.ADLER_MODULE;
s2 %= Adler32Context.ADLER_MODULE;
}
/*
* Handle leftover data.
*/
if(len != 0)
{
if(len >= 16)
{
s2 += s1 += buf[bufPos++];
s2 += s1 += buf[bufPos++];
s2 += s1 += buf[bufPos++];
s2 += s1 += buf[bufPos++];
s2 += s1 += buf[bufPos++];
s2 += s1 += buf[bufPos++];
s2 += s1 += buf[bufPos++];
s2 += s1 += buf[bufPos++];
s2 += s1 += buf[bufPos++];
s2 += s1 += buf[bufPos++];
s2 += s1 += buf[bufPos++];
s2 += s1 += buf[bufPos++];
s2 += s1 += buf[bufPos++];
s2 += s1 += buf[bufPos++];
s2 += s1 += buf[bufPos++];
s2 += s1 += buf[bufPos++];
len -= 16;
}
while(len-- != 0)
s2 += s1 += buf[bufPos++];
if(s1 >= Adler32Context.ADLER_MODULE)
s1 -= Adler32Context.ADLER_MODULE;
s2 %= Adler32Context.ADLER_MODULE;
}
/*
* Return the recombined sums.
*/
preSum1 = (ushort)(s1 & 0xFFFF);
preSum2 = (ushort)(s2 & 0xFFFF);
}
}
#endif

View File

@@ -0,0 +1,194 @@
// /***************************************************************************
// Aaru Data Preservation Suite
// ----------------------------------------------------------------------------
//
// Filename : ssse3.cs
// Author(s) : Natalia Portillo <claunia@claunia.com>
// The Chromium Authors
//
// Component : Checksums.
//
// --[ Description ] ----------------------------------------------------------
//
// Compute Adler32 checksum using SSSE3 vectorization.
//
// --[ License ] --------------------------------------------------------------
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// ----------------------------------------------------------------------------
// Copyright © 2011-2023 Natalia Portillo
// Copyright 2017 The Chromium Authors. All rights reserved.
// ****************************************************************************/
#if NETCOREAPP3_1_OR_GREATER
using System;
using System.Runtime.Intrinsics;
using System.Runtime.Intrinsics.X86;
namespace Aaru.Checksums.Adler32;
static class Ssse3
{
internal static void Step(ref ushort sum1, ref ushort sum2, byte[] buf, uint len)
{
uint s1 = sum1;
uint s2 = sum2;
var bufPos = 0;
/*
* Process the data in blocks.
*/
const uint blockSize = 1 << 5;
uint blocks = len / blockSize;
len -= blocks * blockSize;
while(blocks != 0)
{
uint n = Adler32Context.NMAX / blockSize; /* The NMAX constraint. */
if(n > blocks)
n = blocks;
blocks -= n;
Vector128<byte> tap1 = Vector128.Create(32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17).
AsByte();
Vector128<byte> tap2 = Vector128.Create(16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1).AsByte();
Vector128<byte> zero = Vector128.Create(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0).AsByte();
var ones = Vector128.Create(1, 1, 1, 1, 1, 1, 1, 1);
/*
* Process n blocks of data. At most NMAX data bytes can be
* processed before s2 must be reduced modulo BASE.
*/
var vPs = Vector128.Create(s1 * n, 0, 0, 0);
var vS2 = Vector128.Create(s2, 0, 0, 0);
var vS1 = Vector128.Create(0u, 0, 0, 0);
do
{
/*
* Load 32 input bytes.
*/
var bytes1 = Vector128.Create(BitConverter.ToUInt32(buf, bufPos),
BitConverter.ToUInt32(buf, bufPos + 4),
BitConverter.ToUInt32(buf, bufPos + 8),
BitConverter.ToUInt32(buf, bufPos + 12));
bufPos += 16;
var bytes2 = Vector128.Create(BitConverter.ToUInt32(buf, bufPos),
BitConverter.ToUInt32(buf, bufPos + 4),
BitConverter.ToUInt32(buf, bufPos + 8),
BitConverter.ToUInt32(buf, bufPos + 12));
bufPos += 16;
/*
* Add previous block byte sum to v_ps.
*/
vPs = Sse2.Add(vPs, vS1);
/*
* Horizontally add the bytes for s1, multiply-adds the
* bytes by [ 32, 31, 30, ... ] for s2.
*/
vS1 = Sse2.Add(vS1, Sse2.SumAbsoluteDifferences(bytes1.AsByte(), zero).AsUInt32());
Vector128<short> mad1 =
System.Runtime.Intrinsics.X86.Ssse3.MultiplyAddAdjacent(bytes1.AsByte(), tap1.AsSByte());
vS2 = Sse2.Add(vS2, Sse2.MultiplyAddAdjacent(mad1.AsInt16(), ones.AsInt16()).AsUInt32());
vS1 = Sse2.Add(vS1, Sse2.SumAbsoluteDifferences(bytes2.AsByte(), zero).AsUInt32());
Vector128<short> mad2 =
System.Runtime.Intrinsics.X86.Ssse3.MultiplyAddAdjacent(bytes2.AsByte(), tap2.AsSByte());
vS2 = Sse2.Add(vS2, Sse2.MultiplyAddAdjacent(mad2.AsInt16(), ones.AsInt16()).AsUInt32());
} while(--n != 0);
vS2 = Sse2.Add(vS2, Sse2.ShiftLeftLogical(vPs, 5));
/*
* Sum epi32 ints v_s1(s2) and accumulate in s1(s2).
*/
vS1 = Sse2.Add(vS1, Sse2.Shuffle(vS1, 177));
vS1 = Sse2.Add(vS1, Sse2.Shuffle(vS1, 78));
s1 += (uint)Sse2.ConvertToInt32(vS1.AsInt32());
vS2 = Sse2.Add(vS2, Sse2.Shuffle(vS2, 177));
vS2 = Sse2.Add(vS2, Sse2.Shuffle(vS2, 78));
s2 = (uint)Sse2.ConvertToInt32(vS2.AsInt32());
/*
* Reduce.
*/
s1 %= Adler32Context.ADLER_MODULE;
s2 %= Adler32Context.ADLER_MODULE;
}
/*
* Handle leftover data.
*/
if(len != 0)
{
if(len >= 16)
{
s2 += s1 += buf[bufPos++];
s2 += s1 += buf[bufPos++];
s2 += s1 += buf[bufPos++];
s2 += s1 += buf[bufPos++];
s2 += s1 += buf[bufPos++];
s2 += s1 += buf[bufPos++];
s2 += s1 += buf[bufPos++];
s2 += s1 += buf[bufPos++];
s2 += s1 += buf[bufPos++];
s2 += s1 += buf[bufPos++];
s2 += s1 += buf[bufPos++];
s2 += s1 += buf[bufPos++];
s2 += s1 += buf[bufPos++];
s2 += s1 += buf[bufPos++];
s2 += s1 += buf[bufPos++];
s2 += s1 += buf[bufPos++];
len -= 16;
}
while(len-- != 0)
s2 += s1 += buf[bufPos++];
if(s1 >= Adler32Context.ADLER_MODULE)
s1 -= Adler32Context.ADLER_MODULE;
s2 %= Adler32Context.ADLER_MODULE;
}
/*
* Return the recombined sums.
*/
sum1 = (ushort)(s1 & 0xFFFF);
sum2 = (ushort)(s2 & 0xFFFF);
}
}
#endif

View File

@@ -0,0 +1,434 @@
// /***************************************************************************
// Aaru Data Preservation Suite
// ----------------------------------------------------------------------------
//
// Filename : Adler32Context.cs
// Author(s) : Natalia Portillo <claunia@claunia.com>
//
// Component : Checksums.
//
// --[ Description ] ----------------------------------------------------------
//
// Implements an Adler-32 algorithm.
//
// --[ License ] --------------------------------------------------------------
//
// This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages
// arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it
// freely, subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented; you must not
// claim that you wrote the original software. If you use this software
// in a product, an acknowledgment in the product documentation would be
// appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such, and must not be
// misrepresented as being the original software.
// 3. This notice may not be removed or altered from any source distribution.
//
// ----------------------------------------------------------------------------
// Copyright © 2011-2023 Natalia Portillo
// Copyright (C) 1995-2011 Mark Adler
// Copyright (C) Jean-loup Gailly
// ****************************************************************************/
using System;
using System.Diagnostics.CodeAnalysis;
using System.IO;
using System.Runtime.InteropServices;
#if NET5_0_OR_GREATER
using System.Runtime.Intrinsics.Arm;
#endif
using System.Text;
#if NETCOREAPP3_1_OR_GREATER
using Aaru.Checksums.Adler32;
#endif
using Aaru.CommonTypes.Interfaces;
using Aaru.Helpers;
#if NETCOREAPP3_1_OR_GREATER
using Ssse3 = System.Runtime.Intrinsics.X86.Ssse3;
#endif
namespace Aaru.Checksums;
/// <inheritdoc />
/// <summary>Implements the Adler-32 algorithm</summary>
[SuppressMessage("ReSharper", "UnusedMethodReturnValue.Global")]
public sealed class Adler32Context : IChecksum
{
internal const ushort ADLER_MODULE = 65521;
internal const uint NMAX = 5552;
readonly IntPtr _nativeContext;
readonly bool _useNative;
ushort _sum1, _sum2;
/// <summary>Initializes the Adler-32 sums</summary>
public Adler32Context()
{
_sum1 = 1;
_sum2 = 0;
if(!Native.IsSupported)
return;
_nativeContext = adler32_init();
_useNative = _nativeContext != IntPtr.Zero;
}
#region IChecksum Members
/// <inheritdoc />
public string Name => "Adler-32";
/// <inheritdoc />
public Guid Id => new("D69CF1E7-4A7B-4605-9291-3A1BE4C2951F");
/// <inheritdoc />
public string Author => "Natalia Portillo";
/// <inheritdoc />
/// <summary>Updates the hash with data.</summary>
/// <param name="data">Data buffer.</param>
/// <param name="len">Length of buffer to hash.</param>
public void Update(byte[] data, uint len) => Step(ref _sum1, ref _sum2, data, len, _useNative, _nativeContext);
/// <inheritdoc />
/// <summary>Updates the hash with data.</summary>
/// <param name="data">Data buffer.</param>
public void Update(byte[] data) => Update(data, (uint)data.Length);
/// <inheritdoc />
/// <summary>Returns a byte array of the hash value.</summary>
public byte[] Final()
{
var finalSum = (uint)(_sum2 << 16 | _sum1);
if(!_useNative)
return BigEndianBitConverter.GetBytes(finalSum);
adler32_final(_nativeContext, ref finalSum);
adler32_free(_nativeContext);
return BigEndianBitConverter.GetBytes(finalSum);
}
/// <inheritdoc />
/// <summary>Returns a hexadecimal representation of the hash value.</summary>
public string End()
{
var finalSum = (uint)(_sum2 << 16 | _sum1);
if(_useNative)
{
adler32_final(_nativeContext, ref finalSum);
adler32_free(_nativeContext);
}
var adlerOutput = new StringBuilder();
for(var i = 0; i < BigEndianBitConverter.GetBytes(finalSum).Length; i++)
adlerOutput.Append(BigEndianBitConverter.GetBytes(finalSum)[i].ToString("x2"));
return adlerOutput.ToString();
}
#endregion
[DllImport("libAaru.Checksums.Native", SetLastError = true)]
static extern IntPtr adler32_init();
[DllImport("libAaru.Checksums.Native", SetLastError = true)]
static extern int adler32_update(IntPtr ctx, byte[] data, uint len);
[DllImport("libAaru.Checksums.Native", SetLastError = true)]
static extern int adler32_final(IntPtr ctx, ref uint checksum);
[DllImport("libAaru.Checksums.Native", SetLastError = true)]
static extern void adler32_free(IntPtr ctx);
static void Step(ref ushort preSum1, ref ushort preSum2, byte[] data, uint len, bool useNative,
IntPtr nativeContext)
{
if(useNative)
{
adler32_update(nativeContext, data, len);
return;
}
#if NETCOREAPP3_1_OR_GREATER
if(Ssse3.IsSupported)
{
Adler32.Ssse3.Step(ref preSum1, ref preSum2, data, len);
return;
}
#endif
#if NET5_0_OR_GREATER
if(AdvSimd.IsSupported)
{
Neon.Step(ref preSum1, ref preSum2, data, len);
return;
}
#endif
uint sum1 = preSum1;
uint sum2 = preSum2;
var dataOff = 0;
switch(len)
{
/* in case user likes doing a byte at a time, keep it fast */
case 1:
{
sum1 += data[dataOff];
if(sum1 >= ADLER_MODULE)
sum1 -= ADLER_MODULE;
sum2 += sum1;
if(sum2 >= ADLER_MODULE)
sum2 -= ADLER_MODULE;
preSum1 = (ushort)(sum1 & 0xFFFF);
preSum2 = (ushort)(sum2 & 0xFFFF);
return;
}
/* in case short lengths are provided, keep it somewhat fast */
case < 16:
{
while(len-- > 0)
{
sum1 += data[dataOff++];
sum2 += sum1;
}
if(sum1 >= ADLER_MODULE)
sum1 -= ADLER_MODULE;
sum2 %= ADLER_MODULE; /* only added so many ADLER_MODULE's */
preSum1 = (ushort)(sum1 & 0xFFFF);
preSum2 = (ushort)(sum2 & 0xFFFF);
return;
}
}
/* do length NMAX blocks -- requires just one modulo operation */
while(len >= NMAX)
{
len -= NMAX;
uint n = NMAX / 16;
do
{
sum1 += data[dataOff];
sum2 += sum1;
sum1 += data[dataOff + 1];
sum2 += sum1;
sum1 += data[dataOff + 2];
sum2 += sum1;
sum1 += data[dataOff + 2 + 1];
sum2 += sum1;
sum1 += data[dataOff + 4];
sum2 += sum1;
sum1 += data[dataOff + 4 + 1];
sum2 += sum1;
sum1 += data[dataOff + 4 + 2];
sum2 += sum1;
sum1 += data[dataOff + 4 + 2 + 1];
sum2 += sum1;
sum1 += data[dataOff + 8];
sum2 += sum1;
sum1 += data[dataOff + 8 + 1];
sum2 += sum1;
sum1 += data[dataOff + 8 + 2];
sum2 += sum1;
sum1 += data[dataOff + 8 + 2 + 1];
sum2 += sum1;
sum1 += data[dataOff + 8 + 4];
sum2 += sum1;
sum1 += data[dataOff + 8 + 4 + 1];
sum2 += sum1;
sum1 += data[dataOff + 8 + 4 + 2];
sum2 += sum1;
sum1 += data[dataOff + 8 + 4 + 2 + 1];
sum2 += sum1;
/* 16 sums unrolled */
dataOff += 16;
} while(--n != 0);
sum1 %= ADLER_MODULE;
sum2 %= ADLER_MODULE;
}
/* do remaining bytes (less than NMAX, still just one modulo) */
if(len != 0)
{
/* avoid modulos if none remaining */
while(len >= 16)
{
len -= 16;
sum1 += data[dataOff];
sum2 += sum1;
sum1 += data[dataOff + 1];
sum2 += sum1;
sum1 += data[dataOff + 2];
sum2 += sum1;
sum1 += data[dataOff + 2 + 1];
sum2 += sum1;
sum1 += data[dataOff + 4];
sum2 += sum1;
sum1 += data[dataOff + 4 + 1];
sum2 += sum1;
sum1 += data[dataOff + 4 + 2];
sum2 += sum1;
sum1 += data[dataOff + 4 + 2 + 1];
sum2 += sum1;
sum1 += data[dataOff + 8];
sum2 += sum1;
sum1 += data[dataOff + 8 + 1];
sum2 += sum1;
sum1 += data[dataOff + 8 + 2];
sum2 += sum1;
sum1 += data[dataOff + 8 + 2 + 1];
sum2 += sum1;
sum1 += data[dataOff + 8 + 4];
sum2 += sum1;
sum1 += data[dataOff + 8 + 4 + 1];
sum2 += sum1;
sum1 += data[dataOff + 8 + 4 + 2];
sum2 += sum1;
sum1 += data[dataOff + 8 + 4 + 2 + 1];
sum2 += sum1;
dataOff += 16;
}
while(len-- != 0)
{
sum1 += data[dataOff++];
sum2 += sum1;
}
sum1 %= ADLER_MODULE;
sum2 %= ADLER_MODULE;
}
preSum1 = (ushort)(sum1 & 0xFFFF);
preSum2 = (ushort)(sum2 & 0xFFFF);
}
/// <summary>Gets the hash of a file</summary>
/// <param name="filename">File path.</param>
public static byte[] File(string filename)
{
File(filename, out byte[] hash);
return hash;
}
/// <summary>Gets the hash of a file in hexadecimal and as a byte array.</summary>
/// <param name="filename">File path.</param>
/// <param name="hash">Byte array of the hash value.</param>
public static string File(string filename, out byte[] hash)
{
bool useNative = Native.IsSupported;
IntPtr nativeContext = IntPtr.Zero;
if(useNative)
{
nativeContext = adler32_init();
if(nativeContext == IntPtr.Zero)
useNative = false;
}
var fileStream = new FileStream(filename, FileMode.Open);
ushort localSum1 = 1;
ushort localSum2 = 0;
var buffer = new byte[65536];
int read = fileStream.EnsureRead(buffer, 0, 65536);
while(read > 0)
{
Step(ref localSum1, ref localSum2, buffer, (uint)read, useNative, nativeContext);
read = fileStream.EnsureRead(buffer, 0, 65536);
}
var finalSum = (uint)(localSum2 << 16 | localSum1);
if(useNative)
{
adler32_final(nativeContext, ref finalSum);
adler32_free(nativeContext);
}
hash = BigEndianBitConverter.GetBytes(finalSum);
var adlerOutput = new StringBuilder();
foreach(byte h in hash)
adlerOutput.Append(h.ToString("x2"));
fileStream.Close();
return adlerOutput.ToString();
}
/// <summary>Gets the hash of the specified data buffer.</summary>
/// <param name="data">Data buffer.</param>
/// <param name="len">Length of the data buffer to hash.</param>
/// <param name="hash">Byte array of the hash value.</param>
public static string Data(byte[] data, uint len, out byte[] hash)
{
bool useNative = Native.IsSupported;
IntPtr nativeContext = IntPtr.Zero;
if(useNative)
{
nativeContext = adler32_init();
if(nativeContext == IntPtr.Zero)
useNative = false;
}
ushort localSum1 = 1;
ushort localSum2 = 0;
Step(ref localSum1, ref localSum2, data, len, useNative, nativeContext);
var finalSum = (uint)(localSum2 << 16 | localSum1);
if(useNative)
{
adler32_final(nativeContext, ref finalSum);
adler32_free(nativeContext);
}
hash = BigEndianBitConverter.GetBytes(finalSum);
var adlerOutput = new StringBuilder();
foreach(byte h in hash)
adlerOutput.Append(h.ToString("x2"));
return adlerOutput.ToString();
}
/// <summary>Gets the hash of the specified data buffer.</summary>
/// <param name="data">Data buffer.</param>
/// <param name="hash">Byte array of the hash value.</param>
public static string Data(byte[] data, out byte[] hash) => Data(data, (uint)data.Length, out hash);
}

View File

@@ -0,0 +1,274 @@
// /***************************************************************************
// Aaru Data Preservation Suite
// ----------------------------------------------------------------------------
//
// Filename : CRC16CCITTContext.cs
// Author(s) : Natalia Portillo <claunia@claunia.com>
//
// Component : Checksums.
//
// --[ Description ] ----------------------------------------------------------
//
// Implements a CRC16 algorithm with the CCITT polynomial.
//
// --[ License ] --------------------------------------------------------------
//
// This library is free software; you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as
// published by the Free Software Foundation; either version 2.1 of the
// License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, see <http://www.gnu.org/licenses/>.
//
// ----------------------------------------------------------------------------
// Copyright © 2011-2023 Natalia Portillo
// ****************************************************************************/
using System;
using System.Diagnostics.CodeAnalysis;
namespace Aaru.Checksums;
/// <inheritdoc />
/// <summary>Implements the CRC16 algorithm with CCITT polynomial and seed</summary>
[SuppressMessage("ReSharper", "UnusedMethodReturnValue.Global")]
public sealed class CRC16CcittContext : Crc16Context
{
/// <summary>CCITT CRC16 polynomial</summary>
public const ushort CRC16_CCITT_POLY = 0x8408;
/// <summary>CCITT CRC16 seed</summary>
public const ushort CRC16_CCITT_SEED = 0x0000;
static readonly ushort[][] _ccittCrc16Table =
{
new ushort[]
{
0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50A5, 0x60C6, 0x70E7, 0x8108, 0x9129, 0xA14A, 0xB16B, 0xC18C,
0xD1AD, 0xE1CE, 0xF1EF, 0x1231, 0x0210, 0x3273, 0x2252, 0x52B5, 0x4294, 0x72F7, 0x62D6, 0x9339, 0x8318,
0xB37B, 0xA35A, 0xD3BD, 0xC39C, 0xF3FF, 0xE3DE, 0x2462, 0x3443, 0x0420, 0x1401, 0x64E6, 0x74C7, 0x44A4,
0x5485, 0xA56A, 0xB54B, 0x8528, 0x9509, 0xE5EE, 0xF5CF, 0xC5AC, 0xD58D, 0x3653, 0x2672, 0x1611, 0x0630,
0x76D7, 0x66F6, 0x5695, 0x46B4, 0xB75B, 0xA77A, 0x9719, 0x8738, 0xF7DF, 0xE7FE, 0xD79D, 0xC7BC, 0x48C4,
0x58E5, 0x6886, 0x78A7, 0x0840, 0x1861, 0x2802, 0x3823, 0xC9CC, 0xD9ED, 0xE98E, 0xF9AF, 0x8948, 0x9969,
0xA90A, 0xB92B, 0x5AF5, 0x4AD4, 0x7AB7, 0x6A96, 0x1A71, 0x0A50, 0x3A33, 0x2A12, 0xDBFD, 0xCBDC, 0xFBBF,
0xEB9E, 0x9B79, 0x8B58, 0xBB3B, 0xAB1A, 0x6CA6, 0x7C87, 0x4CE4, 0x5CC5, 0x2C22, 0x3C03, 0x0C60, 0x1C41,
0xEDAE, 0xFD8F, 0xCDEC, 0xDDCD, 0xAD2A, 0xBD0B, 0x8D68, 0x9D49, 0x7E97, 0x6EB6, 0x5ED5, 0x4EF4, 0x3E13,
0x2E32, 0x1E51, 0x0E70, 0xFF9F, 0xEFBE, 0xDFDD, 0xCFFC, 0xBF1B, 0xAF3A, 0x9F59, 0x8F78, 0x9188, 0x81A9,
0xB1CA, 0xA1EB, 0xD10C, 0xC12D, 0xF14E, 0xE16F, 0x1080, 0x00A1, 0x30C2, 0x20E3, 0x5004, 0x4025, 0x7046,
0x6067, 0x83B9, 0x9398, 0xA3FB, 0xB3DA, 0xC33D, 0xD31C, 0xE37F, 0xF35E, 0x02B1, 0x1290, 0x22F3, 0x32D2,
0x4235, 0x5214, 0x6277, 0x7256, 0xB5EA, 0xA5CB, 0x95A8, 0x8589, 0xF56E, 0xE54F, 0xD52C, 0xC50D, 0x34E2,
0x24C3, 0x14A0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405, 0xA7DB, 0xB7FA, 0x8799, 0x97B8, 0xE75F, 0xF77E,
0xC71D, 0xD73C, 0x26D3, 0x36F2, 0x0691, 0x16B0, 0x6657, 0x7676, 0x4615, 0x5634, 0xD94C, 0xC96D, 0xF90E,
0xE92F, 0x99C8, 0x89E9, 0xB98A, 0xA9AB, 0x5844, 0x4865, 0x7806, 0x6827, 0x18C0, 0x08E1, 0x3882, 0x28A3,
0xCB7D, 0xDB5C, 0xEB3F, 0xFB1E, 0x8BF9, 0x9BD8, 0xABBB, 0xBB9A, 0x4A75, 0x5A54, 0x6A37, 0x7A16, 0x0AF1,
0x1AD0, 0x2AB3, 0x3A92, 0xFD2E, 0xED0F, 0xDD6C, 0xCD4D, 0xBDAA, 0xAD8B, 0x9DE8, 0x8DC9, 0x7C26, 0x6C07,
0x5C64, 0x4C45, 0x3CA2, 0x2C83, 0x1CE0, 0x0CC1, 0xEF1F, 0xFF3E, 0xCF5D, 0xDF7C, 0xAF9B, 0xBFBA, 0x8FD9,
0x9FF8, 0x6E17, 0x7E36, 0x4E55, 0x5E74, 0x2E93, 0x3EB2, 0x0ED1, 0x1EF0
},
new ushort[]
{
0x0000, 0x3331, 0x6662, 0x5553, 0xCCC4, 0xFFF5, 0xAAA6, 0x9997, 0x89A9, 0xBA98, 0xEFCB, 0xDCFA, 0x456D,
0x765C, 0x230F, 0x103E, 0x0373, 0x3042, 0x6511, 0x5620, 0xCFB7, 0xFC86, 0xA9D5, 0x9AE4, 0x8ADA, 0xB9EB,
0xECB8, 0xDF89, 0x461E, 0x752F, 0x207C, 0x134D, 0x06E6, 0x35D7, 0x6084, 0x53B5, 0xCA22, 0xF913, 0xAC40,
0x9F71, 0x8F4F, 0xBC7E, 0xE92D, 0xDA1C, 0x438B, 0x70BA, 0x25E9, 0x16D8, 0x0595, 0x36A4, 0x63F7, 0x50C6,
0xC951, 0xFA60, 0xAF33, 0x9C02, 0x8C3C, 0xBF0D, 0xEA5E, 0xD96F, 0x40F8, 0x73C9, 0x269A, 0x15AB, 0x0DCC,
0x3EFD, 0x6BAE, 0x589F, 0xC108, 0xF239, 0xA76A, 0x945B, 0x8465, 0xB754, 0xE207, 0xD136, 0x48A1, 0x7B90,
0x2EC3, 0x1DF2, 0x0EBF, 0x3D8E, 0x68DD, 0x5BEC, 0xC27B, 0xF14A, 0xA419, 0x9728, 0x8716, 0xB427, 0xE174,
0xD245, 0x4BD2, 0x78E3, 0x2DB0, 0x1E81, 0x0B2A, 0x381B, 0x6D48, 0x5E79, 0xC7EE, 0xF4DF, 0xA18C, 0x92BD,
0x8283, 0xB1B2, 0xE4E1, 0xD7D0, 0x4E47, 0x7D76, 0x2825, 0x1B14, 0x0859, 0x3B68, 0x6E3B, 0x5D0A, 0xC49D,
0xF7AC, 0xA2FF, 0x91CE, 0x81F0, 0xB2C1, 0xE792, 0xD4A3, 0x4D34, 0x7E05, 0x2B56, 0x1867, 0x1B98, 0x28A9,
0x7DFA, 0x4ECB, 0xD75C, 0xE46D, 0xB13E, 0x820F, 0x9231, 0xA100, 0xF453, 0xC762, 0x5EF5, 0x6DC4, 0x3897,
0x0BA6, 0x18EB, 0x2BDA, 0x7E89, 0x4DB8, 0xD42F, 0xE71E, 0xB24D, 0x817C, 0x9142, 0xA273, 0xF720, 0xC411,
0x5D86, 0x6EB7, 0x3BE4, 0x08D5, 0x1D7E, 0x2E4F, 0x7B1C, 0x482D, 0xD1BA, 0xE28B, 0xB7D8, 0x84E9, 0x94D7,
0xA7E6, 0xF2B5, 0xC184, 0x5813, 0x6B22, 0x3E71, 0x0D40, 0x1E0D, 0x2D3C, 0x786F, 0x4B5E, 0xD2C9, 0xE1F8,
0xB4AB, 0x879A, 0x97A4, 0xA495, 0xF1C6, 0xC2F7, 0x5B60, 0x6851, 0x3D02, 0x0E33, 0x1654, 0x2565, 0x7036,
0x4307, 0xDA90, 0xE9A1, 0xBCF2, 0x8FC3, 0x9FFD, 0xACCC, 0xF99F, 0xCAAE, 0x5339, 0x6008, 0x355B, 0x066A,
0x1527, 0x2616, 0x7345, 0x4074, 0xD9E3, 0xEAD2, 0xBF81, 0x8CB0, 0x9C8E, 0xAFBF, 0xFAEC, 0xC9DD, 0x504A,
0x637B, 0x3628, 0x0519, 0x10B2, 0x2383, 0x76D0, 0x45E1, 0xDC76, 0xEF47, 0xBA14, 0x8925, 0x991B, 0xAA2A,
0xFF79, 0xCC48, 0x55DF, 0x66EE, 0x33BD, 0x008C, 0x13C1, 0x20F0, 0x75A3, 0x4692, 0xDF05, 0xEC34, 0xB967,
0x8A56, 0x9A68, 0xA959, 0xFC0A, 0xCF3B, 0x56AC, 0x659D, 0x30CE, 0x03FF
},
new ushort[]
{
0x0000, 0x3730, 0x6E60, 0x5950, 0xDCC0, 0xEBF0, 0xB2A0, 0x8590, 0xA9A1, 0x9E91, 0xC7C1, 0xF0F1, 0x7561,
0x4251, 0x1B01, 0x2C31, 0x4363, 0x7453, 0x2D03, 0x1A33, 0x9FA3, 0xA893, 0xF1C3, 0xC6F3, 0xEAC2, 0xDDF2,
0x84A2, 0xB392, 0x3602, 0x0132, 0x5862, 0x6F52, 0x86C6, 0xB1F6, 0xE8A6, 0xDF96, 0x5A06, 0x6D36, 0x3466,
0x0356, 0x2F67, 0x1857, 0x4107, 0x7637, 0xF3A7, 0xC497, 0x9DC7, 0xAAF7, 0xC5A5, 0xF295, 0xABC5, 0x9CF5,
0x1965, 0x2E55, 0x7705, 0x4035, 0x6C04, 0x5B34, 0x0264, 0x3554, 0xB0C4, 0x87F4, 0xDEA4, 0xE994, 0x1DAD,
0x2A9D, 0x73CD, 0x44FD, 0xC16D, 0xF65D, 0xAF0D, 0x983D, 0xB40C, 0x833C, 0xDA6C, 0xED5C, 0x68CC, 0x5FFC,
0x06AC, 0x319C, 0x5ECE, 0x69FE, 0x30AE, 0x079E, 0x820E, 0xB53E, 0xEC6E, 0xDB5E, 0xF76F, 0xC05F, 0x990F,
0xAE3F, 0x2BAF, 0x1C9F, 0x45CF, 0x72FF, 0x9B6B, 0xAC5B, 0xF50B, 0xC23B, 0x47AB, 0x709B, 0x29CB, 0x1EFB,
0x32CA, 0x05FA, 0x5CAA, 0x6B9A, 0xEE0A, 0xD93A, 0x806A, 0xB75A, 0xD808, 0xEF38, 0xB668, 0x8158, 0x04C8,
0x33F8, 0x6AA8, 0x5D98, 0x71A9, 0x4699, 0x1FC9, 0x28F9, 0xAD69, 0x9A59, 0xC309, 0xF439, 0x3B5A, 0x0C6A,
0x553A, 0x620A, 0xE79A, 0xD0AA, 0x89FA, 0xBECA, 0x92FB, 0xA5CB, 0xFC9B, 0xCBAB, 0x4E3B, 0x790B, 0x205B,
0x176B, 0x7839, 0x4F09, 0x1659, 0x2169, 0xA4F9, 0x93C9, 0xCA99, 0xFDA9, 0xD198, 0xE6A8, 0xBFF8, 0x88C8,
0x0D58, 0x3A68, 0x6338, 0x5408, 0xBD9C, 0x8AAC, 0xD3FC, 0xE4CC, 0x615C, 0x566C, 0x0F3C, 0x380C, 0x143D,
0x230D, 0x7A5D, 0x4D6D, 0xC8FD, 0xFFCD, 0xA69D, 0x91AD, 0xFEFF, 0xC9CF, 0x909F, 0xA7AF, 0x223F, 0x150F,
0x4C5F, 0x7B6F, 0x575E, 0x606E, 0x393E, 0x0E0E, 0x8B9E, 0xBCAE, 0xE5FE, 0xD2CE, 0x26F7, 0x11C7, 0x4897,
0x7FA7, 0xFA37, 0xCD07, 0x9457, 0xA367, 0x8F56, 0xB866, 0xE136, 0xD606, 0x5396, 0x64A6, 0x3DF6, 0x0AC6,
0x6594, 0x52A4, 0x0BF4, 0x3CC4, 0xB954, 0x8E64, 0xD734, 0xE004, 0xCC35, 0xFB05, 0xA255, 0x9565, 0x10F5,
0x27C5, 0x7E95, 0x49A5, 0xA031, 0x9701, 0xCE51, 0xF961, 0x7CF1, 0x4BC1, 0x1291, 0x25A1, 0x0990, 0x3EA0,
0x67F0, 0x50C0, 0xD550, 0xE260, 0xBB30, 0x8C00, 0xE352, 0xD462, 0x8D32, 0xBA02, 0x3F92, 0x08A2, 0x51F2,
0x66C2, 0x4AF3, 0x7DC3, 0x2493, 0x13A3, 0x9633, 0xA103, 0xF853, 0xCF63
},
new ushort[]
{
0x0000, 0x76B4, 0xED68, 0x9BDC, 0xCAF1, 0xBC45, 0x2799, 0x512D, 0x85C3, 0xF377, 0x68AB, 0x1E1F, 0x4F32,
0x3986, 0xA25A, 0xD4EE, 0x1BA7, 0x6D13, 0xF6CF, 0x807B, 0xD156, 0xA7E2, 0x3C3E, 0x4A8A, 0x9E64, 0xE8D0,
0x730C, 0x05B8, 0x5495, 0x2221, 0xB9FD, 0xCF49, 0x374E, 0x41FA, 0xDA26, 0xAC92, 0xFDBF, 0x8B0B, 0x10D7,
0x6663, 0xB28D, 0xC439, 0x5FE5, 0x2951, 0x787C, 0x0EC8, 0x9514, 0xE3A0, 0x2CE9, 0x5A5D, 0xC181, 0xB735,
0xE618, 0x90AC, 0x0B70, 0x7DC4, 0xA92A, 0xDF9E, 0x4442, 0x32F6, 0x63DB, 0x156F, 0x8EB3, 0xF807, 0x6E9C,
0x1828, 0x83F4, 0xF540, 0xA46D, 0xD2D9, 0x4905, 0x3FB1, 0xEB5F, 0x9DEB, 0x0637, 0x7083, 0x21AE, 0x571A,
0xCCC6, 0xBA72, 0x753B, 0x038F, 0x9853, 0xEEE7, 0xBFCA, 0xC97E, 0x52A2, 0x2416, 0xF0F8, 0x864C, 0x1D90,
0x6B24, 0x3A09, 0x4CBD, 0xD761, 0xA1D5, 0x59D2, 0x2F66, 0xB4BA, 0xC20E, 0x9323, 0xE597, 0x7E4B, 0x08FF,
0xDC11, 0xAAA5, 0x3179, 0x47CD, 0x16E0, 0x6054, 0xFB88, 0x8D3C, 0x4275, 0x34C1, 0xAF1D, 0xD9A9, 0x8884,
0xFE30, 0x65EC, 0x1358, 0xC7B6, 0xB102, 0x2ADE, 0x5C6A, 0x0D47, 0x7BF3, 0xE02F, 0x969B, 0xDD38, 0xAB8C,
0x3050, 0x46E4, 0x17C9, 0x617D, 0xFAA1, 0x8C15, 0x58FB, 0x2E4F, 0xB593, 0xC327, 0x920A, 0xE4BE, 0x7F62,
0x09D6, 0xC69F, 0xB02B, 0x2BF7, 0x5D43, 0x0C6E, 0x7ADA, 0xE106, 0x97B2, 0x435C, 0x35E8, 0xAE34, 0xD880,
0x89AD, 0xFF19, 0x64C5, 0x1271, 0xEA76, 0x9CC2, 0x071E, 0x71AA, 0x2087, 0x5633, 0xCDEF, 0xBB5B, 0x6FB5,
0x1901, 0x82DD, 0xF469, 0xA544, 0xD3F0, 0x482C, 0x3E98, 0xF1D1, 0x8765, 0x1CB9, 0x6A0D, 0x3B20, 0x4D94,
0xD648, 0xA0FC, 0x7412, 0x02A6, 0x997A, 0xEFCE, 0xBEE3, 0xC857, 0x538B, 0x253F, 0xB3A4, 0xC510, 0x5ECC,
0x2878, 0x7955, 0x0FE1, 0x943D, 0xE289, 0x3667, 0x40D3, 0xDB0F, 0xADBB, 0xFC96, 0x8A22, 0x11FE, 0x674A,
0xA803, 0xDEB7, 0x456B, 0x33DF, 0x62F2, 0x1446, 0x8F9A, 0xF92E, 0x2DC0, 0x5B74, 0xC0A8, 0xB61C, 0xE731,
0x9185, 0x0A59, 0x7CED, 0x84EA, 0xF25E, 0x6982, 0x1F36, 0x4E1B, 0x38AF, 0xA373, 0xD5C7, 0x0129, 0x779D,
0xEC41, 0x9AF5, 0xCBD8, 0xBD6C, 0x26B0, 0x5004, 0x9F4D, 0xE9F9, 0x7225, 0x0491, 0x55BC, 0x2308, 0xB8D4,
0xCE60, 0x1A8E, 0x6C3A, 0xF7E6, 0x8152, 0xD07F, 0xA6CB, 0x3D17, 0x4BA3
},
new ushort[]
{
0x0000, 0xAA51, 0x4483, 0xEED2, 0x8906, 0x2357, 0xCD85, 0x67D4, 0x022D, 0xA87C, 0x46AE, 0xECFF, 0x8B2B,
0x217A, 0xCFA8, 0x65F9, 0x045A, 0xAE0B, 0x40D9, 0xEA88, 0x8D5C, 0x270D, 0xC9DF, 0x638E, 0x0677, 0xAC26,
0x42F4, 0xE8A5, 0x8F71, 0x2520, 0xCBF2, 0x61A3, 0x08B4, 0xA2E5, 0x4C37, 0xE666, 0x81B2, 0x2BE3, 0xC531,
0x6F60, 0x0A99, 0xA0C8, 0x4E1A, 0xE44B, 0x839F, 0x29CE, 0xC71C, 0x6D4D, 0x0CEE, 0xA6BF, 0x486D, 0xE23C,
0x85E8, 0x2FB9, 0xC16B, 0x6B3A, 0x0EC3, 0xA492, 0x4A40, 0xE011, 0x87C5, 0x2D94, 0xC346, 0x6917, 0x1168,
0xBB39, 0x55EB, 0xFFBA, 0x986E, 0x323F, 0xDCED, 0x76BC, 0x1345, 0xB914, 0x57C6, 0xFD97, 0x9A43, 0x3012,
0xDEC0, 0x7491, 0x1532, 0xBF63, 0x51B1, 0xFBE0, 0x9C34, 0x3665, 0xD8B7, 0x72E6, 0x171F, 0xBD4E, 0x539C,
0xF9CD, 0x9E19, 0x3448, 0xDA9A, 0x70CB, 0x19DC, 0xB38D, 0x5D5F, 0xF70E, 0x90DA, 0x3A8B, 0xD459, 0x7E08,
0x1BF1, 0xB1A0, 0x5F72, 0xF523, 0x92F7, 0x38A6, 0xD674, 0x7C25, 0x1D86, 0xB7D7, 0x5905, 0xF354, 0x9480,
0x3ED1, 0xD003, 0x7A52, 0x1FAB, 0xB5FA, 0x5B28, 0xF179, 0x96AD, 0x3CFC, 0xD22E, 0x787F, 0x22D0, 0x8881,
0x6653, 0xCC02, 0xABD6, 0x0187, 0xEF55, 0x4504, 0x20FD, 0x8AAC, 0x647E, 0xCE2F, 0xA9FB, 0x03AA, 0xED78,
0x4729, 0x268A, 0x8CDB, 0x6209, 0xC858, 0xAF8C, 0x05DD, 0xEB0F, 0x415E, 0x24A7, 0x8EF6, 0x6024, 0xCA75,
0xADA1, 0x07F0, 0xE922, 0x4373, 0x2A64, 0x8035, 0x6EE7, 0xC4B6, 0xA362, 0x0933, 0xE7E1, 0x4DB0, 0x2849,
0x8218, 0x6CCA, 0xC69B, 0xA14F, 0x0B1E, 0xE5CC, 0x4F9D, 0x2E3E, 0x846F, 0x6ABD, 0xC0EC, 0xA738, 0x0D69,
0xE3BB, 0x49EA, 0x2C13, 0x8642, 0x6890, 0xC2C1, 0xA515, 0x0F44, 0xE196, 0x4BC7, 0x33B8, 0x99E9, 0x773B,
0xDD6A, 0xBABE, 0x10EF, 0xFE3D, 0x546C, 0x3195, 0x9BC4, 0x7516, 0xDF47, 0xB893, 0x12C2, 0xFC10, 0x5641,
0x37E2, 0x9DB3, 0x7361, 0xD930, 0xBEE4, 0x14B5, 0xFA67, 0x5036, 0x35CF, 0x9F9E, 0x714C, 0xDB1D, 0xBCC9,
0x1698, 0xF84A, 0x521B, 0x3B0C, 0x915D, 0x7F8F, 0xD5DE, 0xB20A, 0x185B, 0xF689, 0x5CD8, 0x3921, 0x9370,
0x7DA2, 0xD7F3, 0xB027, 0x1A76, 0xF4A4, 0x5EF5, 0x3F56, 0x9507, 0x7BD5, 0xD184, 0xB650, 0x1C01, 0xF2D3,
0x5882, 0x3D7B, 0x972A, 0x79F8, 0xD3A9, 0xB47D, 0x1E2C, 0xF0FE, 0x5AAF
},
new ushort[]
{
0x0000, 0x45A0, 0x8B40, 0xCEE0, 0x06A1, 0x4301, 0x8DE1, 0xC841, 0x0D42, 0x48E2, 0x8602, 0xC3A2, 0x0BE3,
0x4E43, 0x80A3, 0xC503, 0x1A84, 0x5F24, 0x91C4, 0xD464, 0x1C25, 0x5985, 0x9765, 0xD2C5, 0x17C6, 0x5266,
0x9C86, 0xD926, 0x1167, 0x54C7, 0x9A27, 0xDF87, 0x3508, 0x70A8, 0xBE48, 0xFBE8, 0x33A9, 0x7609, 0xB8E9,
0xFD49, 0x384A, 0x7DEA, 0xB30A, 0xF6AA, 0x3EEB, 0x7B4B, 0xB5AB, 0xF00B, 0x2F8C, 0x6A2C, 0xA4CC, 0xE16C,
0x292D, 0x6C8D, 0xA26D, 0xE7CD, 0x22CE, 0x676E, 0xA98E, 0xEC2E, 0x246F, 0x61CF, 0xAF2F, 0xEA8F, 0x6A10,
0x2FB0, 0xE150, 0xA4F0, 0x6CB1, 0x2911, 0xE7F1, 0xA251, 0x6752, 0x22F2, 0xEC12, 0xA9B2, 0x61F3, 0x2453,
0xEAB3, 0xAF13, 0x7094, 0x3534, 0xFBD4, 0xBE74, 0x7635, 0x3395, 0xFD75, 0xB8D5, 0x7DD6, 0x3876, 0xF696,
0xB336, 0x7B77, 0x3ED7, 0xF037, 0xB597, 0x5F18, 0x1AB8, 0xD458, 0x91F8, 0x59B9, 0x1C19, 0xD2F9, 0x9759,
0x525A, 0x17FA, 0xD91A, 0x9CBA, 0x54FB, 0x115B, 0xDFBB, 0x9A1B, 0x459C, 0x003C, 0xCEDC, 0x8B7C, 0x433D,
0x069D, 0xC87D, 0x8DDD, 0x48DE, 0x0D7E, 0xC39E, 0x863E, 0x4E7F, 0x0BDF, 0xC53F, 0x809F, 0xD420, 0x9180,
0x5F60, 0x1AC0, 0xD281, 0x9721, 0x59C1, 0x1C61, 0xD962, 0x9CC2, 0x5222, 0x1782, 0xDFC3, 0x9A63, 0x5483,
0x1123, 0xCEA4, 0x8B04, 0x45E4, 0x0044, 0xC805, 0x8DA5, 0x4345, 0x06E5, 0xC3E6, 0x8646, 0x48A6, 0x0D06,
0xC547, 0x80E7, 0x4E07, 0x0BA7, 0xE128, 0xA488, 0x6A68, 0x2FC8, 0xE789, 0xA229, 0x6CC9, 0x2969, 0xEC6A,
0xA9CA, 0x672A, 0x228A, 0xEACB, 0xAF6B, 0x618B, 0x242B, 0xFBAC, 0xBE0C, 0x70EC, 0x354C, 0xFD0D, 0xB8AD,
0x764D, 0x33ED, 0xF6EE, 0xB34E, 0x7DAE, 0x380E, 0xF04F, 0xB5EF, 0x7B0F, 0x3EAF, 0xBE30, 0xFB90, 0x3570,
0x70D0, 0xB891, 0xFD31, 0x33D1, 0x7671, 0xB372, 0xF6D2, 0x3832, 0x7D92, 0xB5D3, 0xF073, 0x3E93, 0x7B33,
0xA4B4, 0xE114, 0x2FF4, 0x6A54, 0xA215, 0xE7B5, 0x2955, 0x6CF5, 0xA9F6, 0xEC56, 0x22B6, 0x6716, 0xAF57,
0xEAF7, 0x2417, 0x61B7, 0x8B38, 0xCE98, 0x0078, 0x45D8, 0x8D99, 0xC839, 0x06D9, 0x4379, 0x867A, 0xC3DA,
0x0D3A, 0x489A, 0x80DB, 0xC57B, 0x0B9B, 0x4E3B, 0x91BC, 0xD41C, 0x1AFC, 0x5F5C, 0x971D, 0xD2BD, 0x1C5D,
0x59FD, 0x9CFE, 0xD95E, 0x17BE, 0x521E, 0x9A5F, 0xDFFF, 0x111F, 0x54BF
},
new ushort[]
{
0x0000, 0xB861, 0x60E3, 0xD882, 0xC1C6, 0x79A7, 0xA125, 0x1944, 0x93AD, 0x2BCC, 0xF34E, 0x4B2F, 0x526B,
0xEA0A, 0x3288, 0x8AE9, 0x377B, 0x8F1A, 0x5798, 0xEFF9, 0xF6BD, 0x4EDC, 0x965E, 0x2E3F, 0xA4D6, 0x1CB7,
0xC435, 0x7C54, 0x6510, 0xDD71, 0x05F3, 0xBD92, 0x6EF6, 0xD697, 0x0E15, 0xB674, 0xAF30, 0x1751, 0xCFD3,
0x77B2, 0xFD5B, 0x453A, 0x9DB8, 0x25D9, 0x3C9D, 0x84FC, 0x5C7E, 0xE41F, 0x598D, 0xE1EC, 0x396E, 0x810F,
0x984B, 0x202A, 0xF8A8, 0x40C9, 0xCA20, 0x7241, 0xAAC3, 0x12A2, 0x0BE6, 0xB387, 0x6B05, 0xD364, 0xDDEC,
0x658D, 0xBD0F, 0x056E, 0x1C2A, 0xA44B, 0x7CC9, 0xC4A8, 0x4E41, 0xF620, 0x2EA2, 0x96C3, 0x8F87, 0x37E6,
0xEF64, 0x5705, 0xEA97, 0x52F6, 0x8A74, 0x3215, 0x2B51, 0x9330, 0x4BB2, 0xF3D3, 0x793A, 0xC15B, 0x19D9,
0xA1B8, 0xB8FC, 0x009D, 0xD81F, 0x607E, 0xB31A, 0x0B7B, 0xD3F9, 0x6B98, 0x72DC, 0xCABD, 0x123F, 0xAA5E,
0x20B7, 0x98D6, 0x4054, 0xF835, 0xE171, 0x5910, 0x8192, 0x39F3, 0x8461, 0x3C00, 0xE482, 0x5CE3, 0x45A7,
0xFDC6, 0x2544, 0x9D25, 0x17CC, 0xAFAD, 0x772F, 0xCF4E, 0xD60A, 0x6E6B, 0xB6E9, 0x0E88, 0xABF9, 0x1398,
0xCB1A, 0x737B, 0x6A3F, 0xD25E, 0x0ADC, 0xB2BD, 0x3854, 0x8035, 0x58B7, 0xE0D6, 0xF992, 0x41F3, 0x9971,
0x2110, 0x9C82, 0x24E3, 0xFC61, 0x4400, 0x5D44, 0xE525, 0x3DA7, 0x85C6, 0x0F2F, 0xB74E, 0x6FCC, 0xD7AD,
0xCEE9, 0x7688, 0xAE0A, 0x166B, 0xC50F, 0x7D6E, 0xA5EC, 0x1D8D, 0x04C9, 0xBCA8, 0x642A, 0xDC4B, 0x56A2,
0xEEC3, 0x3641, 0x8E20, 0x9764, 0x2F05, 0xF787, 0x4FE6, 0xF274, 0x4A15, 0x9297, 0x2AF6, 0x33B2, 0x8BD3,
0x5351, 0xEB30, 0x61D9, 0xD9B8, 0x013A, 0xB95B, 0xA01F, 0x187E, 0xC0FC, 0x789D, 0x7615, 0xCE74, 0x16F6,
0xAE97, 0xB7D3, 0x0FB2, 0xD730, 0x6F51, 0xE5B8, 0x5DD9, 0x855B, 0x3D3A, 0x247E, 0x9C1F, 0x449D, 0xFCFC,
0x416E, 0xF90F, 0x218D, 0x99EC, 0x80A8, 0x38C9, 0xE04B, 0x582A, 0xD2C3, 0x6AA2, 0xB220, 0x0A41, 0x1305,
0xAB64, 0x73E6, 0xCB87, 0x18E3, 0xA082, 0x7800, 0xC061, 0xD925, 0x6144, 0xB9C6, 0x01A7, 0x8B4E, 0x332F,
0xEBAD, 0x53CC, 0x4A88, 0xF2E9, 0x2A6B, 0x920A, 0x2F98, 0x97F9, 0x4F7B, 0xF71A, 0xEE5E, 0x563F, 0x8EBD,
0x36DC, 0xBC35, 0x0454, 0xDCD6, 0x64B7, 0x7DF3, 0xC592, 0x1D10, 0xA571
},
new ushort[]
{
0x0000, 0x47D3, 0x8FA6, 0xC875, 0x0F6D, 0x48BE, 0x80CB, 0xC718, 0x1EDA, 0x5909, 0x917C, 0xD6AF, 0x11B7,
0x5664, 0x9E11, 0xD9C2, 0x3DB4, 0x7A67, 0xB212, 0xF5C1, 0x32D9, 0x750A, 0xBD7F, 0xFAAC, 0x236E, 0x64BD,
0xACC8, 0xEB1B, 0x2C03, 0x6BD0, 0xA3A5, 0xE476, 0x7B68, 0x3CBB, 0xF4CE, 0xB31D, 0x7405, 0x33D6, 0xFBA3,
0xBC70, 0x65B2, 0x2261, 0xEA14, 0xADC7, 0x6ADF, 0x2D0C, 0xE579, 0xA2AA, 0x46DC, 0x010F, 0xC97A, 0x8EA9,
0x49B1, 0x0E62, 0xC617, 0x81C4, 0x5806, 0x1FD5, 0xD7A0, 0x9073, 0x576B, 0x10B8, 0xD8CD, 0x9F1E, 0xF6D0,
0xB103, 0x7976, 0x3EA5, 0xF9BD, 0xBE6E, 0x761B, 0x31C8, 0xE80A, 0xAFD9, 0x67AC, 0x207F, 0xE767, 0xA0B4,
0x68C1, 0x2F12, 0xCB64, 0x8CB7, 0x44C2, 0x0311, 0xC409, 0x83DA, 0x4BAF, 0x0C7C, 0xD5BE, 0x926D, 0x5A18,
0x1DCB, 0xDAD3, 0x9D00, 0x5575, 0x12A6, 0x8DB8, 0xCA6B, 0x021E, 0x45CD, 0x82D5, 0xC506, 0x0D73, 0x4AA0,
0x9362, 0xD4B1, 0x1CC4, 0x5B17, 0x9C0F, 0xDBDC, 0x13A9, 0x547A, 0xB00C, 0xF7DF, 0x3FAA, 0x7879, 0xBF61,
0xF8B2, 0x30C7, 0x7714, 0xAED6, 0xE905, 0x2170, 0x66A3, 0xA1BB, 0xE668, 0x2E1D, 0x69CE, 0xFD81, 0xBA52,
0x7227, 0x35F4, 0xF2EC, 0xB53F, 0x7D4A, 0x3A99, 0xE35B, 0xA488, 0x6CFD, 0x2B2E, 0xEC36, 0xABE5, 0x6390,
0x2443, 0xC035, 0x87E6, 0x4F93, 0x0840, 0xCF58, 0x888B, 0x40FE, 0x072D, 0xDEEF, 0x993C, 0x5149, 0x169A,
0xD182, 0x9651, 0x5E24, 0x19F7, 0x86E9, 0xC13A, 0x094F, 0x4E9C, 0x8984, 0xCE57, 0x0622, 0x41F1, 0x9833,
0xDFE0, 0x1795, 0x5046, 0x975E, 0xD08D, 0x18F8, 0x5F2B, 0xBB5D, 0xFC8E, 0x34FB, 0x7328, 0xB430, 0xF3E3,
0x3B96, 0x7C45, 0xA587, 0xE254, 0x2A21, 0x6DF2, 0xAAEA, 0xED39, 0x254C, 0x629F, 0x0B51, 0x4C82, 0x84F7,
0xC324, 0x043C, 0x43EF, 0x8B9A, 0xCC49, 0x158B, 0x5258, 0x9A2D, 0xDDFE, 0x1AE6, 0x5D35, 0x9540, 0xD293,
0x36E5, 0x7136, 0xB943, 0xFE90, 0x3988, 0x7E5B, 0xB62E, 0xF1FD, 0x283F, 0x6FEC, 0xA799, 0xE04A, 0x2752,
0x6081, 0xA8F4, 0xEF27, 0x7039, 0x37EA, 0xFF9F, 0xB84C, 0x7F54, 0x3887, 0xF0F2, 0xB721, 0x6EE3, 0x2930,
0xE145, 0xA696, 0x618E, 0x265D, 0xEE28, 0xA9FB, 0x4D8D, 0x0A5E, 0xC22B, 0x85F8, 0x42E0, 0x0533, 0xCD46,
0x8A95, 0x5357, 0x1484, 0xDCF1, 0x9B22, 0x5C3A, 0x1BE9, 0xD39C, 0x944F
}
};
/// <summary>Initializes an instance of the CRC16 with CCITT polynomial and seed.</summary>
/// <inheritdoc />
public CRC16CcittContext() : base(CRC16_CCITT_POLY, CRC16_CCITT_SEED, _ccittCrc16Table, true) {}
public new string Name => "CRC-16 (CCITT)";
public new Guid Id => new("4C3BD0D5-24BD-4D45-BC19-A90A5AA5CC9D");
public new string Author => "Natalia Portillo";
/// <summary>Gets the hash of a file</summary>
/// <param name="filename">File path.</param>
public static byte[] File(string filename)
{
File(filename, out byte[] hash);
return hash;
}
/// <summary>Gets the hash of a file in hexadecimal and as a byte array.</summary>
/// <param name="filename">File path.</param>
/// <param name="hash">Byte array of the hash value.</param>
public static string File(string filename, out byte[] hash) =>
File(filename, out hash, CRC16_CCITT_POLY, CRC16_CCITT_SEED, _ccittCrc16Table, true);
/// <summary>Gets the hash of the specified data buffer.</summary>
/// <param name="data">Data buffer.</param>
/// <param name="len">Length of the data buffer to hash.</param>
/// <param name="hash">Byte array of the hash value.</param>
public static string Data(byte[] data, uint len, out byte[] hash) =>
Data(data, len, out hash, CRC16_CCITT_POLY, CRC16_CCITT_SEED, _ccittCrc16Table, true);
/// <summary>Gets the hash of the specified data buffer.</summary>
/// <param name="data">Data buffer.</param>
/// <param name="hash">Byte array of the hash value.</param>
public static string Data(byte[] data, out byte[] hash) => Data(data, (uint)data.Length, out hash);
/// <summary>Calculates the CCITT CRC16 of the specified buffer with the specified parameters</summary>
/// <param name="buffer">Buffer</param>
public static ushort Calculate(byte[] buffer) =>
Calculate(buffer, CRC16_CCITT_POLY, CRC16_CCITT_SEED, _ccittCrc16Table, true);
}

View File

@@ -0,0 +1,649 @@
// /***************************************************************************
// Aaru Data Preservation Suite
// ----------------------------------------------------------------------------
//
// Filename : CRC16Context.cs
// Author(s) : Natalia Portillo <claunia@claunia.com>
//
// Component : Checksums.
//
// --[ Description ] ----------------------------------------------------------
//
// Implements a CRC16 algorithm.
//
// --[ License ] --------------------------------------------------------------
//
// This library is free software; you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as
// published by the Free Software Foundation; either version 2.1 of the
// License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, see <http://www.gnu.org/licenses/>.
//
// ----------------------------------------------------------------------------
// Copyright © 2011-2023 Natalia Portillo
// ****************************************************************************/
using System;
using System.IO;
using System.Runtime.InteropServices;
using System.Text;
using Aaru.CommonTypes.Interfaces;
using Aaru.Helpers;
namespace Aaru.Checksums;
/// <inheritdoc />
/// <summary>Implements a CRC16 algorithm</summary>
public class Crc16Context : IChecksum
{
readonly ushort _finalSeed;
readonly bool _inverse;
readonly IntPtr _nativeContext;
readonly ushort[][]? _table;
readonly bool _useCcitt;
readonly bool _useIbm;
readonly bool _useNative;
ushort _hashInt;
/// <summary>Initializes the CRC16 table with a custom polynomial and seed</summary>
public Crc16Context(ushort polynomial, ushort seed, ushort[][] table, bool inverse)
{
_hashInt = seed;
_finalSeed = seed;
_inverse = inverse;
_useNative = Native.IsSupported;
_useCcitt = polynomial == CRC16CcittContext.CRC16_CCITT_POLY &&
seed == CRC16CcittContext.CRC16_CCITT_SEED &&
inverse;
_useIbm = polynomial == CRC16IbmContext.CRC16_IBM_POLY && seed == CRC16IbmContext.CRC16_IBM_SEED && !inverse;
if(_useCcitt && _useNative)
{
_nativeContext = crc16_ccitt_init();
_useNative = _nativeContext != IntPtr.Zero;
}
else if(_useIbm && _useNative)
{
_nativeContext = crc16_init();
_useNative = _nativeContext != IntPtr.Zero;
}
else
_useNative = false;
if(!_useNative)
_table = table ?? GenerateTable(polynomial, inverse);
}
#region IChecksum Members
/// <inheritdoc />
public string Name => "CRC-16";
/// <inheritdoc />
public Guid Id => new("D69CF1E7-4A7B-4605-9291-3A1BE4C2951F");
/// <inheritdoc />
public string Author => "Natalia Portillo";
/// <inheritdoc />
/// <summary>Updates the hash with data.</summary>
/// <param name="data">Data buffer.</param>
/// <param name="len">Length of buffer to hash.</param>
public void Update(byte[] data, uint len)
{
switch(_useNative)
{
case true when _useCcitt:
crc16_ccitt_update(_nativeContext, data, len);
break;
case true when _useIbm:
crc16_update(_nativeContext, data, len);
break;
default:
{
if(_inverse)
StepInverse(ref _hashInt, _table!, data, len);
else
Step(ref _hashInt, _table!, data, len);
break;
}
}
}
/// <inheritdoc />
/// <summary>Updates the hash with data.</summary>
/// <param name="data">Data buffer.</param>
public void Update(byte[] data) => Update(data, (uint)data.Length);
/// <inheritdoc />
/// <summary>Returns a byte array of the hash value.</summary>
public byte[] Final()
{
ushort crc = 0;
switch(_useNative)
{
case true when _useCcitt:
crc16_ccitt_final(_nativeContext, ref crc);
crc16_ccitt_free(_nativeContext);
break;
case true when _useIbm:
crc16_final(_nativeContext, ref crc);
crc16_free(_nativeContext);
break;
default:
{
if(_inverse)
crc = (ushort)~(_hashInt ^ _finalSeed);
else
crc = (ushort)(_hashInt ^ _finalSeed);
break;
}
}
return BigEndianBitConverter.GetBytes(crc);
}
/// <inheritdoc />
/// <summary>Returns a hexadecimal representation of the hash value.</summary>
public string End()
{
var crc16Output = new StringBuilder();
ushort final = 0;
switch(_useNative)
{
case true when _useCcitt:
crc16_ccitt_final(_nativeContext, ref final);
crc16_ccitt_free(_nativeContext);
break;
case true when _useIbm:
crc16_final(_nativeContext, ref final);
crc16_free(_nativeContext);
break;
default:
{
if(_inverse)
final = (ushort)~(_hashInt ^ _finalSeed);
else
final = (ushort)(_hashInt ^ _finalSeed);
break;
}
}
byte[] finalBytes = BigEndianBitConverter.GetBytes(final);
foreach(byte t in finalBytes)
crc16Output.Append(t.ToString("x2"));
return crc16Output.ToString();
}
#endregion
[DllImport("libAaru.Checksums.Native", SetLastError = true)]
static extern IntPtr crc16_init();
[DllImport("libAaru.Checksums.Native", SetLastError = true)]
static extern int crc16_update(IntPtr ctx, byte[] data, uint len);
[DllImport("libAaru.Checksums.Native", SetLastError = true)]
static extern int crc16_final(IntPtr ctx, ref ushort crc);
[DllImport("libAaru.Checksums.Native", SetLastError = true)]
static extern void crc16_free(IntPtr ctx);
[DllImport("libAaru.Checksums.Native", SetLastError = true)]
static extern IntPtr crc16_ccitt_init();
[DllImport("libAaru.Checksums.Native", SetLastError = true)]
static extern int crc16_ccitt_update(IntPtr ctx, byte[] data, uint len);
[DllImport("libAaru.Checksums.Native", SetLastError = true)]
static extern int crc16_ccitt_final(IntPtr ctx, ref ushort crc);
[DllImport("libAaru.Checksums.Native", SetLastError = true)]
static extern void crc16_ccitt_free(IntPtr ctx);
static void Step(ref ushort previousCrc, ushort[][] table, byte[] data, uint len)
{
// Unroll according to Intel slicing by uint8_t
// http://www.intel.com/technology/comms/perfnet/download/CRC_generators.pdf
// http://sourceforge.net/projects/slicing-by-8/
var currentPos = 0;
const int unroll = 4;
const int bytesAtOnce = 8 * unroll;
ushort crc = previousCrc;
while(len >= bytesAtOnce)
{
int unrolling;
for(unrolling = 0; unrolling < unroll; unrolling++)
{
// TODO: What trick is Microsoft doing here that's faster than arithmetic conversion
uint one = BitConverter.ToUInt32(data, currentPos) ^ crc;
currentPos += 4;
var two = BitConverter.ToUInt32(data, currentPos);
currentPos += 4;
crc = (ushort)(table[0][two >> 24 & 0xFF] ^
table[1][two >> 16 & 0xFF] ^
table[2][two >> 8 & 0xFF] ^
table[3][two & 0xFF] ^
table[4][one >> 24 & 0xFF] ^
table[5][one >> 16 & 0xFF] ^
table[6][one >> 8 & 0xFF] ^
table[7][one & 0xFF]);
}
len -= bytesAtOnce;
}
while(len-- != 0)
crc = (ushort)(crc >> 8 ^ table[0][crc & 0xFF ^ data[currentPos++]]);
previousCrc = crc;
}
static void StepInverse(ref ushort previousCrc, ushort[][] table, byte[] data, uint len)
{
// Unroll according to Intel slicing by uint8_t
// http://www.intel.com/technology/comms/perfnet/download/CRC_generators.pdf
// http://sourceforge.net/projects/slicing-by-8/
var currentPos = 0;
const int unroll = 4;
const int bytesAtOnce = 8 * unroll;
ushort crc = previousCrc;
while(len >= bytesAtOnce)
{
int unrolling;
for(unrolling = 0; unrolling < unroll; unrolling++)
{
crc = (ushort)(table[7][data[currentPos + 0] ^ crc >> 8] ^
table[6][data[currentPos + 1] ^ crc & 0xFF] ^
table[5][data[currentPos + 2]] ^
table[4][data[currentPos + 3]] ^
table[3][data[currentPos + 4]] ^
table[2][data[currentPos + 5]] ^
table[1][data[currentPos + 6]] ^
table[0][data[currentPos + 7]]);
currentPos += 8;
}
len -= bytesAtOnce;
}
while(len-- != 0)
crc = (ushort)(crc << 8 ^ table[0][crc >> 8 ^ data[currentPos++]]);
previousCrc = crc;
}
static ushort[][] GenerateTable(ushort polynomial, bool inverseTable)
{
var table = new ushort[8][];
for(var i = 0; i < 8; i++)
table[i] = new ushort[256];
if(!inverseTable)
{
for(uint i = 0; i < 256; i++)
{
uint entry = i;
for(var j = 0; j < 8; j++)
{
if((entry & 1) == 1)
entry = entry >> 1 ^ polynomial;
else
entry >>= 1;
}
table[0][i] = (ushort)entry;
}
}
else
{
for(uint i = 0; i < 256; i++)
{
uint entry = i << 8;
for(uint j = 0; j < 8; j++)
{
if((entry & 0x8000) > 0)
entry = entry << 1 ^ polynomial;
else
entry <<= 1;
table[0][i] = (ushort)entry;
}
}
}
for(var slice = 1; slice < 8; slice++)
for(var i = 0; i < 256; i++)
{
if(inverseTable)
table[slice][i] = (ushort)(table[slice - 1][i] << 8 ^ table[0][table[slice - 1][i] >> 8]);
else
table[slice][i] = (ushort)(table[slice - 1][i] >> 8 ^ table[0][table[slice - 1][i] & 0xFF]);
}
return table;
}
/// <summary>Gets the hash of a file in hexadecimal and as a byte array.</summary>
/// <param name="filename">File path.</param>
/// <param name="hash">Byte array of the hash value.</param>
/// <param name="polynomial">CRC polynomial</param>
/// <param name="seed">CRC seed</param>
/// <param name="table">CRC lookup table</param>
/// <param name="inverse">Is CRC inverted?</param>
public static string File(string filename, out byte[] hash, ushort polynomial, ushort seed, ushort[][] table,
bool inverse)
{
bool useNative = Native.IsSupported;
bool useCcitt = polynomial == CRC16CcittContext.CRC16_CCITT_POLY &&
seed == CRC16CcittContext.CRC16_CCITT_SEED &&
inverse;
bool useIbm = polynomial == CRC16IbmContext.CRC16_IBM_POLY &&
seed == CRC16IbmContext.CRC16_IBM_SEED &&
!inverse;
IntPtr nativeContext = IntPtr.Zero;
var fileStream = new FileStream(filename, FileMode.Open);
ushort localHashInt = seed;
switch(useNative)
{
case true when useCcitt:
nativeContext = crc16_ccitt_init();
useNative = nativeContext != IntPtr.Zero;
break;
case true when useIbm:
nativeContext = crc16_init();
useNative = nativeContext != IntPtr.Zero;
break;
}
ushort[][] localTable = table ?? GenerateTable(polynomial, inverse);
var buffer = new byte[65536];
int read = fileStream.EnsureRead(buffer, 0, 65536);
while(read > 0)
{
switch(useNative)
{
case true when useCcitt:
crc16_ccitt_update(nativeContext, buffer, (uint)read);
break;
case true when useIbm:
crc16_update(nativeContext, buffer, (uint)read);
break;
default:
{
if(inverse)
StepInverse(ref localHashInt, localTable, buffer, (uint)read);
else
Step(ref localHashInt, localTable, buffer, (uint)read);
break;
}
}
read = fileStream.EnsureRead(buffer, 0, 65536);
}
localHashInt ^= seed;
switch(useNative)
{
case true when useCcitt:
crc16_ccitt_final(nativeContext, ref localHashInt);
crc16_ccitt_free(nativeContext);
break;
case true when useIbm:
crc16_final(nativeContext, ref localHashInt);
crc16_free(nativeContext);
break;
default:
{
if(inverse)
localHashInt = (ushort)~localHashInt;
break;
}
}
hash = BigEndianBitConverter.GetBytes(localHashInt);
var crc16Output = new StringBuilder();
foreach(byte h in hash)
crc16Output.Append(h.ToString("x2"));
fileStream.Close();
return crc16Output.ToString();
}
/// <summary>Gets the hash of the specified data buffer.</summary>
/// <param name="data">Data buffer.</param>
/// <param name="len">Length of the data buffer to hash.</param>
/// <param name="hash">Byte array of the hash value.</param>
/// <param name="polynomial">CRC polynomial</param>
/// <param name="seed">CRC seed</param>
/// <param name="table">CRC lookup table</param>
/// <param name="inverse">Is CRC inverted?</param>
public static string Data(byte[] data, uint len, out byte[] hash, ushort polynomial, ushort seed, ushort[][] table,
bool inverse)
{
bool useNative = Native.IsSupported;
bool useCcitt = polynomial == CRC16CcittContext.CRC16_CCITT_POLY &&
seed == CRC16CcittContext.CRC16_CCITT_SEED &&
inverse;
bool useIbm = polynomial == CRC16IbmContext.CRC16_IBM_POLY &&
seed == CRC16IbmContext.CRC16_IBM_SEED &&
!inverse;
IntPtr nativeContext = IntPtr.Zero;
ushort localHashInt = seed;
switch(useNative)
{
case true when useCcitt:
nativeContext = crc16_ccitt_init();
useNative = nativeContext != IntPtr.Zero;
break;
case true when useIbm:
nativeContext = crc16_init();
useNative = nativeContext != IntPtr.Zero;
break;
}
ushort[][] localTable = table ?? GenerateTable(polynomial, inverse);
switch(useNative)
{
case true when useCcitt:
crc16_ccitt_update(nativeContext, data, len);
break;
case true when useIbm:
crc16_update(nativeContext, data, len);
break;
default:
{
if(inverse)
StepInverse(ref localHashInt, localTable, data, len);
else
Step(ref localHashInt, localTable, data, len);
break;
}
}
localHashInt ^= seed;
switch(useNative)
{
case true when useCcitt:
crc16_ccitt_final(nativeContext, ref localHashInt);
crc16_ccitt_free(nativeContext);
break;
case true when useIbm:
crc16_final(nativeContext, ref localHashInt);
crc16_free(nativeContext);
break;
default:
{
if(inverse)
localHashInt = (ushort)~localHashInt;
break;
}
}
hash = BigEndianBitConverter.GetBytes(localHashInt);
var crc16Output = new StringBuilder();
foreach(byte h in hash)
crc16Output.Append(h.ToString("x2"));
return crc16Output.ToString();
}
/// <summary>Calculates the CRC16 of the specified buffer with the specified parameters</summary>
/// <param name="buffer">Buffer</param>
/// <param name="polynomial">Polynomial</param>
/// <param name="seed">Seed</param>
/// <param name="table">Pre-generated lookup table</param>
/// <param name="inverse">Inverse CRC</param>
/// <returns>CRC16</returns>
public static ushort Calculate(byte[] buffer, ushort polynomial, ushort seed, ushort[][] table, bool inverse)
{
bool useNative = Native.IsSupported;
bool useCcitt = polynomial == CRC16CcittContext.CRC16_CCITT_POLY &&
seed == CRC16CcittContext.CRC16_CCITT_SEED &&
inverse;
bool useIbm = polynomial == CRC16IbmContext.CRC16_IBM_POLY &&
seed == CRC16IbmContext.CRC16_IBM_SEED &&
!inverse;
IntPtr nativeContext = IntPtr.Zero;
ushort localHashInt = seed;
switch(useNative)
{
case true when useCcitt:
nativeContext = crc16_ccitt_init();
useNative = nativeContext != IntPtr.Zero;
break;
case true when useIbm:
nativeContext = crc16_init();
useNative = nativeContext != IntPtr.Zero;
break;
}
ushort[][] localTable = table ?? GenerateTable(polynomial, inverse);
switch(useNative)
{
case true when useCcitt:
crc16_ccitt_update(nativeContext, buffer, (uint)buffer.Length);
break;
case true when useIbm:
crc16_update(nativeContext, buffer, (uint)buffer.Length);
break;
default:
{
if(inverse)
StepInverse(ref localHashInt, localTable, buffer, (uint)buffer.Length);
else
Step(ref localHashInt, localTable, buffer, (uint)buffer.Length);
break;
}
}
localHashInt ^= seed;
switch(useNative)
{
case true when useCcitt:
crc16_ccitt_final(nativeContext, ref localHashInt);
crc16_ccitt_free(nativeContext);
break;
case true when useIbm:
crc16_final(nativeContext, ref localHashInt);
crc16_free(nativeContext);
break;
default:
{
if(inverse)
localHashInt = (ushort)~localHashInt;
break;
}
}
return localHashInt;
}
}

View File

@@ -0,0 +1,276 @@
// /***************************************************************************
// Aaru Data Preservation Suite
// ----------------------------------------------------------------------------
//
// Filename : CRC16IBMContext.cs
// Author(s) : Natalia Portillo <claunia@claunia.com>
//
// Component : Checksums.
//
// --[ Description ] ----------------------------------------------------------
//
// Implements a CRC16 algorithm with the IBM polynomial.
//
// --[ License ] --------------------------------------------------------------
//
// This library is free software; you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as
// published by the Free Software Foundation; either version 2.1 of the
// License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, see <http://www.gnu.org/licenses/>.
//
// ----------------------------------------------------------------------------
// Copyright © 2011-2023 Natalia Portillo
// ****************************************************************************/
using System;
using System.Diagnostics.CodeAnalysis;
namespace Aaru.Checksums;
/// <inheritdoc />
/// <summary>Implements the CRC16 algorithm with IBM polynomial and seed</summary>
[SuppressMessage("ReSharper", "UnusedMethodReturnValue.Global")]
[SuppressMessage("ReSharper", "MemberCanBePrivate.Global")]
[SuppressMessage("ReSharper", "MemberCanBeInternal")]
public sealed class CRC16IbmContext : Crc16Context
{
internal const ushort CRC16_IBM_POLY = 0xA001;
internal const ushort CRC16_IBM_SEED = 0x0000;
static readonly ushort[][] _ibmCrc16Table =
{
new ushort[]
{
0x0000, 0xC0C1, 0xC181, 0x0140, 0xC301, 0x03C0, 0x0280, 0xC241, 0xC601, 0x06C0, 0x0780, 0xC741, 0x0500,
0xC5C1, 0xC481, 0x0440, 0xCC01, 0x0CC0, 0x0D80, 0xCD41, 0x0F00, 0xCFC1, 0xCE81, 0x0E40, 0x0A00, 0xCAC1,
0xCB81, 0x0B40, 0xC901, 0x09C0, 0x0880, 0xC841, 0xD801, 0x18C0, 0x1980, 0xD941, 0x1B00, 0xDBC1, 0xDA81,
0x1A40, 0x1E00, 0xDEC1, 0xDF81, 0x1F40, 0xDD01, 0x1DC0, 0x1C80, 0xDC41, 0x1400, 0xD4C1, 0xD581, 0x1540,
0xD701, 0x17C0, 0x1680, 0xD641, 0xD201, 0x12C0, 0x1380, 0xD341, 0x1100, 0xD1C1, 0xD081, 0x1040, 0xF001,
0x30C0, 0x3180, 0xF141, 0x3300, 0xF3C1, 0xF281, 0x3240, 0x3600, 0xF6C1, 0xF781, 0x3740, 0xF501, 0x35C0,
0x3480, 0xF441, 0x3C00, 0xFCC1, 0xFD81, 0x3D40, 0xFF01, 0x3FC0, 0x3E80, 0xFE41, 0xFA01, 0x3AC0, 0x3B80,
0xFB41, 0x3900, 0xF9C1, 0xF881, 0x3840, 0x2800, 0xE8C1, 0xE981, 0x2940, 0xEB01, 0x2BC0, 0x2A80, 0xEA41,
0xEE01, 0x2EC0, 0x2F80, 0xEF41, 0x2D00, 0xEDC1, 0xEC81, 0x2C40, 0xE401, 0x24C0, 0x2580, 0xE541, 0x2700,
0xE7C1, 0xE681, 0x2640, 0x2200, 0xE2C1, 0xE381, 0x2340, 0xE101, 0x21C0, 0x2080, 0xE041, 0xA001, 0x60C0,
0x6180, 0xA141, 0x6300, 0xA3C1, 0xA281, 0x6240, 0x6600, 0xA6C1, 0xA781, 0x6740, 0xA501, 0x65C0, 0x6480,
0xA441, 0x6C00, 0xACC1, 0xAD81, 0x6D40, 0xAF01, 0x6FC0, 0x6E80, 0xAE41, 0xAA01, 0x6AC0, 0x6B80, 0xAB41,
0x6900, 0xA9C1, 0xA881, 0x6840, 0x7800, 0xB8C1, 0xB981, 0x7940, 0xBB01, 0x7BC0, 0x7A80, 0xBA41, 0xBE01,
0x7EC0, 0x7F80, 0xBF41, 0x7D00, 0xBDC1, 0xBC81, 0x7C40, 0xB401, 0x74C0, 0x7580, 0xB541, 0x7700, 0xB7C1,
0xB681, 0x7640, 0x7200, 0xB2C1, 0xB381, 0x7340, 0xB101, 0x71C0, 0x7080, 0xB041, 0x5000, 0x90C1, 0x9181,
0x5140, 0x9301, 0x53C0, 0x5280, 0x9241, 0x9601, 0x56C0, 0x5780, 0x9741, 0x5500, 0x95C1, 0x9481, 0x5440,
0x9C01, 0x5CC0, 0x5D80, 0x9D41, 0x5F00, 0x9FC1, 0x9E81, 0x5E40, 0x5A00, 0x9AC1, 0x9B81, 0x5B40, 0x9901,
0x59C0, 0x5880, 0x9841, 0x8801, 0x48C0, 0x4980, 0x8941, 0x4B00, 0x8BC1, 0x8A81, 0x4A40, 0x4E00, 0x8EC1,
0x8F81, 0x4F40, 0x8D01, 0x4DC0, 0x4C80, 0x8C41, 0x4400, 0x84C1, 0x8581, 0x4540, 0x8701, 0x47C0, 0x4680,
0x8641, 0x8201, 0x42C0, 0x4380, 0x8341, 0x4100, 0x81C1, 0x8081, 0x4040
},
new ushort[]
{
0x0000, 0x9001, 0x6001, 0xF000, 0xC002, 0x5003, 0xA003, 0x3002, 0xC007, 0x5006, 0xA006, 0x3007, 0x0005,
0x9004, 0x6004, 0xF005, 0xC00D, 0x500C, 0xA00C, 0x300D, 0x000F, 0x900E, 0x600E, 0xF00F, 0x000A, 0x900B,
0x600B, 0xF00A, 0xC008, 0x5009, 0xA009, 0x3008, 0xC019, 0x5018, 0xA018, 0x3019, 0x001B, 0x901A, 0x601A,
0xF01B, 0x001E, 0x901F, 0x601F, 0xF01E, 0xC01C, 0x501D, 0xA01D, 0x301C, 0x0014, 0x9015, 0x6015, 0xF014,
0xC016, 0x5017, 0xA017, 0x3016, 0xC013, 0x5012, 0xA012, 0x3013, 0x0011, 0x9010, 0x6010, 0xF011, 0xC031,
0x5030, 0xA030, 0x3031, 0x0033, 0x9032, 0x6032, 0xF033, 0x0036, 0x9037, 0x6037, 0xF036, 0xC034, 0x5035,
0xA035, 0x3034, 0x003C, 0x903D, 0x603D, 0xF03C, 0xC03E, 0x503F, 0xA03F, 0x303E, 0xC03B, 0x503A, 0xA03A,
0x303B, 0x0039, 0x9038, 0x6038, 0xF039, 0x0028, 0x9029, 0x6029, 0xF028, 0xC02A, 0x502B, 0xA02B, 0x302A,
0xC02F, 0x502E, 0xA02E, 0x302F, 0x002D, 0x902C, 0x602C, 0xF02D, 0xC025, 0x5024, 0xA024, 0x3025, 0x0027,
0x9026, 0x6026, 0xF027, 0x0022, 0x9023, 0x6023, 0xF022, 0xC020, 0x5021, 0xA021, 0x3020, 0xC061, 0x5060,
0xA060, 0x3061, 0x0063, 0x9062, 0x6062, 0xF063, 0x0066, 0x9067, 0x6067, 0xF066, 0xC064, 0x5065, 0xA065,
0x3064, 0x006C, 0x906D, 0x606D, 0xF06C, 0xC06E, 0x506F, 0xA06F, 0x306E, 0xC06B, 0x506A, 0xA06A, 0x306B,
0x0069, 0x9068, 0x6068, 0xF069, 0x0078, 0x9079, 0x6079, 0xF078, 0xC07A, 0x507B, 0xA07B, 0x307A, 0xC07F,
0x507E, 0xA07E, 0x307F, 0x007D, 0x907C, 0x607C, 0xF07D, 0xC075, 0x5074, 0xA074, 0x3075, 0x0077, 0x9076,
0x6076, 0xF077, 0x0072, 0x9073, 0x6073, 0xF072, 0xC070, 0x5071, 0xA071, 0x3070, 0x0050, 0x9051, 0x6051,
0xF050, 0xC052, 0x5053, 0xA053, 0x3052, 0xC057, 0x5056, 0xA056, 0x3057, 0x0055, 0x9054, 0x6054, 0xF055,
0xC05D, 0x505C, 0xA05C, 0x305D, 0x005F, 0x905E, 0x605E, 0xF05F, 0x005A, 0x905B, 0x605B, 0xF05A, 0xC058,
0x5059, 0xA059, 0x3058, 0xC049, 0x5048, 0xA048, 0x3049, 0x004B, 0x904A, 0x604A, 0xF04B, 0x004E, 0x904F,
0x604F, 0xF04E, 0xC04C, 0x504D, 0xA04D, 0x304C, 0x0044, 0x9045, 0x6045, 0xF044, 0xC046, 0x5047, 0xA047,
0x3046, 0xC043, 0x5042, 0xA042, 0x3043, 0x0041, 0x9040, 0x6040, 0xF041
},
new ushort[]
{
0x0000, 0xC051, 0xC0A1, 0x00F0, 0xC141, 0x0110, 0x01E0, 0xC1B1, 0xC281, 0x02D0, 0x0220, 0xC271, 0x03C0,
0xC391, 0xC361, 0x0330, 0xC501, 0x0550, 0x05A0, 0xC5F1, 0x0440, 0xC411, 0xC4E1, 0x04B0, 0x0780, 0xC7D1,
0xC721, 0x0770, 0xC6C1, 0x0690, 0x0660, 0xC631, 0xCA01, 0x0A50, 0x0AA0, 0xCAF1, 0x0B40, 0xCB11, 0xCBE1,
0x0BB0, 0x0880, 0xC8D1, 0xC821, 0x0870, 0xC9C1, 0x0990, 0x0960, 0xC931, 0x0F00, 0xCF51, 0xCFA1, 0x0FF0,
0xCE41, 0x0E10, 0x0EE0, 0xCEB1, 0xCD81, 0x0DD0, 0x0D20, 0xCD71, 0x0CC0, 0xCC91, 0xCC61, 0x0C30, 0xD401,
0x1450, 0x14A0, 0xD4F1, 0x1540, 0xD511, 0xD5E1, 0x15B0, 0x1680, 0xD6D1, 0xD621, 0x1670, 0xD7C1, 0x1790,
0x1760, 0xD731, 0x1100, 0xD151, 0xD1A1, 0x11F0, 0xD041, 0x1010, 0x10E0, 0xD0B1, 0xD381, 0x13D0, 0x1320,
0xD371, 0x12C0, 0xD291, 0xD261, 0x1230, 0x1E00, 0xDE51, 0xDEA1, 0x1EF0, 0xDF41, 0x1F10, 0x1FE0, 0xDFB1,
0xDC81, 0x1CD0, 0x1C20, 0xDC71, 0x1DC0, 0xDD91, 0xDD61, 0x1D30, 0xDB01, 0x1B50, 0x1BA0, 0xDBF1, 0x1A40,
0xDA11, 0xDAE1, 0x1AB0, 0x1980, 0xD9D1, 0xD921, 0x1970, 0xD8C1, 0x1890, 0x1860, 0xD831, 0xE801, 0x2850,
0x28A0, 0xE8F1, 0x2940, 0xE911, 0xE9E1, 0x29B0, 0x2A80, 0xEAD1, 0xEA21, 0x2A70, 0xEBC1, 0x2B90, 0x2B60,
0xEB31, 0x2D00, 0xED51, 0xEDA1, 0x2DF0, 0xEC41, 0x2C10, 0x2CE0, 0xECB1, 0xEF81, 0x2FD0, 0x2F20, 0xEF71,
0x2EC0, 0xEE91, 0xEE61, 0x2E30, 0x2200, 0xE251, 0xE2A1, 0x22F0, 0xE341, 0x2310, 0x23E0, 0xE3B1, 0xE081,
0x20D0, 0x2020, 0xE071, 0x21C0, 0xE191, 0xE161, 0x2130, 0xE701, 0x2750, 0x27A0, 0xE7F1, 0x2640, 0xE611,
0xE6E1, 0x26B0, 0x2580, 0xE5D1, 0xE521, 0x2570, 0xE4C1, 0x2490, 0x2460, 0xE431, 0x3C00, 0xFC51, 0xFCA1,
0x3CF0, 0xFD41, 0x3D10, 0x3DE0, 0xFDB1, 0xFE81, 0x3ED0, 0x3E20, 0xFE71, 0x3FC0, 0xFF91, 0xFF61, 0x3F30,
0xF901, 0x3950, 0x39A0, 0xF9F1, 0x3840, 0xF811, 0xF8E1, 0x38B0, 0x3B80, 0xFBD1, 0xFB21, 0x3B70, 0xFAC1,
0x3A90, 0x3A60, 0xFA31, 0xF601, 0x3650, 0x36A0, 0xF6F1, 0x3740, 0xF711, 0xF7E1, 0x37B0, 0x3480, 0xF4D1,
0xF421, 0x3470, 0xF5C1, 0x3590, 0x3560, 0xF531, 0x3300, 0xF351, 0xF3A1, 0x33F0, 0xF241, 0x3210, 0x32E0,
0xF2B1, 0xF181, 0x31D0, 0x3120, 0xF171, 0x30C0, 0xF091, 0xF061, 0x3030
},
new ushort[]
{
0x0000, 0xFC01, 0xB801, 0x4400, 0x3001, 0xCC00, 0x8800, 0x7401, 0x6002, 0x9C03, 0xD803, 0x2402, 0x5003,
0xAC02, 0xE802, 0x1403, 0xC004, 0x3C05, 0x7805, 0x8404, 0xF005, 0x0C04, 0x4804, 0xB405, 0xA006, 0x5C07,
0x1807, 0xE406, 0x9007, 0x6C06, 0x2806, 0xD407, 0xC00B, 0x3C0A, 0x780A, 0x840B, 0xF00A, 0x0C0B, 0x480B,
0xB40A, 0xA009, 0x5C08, 0x1808, 0xE409, 0x9008, 0x6C09, 0x2809, 0xD408, 0x000F, 0xFC0E, 0xB80E, 0x440F,
0x300E, 0xCC0F, 0x880F, 0x740E, 0x600D, 0x9C0C, 0xD80C, 0x240D, 0x500C, 0xAC0D, 0xE80D, 0x140C, 0xC015,
0x3C14, 0x7814, 0x8415, 0xF014, 0x0C15, 0x4815, 0xB414, 0xA017, 0x5C16, 0x1816, 0xE417, 0x9016, 0x6C17,
0x2817, 0xD416, 0x0011, 0xFC10, 0xB810, 0x4411, 0x3010, 0xCC11, 0x8811, 0x7410, 0x6013, 0x9C12, 0xD812,
0x2413, 0x5012, 0xAC13, 0xE813, 0x1412, 0x001E, 0xFC1F, 0xB81F, 0x441E, 0x301F, 0xCC1E, 0x881E, 0x741F,
0x601C, 0x9C1D, 0xD81D, 0x241C, 0x501D, 0xAC1C, 0xE81C, 0x141D, 0xC01A, 0x3C1B, 0x781B, 0x841A, 0xF01B,
0x0C1A, 0x481A, 0xB41B, 0xA018, 0x5C19, 0x1819, 0xE418, 0x9019, 0x6C18, 0x2818, 0xD419, 0xC029, 0x3C28,
0x7828, 0x8429, 0xF028, 0x0C29, 0x4829, 0xB428, 0xA02B, 0x5C2A, 0x182A, 0xE42B, 0x902A, 0x6C2B, 0x282B,
0xD42A, 0x002D, 0xFC2C, 0xB82C, 0x442D, 0x302C, 0xCC2D, 0x882D, 0x742C, 0x602F, 0x9C2E, 0xD82E, 0x242F,
0x502E, 0xAC2F, 0xE82F, 0x142E, 0x0022, 0xFC23, 0xB823, 0x4422, 0x3023, 0xCC22, 0x8822, 0x7423, 0x6020,
0x9C21, 0xD821, 0x2420, 0x5021, 0xAC20, 0xE820, 0x1421, 0xC026, 0x3C27, 0x7827, 0x8426, 0xF027, 0x0C26,
0x4826, 0xB427, 0xA024, 0x5C25, 0x1825, 0xE424, 0x9025, 0x6C24, 0x2824, 0xD425, 0x003C, 0xFC3D, 0xB83D,
0x443C, 0x303D, 0xCC3C, 0x883C, 0x743D, 0x603E, 0x9C3F, 0xD83F, 0x243E, 0x503F, 0xAC3E, 0xE83E, 0x143F,
0xC038, 0x3C39, 0x7839, 0x8438, 0xF039, 0x0C38, 0x4838, 0xB439, 0xA03A, 0x5C3B, 0x183B, 0xE43A, 0x903B,
0x6C3A, 0x283A, 0xD43B, 0xC037, 0x3C36, 0x7836, 0x8437, 0xF036, 0x0C37, 0x4837, 0xB436, 0xA035, 0x5C34,
0x1834, 0xE435, 0x9034, 0x6C35, 0x2835, 0xD434, 0x0033, 0xFC32, 0xB832, 0x4433, 0x3032, 0xCC33, 0x8833,
0x7432, 0x6031, 0x9C30, 0xD830, 0x2431, 0x5030, 0xAC31, 0xE831, 0x1430
},
new ushort[]
{
0x0000, 0xC03D, 0xC079, 0x0044, 0xC0F1, 0x00CC, 0x0088, 0xC0B5, 0xC1E1, 0x01DC, 0x0198, 0xC1A5, 0x0110,
0xC12D, 0xC169, 0x0154, 0xC3C1, 0x03FC, 0x03B8, 0xC385, 0x0330, 0xC30D, 0xC349, 0x0374, 0x0220, 0xC21D,
0xC259, 0x0264, 0xC2D1, 0x02EC, 0x02A8, 0xC295, 0xC781, 0x07BC, 0x07F8, 0xC7C5, 0x0770, 0xC74D, 0xC709,
0x0734, 0x0660, 0xC65D, 0xC619, 0x0624, 0xC691, 0x06AC, 0x06E8, 0xC6D5, 0x0440, 0xC47D, 0xC439, 0x0404,
0xC4B1, 0x048C, 0x04C8, 0xC4F5, 0xC5A1, 0x059C, 0x05D8, 0xC5E5, 0x0550, 0xC56D, 0xC529, 0x0514, 0xCF01,
0x0F3C, 0x0F78, 0xCF45, 0x0FF0, 0xCFCD, 0xCF89, 0x0FB4, 0x0EE0, 0xCEDD, 0xCE99, 0x0EA4, 0xCE11, 0x0E2C,
0x0E68, 0xCE55, 0x0CC0, 0xCCFD, 0xCCB9, 0x0C84, 0xCC31, 0x0C0C, 0x0C48, 0xCC75, 0xCD21, 0x0D1C, 0x0D58,
0xCD65, 0x0DD0, 0xCDED, 0xCDA9, 0x0D94, 0x0880, 0xC8BD, 0xC8F9, 0x08C4, 0xC871, 0x084C, 0x0808, 0xC835,
0xC961, 0x095C, 0x0918, 0xC925, 0x0990, 0xC9AD, 0xC9E9, 0x09D4, 0xCB41, 0x0B7C, 0x0B38, 0xCB05, 0x0BB0,
0xCB8D, 0xCBC9, 0x0BF4, 0x0AA0, 0xCA9D, 0xCAD9, 0x0AE4, 0xCA51, 0x0A6C, 0x0A28, 0xCA15, 0xDE01, 0x1E3C,
0x1E78, 0xDE45, 0x1EF0, 0xDECD, 0xDE89, 0x1EB4, 0x1FE0, 0xDFDD, 0xDF99, 0x1FA4, 0xDF11, 0x1F2C, 0x1F68,
0xDF55, 0x1DC0, 0xDDFD, 0xDDB9, 0x1D84, 0xDD31, 0x1D0C, 0x1D48, 0xDD75, 0xDC21, 0x1C1C, 0x1C58, 0xDC65,
0x1CD0, 0xDCED, 0xDCA9, 0x1C94, 0x1980, 0xD9BD, 0xD9F9, 0x19C4, 0xD971, 0x194C, 0x1908, 0xD935, 0xD861,
0x185C, 0x1818, 0xD825, 0x1890, 0xD8AD, 0xD8E9, 0x18D4, 0xDA41, 0x1A7C, 0x1A38, 0xDA05, 0x1AB0, 0xDA8D,
0xDAC9, 0x1AF4, 0x1BA0, 0xDB9D, 0xDBD9, 0x1BE4, 0xDB51, 0x1B6C, 0x1B28, 0xDB15, 0x1100, 0xD13D, 0xD179,
0x1144, 0xD1F1, 0x11CC, 0x1188, 0xD1B5, 0xD0E1, 0x10DC, 0x1098, 0xD0A5, 0x1010, 0xD02D, 0xD069, 0x1054,
0xD2C1, 0x12FC, 0x12B8, 0xD285, 0x1230, 0xD20D, 0xD249, 0x1274, 0x1320, 0xD31D, 0xD359, 0x1364, 0xD3D1,
0x13EC, 0x13A8, 0xD395, 0xD681, 0x16BC, 0x16F8, 0xD6C5, 0x1670, 0xD64D, 0xD609, 0x1634, 0x1760, 0xD75D,
0xD719, 0x1724, 0xD791, 0x17AC, 0x17E8, 0xD7D5, 0x1540, 0xD57D, 0xD539, 0x1504, 0xD5B1, 0x158C, 0x15C8,
0xD5F5, 0xD4A1, 0x149C, 0x14D8, 0xD4E5, 0x1450, 0xD46D, 0xD429, 0x1414
},
new ushort[]
{
0x0000, 0xD101, 0xE201, 0x3300, 0x8401, 0x5500, 0x6600, 0xB701, 0x4801, 0x9900, 0xAA00, 0x7B01, 0xCC00,
0x1D01, 0x2E01, 0xFF00, 0x9002, 0x4103, 0x7203, 0xA302, 0x1403, 0xC502, 0xF602, 0x2703, 0xD803, 0x0902,
0x3A02, 0xEB03, 0x5C02, 0x8D03, 0xBE03, 0x6F02, 0x6007, 0xB106, 0x8206, 0x5307, 0xE406, 0x3507, 0x0607,
0xD706, 0x2806, 0xF907, 0xCA07, 0x1B06, 0xAC07, 0x7D06, 0x4E06, 0x9F07, 0xF005, 0x2104, 0x1204, 0xC305,
0x7404, 0xA505, 0x9605, 0x4704, 0xB804, 0x6905, 0x5A05, 0x8B04, 0x3C05, 0xED04, 0xDE04, 0x0F05, 0xC00E,
0x110F, 0x220F, 0xF30E, 0x440F, 0x950E, 0xA60E, 0x770F, 0x880F, 0x590E, 0x6A0E, 0xBB0F, 0x0C0E, 0xDD0F,
0xEE0F, 0x3F0E, 0x500C, 0x810D, 0xB20D, 0x630C, 0xD40D, 0x050C, 0x360C, 0xE70D, 0x180D, 0xC90C, 0xFA0C,
0x2B0D, 0x9C0C, 0x4D0D, 0x7E0D, 0xAF0C, 0xA009, 0x7108, 0x4208, 0x9309, 0x2408, 0xF509, 0xC609, 0x1708,
0xE808, 0x3909, 0x0A09, 0xDB08, 0x6C09, 0xBD08, 0x8E08, 0x5F09, 0x300B, 0xE10A, 0xD20A, 0x030B, 0xB40A,
0x650B, 0x560B, 0x870A, 0x780A, 0xA90B, 0x9A0B, 0x4B0A, 0xFC0B, 0x2D0A, 0x1E0A, 0xCF0B, 0xC01F, 0x111E,
0x221E, 0xF31F, 0x441E, 0x951F, 0xA61F, 0x771E, 0x881E, 0x591F, 0x6A1F, 0xBB1E, 0x0C1F, 0xDD1E, 0xEE1E,
0x3F1F, 0x501D, 0x811C, 0xB21C, 0x631D, 0xD41C, 0x051D, 0x361D, 0xE71C, 0x181C, 0xC91D, 0xFA1D, 0x2B1C,
0x9C1D, 0x4D1C, 0x7E1C, 0xAF1D, 0xA018, 0x7119, 0x4219, 0x9318, 0x2419, 0xF518, 0xC618, 0x1719, 0xE819,
0x3918, 0x0A18, 0xDB19, 0x6C18, 0xBD19, 0x8E19, 0x5F18, 0x301A, 0xE11B, 0xD21B, 0x031A, 0xB41B, 0x651A,
0x561A, 0x871B, 0x781B, 0xA91A, 0x9A1A, 0x4B1B, 0xFC1A, 0x2D1B, 0x1E1B, 0xCF1A, 0x0011, 0xD110, 0xE210,
0x3311, 0x8410, 0x5511, 0x6611, 0xB710, 0x4810, 0x9911, 0xAA11, 0x7B10, 0xCC11, 0x1D10, 0x2E10, 0xFF11,
0x9013, 0x4112, 0x7212, 0xA313, 0x1412, 0xC513, 0xF613, 0x2712, 0xD812, 0x0913, 0x3A13, 0xEB12, 0x5C13,
0x8D12, 0xBE12, 0x6F13, 0x6016, 0xB117, 0x8217, 0x5316, 0xE417, 0x3516, 0x0616, 0xD717, 0x2817, 0xF916,
0xCA16, 0x1B17, 0xAC16, 0x7D17, 0x4E17, 0x9F16, 0xF014, 0x2115, 0x1215, 0xC314, 0x7415, 0xA514, 0x9614,
0x4715, 0xB815, 0x6914, 0x5A14, 0x8B15, 0x3C14, 0xED15, 0xDE15, 0x0F14
},
new ushort[]
{
0x0000, 0xC010, 0xC023, 0x0033, 0xC045, 0x0055, 0x0066, 0xC076, 0xC089, 0x0099, 0x00AA, 0xC0BA, 0x00CC,
0xC0DC, 0xC0EF, 0x00FF, 0xC111, 0x0101, 0x0132, 0xC122, 0x0154, 0xC144, 0xC177, 0x0167, 0x0198, 0xC188,
0xC1BB, 0x01AB, 0xC1DD, 0x01CD, 0x01FE, 0xC1EE, 0xC221, 0x0231, 0x0202, 0xC212, 0x0264, 0xC274, 0xC247,
0x0257, 0x02A8, 0xC2B8, 0xC28B, 0x029B, 0xC2ED, 0x02FD, 0x02CE, 0xC2DE, 0x0330, 0xC320, 0xC313, 0x0303,
0xC375, 0x0365, 0x0356, 0xC346, 0xC3B9, 0x03A9, 0x039A, 0xC38A, 0x03FC, 0xC3EC, 0xC3DF, 0x03CF, 0xC441,
0x0451, 0x0462, 0xC472, 0x0404, 0xC414, 0xC427, 0x0437, 0x04C8, 0xC4D8, 0xC4EB, 0x04FB, 0xC48D, 0x049D,
0x04AE, 0xC4BE, 0x0550, 0xC540, 0xC573, 0x0563, 0xC515, 0x0505, 0x0536, 0xC526, 0xC5D9, 0x05C9, 0x05FA,
0xC5EA, 0x059C, 0xC58C, 0xC5BF, 0x05AF, 0x0660, 0xC670, 0xC643, 0x0653, 0xC625, 0x0635, 0x0606, 0xC616,
0xC6E9, 0x06F9, 0x06CA, 0xC6DA, 0x06AC, 0xC6BC, 0xC68F, 0x069F, 0xC771, 0x0761, 0x0752, 0xC742, 0x0734,
0xC724, 0xC717, 0x0707, 0x07F8, 0xC7E8, 0xC7DB, 0x07CB, 0xC7BD, 0x07AD, 0x079E, 0xC78E, 0xC881, 0x0891,
0x08A2, 0xC8B2, 0x08C4, 0xC8D4, 0xC8E7, 0x08F7, 0x0808, 0xC818, 0xC82B, 0x083B, 0xC84D, 0x085D, 0x086E,
0xC87E, 0x0990, 0xC980, 0xC9B3, 0x09A3, 0xC9D5, 0x09C5, 0x09F6, 0xC9E6, 0xC919, 0x0909, 0x093A, 0xC92A,
0x095C, 0xC94C, 0xC97F, 0x096F, 0x0AA0, 0xCAB0, 0xCA83, 0x0A93, 0xCAE5, 0x0AF5, 0x0AC6, 0xCAD6, 0xCA29,
0x0A39, 0x0A0A, 0xCA1A, 0x0A6C, 0xCA7C, 0xCA4F, 0x0A5F, 0xCBB1, 0x0BA1, 0x0B92, 0xCB82, 0x0BF4, 0xCBE4,
0xCBD7, 0x0BC7, 0x0B38, 0xCB28, 0xCB1B, 0x0B0B, 0xCB7D, 0x0B6D, 0x0B5E, 0xCB4E, 0x0CC0, 0xCCD0, 0xCCE3,
0x0CF3, 0xCC85, 0x0C95, 0x0CA6, 0xCCB6, 0xCC49, 0x0C59, 0x0C6A, 0xCC7A, 0x0C0C, 0xCC1C, 0xCC2F, 0x0C3F,
0xCDD1, 0x0DC1, 0x0DF2, 0xCDE2, 0x0D94, 0xCD84, 0xCDB7, 0x0DA7, 0x0D58, 0xCD48, 0xCD7B, 0x0D6B, 0xCD1D,
0x0D0D, 0x0D3E, 0xCD2E, 0xCEE1, 0x0EF1, 0x0EC2, 0xCED2, 0x0EA4, 0xCEB4, 0xCE87, 0x0E97, 0x0E68, 0xCE78,
0xCE4B, 0x0E5B, 0xCE2D, 0x0E3D, 0x0E0E, 0xCE1E, 0x0FF0, 0xCFE0, 0xCFD3, 0x0FC3, 0xCFB5, 0x0FA5, 0x0F96,
0xCF86, 0xCF79, 0x0F69, 0x0F5A, 0xCF4A, 0x0F3C, 0xCF2C, 0xCF1F, 0x0F0F
},
new ushort[]
{
0x0000, 0xCCC1, 0xD981, 0x1540, 0xF301, 0x3FC0, 0x2A80, 0xE641, 0xA601, 0x6AC0, 0x7F80, 0xB341, 0x5500,
0x99C1, 0x8C81, 0x4040, 0x0C01, 0xC0C0, 0xD580, 0x1941, 0xFF00, 0x33C1, 0x2681, 0xEA40, 0xAA00, 0x66C1,
0x7381, 0xBF40, 0x5901, 0x95C0, 0x8080, 0x4C41, 0x1802, 0xD4C3, 0xC183, 0x0D42, 0xEB03, 0x27C2, 0x3282,
0xFE43, 0xBE03, 0x72C2, 0x6782, 0xAB43, 0x4D02, 0x81C3, 0x9483, 0x5842, 0x1403, 0xD8C2, 0xCD82, 0x0143,
0xE702, 0x2BC3, 0x3E83, 0xF242, 0xB202, 0x7EC3, 0x6B83, 0xA742, 0x4103, 0x8DC2, 0x9882, 0x5443, 0x3004,
0xFCC5, 0xE985, 0x2544, 0xC305, 0x0FC4, 0x1A84, 0xD645, 0x9605, 0x5AC4, 0x4F84, 0x8345, 0x6504, 0xA9C5,
0xBC85, 0x7044, 0x3C05, 0xF0C4, 0xE584, 0x2945, 0xCF04, 0x03C5, 0x1685, 0xDA44, 0x9A04, 0x56C5, 0x4385,
0x8F44, 0x6905, 0xA5C4, 0xB084, 0x7C45, 0x2806, 0xE4C7, 0xF187, 0x3D46, 0xDB07, 0x17C6, 0x0286, 0xCE47,
0x8E07, 0x42C6, 0x5786, 0x9B47, 0x7D06, 0xB1C7, 0xA487, 0x6846, 0x2407, 0xE8C6, 0xFD86, 0x3147, 0xD706,
0x1BC7, 0x0E87, 0xC246, 0x8206, 0x4EC7, 0x5B87, 0x9746, 0x7107, 0xBDC6, 0xA886, 0x6447, 0x6008, 0xACC9,
0xB989, 0x7548, 0x9309, 0x5FC8, 0x4A88, 0x8649, 0xC609, 0x0AC8, 0x1F88, 0xD349, 0x3508, 0xF9C9, 0xEC89,
0x2048, 0x6C09, 0xA0C8, 0xB588, 0x7949, 0x9F08, 0x53C9, 0x4689, 0x8A48, 0xCA08, 0x06C9, 0x1389, 0xDF48,
0x3909, 0xF5C8, 0xE088, 0x2C49, 0x780A, 0xB4CB, 0xA18B, 0x6D4A, 0x8B0B, 0x47CA, 0x528A, 0x9E4B, 0xDE0B,
0x12CA, 0x078A, 0xCB4B, 0x2D0A, 0xE1CB, 0xF48B, 0x384A, 0x740B, 0xB8CA, 0xAD8A, 0x614B, 0x870A, 0x4BCB,
0x5E8B, 0x924A, 0xD20A, 0x1ECB, 0x0B8B, 0xC74A, 0x210B, 0xEDCA, 0xF88A, 0x344B, 0x500C, 0x9CCD, 0x898D,
0x454C, 0xA30D, 0x6FCC, 0x7A8C, 0xB64D, 0xF60D, 0x3ACC, 0x2F8C, 0xE34D, 0x050C, 0xC9CD, 0xDC8D, 0x104C,
0x5C0D, 0x90CC, 0x858C, 0x494D, 0xAF0C, 0x63CD, 0x768D, 0xBA4C, 0xFA0C, 0x36CD, 0x238D, 0xEF4C, 0x090D,
0xC5CC, 0xD08C, 0x1C4D, 0x480E, 0x84CF, 0x918F, 0x5D4E, 0xBB0F, 0x77CE, 0x628E, 0xAE4F, 0xEE0F, 0x22CE,
0x378E, 0xFB4F, 0x1D0E, 0xD1CF, 0xC48F, 0x084E, 0x440F, 0x88CE, 0x9D8E, 0x514F, 0xB70E, 0x7BCF, 0x6E8F,
0xA24E, 0xE20E, 0x2ECF, 0x3B8F, 0xF74E, 0x110F, 0xDDCE, 0xC88E, 0x044F
}
};
/// <summary>Initializes an instance of the CRC16 with IBM polynomial and seed.</summary>
/// <inheritdoc />
public CRC16IbmContext() : base(CRC16_IBM_POLY, CRC16_IBM_SEED, _ibmCrc16Table, false) {}
/// <inheritdoc />
public new string Name => "CRC-16 (IBM)";
/// <inheritdoc />
public new Guid Id => new("0470433E-0C78-4C37-8C9F-BD8E72340E78");
/// <inheritdoc />
public new string Author => "Natalia Portillo";
/// <summary>Gets the hash of a file</summary>
/// <param name="filename">File path.</param>
// ReSharper disable once ReturnTypeCanBeEnumerable.Global
public static byte[] File(string filename)
{
File(filename, out byte[] hash);
return hash;
}
/// <summary>Gets the hash of a file in hexadecimal and as a byte array.</summary>
/// <param name="filename">File path.</param>
/// <param name="hash">Byte array of the hash value.</param>
public static string File(string filename, out byte[] hash) =>
File(filename, out hash, CRC16_IBM_POLY, CRC16_IBM_SEED, _ibmCrc16Table, false);
/// <summary>Gets the hash of the specified data buffer.</summary>
/// <param name="data">Data buffer.</param>
/// <param name="len">Length of the data buffer to hash.</param>
/// <param name="hash">Byte array of the hash value.</param>
public static string Data(byte[] data, uint len, out byte[] hash) =>
Data(data, len, out hash, CRC16_IBM_POLY, CRC16_IBM_SEED, _ibmCrc16Table, false);
/// <summary>Gets the hash of the specified data buffer.</summary>
/// <param name="data">Data buffer.</param>
/// <param name="hash">Byte array of the hash value.</param>
public static string Data(byte[] data, out byte[] hash) => Data(data, (uint)data.Length, out hash);
}

View File

@@ -0,0 +1,136 @@
// /***************************************************************************
// Aaru Data Preservation Suite
// ----------------------------------------------------------------------------
//
// Filename : arm_simd.cs
// Author(s) : Natalia Portillo <claunia@claunia.com>
// The Chromium Authors
//
// Component : Checksums.
//
// --[ Description ] ----------------------------------------------------------
//
// Compute CRC32 checksum using ARM special instructions..
//
// --[ License ] --------------------------------------------------------------
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// ----------------------------------------------------------------------------
// Copyright © 2011-2023 Natalia Portillo
// Copyright 2017 The Chromium Authors. All rights reserved.
// ****************************************************************************/
#if NET5_0_OR_GREATER
using System;
using System.Runtime.Intrinsics.Arm;
namespace Aaru.Checksums.CRC32;
static class ArmSimd
{
internal static uint Step64(byte[] buf, long len, uint crc)
{
uint c = crc;
var bufPos = 0;
while(len >= 64)
{
c = Crc32.Arm64.ComputeCrc32(c, BitConverter.ToUInt64(buf, bufPos));
bufPos += 8;
c = Crc32.Arm64.ComputeCrc32(c, BitConverter.ToUInt64(buf, bufPos));
bufPos += 8;
c = Crc32.Arm64.ComputeCrc32(c, BitConverter.ToUInt64(buf, bufPos));
bufPos += 8;
c = Crc32.Arm64.ComputeCrc32(c, BitConverter.ToUInt64(buf, bufPos));
bufPos += 8;
c = Crc32.Arm64.ComputeCrc32(c, BitConverter.ToUInt64(buf, bufPos));
bufPos += 8;
c = Crc32.Arm64.ComputeCrc32(c, BitConverter.ToUInt64(buf, bufPos));
bufPos += 8;
c = Crc32.Arm64.ComputeCrc32(c, BitConverter.ToUInt64(buf, bufPos));
bufPos += 8;
c = Crc32.Arm64.ComputeCrc32(c, BitConverter.ToUInt64(buf, bufPos));
bufPos += 8;
len -= 64;
}
while(len >= 8)
{
c = Crc32.Arm64.ComputeCrc32(c, BitConverter.ToUInt64(buf, bufPos));
bufPos += 8;
len -= 8;
}
while(len-- > 0)
c = Crc32.ComputeCrc32(c, buf[bufPos++]);
return c;
}
internal static uint Step32(byte[] buf, long len, uint crc)
{
uint c = crc;
var bufPos = 0;
while(len >= 32)
{
c = Crc32.ComputeCrc32(c, BitConverter.ToUInt32(buf, bufPos));
bufPos += 4;
c = Crc32.ComputeCrc32(c, BitConverter.ToUInt32(buf, bufPos));
bufPos += 4;
c = Crc32.ComputeCrc32(c, BitConverter.ToUInt32(buf, bufPos));
bufPos += 4;
c = Crc32.ComputeCrc32(c, BitConverter.ToUInt32(buf, bufPos));
bufPos += 4;
c = Crc32.ComputeCrc32(c, BitConverter.ToUInt32(buf, bufPos));
bufPos += 4;
c = Crc32.ComputeCrc32(c, BitConverter.ToUInt32(buf, bufPos));
bufPos += 4;
c = Crc32.ComputeCrc32(c, BitConverter.ToUInt32(buf, bufPos));
bufPos += 4;
c = Crc32.ComputeCrc32(c, BitConverter.ToUInt32(buf, bufPos));
bufPos += 4;
len -= 32;
}
while(len >= 4)
{
c = Crc32.ComputeCrc32(c, BitConverter.ToUInt32(buf, bufPos));
bufPos += 4;
len -= 4;
}
while(len-- > 0)
c = Crc32.ComputeCrc32(c, buf[bufPos++]);
return c;
}
}
#endif

View File

@@ -0,0 +1,227 @@
// /***************************************************************************
// Aaru Data Preservation Suite
// ----------------------------------------------------------------------------
//
// Filename : clmul.cs
// Author(s) : Natalia Portillo <claunia@claunia.com>
// Wajdi Feghali <wajdi.k.feghali@intel.com>
// Jim Guilford <james.guilford@intel.com>
// Vinodh Gopal <vinodh.gopal@intel.com>
// Erdinc Ozturk <erdinc.ozturk@intel.com>
// Jim Kukunas <james.t.kukunas@linux.intel.com>
// Marian Beermann
//
// Component : Checksums.
//
// --[ Description ] ----------------------------------------------------------
//
// Compute the CRC32 using a parallelized folding approach with the PCLMULQDQ
// instruction.
//
// A white paper describing this algorithm can be found at:
// http://www.intel.com/content/dam/www/public/us/en/documents/white-papers/fast-crc-computation-generic-polynomials-pclmulqdq-paper.pdf
//
// --[ License ] --------------------------------------------------------------
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from
// the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it
// freely, subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented; you must not
// claim that you wrote the original software. If you use this software
// in a product, an acknowledgment in the product documentation would be
// appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such, and must not be
// misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source distribution.
//
// ----------------------------------------------------------------------------
// Copyright © 2011-2023 Natalia Portillo
// Copyright (c) 2016 Marian Beermann (add support for initial value, restructuring)
// Copyright (C) 2013 Intel Corporation. All rights reserved.
// ****************************************************************************/
#if NETCOREAPP3_1_OR_GREATER
using System;
using System.Runtime.CompilerServices;
using System.Runtime.Intrinsics;
using System.Runtime.Intrinsics.X86;
namespace Aaru.Checksums.CRC32;
static class Clmul
{
static readonly uint[] _crcK =
{
0xccaa009e, 0x00000000, /* rk1 */ 0x751997d0, 0x00000001, /* rk2 */ 0xccaa009e, 0x00000000, /* rk5 */
0x63cd6124, 0x00000001, /* rk6 */ 0xf7011640, 0x00000001, /* rk7 */ 0xdb710640, 0x00000001 /* rk8 */
};
[MethodImpl(MethodImplOptions.AggressiveInlining)]
static void Fold4(ref Vector128<uint> xmmCRC0, ref Vector128<uint> xmmCRC1, ref Vector128<uint> xmmCRC2,
ref Vector128<uint> xmmCRC3)
{
var xmmFold4 = Vector128.Create(0xc6e41596, 0x00000001, 0x54442bd4, 0x00000001);
Vector128<uint> xTmp0 = xmmCRC0;
Vector128<uint> xTmp1 = xmmCRC1;
Vector128<uint> xTmp2 = xmmCRC2;
Vector128<uint> xTmp3 = xmmCRC3;
xmmCRC0 = Pclmulqdq.CarrylessMultiply(xmmCRC0.AsUInt64(), xmmFold4.AsUInt64(), 0x01).AsUInt32();
xTmp0 = Pclmulqdq.CarrylessMultiply(xTmp0.AsUInt64(), xmmFold4.AsUInt64(), 0x10).AsUInt32();
Vector128<float> psCRC0 = xmmCRC0.AsSingle();
Vector128<float> psT0 = xTmp0.AsSingle();
Vector128<float> psRes0 = Sse.Xor(psCRC0, psT0);
xmmCRC1 = Pclmulqdq.CarrylessMultiply(xmmCRC1.AsUInt64(), xmmFold4.AsUInt64(), 0x01).AsUInt32();
xTmp1 = Pclmulqdq.CarrylessMultiply(xTmp1.AsUInt64(), xmmFold4.AsUInt64(), 0x10).AsUInt32();
Vector128<float> psCRC1 = xmmCRC1.AsSingle();
Vector128<float> psT1 = xTmp1.AsSingle();
Vector128<float> psRes1 = Sse.Xor(psCRC1, psT1);
xmmCRC2 = Pclmulqdq.CarrylessMultiply(xmmCRC2.AsUInt64(), xmmFold4.AsUInt64(), 0x01).AsUInt32();
xTmp2 = Pclmulqdq.CarrylessMultiply(xTmp2.AsUInt64(), xmmFold4.AsUInt64(), 0x10).AsUInt32();
Vector128<float> psCRC2 = xmmCRC2.AsSingle();
Vector128<float> psT2 = xTmp2.AsSingle();
Vector128<float> psRes2 = Sse.Xor(psCRC2, psT2);
xmmCRC3 = Pclmulqdq.CarrylessMultiply(xmmCRC3.AsUInt64(), xmmFold4.AsUInt64(), 0x01).AsUInt32();
xTmp3 = Pclmulqdq.CarrylessMultiply(xTmp3.AsUInt64(), xmmFold4.AsUInt64(), 0x10).AsUInt32();
Vector128<float> psCRC3 = xmmCRC3.AsSingle();
Vector128<float> psT3 = xTmp3.AsSingle();
Vector128<float> psRes3 = Sse.Xor(psCRC3, psT3);
xmmCRC0 = psRes0.AsUInt32();
xmmCRC1 = psRes1.AsUInt32();
xmmCRC2 = psRes2.AsUInt32();
xmmCRC3 = psRes3.AsUInt32();
}
internal static uint Step(byte[] src, long len, uint initialCRC)
{
Vector128<uint> xmmInitial = Sse2.ConvertScalarToVector128UInt32(initialCRC);
Vector128<uint> xmmCRC0 = Sse2.ConvertScalarToVector128UInt32(0x9db42487);
Vector128<uint> xmmCRC1 = Vector128<uint>.Zero;
Vector128<uint> xmmCRC2 = Vector128<uint>.Zero;
Vector128<uint> xmmCRC3 = Vector128<uint>.Zero;
var bufPos = 0;
var first = true;
/* fold 512 to 32 step variable declarations for ISO-C90 compat. */
var xmmMask = Vector128.Create(0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000);
var xmmMask2 = Vector128.Create(0x00000000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF);
while((len -= 64) >= 0)
{
var xmmT0 = Vector128.Create(BitConverter.ToUInt32(src, bufPos), BitConverter.ToUInt32(src, bufPos + 4),
BitConverter.ToUInt32(src, bufPos + 8),
BitConverter.ToUInt32(src, bufPos + 12));
bufPos += 16;
var xmmT1 = Vector128.Create(BitConverter.ToUInt32(src, bufPos), BitConverter.ToUInt32(src, bufPos + 4),
BitConverter.ToUInt32(src, bufPos + 8),
BitConverter.ToUInt32(src, bufPos + 12));
bufPos += 16;
var xmmT2 = Vector128.Create(BitConverter.ToUInt32(src, bufPos), BitConverter.ToUInt32(src, bufPos + 4),
BitConverter.ToUInt32(src, bufPos + 8),
BitConverter.ToUInt32(src, bufPos + 12));
bufPos += 16;
var xmmT3 = Vector128.Create(BitConverter.ToUInt32(src, bufPos), BitConverter.ToUInt32(src, bufPos + 4),
BitConverter.ToUInt32(src, bufPos + 8),
BitConverter.ToUInt32(src, bufPos + 12));
bufPos += 16;
if(first)
{
first = false;
xmmT0 = Sse2.Xor(xmmT0, xmmInitial);
}
Fold4(ref xmmCRC0, ref xmmCRC1, ref xmmCRC2, ref xmmCRC3);
xmmCRC0 = Sse2.Xor(xmmCRC0, xmmT0);
xmmCRC1 = Sse2.Xor(xmmCRC1, xmmT1);
xmmCRC2 = Sse2.Xor(xmmCRC2, xmmT2);
xmmCRC3 = Sse2.Xor(xmmCRC3, xmmT3);
}
/* fold 512 to 32 */
/*
* k1
*/
var crcFold = Vector128.Create(_crcK[0], _crcK[1], _crcK[2], _crcK[3]);
Vector128<uint> xTmp0 = Pclmulqdq.CarrylessMultiply(xmmCRC0.AsUInt64(), crcFold.AsUInt64(), 0x10).AsUInt32();
xmmCRC0 = Pclmulqdq.CarrylessMultiply(xmmCRC0.AsUInt64(), crcFold.AsUInt64(), 0x01).AsUInt32();
xmmCRC1 = Sse2.Xor(xmmCRC1, xTmp0);
xmmCRC1 = Sse2.Xor(xmmCRC1, xmmCRC0);
Vector128<uint> xTmp1 = Pclmulqdq.CarrylessMultiply(xmmCRC1.AsUInt64(), crcFold.AsUInt64(), 0x10).AsUInt32();
xmmCRC1 = Pclmulqdq.CarrylessMultiply(xmmCRC1.AsUInt64(), crcFold.AsUInt64(), 0x01).AsUInt32();
xmmCRC2 = Sse2.Xor(xmmCRC2, xTmp1);
xmmCRC2 = Sse2.Xor(xmmCRC2, xmmCRC1);
Vector128<uint> xTmp2 = Pclmulqdq.CarrylessMultiply(xmmCRC2.AsUInt64(), crcFold.AsUInt64(), 0x10).AsUInt32();
xmmCRC2 = Pclmulqdq.CarrylessMultiply(xmmCRC2.AsUInt64(), crcFold.AsUInt64(), 0x01).AsUInt32();
xmmCRC3 = Sse2.Xor(xmmCRC3, xTmp2);
xmmCRC3 = Sse2.Xor(xmmCRC3, xmmCRC2);
/*
* k5
*/
crcFold = Vector128.Create(_crcK[4], _crcK[5], _crcK[6], _crcK[7]);
xmmCRC0 = xmmCRC3;
xmmCRC3 = Pclmulqdq.CarrylessMultiply(xmmCRC3.AsUInt64(), crcFold.AsUInt64(), 0).AsUInt32();
xmmCRC0 = Sse2.ShiftRightLogical128BitLane(xmmCRC0, 8);
xmmCRC3 = Sse2.Xor(xmmCRC3, xmmCRC0);
xmmCRC0 = xmmCRC3;
xmmCRC3 = Sse2.ShiftLeftLogical128BitLane(xmmCRC3, 4);
xmmCRC3 = Pclmulqdq.CarrylessMultiply(xmmCRC3.AsUInt64(), crcFold.AsUInt64(), 0x10).AsUInt32();
xmmCRC3 = Sse2.Xor(xmmCRC3, xmmCRC0);
xmmCRC3 = Sse2.And(xmmCRC3, xmmMask2);
/*
* k7
*/
xmmCRC1 = xmmCRC3;
xmmCRC2 = xmmCRC3;
crcFold = Vector128.Create(_crcK[8], _crcK[9], _crcK[10], _crcK[11]);
xmmCRC3 = Pclmulqdq.CarrylessMultiply(xmmCRC3.AsUInt64(), crcFold.AsUInt64(), 0).AsUInt32();
xmmCRC3 = Sse2.Xor(xmmCRC3, xmmCRC2);
xmmCRC3 = Sse2.And(xmmCRC3, xmmMask);
xmmCRC2 = xmmCRC3;
xmmCRC3 = Pclmulqdq.CarrylessMultiply(xmmCRC3.AsUInt64(), crcFold.AsUInt64(), 0x10).AsUInt32();
xmmCRC3 = Sse2.Xor(xmmCRC3, xmmCRC2);
xmmCRC3 = Sse2.Xor(xmmCRC3, xmmCRC1);
/*
* could just as well write xmm_crc3[2], doing a movaps and truncating, but
* no real advantage - it's a tiny bit slower per call, while no additional CPUs
* would be supported by only requiring SSSE3 and CLMUL instead of SSE4.1 + CLMUL
*/
return ~Sse41.Extract(xmmCRC3, 2);
}
}
#endif

View File

@@ -0,0 +1,671 @@
// /***************************************************************************
// Aaru Data Preservation Suite
// ----------------------------------------------------------------------------
//
// Filename : CRC32Context.cs
// Author(s) : Natalia Portillo <claunia@claunia.com>
//
// Component : Checksums.
//
// --[ Description ] ----------------------------------------------------------
//
// Implements a CRC32 algorithm.
//
// --[ License ] --------------------------------------------------------------
//
// This library is free software; you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as
// published by the Free Software Foundation; either version 2.1 of the
// License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, see <http://www.gnu.org/licenses/>.
//
// ----------------------------------------------------------------------------
// Copyright © 2011-2023 Natalia Portillo
// ****************************************************************************/
using System;
using System.Diagnostics.CodeAnalysis;
using System.IO;
using System.Runtime.InteropServices;
#if NET5_0_OR_GREATER
using System.Runtime.Intrinsics.Arm;
#endif
#if NETCOREAPP3_1_OR_GREATER
using System.Runtime.Intrinsics.X86;
#endif
using System.Text;
#if NETCOREAPP3_1_OR_GREATER
using Aaru.Checksums.CRC32;
#endif
using Aaru.CommonTypes.Interfaces;
using Aaru.Helpers;
namespace Aaru.Checksums;
/// <inheritdoc />
/// <summary>Implements a CRC32 algorithm</summary>
[SuppressMessage("ReSharper", "UnusedMember.Global")]
[SuppressMessage("ReSharper", "MemberCanBeInternal")]
[SuppressMessage("ReSharper", "UnusedMethodReturnValue.Global")]
[SuppressMessage("ReSharper", "MemberCanBePrivate.Global")]
public sealed class Crc32Context : IChecksum
{
const uint CRC32_ISO_POLY = 0xEDB88320;
const uint CRC32_ISO_SEED = 0xFFFFFFFF;
internal static readonly uint[][] ISOCrc32Table =
{
new uint[]
{
0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, 0x076DC419, 0x706AF48F, 0xE963A535, 0x9E6495A3, 0x0EDB8832,
0x79DCB8A4, 0xE0D5E91E, 0x97D2D988, 0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91, 0x1DB71064, 0x6AB020F2,
0xF3B97148, 0x84BE41DE, 0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7, 0x136C9856, 0x646BA8C0, 0xFD62F97A,
0x8A65C9EC, 0x14015C4F, 0x63066CD9, 0xFA0F3D63, 0x8D080DF5, 0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172,
0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B, 0x35B5A8FA, 0x42B2986C, 0xDBBBC9D6, 0xACBCF940, 0x32D86CE3,
0x45DF5C75, 0xDCD60DCF, 0xABD13D59, 0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116, 0x21B4F4B5, 0x56B3C423,
0xCFBA9599, 0xB8BDA50F, 0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924, 0x2F6F7C87, 0x58684C11, 0xC1611DAB,
0xB6662D3D, 0x76DC4190, 0x01DB7106, 0x98D220BC, 0xEFD5102A, 0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433,
0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818, 0x7F6A0DBB, 0x086D3D2D, 0x91646C97, 0xE6635C01, 0x6B6B51F4,
0x1C6C6162, 0x856530D8, 0xF262004E, 0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457, 0x65B0D9C6, 0x12B7E950,
0x8BBEB8EA, 0xFCB9887C, 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65, 0x4DB26158, 0x3AB551CE, 0xA3BC0074,
0xD4BB30E2, 0x4ADFA541, 0x3DD895D7, 0xA4D1C46D, 0xD3D6F4FB, 0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0,
0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9, 0x5005713C, 0x270241AA, 0xBE0B1010, 0xC90C2086, 0x5768B525,
0x206F85B3, 0xB966D409, 0xCE61E49F, 0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4, 0x59B33D17, 0x2EB40D81,
0xB7BD5C3B, 0xC0BA6CAD, 0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A, 0xEAD54739, 0x9DD277AF, 0x04DB2615,
0x73DC1683, 0xE3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8, 0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1,
0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE, 0xF762575D, 0x806567CB, 0x196C3671, 0x6E6B06E7, 0xFED41B76,
0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC, 0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5, 0xD6D6A3E8, 0xA1D1937E,
0x38D8C2C4, 0x4FDFF252, 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B, 0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6,
0x41047A60, 0xDF60EFC3, 0xA867DF55, 0x316E8EEF, 0x4669BE79, 0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236,
0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F, 0xC5BA3BBE, 0xB2BD0B28, 0x2BB45A92, 0x5CB36A04, 0xC2D7FFA7,
0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D, 0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A, 0x9C0906A9, 0xEB0E363F,
0x72076785, 0x05005713, 0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38, 0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7,
0x0BDBDF21, 0x86D3D2D4, 0xF1D4E242, 0x68DDB3F8, 0x1FDA836E, 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777,
0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C, 0x8F659EFF, 0xF862AE69, 0x616BFFD3, 0x166CCF45, 0xA00AE278,
0xD70DD2EE, 0x4E048354, 0x3903B3C2, 0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB, 0xAED16A4A, 0xD9D65ADC,
0x40DF0B66, 0x37D83BF0, 0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9, 0xBDBDF21C, 0xCABAC28A, 0x53B39330,
0x24B4A3A6, 0xBAD03605, 0xCDD70693, 0x54DE5729, 0x23D967BF, 0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94,
0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D
},
new uint[]
{
0x00000000, 0x191B3141, 0x32366282, 0x2B2D53C3, 0x646CC504, 0x7D77F445, 0x565AA786, 0x4F4196C7, 0xC8D98A08,
0xD1C2BB49, 0xFAEFE88A, 0xE3F4D9CB, 0xACB54F0C, 0xB5AE7E4D, 0x9E832D8E, 0x87981CCF, 0x4AC21251, 0x53D92310,
0x78F470D3, 0x61EF4192, 0x2EAED755, 0x37B5E614, 0x1C98B5D7, 0x05838496, 0x821B9859, 0x9B00A918, 0xB02DFADB,
0xA936CB9A, 0xE6775D5D, 0xFF6C6C1C, 0xD4413FDF, 0xCD5A0E9E, 0x958424A2, 0x8C9F15E3, 0xA7B24620, 0xBEA97761,
0xF1E8E1A6, 0xE8F3D0E7, 0xC3DE8324, 0xDAC5B265, 0x5D5DAEAA, 0x44469FEB, 0x6F6BCC28, 0x7670FD69, 0x39316BAE,
0x202A5AEF, 0x0B07092C, 0x121C386D, 0xDF4636F3, 0xC65D07B2, 0xED705471, 0xF46B6530, 0xBB2AF3F7, 0xA231C2B6,
0x891C9175, 0x9007A034, 0x179FBCFB, 0x0E848DBA, 0x25A9DE79, 0x3CB2EF38, 0x73F379FF, 0x6AE848BE, 0x41C51B7D,
0x58DE2A3C, 0xF0794F05, 0xE9627E44, 0xC24F2D87, 0xDB541CC6, 0x94158A01, 0x8D0EBB40, 0xA623E883, 0xBF38D9C2,
0x38A0C50D, 0x21BBF44C, 0x0A96A78F, 0x138D96CE, 0x5CCC0009, 0x45D73148, 0x6EFA628B, 0x77E153CA, 0xBABB5D54,
0xA3A06C15, 0x888D3FD6, 0x91960E97, 0xDED79850, 0xC7CCA911, 0xECE1FAD2, 0xF5FACB93, 0x7262D75C, 0x6B79E61D,
0x4054B5DE, 0x594F849F, 0x160E1258, 0x0F152319, 0x243870DA, 0x3D23419B, 0x65FD6BA7, 0x7CE65AE6, 0x57CB0925,
0x4ED03864, 0x0191AEA3, 0x188A9FE2, 0x33A7CC21, 0x2ABCFD60, 0xAD24E1AF, 0xB43FD0EE, 0x9F12832D, 0x8609B26C,
0xC94824AB, 0xD05315EA, 0xFB7E4629, 0xE2657768, 0x2F3F79F6, 0x362448B7, 0x1D091B74, 0x04122A35, 0x4B53BCF2,
0x52488DB3, 0x7965DE70, 0x607EEF31, 0xE7E6F3FE, 0xFEFDC2BF, 0xD5D0917C, 0xCCCBA03D, 0x838A36FA, 0x9A9107BB,
0xB1BC5478, 0xA8A76539, 0x3B83984B, 0x2298A90A, 0x09B5FAC9, 0x10AECB88, 0x5FEF5D4F, 0x46F46C0E, 0x6DD93FCD,
0x74C20E8C, 0xF35A1243, 0xEA412302, 0xC16C70C1, 0xD8774180, 0x9736D747, 0x8E2DE606, 0xA500B5C5, 0xBC1B8484,
0x71418A1A, 0x685ABB5B, 0x4377E898, 0x5A6CD9D9, 0x152D4F1E, 0x0C367E5F, 0x271B2D9C, 0x3E001CDD, 0xB9980012,
0xA0833153, 0x8BAE6290, 0x92B553D1, 0xDDF4C516, 0xC4EFF457, 0xEFC2A794, 0xF6D996D5, 0xAE07BCE9, 0xB71C8DA8,
0x9C31DE6B, 0x852AEF2A, 0xCA6B79ED, 0xD37048AC, 0xF85D1B6F, 0xE1462A2E, 0x66DE36E1, 0x7FC507A0, 0x54E85463,
0x4DF36522, 0x02B2F3E5, 0x1BA9C2A4, 0x30849167, 0x299FA026, 0xE4C5AEB8, 0xFDDE9FF9, 0xD6F3CC3A, 0xCFE8FD7B,
0x80A96BBC, 0x99B25AFD, 0xB29F093E, 0xAB84387F, 0x2C1C24B0, 0x350715F1, 0x1E2A4632, 0x07317773, 0x4870E1B4,
0x516BD0F5, 0x7A468336, 0x635DB277, 0xCBFAD74E, 0xD2E1E60F, 0xF9CCB5CC, 0xE0D7848D, 0xAF96124A, 0xB68D230B,
0x9DA070C8, 0x84BB4189, 0x03235D46, 0x1A386C07, 0x31153FC4, 0x280E0E85, 0x674F9842, 0x7E54A903, 0x5579FAC0,
0x4C62CB81, 0x8138C51F, 0x9823F45E, 0xB30EA79D, 0xAA1596DC, 0xE554001B, 0xFC4F315A, 0xD7626299, 0xCE7953D8,
0x49E14F17, 0x50FA7E56, 0x7BD72D95, 0x62CC1CD4, 0x2D8D8A13, 0x3496BB52, 0x1FBBE891, 0x06A0D9D0, 0x5E7EF3EC,
0x4765C2AD, 0x6C48916E, 0x7553A02F, 0x3A1236E8, 0x230907A9, 0x0824546A, 0x113F652B, 0x96A779E4, 0x8FBC48A5,
0xA4911B66, 0xBD8A2A27, 0xF2CBBCE0, 0xEBD08DA1, 0xC0FDDE62, 0xD9E6EF23, 0x14BCE1BD, 0x0DA7D0FC, 0x268A833F,
0x3F91B27E, 0x70D024B9, 0x69CB15F8, 0x42E6463B, 0x5BFD777A, 0xDC656BB5, 0xC57E5AF4, 0xEE530937, 0xF7483876,
0xB809AEB1, 0xA1129FF0, 0x8A3FCC33, 0x9324FD72
},
new uint[]
{
0x00000000, 0x01C26A37, 0x0384D46E, 0x0246BE59, 0x0709A8DC, 0x06CBC2EB, 0x048D7CB2, 0x054F1685, 0x0E1351B8,
0x0FD13B8F, 0x0D9785D6, 0x0C55EFE1, 0x091AF964, 0x08D89353, 0x0A9E2D0A, 0x0B5C473D, 0x1C26A370, 0x1DE4C947,
0x1FA2771E, 0x1E601D29, 0x1B2F0BAC, 0x1AED619B, 0x18ABDFC2, 0x1969B5F5, 0x1235F2C8, 0x13F798FF, 0x11B126A6,
0x10734C91, 0x153C5A14, 0x14FE3023, 0x16B88E7A, 0x177AE44D, 0x384D46E0, 0x398F2CD7, 0x3BC9928E, 0x3A0BF8B9,
0x3F44EE3C, 0x3E86840B, 0x3CC03A52, 0x3D025065, 0x365E1758, 0x379C7D6F, 0x35DAC336, 0x3418A901, 0x3157BF84,
0x3095D5B3, 0x32D36BEA, 0x331101DD, 0x246BE590, 0x25A98FA7, 0x27EF31FE, 0x262D5BC9, 0x23624D4C, 0x22A0277B,
0x20E69922, 0x2124F315, 0x2A78B428, 0x2BBADE1F, 0x29FC6046, 0x283E0A71, 0x2D711CF4, 0x2CB376C3, 0x2EF5C89A,
0x2F37A2AD, 0x709A8DC0, 0x7158E7F7, 0x731E59AE, 0x72DC3399, 0x7793251C, 0x76514F2B, 0x7417F172, 0x75D59B45,
0x7E89DC78, 0x7F4BB64F, 0x7D0D0816, 0x7CCF6221, 0x798074A4, 0x78421E93, 0x7A04A0CA, 0x7BC6CAFD, 0x6CBC2EB0,
0x6D7E4487, 0x6F38FADE, 0x6EFA90E9, 0x6BB5866C, 0x6A77EC5B, 0x68315202, 0x69F33835, 0x62AF7F08, 0x636D153F,
0x612BAB66, 0x60E9C151, 0x65A6D7D4, 0x6464BDE3, 0x662203BA, 0x67E0698D, 0x48D7CB20, 0x4915A117, 0x4B531F4E,
0x4A917579, 0x4FDE63FC, 0x4E1C09CB, 0x4C5AB792, 0x4D98DDA5, 0x46C49A98, 0x4706F0AF, 0x45404EF6, 0x448224C1,
0x41CD3244, 0x400F5873, 0x4249E62A, 0x438B8C1D, 0x54F16850, 0x55330267, 0x5775BC3E, 0x56B7D609, 0x53F8C08C,
0x523AAABB, 0x507C14E2, 0x51BE7ED5, 0x5AE239E8, 0x5B2053DF, 0x5966ED86, 0x58A487B1, 0x5DEB9134, 0x5C29FB03,
0x5E6F455A, 0x5FAD2F6D, 0xE1351B80, 0xE0F771B7, 0xE2B1CFEE, 0xE373A5D9, 0xE63CB35C, 0xE7FED96B, 0xE5B86732,
0xE47A0D05, 0xEF264A38, 0xEEE4200F, 0xECA29E56, 0xED60F461, 0xE82FE2E4, 0xE9ED88D3, 0xEBAB368A, 0xEA695CBD,
0xFD13B8F0, 0xFCD1D2C7, 0xFE976C9E, 0xFF5506A9, 0xFA1A102C, 0xFBD87A1B, 0xF99EC442, 0xF85CAE75, 0xF300E948,
0xF2C2837F, 0xF0843D26, 0xF1465711, 0xF4094194, 0xF5CB2BA3, 0xF78D95FA, 0xF64FFFCD, 0xD9785D60, 0xD8BA3757,
0xDAFC890E, 0xDB3EE339, 0xDE71F5BC, 0xDFB39F8B, 0xDDF521D2, 0xDC374BE5, 0xD76B0CD8, 0xD6A966EF, 0xD4EFD8B6,
0xD52DB281, 0xD062A404, 0xD1A0CE33, 0xD3E6706A, 0xD2241A5D, 0xC55EFE10, 0xC49C9427, 0xC6DA2A7E, 0xC7184049,
0xC25756CC, 0xC3953CFB, 0xC1D382A2, 0xC011E895, 0xCB4DAFA8, 0xCA8FC59F, 0xC8C97BC6, 0xC90B11F1, 0xCC440774,
0xCD866D43, 0xCFC0D31A, 0xCE02B92D, 0x91AF9640, 0x906DFC77, 0x922B422E, 0x93E92819, 0x96A63E9C, 0x976454AB,
0x9522EAF2, 0x94E080C5, 0x9FBCC7F8, 0x9E7EADCF, 0x9C381396, 0x9DFA79A1, 0x98B56F24, 0x99770513, 0x9B31BB4A,
0x9AF3D17D, 0x8D893530, 0x8C4B5F07, 0x8E0DE15E, 0x8FCF8B69, 0x8A809DEC, 0x8B42F7DB, 0x89044982, 0x88C623B5,
0x839A6488, 0x82580EBF, 0x801EB0E6, 0x81DCDAD1, 0x8493CC54, 0x8551A663, 0x8717183A, 0x86D5720D, 0xA9E2D0A0,
0xA820BA97, 0xAA6604CE, 0xABA46EF9, 0xAEEB787C, 0xAF29124B, 0xAD6FAC12, 0xACADC625, 0xA7F18118, 0xA633EB2F,
0xA4755576, 0xA5B73F41, 0xA0F829C4, 0xA13A43F3, 0xA37CFDAA, 0xA2BE979D, 0xB5C473D0, 0xB40619E7, 0xB640A7BE,
0xB782CD89, 0xB2CDDB0C, 0xB30FB13B, 0xB1490F62, 0xB08B6555, 0xBBD72268, 0xBA15485F, 0xB853F606, 0xB9919C31,
0xBCDE8AB4, 0xBD1CE083, 0xBF5A5EDA, 0xBE9834ED
},
new uint[]
{
0x00000000, 0xB8BC6765, 0xAA09C88B, 0x12B5AFEE, 0x8F629757, 0x37DEF032, 0x256B5FDC, 0x9DD738B9, 0xC5B428EF,
0x7D084F8A, 0x6FBDE064, 0xD7018701, 0x4AD6BFB8, 0xF26AD8DD, 0xE0DF7733, 0x58631056, 0x5019579F, 0xE8A530FA,
0xFA109F14, 0x42ACF871, 0xDF7BC0C8, 0x67C7A7AD, 0x75720843, 0xCDCE6F26, 0x95AD7F70, 0x2D111815, 0x3FA4B7FB,
0x8718D09E, 0x1ACFE827, 0xA2738F42, 0xB0C620AC, 0x087A47C9, 0xA032AF3E, 0x188EC85B, 0x0A3B67B5, 0xB28700D0,
0x2F503869, 0x97EC5F0C, 0x8559F0E2, 0x3DE59787, 0x658687D1, 0xDD3AE0B4, 0xCF8F4F5A, 0x7733283F, 0xEAE41086,
0x525877E3, 0x40EDD80D, 0xF851BF68, 0xF02BF8A1, 0x48979FC4, 0x5A22302A, 0xE29E574F, 0x7F496FF6, 0xC7F50893,
0xD540A77D, 0x6DFCC018, 0x359FD04E, 0x8D23B72B, 0x9F9618C5, 0x272A7FA0, 0xBAFD4719, 0x0241207C, 0x10F48F92,
0xA848E8F7, 0x9B14583D, 0x23A83F58, 0x311D90B6, 0x89A1F7D3, 0x1476CF6A, 0xACCAA80F, 0xBE7F07E1, 0x06C36084,
0x5EA070D2, 0xE61C17B7, 0xF4A9B859, 0x4C15DF3C, 0xD1C2E785, 0x697E80E0, 0x7BCB2F0E, 0xC377486B, 0xCB0D0FA2,
0x73B168C7, 0x6104C729, 0xD9B8A04C, 0x446F98F5, 0xFCD3FF90, 0xEE66507E, 0x56DA371B, 0x0EB9274D, 0xB6054028,
0xA4B0EFC6, 0x1C0C88A3, 0x81DBB01A, 0x3967D77F, 0x2BD27891, 0x936E1FF4, 0x3B26F703, 0x839A9066, 0x912F3F88,
0x299358ED, 0xB4446054, 0x0CF80731, 0x1E4DA8DF, 0xA6F1CFBA, 0xFE92DFEC, 0x462EB889, 0x549B1767, 0xEC277002,
0x71F048BB, 0xC94C2FDE, 0xDBF98030, 0x6345E755, 0x6B3FA09C, 0xD383C7F9, 0xC1366817, 0x798A0F72, 0xE45D37CB,
0x5CE150AE, 0x4E54FF40, 0xF6E89825, 0xAE8B8873, 0x1637EF16, 0x048240F8, 0xBC3E279D, 0x21E91F24, 0x99557841,
0x8BE0D7AF, 0x335CB0CA, 0xED59B63B, 0x55E5D15E, 0x47507EB0, 0xFFEC19D5, 0x623B216C, 0xDA874609, 0xC832E9E7,
0x708E8E82, 0x28ED9ED4, 0x9051F9B1, 0x82E4565F, 0x3A58313A, 0xA78F0983, 0x1F336EE6, 0x0D86C108, 0xB53AA66D,
0xBD40E1A4, 0x05FC86C1, 0x1749292F, 0xAFF54E4A, 0x322276F3, 0x8A9E1196, 0x982BBE78, 0x2097D91D, 0x78F4C94B,
0xC048AE2E, 0xD2FD01C0, 0x6A4166A5, 0xF7965E1C, 0x4F2A3979, 0x5D9F9697, 0xE523F1F2, 0x4D6B1905, 0xF5D77E60,
0xE762D18E, 0x5FDEB6EB, 0xC2098E52, 0x7AB5E937, 0x680046D9, 0xD0BC21BC, 0x88DF31EA, 0x3063568F, 0x22D6F961,
0x9A6A9E04, 0x07BDA6BD, 0xBF01C1D8, 0xADB46E36, 0x15080953, 0x1D724E9A, 0xA5CE29FF, 0xB77B8611, 0x0FC7E174,
0x9210D9CD, 0x2AACBEA8, 0x38191146, 0x80A57623, 0xD8C66675, 0x607A0110, 0x72CFAEFE, 0xCA73C99B, 0x57A4F122,
0xEF189647, 0xFDAD39A9, 0x45115ECC, 0x764DEE06, 0xCEF18963, 0xDC44268D, 0x64F841E8, 0xF92F7951, 0x41931E34,
0x5326B1DA, 0xEB9AD6BF, 0xB3F9C6E9, 0x0B45A18C, 0x19F00E62, 0xA14C6907, 0x3C9B51BE, 0x842736DB, 0x96929935,
0x2E2EFE50, 0x2654B999, 0x9EE8DEFC, 0x8C5D7112, 0x34E11677, 0xA9362ECE, 0x118A49AB, 0x033FE645, 0xBB838120,
0xE3E09176, 0x5B5CF613, 0x49E959FD, 0xF1553E98, 0x6C820621, 0xD43E6144, 0xC68BCEAA, 0x7E37A9CF, 0xD67F4138,
0x6EC3265D, 0x7C7689B3, 0xC4CAEED6, 0x591DD66F, 0xE1A1B10A, 0xF3141EE4, 0x4BA87981, 0x13CB69D7, 0xAB770EB2,
0xB9C2A15C, 0x017EC639, 0x9CA9FE80, 0x241599E5, 0x36A0360B, 0x8E1C516E, 0x866616A7, 0x3EDA71C2, 0x2C6FDE2C,
0x94D3B949, 0x090481F0, 0xB1B8E695, 0xA30D497B, 0x1BB12E1E, 0x43D23E48, 0xFB6E592D, 0xE9DBF6C3, 0x516791A6,
0xCCB0A91F, 0x740CCE7A, 0x66B96194, 0xDE0506F1
},
new uint[]
{
0x00000000, 0x3D6029B0, 0x7AC05360, 0x47A07AD0, 0xF580A6C0, 0xC8E08F70, 0x8F40F5A0, 0xB220DC10, 0x30704BC1,
0x0D106271, 0x4AB018A1, 0x77D03111, 0xC5F0ED01, 0xF890C4B1, 0xBF30BE61, 0x825097D1, 0x60E09782, 0x5D80BE32,
0x1A20C4E2, 0x2740ED52, 0x95603142, 0xA80018F2, 0xEFA06222, 0xD2C04B92, 0x5090DC43, 0x6DF0F5F3, 0x2A508F23,
0x1730A693, 0xA5107A83, 0x98705333, 0xDFD029E3, 0xE2B00053, 0xC1C12F04, 0xFCA106B4, 0xBB017C64, 0x866155D4,
0x344189C4, 0x0921A074, 0x4E81DAA4, 0x73E1F314, 0xF1B164C5, 0xCCD14D75, 0x8B7137A5, 0xB6111E15, 0x0431C205,
0x3951EBB5, 0x7EF19165, 0x4391B8D5, 0xA121B886, 0x9C419136, 0xDBE1EBE6, 0xE681C256, 0x54A11E46, 0x69C137F6,
0x2E614D26, 0x13016496, 0x9151F347, 0xAC31DAF7, 0xEB91A027, 0xD6F18997, 0x64D15587, 0x59B17C37, 0x1E1106E7,
0x23712F57, 0x58F35849, 0x659371F9, 0x22330B29, 0x1F532299, 0xAD73FE89, 0x9013D739, 0xD7B3ADE9, 0xEAD38459,
0x68831388, 0x55E33A38, 0x124340E8, 0x2F236958, 0x9D03B548, 0xA0639CF8, 0xE7C3E628, 0xDAA3CF98, 0x3813CFCB,
0x0573E67B, 0x42D39CAB, 0x7FB3B51B, 0xCD93690B, 0xF0F340BB, 0xB7533A6B, 0x8A3313DB, 0x0863840A, 0x3503ADBA,
0x72A3D76A, 0x4FC3FEDA, 0xFDE322CA, 0xC0830B7A, 0x872371AA, 0xBA43581A, 0x9932774D, 0xA4525EFD, 0xE3F2242D,
0xDE920D9D, 0x6CB2D18D, 0x51D2F83D, 0x167282ED, 0x2B12AB5D, 0xA9423C8C, 0x9422153C, 0xD3826FEC, 0xEEE2465C,
0x5CC29A4C, 0x61A2B3FC, 0x2602C92C, 0x1B62E09C, 0xF9D2E0CF, 0xC4B2C97F, 0x8312B3AF, 0xBE729A1F, 0x0C52460F,
0x31326FBF, 0x7692156F, 0x4BF23CDF, 0xC9A2AB0E, 0xF4C282BE, 0xB362F86E, 0x8E02D1DE, 0x3C220DCE, 0x0142247E,
0x46E25EAE, 0x7B82771E, 0xB1E6B092, 0x8C869922, 0xCB26E3F2, 0xF646CA42, 0x44661652, 0x79063FE2, 0x3EA64532,
0x03C66C82, 0x8196FB53, 0xBCF6D2E3, 0xFB56A833, 0xC6368183, 0x74165D93, 0x49767423, 0x0ED60EF3, 0x33B62743,
0xD1062710, 0xEC660EA0, 0xABC67470, 0x96A65DC0, 0x248681D0, 0x19E6A860, 0x5E46D2B0, 0x6326FB00, 0xE1766CD1,
0xDC164561, 0x9BB63FB1, 0xA6D61601, 0x14F6CA11, 0x2996E3A1, 0x6E369971, 0x5356B0C1, 0x70279F96, 0x4D47B626,
0x0AE7CCF6, 0x3787E546, 0x85A73956, 0xB8C710E6, 0xFF676A36, 0xC2074386, 0x4057D457, 0x7D37FDE7, 0x3A978737,
0x07F7AE87, 0xB5D77297, 0x88B75B27, 0xCF1721F7, 0xF2770847, 0x10C70814, 0x2DA721A4, 0x6A075B74, 0x576772C4,
0xE547AED4, 0xD8278764, 0x9F87FDB4, 0xA2E7D404, 0x20B743D5, 0x1DD76A65, 0x5A7710B5, 0x67173905, 0xD537E515,
0xE857CCA5, 0xAFF7B675, 0x92979FC5, 0xE915E8DB, 0xD475C16B, 0x93D5BBBB, 0xAEB5920B, 0x1C954E1B, 0x21F567AB,
0x66551D7B, 0x5B3534CB, 0xD965A31A, 0xE4058AAA, 0xA3A5F07A, 0x9EC5D9CA, 0x2CE505DA, 0x11852C6A, 0x562556BA,
0x6B457F0A, 0x89F57F59, 0xB49556E9, 0xF3352C39, 0xCE550589, 0x7C75D999, 0x4115F029, 0x06B58AF9, 0x3BD5A349,
0xB9853498, 0x84E51D28, 0xC34567F8, 0xFE254E48, 0x4C059258, 0x7165BBE8, 0x36C5C138, 0x0BA5E888, 0x28D4C7DF,
0x15B4EE6F, 0x521494BF, 0x6F74BD0F, 0xDD54611F, 0xE03448AF, 0xA794327F, 0x9AF41BCF, 0x18A48C1E, 0x25C4A5AE,
0x6264DF7E, 0x5F04F6CE, 0xED242ADE, 0xD044036E, 0x97E479BE, 0xAA84500E, 0x4834505D, 0x755479ED, 0x32F4033D,
0x0F942A8D, 0xBDB4F69D, 0x80D4DF2D, 0xC774A5FD, 0xFA148C4D, 0x78441B9C, 0x4524322C, 0x028448FC, 0x3FE4614C,
0x8DC4BD5C, 0xB0A494EC, 0xF704EE3C, 0xCA64C78C
},
new uint[]
{
0x00000000, 0xCB5CD3A5, 0x4DC8A10B, 0x869472AE, 0x9B914216, 0x50CD91B3, 0xD659E31D, 0x1D0530B8, 0xEC53826D,
0x270F51C8, 0xA19B2366, 0x6AC7F0C3, 0x77C2C07B, 0xBC9E13DE, 0x3A0A6170, 0xF156B2D5, 0x03D6029B, 0xC88AD13E,
0x4E1EA390, 0x85427035, 0x9847408D, 0x531B9328, 0xD58FE186, 0x1ED33223, 0xEF8580F6, 0x24D95353, 0xA24D21FD,
0x6911F258, 0x7414C2E0, 0xBF481145, 0x39DC63EB, 0xF280B04E, 0x07AC0536, 0xCCF0D693, 0x4A64A43D, 0x81387798,
0x9C3D4720, 0x57619485, 0xD1F5E62B, 0x1AA9358E, 0xEBFF875B, 0x20A354FE, 0xA6372650, 0x6D6BF5F5, 0x706EC54D,
0xBB3216E8, 0x3DA66446, 0xF6FAB7E3, 0x047A07AD, 0xCF26D408, 0x49B2A6A6, 0x82EE7503, 0x9FEB45BB, 0x54B7961E,
0xD223E4B0, 0x197F3715, 0xE82985C0, 0x23755665, 0xA5E124CB, 0x6EBDF76E, 0x73B8C7D6, 0xB8E41473, 0x3E7066DD,
0xF52CB578, 0x0F580A6C, 0xC404D9C9, 0x4290AB67, 0x89CC78C2, 0x94C9487A, 0x5F959BDF, 0xD901E971, 0x125D3AD4,
0xE30B8801, 0x28575BA4, 0xAEC3290A, 0x659FFAAF, 0x789ACA17, 0xB3C619B2, 0x35526B1C, 0xFE0EB8B9, 0x0C8E08F7,
0xC7D2DB52, 0x4146A9FC, 0x8A1A7A59, 0x971F4AE1, 0x5C439944, 0xDAD7EBEA, 0x118B384F, 0xE0DD8A9A, 0x2B81593F,
0xAD152B91, 0x6649F834, 0x7B4CC88C, 0xB0101B29, 0x36846987, 0xFDD8BA22, 0x08F40F5A, 0xC3A8DCFF, 0x453CAE51,
0x8E607DF4, 0x93654D4C, 0x58399EE9, 0xDEADEC47, 0x15F13FE2, 0xE4A78D37, 0x2FFB5E92, 0xA96F2C3C, 0x6233FF99,
0x7F36CF21, 0xB46A1C84, 0x32FE6E2A, 0xF9A2BD8F, 0x0B220DC1, 0xC07EDE64, 0x46EAACCA, 0x8DB67F6F, 0x90B34FD7,
0x5BEF9C72, 0xDD7BEEDC, 0x16273D79, 0xE7718FAC, 0x2C2D5C09, 0xAAB92EA7, 0x61E5FD02, 0x7CE0CDBA, 0xB7BC1E1F,
0x31286CB1, 0xFA74BF14, 0x1EB014D8, 0xD5ECC77D, 0x5378B5D3, 0x98246676, 0x852156CE, 0x4E7D856B, 0xC8E9F7C5,
0x03B52460, 0xF2E396B5, 0x39BF4510, 0xBF2B37BE, 0x7477E41B, 0x6972D4A3, 0xA22E0706, 0x24BA75A8, 0xEFE6A60D,
0x1D661643, 0xD63AC5E6, 0x50AEB748, 0x9BF264ED, 0x86F75455, 0x4DAB87F0, 0xCB3FF55E, 0x006326FB, 0xF135942E,
0x3A69478B, 0xBCFD3525, 0x77A1E680, 0x6AA4D638, 0xA1F8059D, 0x276C7733, 0xEC30A496, 0x191C11EE, 0xD240C24B,
0x54D4B0E5, 0x9F886340, 0x828D53F8, 0x49D1805D, 0xCF45F2F3, 0x04192156, 0xF54F9383, 0x3E134026, 0xB8873288,
0x73DBE12D, 0x6EDED195, 0xA5820230, 0x2316709E, 0xE84AA33B, 0x1ACA1375, 0xD196C0D0, 0x5702B27E, 0x9C5E61DB,
0x815B5163, 0x4A0782C6, 0xCC93F068, 0x07CF23CD, 0xF6999118, 0x3DC542BD, 0xBB513013, 0x700DE3B6, 0x6D08D30E,
0xA65400AB, 0x20C07205, 0xEB9CA1A0, 0x11E81EB4, 0xDAB4CD11, 0x5C20BFBF, 0x977C6C1A, 0x8A795CA2, 0x41258F07,
0xC7B1FDA9, 0x0CED2E0C, 0xFDBB9CD9, 0x36E74F7C, 0xB0733DD2, 0x7B2FEE77, 0x662ADECF, 0xAD760D6A, 0x2BE27FC4,
0xE0BEAC61, 0x123E1C2F, 0xD962CF8A, 0x5FF6BD24, 0x94AA6E81, 0x89AF5E39, 0x42F38D9C, 0xC467FF32, 0x0F3B2C97,
0xFE6D9E42, 0x35314DE7, 0xB3A53F49, 0x78F9ECEC, 0x65FCDC54, 0xAEA00FF1, 0x28347D5F, 0xE368AEFA, 0x16441B82,
0xDD18C827, 0x5B8CBA89, 0x90D0692C, 0x8DD55994, 0x46898A31, 0xC01DF89F, 0x0B412B3A, 0xFA1799EF, 0x314B4A4A,
0xB7DF38E4, 0x7C83EB41, 0x6186DBF9, 0xAADA085C, 0x2C4E7AF2, 0xE712A957, 0x15921919, 0xDECECABC, 0x585AB812,
0x93066BB7, 0x8E035B0F, 0x455F88AA, 0xC3CBFA04, 0x089729A1, 0xF9C19B74, 0x329D48D1, 0xB4093A7F, 0x7F55E9DA,
0x6250D962, 0xA90C0AC7, 0x2F987869, 0xE4C4ABCC
},
new uint[]
{
0x00000000, 0xA6770BB4, 0x979F1129, 0x31E81A9D, 0xF44F2413, 0x52382FA7, 0x63D0353A, 0xC5A73E8E, 0x33EF4E67,
0x959845D3, 0xA4705F4E, 0x020754FA, 0xC7A06A74, 0x61D761C0, 0x503F7B5D, 0xF64870E9, 0x67DE9CCE, 0xC1A9977A,
0xF0418DE7, 0x56368653, 0x9391B8DD, 0x35E6B369, 0x040EA9F4, 0xA279A240, 0x5431D2A9, 0xF246D91D, 0xC3AEC380,
0x65D9C834, 0xA07EF6BA, 0x0609FD0E, 0x37E1E793, 0x9196EC27, 0xCFBD399C, 0x69CA3228, 0x582228B5, 0xFE552301,
0x3BF21D8F, 0x9D85163B, 0xAC6D0CA6, 0x0A1A0712, 0xFC5277FB, 0x5A257C4F, 0x6BCD66D2, 0xCDBA6D66, 0x081D53E8,
0xAE6A585C, 0x9F8242C1, 0x39F54975, 0xA863A552, 0x0E14AEE6, 0x3FFCB47B, 0x998BBFCF, 0x5C2C8141, 0xFA5B8AF5,
0xCBB39068, 0x6DC49BDC, 0x9B8CEB35, 0x3DFBE081, 0x0C13FA1C, 0xAA64F1A8, 0x6FC3CF26, 0xC9B4C492, 0xF85CDE0F,
0x5E2BD5BB, 0x440B7579, 0xE27C7ECD, 0xD3946450, 0x75E36FE4, 0xB044516A, 0x16335ADE, 0x27DB4043, 0x81AC4BF7,
0x77E43B1E, 0xD19330AA, 0xE07B2A37, 0x460C2183, 0x83AB1F0D, 0x25DC14B9, 0x14340E24, 0xB2430590, 0x23D5E9B7,
0x85A2E203, 0xB44AF89E, 0x123DF32A, 0xD79ACDA4, 0x71EDC610, 0x4005DC8D, 0xE672D739, 0x103AA7D0, 0xB64DAC64,
0x87A5B6F9, 0x21D2BD4D, 0xE47583C3, 0x42028877, 0x73EA92EA, 0xD59D995E, 0x8BB64CE5, 0x2DC14751, 0x1C295DCC,
0xBA5E5678, 0x7FF968F6, 0xD98E6342, 0xE86679DF, 0x4E11726B, 0xB8590282, 0x1E2E0936, 0x2FC613AB, 0x89B1181F,
0x4C162691, 0xEA612D25, 0xDB8937B8, 0x7DFE3C0C, 0xEC68D02B, 0x4A1FDB9F, 0x7BF7C102, 0xDD80CAB6, 0x1827F438,
0xBE50FF8C, 0x8FB8E511, 0x29CFEEA5, 0xDF879E4C, 0x79F095F8, 0x48188F65, 0xEE6F84D1, 0x2BC8BA5F, 0x8DBFB1EB,
0xBC57AB76, 0x1A20A0C2, 0x8816EAF2, 0x2E61E146, 0x1F89FBDB, 0xB9FEF06F, 0x7C59CEE1, 0xDA2EC555, 0xEBC6DFC8,
0x4DB1D47C, 0xBBF9A495, 0x1D8EAF21, 0x2C66B5BC, 0x8A11BE08, 0x4FB68086, 0xE9C18B32, 0xD82991AF, 0x7E5E9A1B,
0xEFC8763C, 0x49BF7D88, 0x78576715, 0xDE206CA1, 0x1B87522F, 0xBDF0599B, 0x8C184306, 0x2A6F48B2, 0xDC27385B,
0x7A5033EF, 0x4BB82972, 0xEDCF22C6, 0x28681C48, 0x8E1F17FC, 0xBFF70D61, 0x198006D5, 0x47ABD36E, 0xE1DCD8DA,
0xD034C247, 0x7643C9F3, 0xB3E4F77D, 0x1593FCC9, 0x247BE654, 0x820CEDE0, 0x74449D09, 0xD23396BD, 0xE3DB8C20,
0x45AC8794, 0x800BB91A, 0x267CB2AE, 0x1794A833, 0xB1E3A387, 0x20754FA0, 0x86024414, 0xB7EA5E89, 0x119D553D,
0xD43A6BB3, 0x724D6007, 0x43A57A9A, 0xE5D2712E, 0x139A01C7, 0xB5ED0A73, 0x840510EE, 0x22721B5A, 0xE7D525D4,
0x41A22E60, 0x704A34FD, 0xD63D3F49, 0xCC1D9F8B, 0x6A6A943F, 0x5B828EA2, 0xFDF58516, 0x3852BB98, 0x9E25B02C,
0xAFCDAAB1, 0x09BAA105, 0xFFF2D1EC, 0x5985DA58, 0x686DC0C5, 0xCE1ACB71, 0x0BBDF5FF, 0xADCAFE4B, 0x9C22E4D6,
0x3A55EF62, 0xABC30345, 0x0DB408F1, 0x3C5C126C, 0x9A2B19D8, 0x5F8C2756, 0xF9FB2CE2, 0xC813367F, 0x6E643DCB,
0x982C4D22, 0x3E5B4696, 0x0FB35C0B, 0xA9C457BF, 0x6C636931, 0xCA146285, 0xFBFC7818, 0x5D8B73AC, 0x03A0A617,
0xA5D7ADA3, 0x943FB73E, 0x3248BC8A, 0xF7EF8204, 0x519889B0, 0x6070932D, 0xC6079899, 0x304FE870, 0x9638E3C4,
0xA7D0F959, 0x01A7F2ED, 0xC400CC63, 0x6277C7D7, 0x539FDD4A, 0xF5E8D6FE, 0x647E3AD9, 0xC209316D, 0xF3E12BF0,
0x55962044, 0x90311ECA, 0x3646157E, 0x07AE0FE3, 0xA1D90457, 0x579174BE, 0xF1E67F0A, 0xC00E6597, 0x66796E23,
0xA3DE50AD, 0x05A95B19, 0x34414184, 0x92364A30
},
new uint[]
{
0x00000000, 0xCCAA009E, 0x4225077D, 0x8E8F07E3, 0x844A0EFA, 0x48E00E64, 0xC66F0987, 0x0AC50919, 0xD3E51BB5,
0x1F4F1B2B, 0x91C01CC8, 0x5D6A1C56, 0x57AF154F, 0x9B0515D1, 0x158A1232, 0xD92012AC, 0x7CBB312B, 0xB01131B5,
0x3E9E3656, 0xF23436C8, 0xF8F13FD1, 0x345B3F4F, 0xBAD438AC, 0x767E3832, 0xAF5E2A9E, 0x63F42A00, 0xED7B2DE3,
0x21D12D7D, 0x2B142464, 0xE7BE24FA, 0x69312319, 0xA59B2387, 0xF9766256, 0x35DC62C8, 0xBB53652B, 0x77F965B5,
0x7D3C6CAC, 0xB1966C32, 0x3F196BD1, 0xF3B36B4F, 0x2A9379E3, 0xE639797D, 0x68B67E9E, 0xA41C7E00, 0xAED97719,
0x62737787, 0xECFC7064, 0x205670FA, 0x85CD537D, 0x496753E3, 0xC7E85400, 0x0B42549E, 0x01875D87, 0xCD2D5D19,
0x43A25AFA, 0x8F085A64, 0x562848C8, 0x9A824856, 0x140D4FB5, 0xD8A74F2B, 0xD2624632, 0x1EC846AC, 0x9047414F,
0x5CED41D1, 0x299DC2ED, 0xE537C273, 0x6BB8C590, 0xA712C50E, 0xADD7CC17, 0x617DCC89, 0xEFF2CB6A, 0x2358CBF4,
0xFA78D958, 0x36D2D9C6, 0xB85DDE25, 0x74F7DEBB, 0x7E32D7A2, 0xB298D73C, 0x3C17D0DF, 0xF0BDD041, 0x5526F3C6,
0x998CF358, 0x1703F4BB, 0xDBA9F425, 0xD16CFD3C, 0x1DC6FDA2, 0x9349FA41, 0x5FE3FADF, 0x86C3E873, 0x4A69E8ED,
0xC4E6EF0E, 0x084CEF90, 0x0289E689, 0xCE23E617, 0x40ACE1F4, 0x8C06E16A, 0xD0EBA0BB, 0x1C41A025, 0x92CEA7C6,
0x5E64A758, 0x54A1AE41, 0x980BAEDF, 0x1684A93C, 0xDA2EA9A2, 0x030EBB0E, 0xCFA4BB90, 0x412BBC73, 0x8D81BCED,
0x8744B5F4, 0x4BEEB56A, 0xC561B289, 0x09CBB217, 0xAC509190, 0x60FA910E, 0xEE7596ED, 0x22DF9673, 0x281A9F6A,
0xE4B09FF4, 0x6A3F9817, 0xA6959889, 0x7FB58A25, 0xB31F8ABB, 0x3D908D58, 0xF13A8DC6, 0xFBFF84DF, 0x37558441,
0xB9DA83A2, 0x7570833C, 0x533B85DA, 0x9F918544, 0x111E82A7, 0xDDB48239, 0xD7718B20, 0x1BDB8BBE, 0x95548C5D,
0x59FE8CC3, 0x80DE9E6F, 0x4C749EF1, 0xC2FB9912, 0x0E51998C, 0x04949095, 0xC83E900B, 0x46B197E8, 0x8A1B9776,
0x2F80B4F1, 0xE32AB46F, 0x6DA5B38C, 0xA10FB312, 0xABCABA0B, 0x6760BA95, 0xE9EFBD76, 0x2545BDE8, 0xFC65AF44,
0x30CFAFDA, 0xBE40A839, 0x72EAA8A7, 0x782FA1BE, 0xB485A120, 0x3A0AA6C3, 0xF6A0A65D, 0xAA4DE78C, 0x66E7E712,
0xE868E0F1, 0x24C2E06F, 0x2E07E976, 0xE2ADE9E8, 0x6C22EE0B, 0xA088EE95, 0x79A8FC39, 0xB502FCA7, 0x3B8DFB44,
0xF727FBDA, 0xFDE2F2C3, 0x3148F25D, 0xBFC7F5BE, 0x736DF520, 0xD6F6D6A7, 0x1A5CD639, 0x94D3D1DA, 0x5879D144,
0x52BCD85D, 0x9E16D8C3, 0x1099DF20, 0xDC33DFBE, 0x0513CD12, 0xC9B9CD8C, 0x4736CA6F, 0x8B9CCAF1, 0x8159C3E8,
0x4DF3C376, 0xC37CC495, 0x0FD6C40B, 0x7AA64737, 0xB60C47A9, 0x3883404A, 0xF42940D4, 0xFEEC49CD, 0x32464953,
0xBCC94EB0, 0x70634E2E, 0xA9435C82, 0x65E95C1C, 0xEB665BFF, 0x27CC5B61, 0x2D095278, 0xE1A352E6, 0x6F2C5505,
0xA386559B, 0x061D761C, 0xCAB77682, 0x44387161, 0x889271FF, 0x825778E6, 0x4EFD7878, 0xC0727F9B, 0x0CD87F05,
0xD5F86DA9, 0x19526D37, 0x97DD6AD4, 0x5B776A4A, 0x51B26353, 0x9D1863CD, 0x1397642E, 0xDF3D64B0, 0x83D02561,
0x4F7A25FF, 0xC1F5221C, 0x0D5F2282, 0x079A2B9B, 0xCB302B05, 0x45BF2CE6, 0x89152C78, 0x50353ED4, 0x9C9F3E4A,
0x121039A9, 0xDEBA3937, 0xD47F302E, 0x18D530B0, 0x965A3753, 0x5AF037CD, 0xFF6B144A, 0x33C114D4, 0xBD4E1337,
0x71E413A9, 0x7B211AB0, 0xB78B1A2E, 0x39041DCD, 0xF5AE1D53, 0x2C8E0FFF, 0xE0240F61, 0x6EAB0882, 0xA201081C,
0xA8C40105, 0x646E019B, 0xEAE10678, 0x264B06E6
}
};
readonly uint _finalSeed;
readonly IntPtr _nativeContext;
readonly uint[][]? _table;
readonly bool _useIso;
readonly bool _useNative;
uint _hashInt;
/// <summary>Initializes the CRC32 table and seed as CRC32-ISO</summary>
public Crc32Context()
{
_hashInt = CRC32_ISO_SEED;
_finalSeed = CRC32_ISO_SEED;
_table = ISOCrc32Table;
_useIso = true;
if(!Native.IsSupported)
return;
_nativeContext = crc32_init();
_useNative = _nativeContext != IntPtr.Zero;
}
/// <summary>Initializes the CRC32 table with a custom polynomial and seed</summary>
public Crc32Context(uint polynomial, uint seed)
{
_hashInt = seed;
_finalSeed = seed;
_useIso = polynomial == CRC32_ISO_POLY && seed == CRC32_ISO_SEED;
if(Native.IsSupported && _useIso)
{
_nativeContext = crc32_init();
_useNative = _nativeContext != IntPtr.Zero;
}
else
_table = GenerateTable(polynomial);
}
#region IChecksum Members
/// <inheritdoc />
public string Name => "CRC-32";
/// <inheritdoc />
public Guid Id => new("BCC4E18A-79CD-4B52-8A57-2B599E5176B3");
/// <inheritdoc />
public string Author => "Natalia Portillo";
/// <inheritdoc />
/// <summary>Updates the hash with data.</summary>
/// <param name="data">Data buffer.</param>
/// <param name="len">Length of buffer to hash.</param>
public void Update(byte[] data, uint len) =>
Step(ref _hashInt, _table!, data, len, _useIso, _useNative, _nativeContext);
/// <inheritdoc />
/// <summary>Updates the hash with data.</summary>
/// <param name="data">Data buffer.</param>
public void Update(byte[] data) => Update(data, (uint)data.Length);
/// <inheritdoc />
/// <summary>Returns a byte array of the hash value.</summary>
public byte[] Final()
{
uint crc = _hashInt ^ _finalSeed;
if(!_useNative || !_useIso)
return BigEndianBitConverter.GetBytes(crc);
crc32_final(_nativeContext, ref crc);
crc32_free(_nativeContext);
return BigEndianBitConverter.GetBytes(crc);
}
/// <inheritdoc />
/// <summary>Returns a hexadecimal representation of the hash value.</summary>
public string End()
{
uint crc = _hashInt ^ _finalSeed;
var crc32Output = new StringBuilder();
if(_useNative && _useIso)
{
crc32_final(_nativeContext, ref crc);
crc32_free(_nativeContext);
}
for(var i = 0; i < BigEndianBitConverter.GetBytes(crc).Length; i++)
crc32Output.Append(BigEndianBitConverter.GetBytes(crc)[i].ToString("x2"));
return crc32Output.ToString();
}
#endregion
[DllImport("libAaru.Checksums.Native", SetLastError = true)]
static extern IntPtr crc32_init();
[DllImport("libAaru.Checksums.Native", SetLastError = true)]
static extern int crc32_update(IntPtr ctx, byte[] data, uint len);
[DllImport("libAaru.Checksums.Native", SetLastError = true)]
static extern int crc32_final(IntPtr ctx, ref uint crc);
[DllImport("libAaru.Checksums.Native", SetLastError = true)]
static extern void crc32_free(IntPtr ctx);
static uint[][] GenerateTable(uint polynomial)
{
var table = new uint[8][];
for(var i = 0; i < 8; i++)
table[i] = new uint[256];
for(var i = 0; i < 256; i++)
{
var entry = (uint)i;
for(var j = 0; j < 8; j++)
{
if((entry & 1) == 1)
entry = entry >> 1 ^ polynomial;
else
entry >>= 1;
}
table[0][i] = entry;
}
for(var slice = 1; slice < 8; slice++)
for(var i = 0; i < 256; i++)
table[slice][i] = table[slice - 1][i] >> 8 ^ table[0][table[slice - 1][i] & 0xFF];
return table;
}
static void Step(ref uint previousCrc, uint[][] table, byte[] data, uint len, bool useIso, bool useNative,
IntPtr nativeContext)
{
if(useNative && useIso)
{
crc32_update(nativeContext, data, len);
return;
}
var currentPos = 0;
if(useIso)
{
#if NETCOREAPP3_1_OR_GREATER
if(Pclmulqdq.IsSupported && Sse41.IsSupported && Ssse3.IsSupported && Sse2.IsSupported)
{
// Only works in blocks of 16 bytes
uint blocks = len / 64;
if(blocks > 0)
{
previousCrc = ~Clmul.Step(data, blocks * 64, ~previousCrc);
currentPos = (int)(blocks * 64);
len -= blocks * 64;
}
if(len == 0)
return;
}
#endif
#if NET5_0_OR_GREATER
if(Crc32.Arm64.IsSupported)
{
previousCrc = ArmSimd.Step64(data, len, previousCrc);
return;
}
if(Crc32.IsSupported)
{
previousCrc = ArmSimd.Step32(data, len, previousCrc);
return;
}
#endif
}
// Unroll according to Intel slicing by uint8_t
// http://www.intel.com/technology/comms/perfnet/download/CRC_generators.pdf
// http://sourceforge.net/projects/slicing-by-8/
const int unroll = 4;
const int bytesAtOnce = 8 * unroll;
uint crc = previousCrc;
while(len >= bytesAtOnce)
{
int unrolling;
for(unrolling = 0; unrolling < unroll; unrolling++)
{
uint one = BitConverter.ToUInt32(data, currentPos) ^ crc;
currentPos += 4;
var two = BitConverter.ToUInt32(data, currentPos);
currentPos += 4;
crc = table[0][two >> 24 & 0xFF] ^
table[1][two >> 16 & 0xFF] ^
table[2][two >> 8 & 0xFF] ^
table[3][two & 0xFF] ^
table[4][one >> 24 & 0xFF] ^
table[5][one >> 16 & 0xFF] ^
table[6][one >> 8 & 0xFF] ^
table[7][one & 0xFF];
}
len -= bytesAtOnce;
}
while(len-- != 0)
crc = crc >> 8 ^ table[0][crc & 0xFF ^ data[currentPos++]];
previousCrc = crc;
}
/// <summary>Gets the hash of a file</summary>
/// <param name="filename">File path.</param>
// ReSharper disable once ReturnTypeCanBeEnumerable.Global
public static byte[] File(string filename)
{
File(filename, out byte[] hash);
return hash;
}
/// <summary>Gets the hash of a file in hexadecimal and as a byte array.</summary>
/// <param name="filename">File path.</param>
/// <param name="hash">Byte array of the hash value.</param>
public static string File(string filename, out byte[] hash) =>
File(filename, out hash, CRC32_ISO_POLY, CRC32_ISO_SEED);
/// <summary>Gets the hash of a file in hexadecimal and as a byte array.</summary>
/// <param name="filename">File path.</param>
/// <param name="hash">Byte array of the hash value.</param>
/// <param name="polynomial">CRC polynomial</param>
/// <param name="seed">CRC seed</param>
public static string File(string filename, out byte[] hash, uint polynomial, uint seed)
{
bool useIso = polynomial == CRC32_ISO_POLY && seed == CRC32_ISO_SEED;
bool useNative = Native.IsSupported;
IntPtr nativeContext = IntPtr.Zero;
if(useNative && useIso)
{
nativeContext = crc32_init();
useNative = nativeContext != IntPtr.Zero;
}
var fileStream = new FileStream(filename, FileMode.Open);
uint localHashInt = seed;
uint[][] localTable = GenerateTable(polynomial);
var buffer = new byte[65536];
int read = fileStream.EnsureRead(buffer, 0, 65536);
while(read > 0)
{
Step(ref localHashInt, localTable, buffer, (uint)read, useIso, useNative, nativeContext);
read = fileStream.EnsureRead(buffer, 0, 65536);
}
localHashInt ^= seed;
if(useNative && useIso)
{
crc32_final(nativeContext, ref localHashInt);
crc32_free(nativeContext);
}
hash = BigEndianBitConverter.GetBytes(localHashInt);
var crc32Output = new StringBuilder();
foreach(byte h in hash)
crc32Output.Append(h.ToString("x2"));
fileStream.Close();
return crc32Output.ToString();
}
/// <summary>Gets the hash of the specified data buffer.</summary>
/// <param name="data">Data buffer.</param>
/// <param name="len">Length of the data buffer to hash.</param>
/// <param name="hash">Byte array of the hash value.</param>
public static string Data(byte[] data, uint len, out byte[] hash) =>
Data(data, len, out hash, CRC32_ISO_POLY, CRC32_ISO_SEED);
/// <summary>Gets the hash of the specified data buffer.</summary>
/// <param name="data">Data buffer.</param>
/// <param name="len">Length of the data buffer to hash.</param>
/// <param name="hash">Byte array of the hash value.</param>
/// <param name="polynomial">CRC polynomial</param>
/// <param name="seed">CRC seed</param>
public static string Data(byte[] data, uint len, out byte[] hash, uint polynomial, uint seed)
{
bool useIso = polynomial == CRC32_ISO_POLY && seed == CRC32_ISO_SEED;
bool useNative = Native.IsSupported;
IntPtr nativeContext = IntPtr.Zero;
if(useNative && useIso)
{
nativeContext = crc32_init();
useNative = nativeContext != IntPtr.Zero;
}
uint localHashInt = seed;
uint[][] localTable = GenerateTable(polynomial);
Step(ref localHashInt, localTable, data, len, useIso, useNative, nativeContext);
localHashInt ^= seed;
if(useNative && useIso)
{
crc32_final(nativeContext, ref localHashInt);
crc32_free(nativeContext);
}
hash = BigEndianBitConverter.GetBytes(localHashInt);
var crc32Output = new StringBuilder();
foreach(byte h in hash)
crc32Output.Append(h.ToString("x2"));
return crc32Output.ToString();
}
/// <summary>Gets the hash of the specified data buffer.</summary>
/// <param name="data">Data buffer.</param>
/// <param name="hash">Byte array of the hash value.</param>
public static string Data(byte[] data, out byte[] hash) => Data(data, (uint)data.Length, out hash);
}

View File

@@ -0,0 +1,111 @@
// /***************************************************************************
// Aaru Data Preservation Suite
// ----------------------------------------------------------------------------
//
// Filename : clmul.cs
// Author(s) : Natalia Portillo <claunia@claunia.com>
//
// Component : Checksums.
//
// --[ Description ] ----------------------------------------------------------
//
// Compute the CRC64 using a parallelized folding approach with the PCLMULQDQ
// instruction.
//
// --[ License ] --------------------------------------------------------------
//
// This file is under the public domain:
// https://github.com/rawrunprotected/crc
//
// ----------------------------------------------------------------------------
// Copyright © 2011-2023 Natalia Portillo
// ****************************************************************************/
#if NETCOREAPP3_1_OR_GREATER
using System;
using System.Runtime.CompilerServices;
using System.Runtime.Intrinsics;
using System.Runtime.Intrinsics.X86;
namespace Aaru.Checksums.CRC64;
static class Clmul
{
static readonly byte[] _shuffleMasks =
{
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x8f, 0x8e,
0x8d, 0x8c, 0x8b, 0x8a, 0x89, 0x88, 0x87, 0x86, 0x85, 0x84, 0x83, 0x82, 0x81, 0x80
};
[MethodImpl(MethodImplOptions.AggressiveInlining)]
static void ShiftRight128(Vector128<ulong> initial, uint n, out Vector128<ulong> outLeft,
out Vector128<ulong> outRight)
{
uint maskPos = 16 - n;
var maskA = Vector128.Create(_shuffleMasks[maskPos], _shuffleMasks[maskPos + 1], _shuffleMasks[maskPos + 2],
_shuffleMasks[maskPos + 3], _shuffleMasks[maskPos + 4], _shuffleMasks[maskPos + 5],
_shuffleMasks[maskPos + 6], _shuffleMasks[maskPos + 7], _shuffleMasks[maskPos + 8],
_shuffleMasks[maskPos + 9], _shuffleMasks[maskPos + 10],
_shuffleMasks[maskPos + 11], _shuffleMasks[maskPos + 12],
_shuffleMasks[maskPos + 13], _shuffleMasks[maskPos + 14],
_shuffleMasks[maskPos + 15]);
Vector128<byte> maskB = Sse2.Xor(maskA, Sse2.CompareEqual(Vector128<byte>.Zero, Vector128<byte>.Zero));
outLeft = Ssse3.Shuffle(initial.AsByte(), maskB).AsUInt64();
outRight = Ssse3.Shuffle(initial.AsByte(), maskA).AsUInt64();
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
static Vector128<ulong> Fold(Vector128<ulong> input, Vector128<ulong> foldConstants) =>
Sse2.Xor(Pclmulqdq.CarrylessMultiply(input, foldConstants, 0x00),
Pclmulqdq.CarrylessMultiply(input, foldConstants, 0x11));
internal static ulong Step(ulong crc, byte[] data, uint length)
{
var bufPos = 16;
const ulong k1 = 0xe05dd497ca393ae4;
const ulong k2 = 0xdabe95afc7875f40;
const ulong mu = 0x9c3e466c172963d5;
const ulong pol = 0x92d8af2baf0e1e85;
var foldConstants1 = Vector128.Create(k1, k2);
var foldConstants2 = Vector128.Create(mu, pol);
var initialCrc = Vector128.Create(~crc, 0);
length -= 16;
// Initial CRC can simply be added to data
ShiftRight128(initialCrc, 0, out Vector128<ulong> crc0, out Vector128<ulong> crc1);
Vector128<ulong> accumulator =
Sse2.Xor(Fold(Sse2.Xor(crc0, Vector128.Create(BitConverter.ToUInt64(data, 0), BitConverter.ToUInt64(data, 8))), foldConstants1),
crc1);
while(length >= 32)
{
accumulator =
Fold(Sse2.Xor(Vector128.Create(BitConverter.ToUInt64(data, bufPos), BitConverter.ToUInt64(data, bufPos + 8)), accumulator),
foldConstants1);
length -= 16;
bufPos += 16;
}
Vector128<ulong> p = Sse2.Xor(accumulator,
Vector128.Create(BitConverter.ToUInt64(data, bufPos),
BitConverter.ToUInt64(data, bufPos + 8)));
Vector128<ulong> r = Sse2.Xor(Pclmulqdq.CarrylessMultiply(p, foldConstants1, 0x10),
Sse2.ShiftRightLogical128BitLane(p, 8));
// Final Barrett reduction
Vector128<ulong> t1 = Pclmulqdq.CarrylessMultiply(r, foldConstants2, 0x00);
Vector128<ulong> t2 =
Sse2.Xor(Sse2.Xor(Pclmulqdq.CarrylessMultiply(t1, foldConstants2, 0x10), Sse2.ShiftLeftLogical128BitLane(t1, 8)),
r);
return ~((ulong)Sse41.Extract(t2.AsUInt32(), 3) << 32 | Sse41.Extract(t2.AsUInt32(), 2));
}
}
#endif

View File

@@ -0,0 +1,608 @@
// /***************************************************************************
// Aaru Data Preservation Suite
// ----------------------------------------------------------------------------
//
// Filename : CRC64Context.cs
// Author(s) : Natalia Portillo <claunia@claunia.com>
//
// Component : Checksums.
//
// --[ Description ] ----------------------------------------------------------
//
// Implements a CRC64 algorithm.
//
// --[ License ] --------------------------------------------------------------
//
// This library is free software; you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as
// published by the Free Software Foundation; either version 2.1 of the
// License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, see <http://www.gnu.org/licenses/>.
//
// ----------------------------------------------------------------------------
// Copyright © 2011-2023 Natalia Portillo
// ****************************************************************************/
using System;
using System.Diagnostics.CodeAnalysis;
using System.IO;
using System.Runtime.InteropServices;
#if NETCOREAPP3_1_OR_GREATER
using System.Runtime.Intrinsics.X86;
#endif
using System.Text;
#if NETCOREAPP3_1_OR_GREATER
using Aaru.Checksums.CRC64;
#endif
using Aaru.CommonTypes.Interfaces;
using Aaru.Helpers;
namespace Aaru.Checksums;
/// <inheritdoc />
/// <summary>Implements a CRC64 algorithm</summary>
[SuppressMessage("ReSharper", "UnusedMember.Global")]
[SuppressMessage("ReSharper", "UnusedMethodReturnValue.Global")]
[SuppressMessage("ReSharper", "MemberCanBePrivate.Global")]
[SuppressMessage("ReSharper", "MemberCanBeInternal")]
public sealed class Crc64Context : IChecksum
{
/// <summary>ECMA CRC64 polynomial</summary>
const ulong CRC64_ECMA_POLY = 0xC96C5795D7870F42;
/// <summary>ECMA CRC64 seed</summary>
const ulong CRC64_ECMA_SEED = 0xFFFFFFFFFFFFFFFF;
static readonly ulong[][] _ecmaCrc64Table =
{
new ulong[]
{
0x0000000000000000, 0xB32E4CBE03A75F6F, 0xF4843657A840A05B, 0x47AA7AE9ABE7FF34, 0x7BD0C384FF8F5E33,
0xC8FE8F3AFC28015C, 0x8F54F5D357CFFE68, 0x3C7AB96D5468A107, 0xF7A18709FF1EBC66, 0x448FCBB7FCB9E309,
0x0325B15E575E1C3D, 0xB00BFDE054F94352, 0x8C71448D0091E255, 0x3F5F08330336BD3A, 0x78F572DAA8D1420E,
0xCBDB3E64AB761D61, 0x7D9BA13851336649, 0xCEB5ED8652943926, 0x891F976FF973C612, 0x3A31DBD1FAD4997D,
0x064B62BCAEBC387A, 0xB5652E02AD1B6715, 0xF2CF54EB06FC9821, 0x41E11855055BC74E, 0x8A3A2631AE2DDA2F,
0x39146A8FAD8A8540, 0x7EBE1066066D7A74, 0xCD905CD805CA251B, 0xF1EAE5B551A2841C, 0x42C4A90B5205DB73,
0x056ED3E2F9E22447, 0xB6409F5CFA457B28, 0xFB374270A266CC92, 0x48190ECEA1C193FD, 0x0FB374270A266CC9,
0xBC9D3899098133A6, 0x80E781F45DE992A1, 0x33C9CD4A5E4ECDCE, 0x7463B7A3F5A932FA, 0xC74DFB1DF60E6D95,
0x0C96C5795D7870F4, 0xBFB889C75EDF2F9B, 0xF812F32EF538D0AF, 0x4B3CBF90F69F8FC0, 0x774606FDA2F72EC7,
0xC4684A43A15071A8, 0x83C230AA0AB78E9C, 0x30EC7C140910D1F3, 0x86ACE348F355AADB, 0x3582AFF6F0F2F5B4,
0x7228D51F5B150A80, 0xC10699A158B255EF, 0xFD7C20CC0CDAF4E8, 0x4E526C720F7DAB87, 0x09F8169BA49A54B3,
0xBAD65A25A73D0BDC, 0x710D64410C4B16BD, 0xC22328FF0FEC49D2, 0x85895216A40BB6E6, 0x36A71EA8A7ACE989,
0x0ADDA7C5F3C4488E, 0xB9F3EB7BF06317E1, 0xFE5991925B84E8D5, 0x4D77DD2C5823B7BA, 0x64B62BCAEBC387A1,
0xD7986774E864D8CE, 0x90321D9D438327FA, 0x231C512340247895, 0x1F66E84E144CD992, 0xAC48A4F017EB86FD,
0xEBE2DE19BC0C79C9, 0x58CC92A7BFAB26A6, 0x9317ACC314DD3BC7, 0x2039E07D177A64A8, 0x67939A94BC9D9B9C,
0xD4BDD62ABF3AC4F3, 0xE8C76F47EB5265F4, 0x5BE923F9E8F53A9B, 0x1C4359104312C5AF, 0xAF6D15AE40B59AC0,
0x192D8AF2BAF0E1E8, 0xAA03C64CB957BE87, 0xEDA9BCA512B041B3, 0x5E87F01B11171EDC, 0x62FD4976457FBFDB,
0xD1D305C846D8E0B4, 0x96797F21ED3F1F80, 0x2557339FEE9840EF, 0xEE8C0DFB45EE5D8E, 0x5DA24145464902E1,
0x1A083BACEDAEFDD5, 0xA9267712EE09A2BA, 0x955CCE7FBA6103BD, 0x267282C1B9C65CD2, 0x61D8F8281221A3E6,
0xD2F6B4961186FC89, 0x9F8169BA49A54B33, 0x2CAF25044A02145C, 0x6B055FEDE1E5EB68, 0xD82B1353E242B407,
0xE451AA3EB62A1500, 0x577FE680B58D4A6F, 0x10D59C691E6AB55B, 0xA3FBD0D71DCDEA34, 0x6820EEB3B6BBF755,
0xDB0EA20DB51CA83A, 0x9CA4D8E41EFB570E, 0x2F8A945A1D5C0861, 0x13F02D374934A966, 0xA0DE61894A93F609,
0xE7741B60E174093D, 0x545A57DEE2D35652, 0xE21AC88218962D7A, 0x5134843C1B317215, 0x169EFED5B0D68D21,
0xA5B0B26BB371D24E, 0x99CA0B06E7197349, 0x2AE447B8E4BE2C26, 0x6D4E3D514F59D312, 0xDE6071EF4CFE8C7D,
0x15BB4F8BE788911C, 0xA6950335E42FCE73, 0xE13F79DC4FC83147, 0x521135624C6F6E28, 0x6E6B8C0F1807CF2F,
0xDD45C0B11BA09040, 0x9AEFBA58B0476F74, 0x29C1F6E6B3E0301B, 0xC96C5795D7870F42, 0x7A421B2BD420502D,
0x3DE861C27FC7AF19, 0x8EC62D7C7C60F076, 0xB2BC941128085171, 0x0192D8AF2BAF0E1E, 0x4638A2468048F12A,
0xF516EEF883EFAE45, 0x3ECDD09C2899B324, 0x8DE39C222B3EEC4B, 0xCA49E6CB80D9137F, 0x7967AA75837E4C10,
0x451D1318D716ED17, 0xF6335FA6D4B1B278, 0xB199254F7F564D4C, 0x02B769F17CF11223, 0xB4F7F6AD86B4690B,
0x07D9BA1385133664, 0x4073C0FA2EF4C950, 0xF35D8C442D53963F, 0xCF273529793B3738, 0x7C0979977A9C6857,
0x3BA3037ED17B9763, 0x888D4FC0D2DCC80C, 0x435671A479AAD56D, 0xF0783D1A7A0D8A02, 0xB7D247F3D1EA7536,
0x04FC0B4DD24D2A59, 0x3886B22086258B5E, 0x8BA8FE9E8582D431, 0xCC0284772E652B05, 0x7F2CC8C92DC2746A,
0x325B15E575E1C3D0, 0x8175595B76469CBF, 0xC6DF23B2DDA1638B, 0x75F16F0CDE063CE4, 0x498BD6618A6E9DE3,
0xFAA59ADF89C9C28C, 0xBD0FE036222E3DB8, 0x0E21AC88218962D7, 0xC5FA92EC8AFF7FB6, 0x76D4DE52895820D9,
0x317EA4BB22BFDFED, 0x8250E80521188082, 0xBE2A516875702185, 0x0D041DD676D77EEA, 0x4AAE673FDD3081DE,
0xF9802B81DE97DEB1, 0x4FC0B4DD24D2A599, 0xFCEEF8632775FAF6, 0xBB44828A8C9205C2, 0x086ACE348F355AAD,
0x34107759DB5DFBAA, 0x873E3BE7D8FAA4C5, 0xC094410E731D5BF1, 0x73BA0DB070BA049E, 0xB86133D4DBCC19FF,
0x0B4F7F6AD86B4690, 0x4CE50583738CB9A4, 0xFFCB493D702BE6CB, 0xC3B1F050244347CC, 0x709FBCEE27E418A3,
0x3735C6078C03E797, 0x841B8AB98FA4B8F8, 0xADDA7C5F3C4488E3, 0x1EF430E13FE3D78C, 0x595E4A08940428B8,
0xEA7006B697A377D7, 0xD60ABFDBC3CBD6D0, 0x6524F365C06C89BF, 0x228E898C6B8B768B, 0x91A0C532682C29E4,
0x5A7BFB56C35A3485, 0xE955B7E8C0FD6BEA, 0xAEFFCD016B1A94DE, 0x1DD181BF68BDCBB1, 0x21AB38D23CD56AB6,
0x9285746C3F7235D9, 0xD52F0E859495CAED, 0x6601423B97329582, 0xD041DD676D77EEAA, 0x636F91D96ED0B1C5,
0x24C5EB30C5374EF1, 0x97EBA78EC690119E, 0xAB911EE392F8B099, 0x18BF525D915FEFF6, 0x5F1528B43AB810C2,
0xEC3B640A391F4FAD, 0x27E05A6E926952CC, 0x94CE16D091CE0DA3, 0xD3646C393A29F297, 0x604A2087398EADF8,
0x5C3099EA6DE60CFF, 0xEF1ED5546E415390, 0xA8B4AFBDC5A6ACA4, 0x1B9AE303C601F3CB, 0x56ED3E2F9E224471,
0xE5C372919D851B1E, 0xA26908783662E42A, 0x114744C635C5BB45, 0x2D3DFDAB61AD1A42, 0x9E13B115620A452D,
0xD9B9CBFCC9EDBA19, 0x6A978742CA4AE576, 0xA14CB926613CF817, 0x1262F598629BA778, 0x55C88F71C97C584C,
0xE6E6C3CFCADB0723, 0xDA9C7AA29EB3A624, 0x69B2361C9D14F94B, 0x2E184CF536F3067F, 0x9D36004B35545910,
0x2B769F17CF112238, 0x9858D3A9CCB67D57, 0xDFF2A94067518263, 0x6CDCE5FE64F6DD0C, 0x50A65C93309E7C0B,
0xE388102D33392364, 0xA4226AC498DEDC50, 0x170C267A9B79833F, 0xDCD7181E300F9E5E, 0x6FF954A033A8C131,
0x28532E49984F3E05, 0x9B7D62F79BE8616A, 0xA707DB9ACF80C06D, 0x14299724CC279F02, 0x5383EDCD67C06036,
0xE0ADA17364673F59
},
new ulong[]
{
0x0000000000000000, 0x54E979925CD0F10D, 0xA9D2F324B9A1E21A, 0xFD3B8AB6E5711317, 0xC17D4962DC4DDAB1,
0x959430F0809D2BBC, 0x68AFBA4665EC38AB, 0x3C46C3D4393CC9A6, 0x10223DEE1795ABE7, 0x44CB447C4B455AEA,
0xB9F0CECAAE3449FD, 0xED19B758F2E4B8F0, 0xD15F748CCBD87156, 0x85B60D1E9708805B, 0x788D87A87279934C,
0x2C64FE3A2EA96241, 0x20447BDC2F2B57CE, 0x74AD024E73FBA6C3, 0x899688F8968AB5D4, 0xDD7FF16ACA5A44D9,
0xE13932BEF3668D7F, 0xB5D04B2CAFB67C72, 0x48EBC19A4AC76F65, 0x1C02B80816179E68, 0x3066463238BEFC29,
0x648F3FA0646E0D24, 0x99B4B516811F1E33, 0xCD5DCC84DDCFEF3E, 0xF11B0F50E4F32698, 0xA5F276C2B823D795,
0x58C9FC745D52C482, 0x0C2085E60182358F, 0x4088F7B85E56AF9C, 0x14618E2A02865E91, 0xE95A049CE7F74D86,
0xBDB37D0EBB27BC8B, 0x81F5BEDA821B752D, 0xD51CC748DECB8420, 0x28274DFE3BBA9737, 0x7CCE346C676A663A,
0x50AACA5649C3047B, 0x0443B3C41513F576, 0xF9783972F062E661, 0xAD9140E0ACB2176C, 0x91D78334958EDECA,
0xC53EFAA6C95E2FC7, 0x380570102C2F3CD0, 0x6CEC098270FFCDDD, 0x60CC8C64717DF852, 0x3425F5F62DAD095F,
0xC91E7F40C8DC1A48, 0x9DF706D2940CEB45, 0xA1B1C506AD3022E3, 0xF558BC94F1E0D3EE, 0x086336221491C0F9,
0x5C8A4FB0484131F4, 0x70EEB18A66E853B5, 0x2407C8183A38A2B8, 0xD93C42AEDF49B1AF, 0x8DD53B3C839940A2,
0xB193F8E8BAA58904, 0xE57A817AE6757809, 0x18410BCC03046B1E, 0x4CA8725E5FD49A13, 0x8111EF70BCAD5F38,
0xD5F896E2E07DAE35, 0x28C31C54050CBD22, 0x7C2A65C659DC4C2F, 0x406CA61260E08589, 0x1485DF803C307484,
0xE9BE5536D9416793, 0xBD572CA48591969E, 0x9133D29EAB38F4DF, 0xC5DAAB0CF7E805D2, 0x38E121BA129916C5,
0x6C0858284E49E7C8, 0x504E9BFC77752E6E, 0x04A7E26E2BA5DF63, 0xF99C68D8CED4CC74, 0xAD75114A92043D79,
0xA15594AC938608F6, 0xF5BCED3ECF56F9FB, 0x088767882A27EAEC, 0x5C6E1E1A76F71BE1, 0x6028DDCE4FCBD247,
0x34C1A45C131B234A, 0xC9FA2EEAF66A305D, 0x9D135778AABAC150, 0xB177A9428413A311, 0xE59ED0D0D8C3521C,
0x18A55A663DB2410B, 0x4C4C23F46162B006, 0x700AE020585E79A0, 0x24E399B2048E88AD, 0xD9D81304E1FF9BBA,
0x8D316A96BD2F6AB7, 0xC19918C8E2FBF0A4, 0x9570615ABE2B01A9, 0x684BEBEC5B5A12BE, 0x3CA2927E078AE3B3,
0x00E451AA3EB62A15, 0x540D28386266DB18, 0xA936A28E8717C80F, 0xFDDFDB1CDBC73902, 0xD1BB2526F56E5B43,
0x85525CB4A9BEAA4E, 0x7869D6024CCFB959, 0x2C80AF90101F4854, 0x10C66C44292381F2, 0x442F15D675F370FF,
0xB9149F60908263E8, 0xEDFDE6F2CC5292E5, 0xE1DD6314CDD0A76A, 0xB5341A8691005667, 0x480F903074714570,
0x1CE6E9A228A1B47D, 0x20A02A76119D7DDB, 0x744953E44D4D8CD6, 0x8972D952A83C9FC1, 0xDD9BA0C0F4EC6ECC,
0xF1FF5EFADA450C8D, 0xA51627688695FD80, 0x582DADDE63E4EE97, 0x0CC4D44C3F341F9A, 0x308217980608D63C,
0x646B6E0A5AD82731, 0x9950E4BCBFA93426, 0xCDB99D2EE379C52B, 0x90FB71CAD654A0F5, 0xC41208588A8451F8,
0x392982EE6FF542EF, 0x6DC0FB7C3325B3E2, 0x518638A80A197A44, 0x056F413A56C98B49, 0xF854CB8CB3B8985E,
0xACBDB21EEF686953, 0x80D94C24C1C10B12, 0xD43035B69D11FA1F, 0x290BBF007860E908, 0x7DE2C69224B01805,
0x41A405461D8CD1A3, 0x154D7CD4415C20AE, 0xE876F662A42D33B9, 0xBC9F8FF0F8FDC2B4, 0xB0BF0A16F97FF73B,
0xE4567384A5AF0636, 0x196DF93240DE1521, 0x4D8480A01C0EE42C, 0x71C2437425322D8A, 0x252B3AE679E2DC87,
0xD810B0509C93CF90, 0x8CF9C9C2C0433E9D, 0xA09D37F8EEEA5CDC, 0xF4744E6AB23AADD1, 0x094FC4DC574BBEC6,
0x5DA6BD4E0B9B4FCB, 0x61E07E9A32A7866D, 0x350907086E777760, 0xC8328DBE8B066477, 0x9CDBF42CD7D6957A,
0xD073867288020F69, 0x849AFFE0D4D2FE64, 0x79A1755631A3ED73, 0x2D480CC46D731C7E, 0x110ECF10544FD5D8,
0x45E7B682089F24D5, 0xB8DC3C34EDEE37C2, 0xEC3545A6B13EC6CF, 0xC051BB9C9F97A48E, 0x94B8C20EC3475583,
0x698348B826364694, 0x3D6A312A7AE6B799, 0x012CF2FE43DA7E3F, 0x55C58B6C1F0A8F32, 0xA8FE01DAFA7B9C25,
0xFC177848A6AB6D28, 0xF037FDAEA72958A7, 0xA4DE843CFBF9A9AA, 0x59E50E8A1E88BABD, 0x0D0C771842584BB0,
0x314AB4CC7B648216, 0x65A3CD5E27B4731B, 0x989847E8C2C5600C, 0xCC713E7A9E159101, 0xE015C040B0BCF340,
0xB4FCB9D2EC6C024D, 0x49C73364091D115A, 0x1D2E4AF655CDE057, 0x216889226CF129F1, 0x7581F0B03021D8FC,
0x88BA7A06D550CBEB, 0xDC53039489803AE6, 0x11EA9EBA6AF9FFCD, 0x4503E72836290EC0, 0xB8386D9ED3581DD7,
0xECD1140C8F88ECDA, 0xD097D7D8B6B4257C, 0x847EAE4AEA64D471, 0x794524FC0F15C766, 0x2DAC5D6E53C5366B,
0x01C8A3547D6C542A, 0x5521DAC621BCA527, 0xA81A5070C4CDB630, 0xFCF329E2981D473D, 0xC0B5EA36A1218E9B,
0x945C93A4FDF17F96, 0x6967191218806C81, 0x3D8E608044509D8C, 0x31AEE56645D2A803, 0x65479CF41902590E,
0x987C1642FC734A19, 0xCC956FD0A0A3BB14, 0xF0D3AC04999F72B2, 0xA43AD596C54F83BF, 0x59015F20203E90A8,
0x0DE826B27CEE61A5, 0x218CD888524703E4, 0x7565A11A0E97F2E9, 0x885E2BACEBE6E1FE, 0xDCB7523EB73610F3,
0xE0F191EA8E0AD955, 0xB418E878D2DA2858, 0x492362CE37AB3B4F, 0x1DCA1B5C6B7BCA42, 0x5162690234AF5051,
0x058B1090687FA15C, 0xF8B09A268D0EB24B, 0xAC59E3B4D1DE4346, 0x901F2060E8E28AE0, 0xC4F659F2B4327BED,
0x39CDD344514368FA, 0x6D24AAD60D9399F7, 0x414054EC233AFBB6, 0x15A92D7E7FEA0ABB, 0xE892A7C89A9B19AC,
0xBC7BDE5AC64BE8A1, 0x803D1D8EFF772107, 0xD4D4641CA3A7D00A, 0x29EFEEAA46D6C31D, 0x7D0697381A063210,
0x712612DE1B84079F, 0x25CF6B4C4754F692, 0xD8F4E1FAA225E585, 0x8C1D9868FEF51488, 0xB05B5BBCC7C9DD2E,
0xE4B2222E9B192C23, 0x1989A8987E683F34, 0x4D60D10A22B8CE39, 0x61042F300C11AC78, 0x35ED56A250C15D75,
0xC8D6DC14B5B04E62, 0x9C3FA586E960BF6F, 0xA0796652D05C76C9, 0xF4901FC08C8C87C4, 0x09AB957669FD94D3,
0x5D42ECE4352D65DE
},
new ulong[]
{
0x0000000000000000, 0x3F0BE14A916A6DCB, 0x7E17C29522D4DB96, 0x411C23DFB3BEB65D, 0xFC2F852A45A9B72C,
0xC3246460D4C3DAE7, 0x823847BF677D6CBA, 0xBD33A6F5F6170171, 0x6A87A57F245D70DD, 0x558C4435B5371D16,
0x149067EA0689AB4B, 0x2B9B86A097E3C680, 0x96A8205561F4C7F1, 0xA9A3C11FF09EAA3A, 0xE8BFE2C043201C67,
0xD7B4038AD24A71AC, 0xD50F4AFE48BAE1BA, 0xEA04ABB4D9D08C71, 0xAB18886B6A6E3A2C, 0x94136921FB0457E7,
0x2920CFD40D135696, 0x162B2E9E9C793B5D, 0x57370D412FC78D00, 0x683CEC0BBEADE0CB, 0xBF88EF816CE79167,
0x80830ECBFD8DFCAC, 0xC19F2D144E334AF1, 0xFE94CC5EDF59273A, 0x43A76AAB294E264B, 0x7CAC8BE1B8244B80,
0x3DB0A83E0B9AFDDD, 0x02BB49749AF09016, 0x38C63AD73E7BDDF1, 0x07CDDB9DAF11B03A, 0x46D1F8421CAF0667,
0x79DA19088DC56BAC, 0xC4E9BFFD7BD26ADD, 0xFBE25EB7EAB80716, 0xBAFE7D685906B14B, 0x85F59C22C86CDC80,
0x52419FA81A26AD2C, 0x6D4A7EE28B4CC0E7, 0x2C565D3D38F276BA, 0x135DBC77A9981B71, 0xAE6E1A825F8F1A00,
0x9165FBC8CEE577CB, 0xD079D8177D5BC196, 0xEF72395DEC31AC5D, 0xEDC9702976C13C4B, 0xD2C29163E7AB5180,
0x93DEB2BC5415E7DD, 0xACD553F6C57F8A16, 0x11E6F50333688B67, 0x2EED1449A202E6AC, 0x6FF1379611BC50F1,
0x50FAD6DC80D63D3A, 0x874ED556529C4C96, 0xB845341CC3F6215D, 0xF95917C370489700, 0xC652F689E122FACB,
0x7B61507C1735FBBA, 0x446AB136865F9671, 0x057692E935E1202C, 0x3A7D73A3A48B4DE7, 0x718C75AE7CF7BBE2,
0x4E8794E4ED9DD629, 0x0F9BB73B5E236074, 0x30905671CF490DBF, 0x8DA3F084395E0CCE, 0xB2A811CEA8346105,
0xF3B432111B8AD758, 0xCCBFD35B8AE0BA93, 0x1B0BD0D158AACB3F, 0x2400319BC9C0A6F4, 0x651C12447A7E10A9,
0x5A17F30EEB147D62, 0xE72455FB1D037C13, 0xD82FB4B18C6911D8, 0x9933976E3FD7A785, 0xA6387624AEBDCA4E,
0xA4833F50344D5A58, 0x9B88DE1AA5273793, 0xDA94FDC5169981CE, 0xE59F1C8F87F3EC05, 0x58ACBA7A71E4ED74,
0x67A75B30E08E80BF, 0x26BB78EF533036E2, 0x19B099A5C25A5B29, 0xCE049A2F10102A85, 0xF10F7B65817A474E,
0xB01358BA32C4F113, 0x8F18B9F0A3AE9CD8, 0x322B1F0555B99DA9, 0x0D20FE4FC4D3F062, 0x4C3CDD90776D463F,
0x73373CDAE6072BF4, 0x494A4F79428C6613, 0x7641AE33D3E60BD8, 0x375D8DEC6058BD85, 0x08566CA6F132D04E,
0xB565CA530725D13F, 0x8A6E2B19964FBCF4, 0xCB7208C625F10AA9, 0xF479E98CB49B6762, 0x23CDEA0666D116CE,
0x1CC60B4CF7BB7B05, 0x5DDA28934405CD58, 0x62D1C9D9D56FA093, 0xDFE26F2C2378A1E2, 0xE0E98E66B212CC29,
0xA1F5ADB901AC7A74, 0x9EFE4CF390C617BF, 0x9C4505870A3687A9, 0xA34EE4CD9B5CEA62, 0xE252C71228E25C3F,
0xDD592658B98831F4, 0x606A80AD4F9F3085, 0x5F6161E7DEF55D4E, 0x1E7D42386D4BEB13, 0x2176A372FC2186D8,
0xF6C2A0F82E6BF774, 0xC9C941B2BF019ABF, 0x88D5626D0CBF2CE2, 0xB7DE83279DD54129, 0x0AED25D26BC24058,
0x35E6C498FAA82D93, 0x74FAE74749169BCE, 0x4BF1060DD87CF605, 0xE318EB5CF9EF77C4, 0xDC130A1668851A0F,
0x9D0F29C9DB3BAC52, 0xA204C8834A51C199, 0x1F376E76BC46C0E8, 0x203C8F3C2D2CAD23, 0x6120ACE39E921B7E,
0x5E2B4DA90FF876B5, 0x899F4E23DDB20719, 0xB694AF694CD86AD2, 0xF7888CB6FF66DC8F, 0xC8836DFC6E0CB144,
0x75B0CB09981BB035, 0x4ABB2A430971DDFE, 0x0BA7099CBACF6BA3, 0x34ACE8D62BA50668, 0x3617A1A2B155967E,
0x091C40E8203FFBB5, 0x4800633793814DE8, 0x770B827D02EB2023, 0xCA382488F4FC2152, 0xF533C5C265964C99,
0xB42FE61DD628FAC4, 0x8B2407574742970F, 0x5C9004DD9508E6A3, 0x639BE59704628B68, 0x2287C648B7DC3D35,
0x1D8C270226B650FE, 0xA0BF81F7D0A1518F, 0x9FB460BD41CB3C44, 0xDEA84362F2758A19, 0xE1A3A228631FE7D2,
0xDBDED18BC794AA35, 0xE4D530C156FEC7FE, 0xA5C9131EE54071A3, 0x9AC2F254742A1C68, 0x27F154A1823D1D19,
0x18FAB5EB135770D2, 0x59E69634A0E9C68F, 0x66ED777E3183AB44, 0xB15974F4E3C9DAE8, 0x8E5295BE72A3B723,
0xCF4EB661C11D017E, 0xF045572B50776CB5, 0x4D76F1DEA6606DC4, 0x727D1094370A000F, 0x3361334B84B4B652,
0x0C6AD20115DEDB99, 0x0ED19B758F2E4B8F, 0x31DA7A3F1E442644, 0x70C659E0ADFA9019, 0x4FCDB8AA3C90FDD2,
0xF2FE1E5FCA87FCA3, 0xCDF5FF155BED9168, 0x8CE9DCCAE8532735, 0xB3E23D8079394AFE, 0x64563E0AAB733B52,
0x5B5DDF403A195699, 0x1A41FC9F89A7E0C4, 0x254A1DD518CD8D0F, 0x9879BB20EEDA8C7E, 0xA7725A6A7FB0E1B5,
0xE66E79B5CC0E57E8, 0xD96598FF5D643A23, 0x92949EF28518CC26, 0xAD9F7FB81472A1ED, 0xEC835C67A7CC17B0,
0xD388BD2D36A67A7B, 0x6EBB1BD8C0B17B0A, 0x51B0FA9251DB16C1, 0x10ACD94DE265A09C, 0x2FA73807730FCD57,
0xF8133B8DA145BCFB, 0xC718DAC7302FD130, 0x8604F9188391676D, 0xB90F185212FB0AA6, 0x043CBEA7E4EC0BD7,
0x3B375FED7586661C, 0x7A2B7C32C638D041, 0x45209D785752BD8A, 0x479BD40CCDA22D9C, 0x789035465CC84057,
0x398C1699EF76F60A, 0x0687F7D37E1C9BC1, 0xBBB45126880B9AB0, 0x84BFB06C1961F77B, 0xC5A393B3AADF4126,
0xFAA872F93BB52CED, 0x2D1C7173E9FF5D41, 0x121790397895308A, 0x530BB3E6CB2B86D7, 0x6C0052AC5A41EB1C,
0xD133F459AC56EA6D, 0xEE3815133D3C87A6, 0xAF2436CC8E8231FB, 0x902FD7861FE85C30, 0xAA52A425BB6311D7,
0x9559456F2A097C1C, 0xD44566B099B7CA41, 0xEB4E87FA08DDA78A, 0x567D210FFECAA6FB, 0x6976C0456FA0CB30,
0x286AE39ADC1E7D6D, 0x176102D04D7410A6, 0xC0D5015A9F3E610A, 0xFFDEE0100E540CC1, 0xBEC2C3CFBDEABA9C,
0x81C922852C80D757, 0x3CFA8470DA97D626, 0x03F1653A4BFDBBED, 0x42ED46E5F8430DB0, 0x7DE6A7AF6929607B,
0x7F5DEEDBF3D9F06D, 0x40560F9162B39DA6, 0x014A2C4ED10D2BFB, 0x3E41CD0440674630, 0x83726BF1B6704741,
0xBC798ABB271A2A8A, 0xFD65A96494A49CD7, 0xC26E482E05CEF11C, 0x15DA4BA4D78480B0, 0x2AD1AAEE46EEED7B,
0x6BCD8931F5505B26, 0x54C6687B643A36ED, 0xE9F5CE8E922D379C, 0xD6FE2FC403475A57, 0x97E20C1BB0F9EC0A,
0xA8E9ED51219381C1
},
new ulong[]
{
0x0000000000000000, 0x1DEE8A5E222CA1DC, 0x3BDD14BC445943B8, 0x26339EE26675E264, 0x77BA297888B28770,
0x6A54A326AA9E26AC, 0x4C673DC4CCEBC4C8, 0x5189B79AEEC76514, 0xEF7452F111650EE0, 0xF29AD8AF3349AF3C,
0xD4A9464D553C4D58, 0xC947CC137710EC84, 0x98CE7B8999D78990, 0x8520F1D7BBFB284C, 0xA3136F35DD8ECA28,
0xBEFDE56BFFA26BF4, 0x4C300AC98DC40345, 0x51DE8097AFE8A299, 0x77ED1E75C99D40FD, 0x6A03942BEBB1E121,
0x3B8A23B105768435, 0x2664A9EF275A25E9, 0x0057370D412FC78D, 0x1DB9BD5363036651, 0xA34458389CA10DA5,
0xBEAAD266BE8DAC79, 0x98994C84D8F84E1D, 0x8577C6DAFAD4EFC1, 0xD4FE714014138AD5, 0xC910FB1E363F2B09,
0xEF2365FC504AC96D, 0xF2CDEFA2726668B1, 0x986015931B88068A, 0x858E9FCD39A4A756, 0xA3BD012F5FD14532,
0xBE538B717DFDE4EE, 0xEFDA3CEB933A81FA, 0xF234B6B5B1162026, 0xD4072857D763C242, 0xC9E9A209F54F639E,
0x771447620AED086A, 0x6AFACD3C28C1A9B6, 0x4CC953DE4EB44BD2, 0x5127D9806C98EA0E, 0x00AE6E1A825F8F1A,
0x1D40E444A0732EC6, 0x3B737AA6C606CCA2, 0x269DF0F8E42A6D7E, 0xD4501F5A964C05CF, 0xC9BE9504B460A413,
0xEF8D0BE6D2154677, 0xF26381B8F039E7AB, 0xA3EA36221EFE82BF, 0xBE04BC7C3CD22363, 0x9837229E5AA7C107,
0x85D9A8C0788B60DB, 0x3B244DAB87290B2F, 0x26CAC7F5A505AAF3, 0x00F95917C3704897, 0x1D17D349E15CE94B,
0x4C9E64D30F9B8C5F, 0x5170EE8D2DB72D83, 0x7743706F4BC2CFE7, 0x6AADFA3169EE6E3B, 0xA218840D981E1391,
0xBFF60E53BA32B24D, 0x99C590B1DC475029, 0x842B1AEFFE6BF1F5, 0xD5A2AD7510AC94E1, 0xC84C272B3280353D,
0xEE7FB9C954F5D759, 0xF391339776D97685, 0x4D6CD6FC897B1D71, 0x50825CA2AB57BCAD, 0x76B1C240CD225EC9,
0x6B5F481EEF0EFF15, 0x3AD6FF8401C99A01, 0x273875DA23E53BDD, 0x010BEB384590D9B9, 0x1CE5616667BC7865,
0xEE288EC415DA10D4, 0xF3C6049A37F6B108, 0xD5F59A785183536C, 0xC81B102673AFF2B0, 0x9992A7BC9D6897A4,
0x847C2DE2BF443678, 0xA24FB300D931D41C, 0xBFA1395EFB1D75C0, 0x015CDC3504BF1E34, 0x1CB2566B2693BFE8,
0x3A81C88940E65D8C, 0x276F42D762CAFC50, 0x76E6F54D8C0D9944, 0x6B087F13AE213898, 0x4D3BE1F1C854DAFC,
0x50D56BAFEA787B20, 0x3A78919E8396151B, 0x27961BC0A1BAB4C7, 0x01A58522C7CF56A3, 0x1C4B0F7CE5E3F77F,
0x4DC2B8E60B24926B, 0x502C32B8290833B7, 0x761FAC5A4F7DD1D3, 0x6BF126046D51700F, 0xD50CC36F92F31BFB,
0xC8E24931B0DFBA27, 0xEED1D7D3D6AA5843, 0xF33F5D8DF486F99F, 0xA2B6EA171A419C8B, 0xBF586049386D3D57,
0x996BFEAB5E18DF33, 0x848574F57C347EEF, 0x76489B570E52165E, 0x6BA611092C7EB782, 0x4D958FEB4A0B55E6,
0x507B05B56827F43A, 0x01F2B22F86E0912E, 0x1C1C3871A4CC30F2, 0x3A2FA693C2B9D296, 0x27C12CCDE095734A,
0x993CC9A61F3718BE, 0x84D243F83D1BB962, 0xA2E1DD1A5B6E5B06, 0xBF0F57447942FADA, 0xEE86E0DE97859FCE,
0xF3686A80B5A93E12, 0xD55BF462D3DCDC76, 0xC8B57E3CF1F07DAA, 0xD6E9A7309F3239A7, 0xCB072D6EBD1E987B,
0xED34B38CDB6B7A1F, 0xF0DA39D2F947DBC3, 0xA1538E481780BED7, 0xBCBD041635AC1F0B, 0x9A8E9AF453D9FD6F,
0x876010AA71F55CB3, 0x399DF5C18E573747, 0x24737F9FAC7B969B, 0x0240E17DCA0E74FF, 0x1FAE6B23E822D523,
0x4E27DCB906E5B037, 0x53C956E724C911EB, 0x75FAC80542BCF38F, 0x6814425B60905253, 0x9AD9ADF912F63AE2,
0x873727A730DA9B3E, 0xA104B94556AF795A, 0xBCEA331B7483D886, 0xED6384819A44BD92, 0xF08D0EDFB8681C4E,
0xD6BE903DDE1DFE2A, 0xCB501A63FC315FF6, 0x75ADFF0803933402, 0x6843755621BF95DE, 0x4E70EBB447CA77BA,
0x539E61EA65E6D666, 0x0217D6708B21B372, 0x1FF95C2EA90D12AE, 0x39CAC2CCCF78F0CA, 0x24244892ED545116,
0x4E89B2A384BA3F2D, 0x536738FDA6969EF1, 0x7554A61FC0E37C95, 0x68BA2C41E2CFDD49, 0x39339BDB0C08B85D,
0x24DD11852E241981, 0x02EE8F674851FBE5, 0x1F0005396A7D5A39, 0xA1FDE05295DF31CD, 0xBC136A0CB7F39011,
0x9A20F4EED1867275, 0x87CE7EB0F3AAD3A9, 0xD647C92A1D6DB6BD, 0xCBA943743F411761, 0xED9ADD965934F505,
0xF07457C87B1854D9, 0x02B9B86A097E3C68, 0x1F5732342B529DB4, 0x3964ACD64D277FD0, 0x248A26886F0BDE0C,
0x7503911281CCBB18, 0x68ED1B4CA3E01AC4, 0x4EDE85AEC595F8A0, 0x53300FF0E7B9597C, 0xEDCDEA9B181B3288,
0xF02360C53A379354, 0xD610FE275C427130, 0xCBFE74797E6ED0EC, 0x9A77C3E390A9B5F8, 0x879949BDB2851424,
0xA1AAD75FD4F0F640, 0xBC445D01F6DC579C, 0x74F1233D072C2A36, 0x691FA96325008BEA, 0x4F2C37814375698E,
0x52C2BDDF6159C852, 0x034B0A458F9EAD46, 0x1EA5801BADB20C9A, 0x38961EF9CBC7EEFE, 0x257894A7E9EB4F22,
0x9B8571CC164924D6, 0x866BFB923465850A, 0xA05865705210676E, 0xBDB6EF2E703CC6B2, 0xEC3F58B49EFBA3A6,
0xF1D1D2EABCD7027A, 0xD7E24C08DAA2E01E, 0xCA0CC656F88E41C2, 0x38C129F48AE82973, 0x252FA3AAA8C488AF,
0x031C3D48CEB16ACB, 0x1EF2B716EC9DCB17, 0x4F7B008C025AAE03, 0x52958AD220760FDF, 0x74A614304603EDBB,
0x69489E6E642F4C67, 0xD7B57B059B8D2793, 0xCA5BF15BB9A1864F, 0xEC686FB9DFD4642B, 0xF186E5E7FDF8C5F7,
0xA00F527D133FA0E3, 0xBDE1D8233113013F, 0x9BD246C15766E35B, 0x863CCC9F754A4287, 0xEC9136AE1CA42CBC,
0xF17FBCF03E888D60, 0xD74C221258FD6F04, 0xCAA2A84C7AD1CED8, 0x9B2B1FD69416ABCC, 0x86C59588B63A0A10,
0xA0F60B6AD04FE874, 0xBD188134F26349A8, 0x03E5645F0DC1225C, 0x1E0BEE012FED8380, 0x383870E3499861E4,
0x25D6FABD6BB4C038, 0x745F4D278573A52C, 0x69B1C779A75F04F0, 0x4F82599BC12AE694, 0x526CD3C5E3064748,
0xA0A13C6791602FF9, 0xBD4FB639B34C8E25, 0x9B7C28DBD5396C41, 0x8692A285F715CD9D, 0xD71B151F19D2A889,
0xCAF59F413BFE0955, 0xECC601A35D8BEB31, 0xF1288BFD7FA74AED, 0x4FD56E9680052119, 0x523BE4C8A22980C5,
0x74087A2AC45C62A1, 0x69E6F074E670C37D, 0x386F47EE08B7A669, 0x2581CDB02A9B07B5, 0x03B253524CEEE5D1,
0x1E5CD90C6EC2440D
}
};
readonly ulong _finalSeed;
readonly IntPtr _nativeContext;
readonly ulong[][]? _table;
readonly bool _useEcma;
readonly bool _useNative;
ulong _hashInt;
/// <summary>Initializes the CRC64 table and seed as CRC64-ECMA</summary>
public Crc64Context()
{
_hashInt = CRC64_ECMA_SEED;
_table = _ecmaCrc64Table;
_finalSeed = CRC64_ECMA_SEED;
_useEcma = true;
if(!Native.IsSupported)
return;
_nativeContext = crc64_init();
_useNative = _nativeContext != IntPtr.Zero;
}
/// <summary>Initializes the CRC16 table with a custom polynomial and seed</summary>
public Crc64Context(ulong polynomial, ulong seed)
{
_hashInt = seed;
_finalSeed = seed;
_useEcma = polynomial == CRC64_ECMA_POLY && seed == CRC64_ECMA_SEED;
if(Native.IsSupported && _useEcma)
{
_nativeContext = crc64_init();
_useNative = _nativeContext != IntPtr.Zero;
}
else
_table = GenerateTable(polynomial);
}
#region IChecksum Members
/// <inheritdoc />
public string Name => "CRC-64 (ECMA)";
/// <inheritdoc />
public Guid Id => new("D0C0D902-420A-45DA-A235-9D48BEE4B1CE");
/// <inheritdoc />
public string Author => "Natalia Portillo";
/// <inheritdoc />
/// <summary>Updates the hash with data.</summary>
/// <param name="data">Data buffer.</param>
/// <param name="len">Length of buffer to hash.</param>
public void Update(byte[] data, uint len) =>
Step(ref _hashInt, _table!, data, len, _useEcma, _useNative, _nativeContext);
/// <inheritdoc />
/// <summary>Updates the hash with data.</summary>
/// <param name="data">Data buffer.</param>
public void Update(byte[] data) => Update(data, (uint)data.Length);
/// <inheritdoc />
/// <summary>Returns a byte array of the hash value.</summary>
public byte[] Final()
{
ulong crc = _hashInt ^ _finalSeed;
if(!_useNative || !_useEcma)
return BigEndianBitConverter.GetBytes(crc);
crc64_final(_nativeContext, ref crc);
crc64_free(_nativeContext);
return BigEndianBitConverter.GetBytes(crc);
}
/// <inheritdoc />
/// <summary>Returns a hexadecimal representation of the hash value.</summary>
public string End()
{
ulong crc = _hashInt ^ _finalSeed;
var crc64Output = new StringBuilder();
if(_useNative && _useEcma)
{
crc64_final(_nativeContext, ref crc);
crc64_free(_nativeContext);
}
for(var i = 0; i < BigEndianBitConverter.GetBytes(crc).Length; i++)
crc64Output.Append(BigEndianBitConverter.GetBytes(crc)[i].ToString("x2"));
return crc64Output.ToString();
}
#endregion
[DllImport("libAaru.Checksums.Native", SetLastError = true)]
static extern IntPtr crc64_init();
[DllImport("libAaru.Checksums.Native", SetLastError = true)]
static extern int crc64_update(IntPtr ctx, byte[] data, uint len);
[DllImport("libAaru.Checksums.Native", SetLastError = true)]
static extern int crc64_final(IntPtr ctx, ref ulong crc);
[DllImport("libAaru.Checksums.Native", SetLastError = true)]
static extern void crc64_free(IntPtr ctx);
static ulong[][] GenerateTable(ulong polynomial)
{
var table = new ulong[8][];
for(var i = 0; i < 8; i++)
table[i] = new ulong[256];
for(var i = 0; i < 256; i++)
{
var entry = (ulong)i;
for(var j = 0; j < 8; j++)
{
if((entry & 1) == 1)
entry = entry >> 1 ^ polynomial;
else
entry >>= 1;
}
table[0][i] = entry;
}
for(var slice = 1; slice < 4; slice++)
for(var i = 0; i < 256; i++)
table[slice][i] = table[slice - 1][i] >> 8 ^ table[0][table[slice - 1][i] & 0xFF];
return table;
}
static void Step(ref ulong previousCrc, ulong[][] table, byte[] data, uint len, bool useEcma, bool useNative,
IntPtr nativeContext)
{
if(useNative && useEcma)
{
crc64_update(nativeContext, data, len);
return;
}
var dataOff = 0;
#if NETCOREAPP3_1_OR_GREATER
if(useEcma && Pclmulqdq.IsSupported && Sse41.IsSupported && Ssse3.IsSupported && Sse2.IsSupported)
{
// Only works in blocks of 32 bytes
uint blocks = len / 32;
if(blocks > 0)
{
previousCrc = ~Clmul.Step(~previousCrc, data, blocks * 32);
dataOff = (int)(blocks * 32);
len -= blocks * 32;
}
if(len == 0)
return;
}
#endif
// Unroll according to Intel slicing by uint8_t
// http://www.intel.com/technology/comms/perfnet/download/CRC_generators.pdf
// http://sourceforge.net/projects/slicing-by-8/
ulong crc = previousCrc;
if(len > 4)
{
long limit = dataOff + (len & ~(uint)3);
len &= 3;
while(dataOff < limit)
{
var tmp = (uint)(crc ^ BitConverter.ToUInt32(data, dataOff));
dataOff += 4;
crc = table[3][tmp & 0xFF] ^
table[2][tmp >> 8 & 0xFF] ^
crc >> 32 ^
table[1][tmp >> 16 & 0xFF] ^
table[0][tmp >> 24];
}
}
while(len-- != 0)
crc = table[0][data[dataOff++] ^ crc & 0xFF] ^ crc >> 8;
previousCrc = crc;
}
/// <summary>Gets the hash of a file</summary>
/// <param name="filename">File path.</param>
// ReSharper disable once ReturnTypeCanBeEnumerable.Global
public static byte[] File(string filename)
{
File(filename, out byte[] localHash);
return localHash;
}
/// <summary>Gets the hash of a file in hexadecimal and as a byte array.</summary>
/// <param name="filename">File path.</param>
/// <param name="hash">Byte array of the hash value.</param>
public static string File(string filename, out byte[] hash) =>
File(filename, out hash, CRC64_ECMA_POLY, CRC64_ECMA_SEED);
/// <summary>Gets the hash of a file in hexadecimal and as a byte array.</summary>
/// <param name="filename">File path.</param>
/// <param name="hash">Byte array of the hash value.</param>
/// <param name="polynomial">CRC polynomial</param>
/// <param name="seed">CRC seed</param>
public static string File(string filename, out byte[] hash, ulong polynomial, ulong seed)
{
bool useEcma = polynomial == CRC64_ECMA_POLY && seed == CRC64_ECMA_SEED;
bool useNative = Native.IsSupported;
IntPtr nativeContext = IntPtr.Zero;
if(useNative && useEcma)
{
nativeContext = crc64_init();
useNative = nativeContext != IntPtr.Zero;
}
var fileStream = new FileStream(filename, FileMode.Open);
ulong localHashInt = seed;
ulong[][] localTable = GenerateTable(polynomial);
var buffer = new byte[65536];
int read = fileStream.EnsureRead(buffer, 0, 65536);
while(read > 0)
{
Step(ref localHashInt, localTable, buffer, (uint)read, useEcma, useNative, nativeContext);
read = fileStream.EnsureRead(buffer, 0, 65536);
}
localHashInt ^= seed;
if(useNative && useEcma)
{
crc64_final(nativeContext, ref localHashInt);
crc64_free(nativeContext);
}
hash = BigEndianBitConverter.GetBytes(localHashInt);
var crc64Output = new StringBuilder();
foreach(byte h in hash)
crc64Output.Append(h.ToString("x2"));
fileStream.Close();
return crc64Output.ToString();
}
/// <summary>Gets the hash of the specified data buffer.</summary>
/// <param name="data">Data buffer.</param>
/// <param name="len">Length of the data buffer to hash.</param>
/// <param name="hash">Byte array of the hash value.</param>
public static string Data(byte[] data, uint len, out byte[] hash) =>
Data(data, len, out hash, CRC64_ECMA_POLY, CRC64_ECMA_SEED);
/// <summary>Gets the hash of the specified data buffer.</summary>
/// <param name="data">Data buffer.</param>
/// <param name="len">Length of the data buffer to hash.</param>
/// <param name="hash">Byte array of the hash value.</param>
/// <param name="polynomial">CRC polynomial</param>
/// <param name="seed">CRC seed</param>
public static string Data(byte[] data, uint len, out byte[] hash, ulong polynomial, ulong seed)
{
bool useEcma = polynomial == CRC64_ECMA_POLY && seed == CRC64_ECMA_SEED;
bool useNative = Native.IsSupported;
IntPtr nativeContext = IntPtr.Zero;
if(useNative && useEcma)
{
nativeContext = crc64_init();
useNative = nativeContext != IntPtr.Zero;
}
ulong localHashInt = seed;
ulong[][] localTable = GenerateTable(polynomial);
Step(ref localHashInt, localTable, data, len, useEcma, useNative, nativeContext);
localHashInt ^= seed;
if(useNative && useEcma)
{
crc64_final(nativeContext, ref localHashInt);
crc64_free(nativeContext);
}
hash = BigEndianBitConverter.GetBytes(localHashInt);
var crc64Output = new StringBuilder();
foreach(byte h in hash)
crc64Output.Append(h.ToString("x2"));
return crc64Output.ToString();
}
/// <summary>Gets the hash of the specified data buffer.</summary>
/// <param name="data">Data buffer.</param>
/// <param name="hash">Byte array of the hash value.</param>
public static string Data(byte[] data, out byte[] hash) => Data(data, (uint)data.Length, out hash);
}

View File

@@ -0,0 +1,219 @@
// /***************************************************************************
// Aaru Data Preservation Suite
// ----------------------------------------------------------------------------
//
// Filename : neon.cs
// Author(s) : Natalia Portillo <claunia@claunia.com>
// The Chromium Authors
//
// Component : Checksums.
//
// --[ Description ] ----------------------------------------------------------
//
// Compute Fletcher32 checksum using NEON vectorization.
//
// --[ License ] --------------------------------------------------------------
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// ----------------------------------------------------------------------------
// Copyright © 2011-2023 Natalia Portillo
// Copyright 2017 The Chromium Authors. All rights reserved.
// ****************************************************************************/
#if NET5_0_OR_GREATER
using System.Runtime.Intrinsics;
using System.Runtime.Intrinsics.Arm;
namespace Aaru.Checksums.Fletcher32;
static class Neon
{
internal static void Step(ref ushort preSum1, ref ushort preSum2, byte[] buf, uint len)
{
/*
* Split Fletcher-32 into component sums.
*/
uint s1 = preSum1;
uint s2 = preSum2;
var bufPos = 0;
/*
* Process the data in blocks.
*/
const uint block_Size = 1 << 5;
uint blocks = len / block_Size;
len -= blocks * block_Size;
while(blocks != 0)
{
uint n = Fletcher32Context.NMAX / block_Size; /* The NMAX constraint. */
if(n > blocks)
n = blocks;
blocks -= n;
/*
* Process n blocks of data. At most NMAX data bytes can be
* processed before s2 must be reduced modulo FLETCHER_MODULE.
*/
var v_S2 = Vector128.Create(s1 * n, 0, 0, 0);
var v_S1 = Vector128.Create(0u, 0, 0, 0);
Vector128<ushort> v_Column_Sum_1 = AdvSimd.DuplicateToVector128((ushort)0);
Vector128<ushort> v_Column_Sum_2 = AdvSimd.DuplicateToVector128((ushort)0);
Vector128<ushort> v_Column_Sum_3 = AdvSimd.DuplicateToVector128((ushort)0);
Vector128<ushort> v_Column_Sum_4 = AdvSimd.DuplicateToVector128((ushort)0);
do
{
/*
* Load 32 input bytes.
*/
var bytes1 = Vector128.Create(buf[bufPos], buf[bufPos + 1], buf[bufPos + 2], buf[bufPos + 3],
buf[bufPos + 4], buf[bufPos + 5], buf[bufPos + 6], buf[bufPos + 7],
buf[bufPos + 8], buf[bufPos + 9], buf[bufPos + 10], buf[bufPos + 11],
buf[bufPos + 12], buf[bufPos + 13], buf[bufPos + 14], buf[bufPos + 15]);
bufPos += 16;
var bytes2 = Vector128.Create(buf[bufPos], buf[bufPos + 1], buf[bufPos + 2], buf[bufPos + 3],
buf[bufPos + 4], buf[bufPos + 5], buf[bufPos + 6], buf[bufPos + 7],
buf[bufPos + 8], buf[bufPos + 9], buf[bufPos + 10], buf[bufPos + 11],
buf[bufPos + 12], buf[bufPos + 13], buf[bufPos + 14], buf[bufPos + 15]);
bufPos += 16;
/*
* Add previous block byte sum to v_s2.
*/
v_S2 = AdvSimd.Add(v_S2, v_S1);
/*
* Horizontally add the bytes for s1.
*/
v_S1 =
AdvSimd.AddPairwiseWideningAndAdd(v_S1,
AdvSimd.
AddPairwiseWideningAndAdd(AdvSimd.AddPairwiseWidening(bytes1),
bytes2));
/*
* Vertically add the bytes for s2.
*/
v_Column_Sum_1 = AdvSimd.AddWideningLower(v_Column_Sum_1, bytes1.GetLower());
v_Column_Sum_2 = AdvSimd.AddWideningLower(v_Column_Sum_2, bytes1.GetUpper());
v_Column_Sum_3 = AdvSimd.AddWideningLower(v_Column_Sum_3, bytes2.GetLower());
v_Column_Sum_4 = AdvSimd.AddWideningLower(v_Column_Sum_4, bytes2.GetUpper());
} while(--n != 0);
v_S2 = AdvSimd.ShiftLeftLogical(v_S2, 5);
/*
* Multiply-add bytes by [ 32, 31, 30, ... ] for s2.
*/
v_S2 = AdvSimd.MultiplyWideningLowerAndAdd(v_S2, v_Column_Sum_1.GetLower(),
Vector64.Create((ushort)32, 31, 30, 29));
v_S2 = AdvSimd.MultiplyWideningLowerAndAdd(v_S2, v_Column_Sum_1.GetUpper(),
Vector64.Create((ushort)28, 27, 26, 25));
v_S2 = AdvSimd.MultiplyWideningLowerAndAdd(v_S2, v_Column_Sum_2.GetLower(),
Vector64.Create((ushort)24, 23, 22, 21));
v_S2 = AdvSimd.MultiplyWideningLowerAndAdd(v_S2, v_Column_Sum_2.GetUpper(),
Vector64.Create((ushort)20, 19, 18, 17));
v_S2 = AdvSimd.MultiplyWideningLowerAndAdd(v_S2, v_Column_Sum_3.GetLower(),
Vector64.Create((ushort)16, 15, 14, 13));
v_S2 = AdvSimd.MultiplyWideningLowerAndAdd(v_S2, v_Column_Sum_3.GetUpper(),
Vector64.Create((ushort)12, 11, 10, 9));
v_S2 = AdvSimd.MultiplyWideningLowerAndAdd(v_S2, v_Column_Sum_4.GetLower(),
Vector64.Create((ushort)8, 7, 6, 5));
v_S2 = AdvSimd.MultiplyWideningLowerAndAdd(v_S2, v_Column_Sum_4.GetUpper(),
Vector64.Create((ushort)4, 3, 2, 1));
/*
* Sum epi32 ints v_s1(s2) and accumulate in s1(s2).
*/
Vector64<uint> sum1 = AdvSimd.AddPairwise(v_S1.GetLower(), v_S1.GetUpper());
Vector64<uint> sum2 = AdvSimd.AddPairwise(v_S2.GetLower(), v_S2.GetUpper());
Vector64<uint> s1S2 = AdvSimd.AddPairwise(sum1, sum2);
s1 += AdvSimd.Extract(s1S2, 0);
s2 += AdvSimd.Extract(s1S2, 1);
/*
* Reduce.
*/
s1 %= Fletcher32Context.FLETCHER_MODULE;
s2 %= Fletcher32Context.FLETCHER_MODULE;
}
/*
* Handle leftover data.
*/
if(len != 0)
{
if(len >= 16)
{
s2 += s1 += buf[bufPos++];
s2 += s1 += buf[bufPos++];
s2 += s1 += buf[bufPos++];
s2 += s1 += buf[bufPos++];
s2 += s1 += buf[bufPos++];
s2 += s1 += buf[bufPos++];
s2 += s1 += buf[bufPos++];
s2 += s1 += buf[bufPos++];
s2 += s1 += buf[bufPos++];
s2 += s1 += buf[bufPos++];
s2 += s1 += buf[bufPos++];
s2 += s1 += buf[bufPos++];
s2 += s1 += buf[bufPos++];
s2 += s1 += buf[bufPos++];
s2 += s1 += buf[bufPos++];
s2 += s1 += buf[bufPos++];
len -= 16;
}
while(len-- != 0)
s2 += s1 += buf[bufPos++];
if(s1 >= Fletcher32Context.FLETCHER_MODULE)
s1 -= Fletcher32Context.FLETCHER_MODULE;
s2 %= Fletcher32Context.FLETCHER_MODULE;
}
/*
* Return the recombined sums.
*/
preSum1 = (ushort)(s1 & 0xFFFF);
preSum2 = (ushort)(s2 & 0xFFFF);
}
}
#endif

View File

@@ -0,0 +1,193 @@
// /***************************************************************************
// Aaru Data Preservation Suite
// ----------------------------------------------------------------------------
//
// Filename : ssse3.cs
// Author(s) : Natalia Portillo <claunia@claunia.com>
// The Chromium Authors
//
// Component : Checksums.
//
// --[ Description ] ----------------------------------------------------------
//
// Compute Fletcher32 checksum using SSSE3 vectorization.
//
// --[ License ] --------------------------------------------------------------
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// ----------------------------------------------------------------------------
// Copyright © 2011-2023 Natalia Portillo
// Copyright 2017 The Chromium Authors. All rights reserved.
// ****************************************************************************/
#if NETCOREAPP3_1_OR_GREATER
using System;
using System.Runtime.Intrinsics;
using System.Runtime.Intrinsics.X86;
namespace Aaru.Checksums.Fletcher32;
static class Ssse3
{
internal static void Step(ref ushort sum1, ref ushort sum2, byte[] buf, uint len)
{
uint s1 = sum1;
uint s2 = sum2;
var bufPos = 0;
/*
* Process the data in blocks.
*/
const uint block_Size = 1 << 5;
uint blocks = len / block_Size;
len -= blocks * block_Size;
while(blocks != 0)
{
uint n = Fletcher32Context.NMAX / block_Size; /* The NMAX constraint. */
if(n > blocks)
n = blocks;
blocks -= n;
Vector128<byte> tap1 = Vector128.Create(32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17).
AsByte();
Vector128<byte> tap2 = Vector128.Create(16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1).AsByte();
Vector128<byte> zero = Vector128.Create(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0).AsByte();
var ones = Vector128.Create(1, 1, 1, 1, 1, 1, 1, 1);
/*
* Process n blocks of data. At most NMAX data bytes can be
* processed before s2 must be reduced modulo BASE.
*/
var v_Ps = Vector128.Create(s1 * n, 0, 0, 0);
var v_S2 = Vector128.Create(s2, 0, 0, 0);
var v_S1 = Vector128.Create(0u, 0, 0, 0);
do
{
/*
* Load 32 input bytes.
*/
var bytes1 = Vector128.Create(BitConverter.ToUInt32(buf, bufPos),
BitConverter.ToUInt32(buf, bufPos + 4),
BitConverter.ToUInt32(buf, bufPos + 8),
BitConverter.ToUInt32(buf, bufPos + 12));
bufPos += 16;
var bytes2 = Vector128.Create(BitConverter.ToUInt32(buf, bufPos),
BitConverter.ToUInt32(buf, bufPos + 4),
BitConverter.ToUInt32(buf, bufPos + 8),
BitConverter.ToUInt32(buf, bufPos + 12));
bufPos += 16;
/*
* Add previous block byte sum to v_ps.
*/
v_Ps = Sse2.Add(v_Ps, v_S1);
/*
* Horizontally add the bytes for s1, multiply-adds the
* bytes by [ 32, 31, 30, ... ] for s2.
*/
v_S1 = Sse2.Add(v_S1, Sse2.SumAbsoluteDifferences(bytes1.AsByte(), zero).AsUInt32());
Vector128<short> mad1 =
System.Runtime.Intrinsics.X86.Ssse3.MultiplyAddAdjacent(bytes1.AsByte(), tap1.AsSByte());
v_S2 = Sse2.Add(v_S2, Sse2.MultiplyAddAdjacent(mad1.AsInt16(), ones.AsInt16()).AsUInt32());
v_S1 = Sse2.Add(v_S1, Sse2.SumAbsoluteDifferences(bytes2.AsByte(), zero).AsUInt32());
Vector128<short> mad2 =
System.Runtime.Intrinsics.X86.Ssse3.MultiplyAddAdjacent(bytes2.AsByte(), tap2.AsSByte());
v_S2 = Sse2.Add(v_S2, Sse2.MultiplyAddAdjacent(mad2.AsInt16(), ones.AsInt16()).AsUInt32());
} while(--n != 0);
v_S2 = Sse2.Add(v_S2, Sse2.ShiftLeftLogical(v_Ps, 5));
/*
* Sum epi32 ints v_s1(s2) and accumulate in s1(s2).
*/
v_S1 = Sse2.Add(v_S1, Sse2.Shuffle(v_S1, 177));
v_S1 = Sse2.Add(v_S1, Sse2.Shuffle(v_S1, 78));
s1 += (uint)Sse2.ConvertToInt32(v_S1.AsInt32());
v_S2 = Sse2.Add(v_S2, Sse2.Shuffle(v_S2, 177));
v_S2 = Sse2.Add(v_S2, Sse2.Shuffle(v_S2, 78));
s2 = (uint)Sse2.ConvertToInt32(v_S2.AsInt32());
/*
* Reduce.
*/
s1 %= Fletcher32Context.FLETCHER_MODULE;
s2 %= Fletcher32Context.FLETCHER_MODULE;
}
/*
* Handle leftover data.
*/
if(len != 0)
{
if(len >= 16)
{
s2 += s1 += buf[bufPos++];
s2 += s1 += buf[bufPos++];
s2 += s1 += buf[bufPos++];
s2 += s1 += buf[bufPos++];
s2 += s1 += buf[bufPos++];
s2 += s1 += buf[bufPos++];
s2 += s1 += buf[bufPos++];
s2 += s1 += buf[bufPos++];
s2 += s1 += buf[bufPos++];
s2 += s1 += buf[bufPos++];
s2 += s1 += buf[bufPos++];
s2 += s1 += buf[bufPos++];
s2 += s1 += buf[bufPos++];
s2 += s1 += buf[bufPos++];
s2 += s1 += buf[bufPos++];
s2 += s1 += buf[bufPos++];
len -= 16;
}
while(len-- != 0)
s2 += s1 += buf[bufPos++];
if(s1 >= Fletcher32Context.FLETCHER_MODULE)
s1 -= Fletcher32Context.FLETCHER_MODULE;
s2 %= Fletcher32Context.FLETCHER_MODULE;
}
/*
* Return the recombined sums.
*/
sum1 = (ushort)(s1 & 0xFFFF);
sum2 = (ushort)(s2 & 0xFFFF);
}
}
#endif

View File

@@ -0,0 +1,777 @@
// /***************************************************************************
// Aaru Data Preservation Suite
// ----------------------------------------------------------------------------
//
// Filename : FletcherContext.cs
// Author(s) : Natalia Portillo <claunia@claunia.com>
//
// Component : Checksums.
//
// --[ Description ] ----------------------------------------------------------
//
// Implements Fletcher-32 and Fletcher-16 algorithms.
//
// --[ License ] --------------------------------------------------------------
//
// This library is free software; you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as
// published by the Free Software Foundation; either version 2.1 of the
// License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, see <http://www.gnu.org/licenses/>.
//
// ----------------------------------------------------------------------------
// Copyright © 2011-2023 Natalia Portillo
// ****************************************************************************/
// Disabled because the speed is abnormally slow
using System;
using System.Diagnostics.CodeAnalysis;
using System.IO;
using System.Runtime.InteropServices;
#if NET5_0_OR_GREATER
using System.Runtime.Intrinsics.Arm;
#endif
using System.Text;
#if NETCOREAPP3_1_OR_GREATER
using Aaru.Checksums.Fletcher32;
#endif
using Aaru.CommonTypes.Interfaces;
using Aaru.Helpers;
#if NETCOREAPP3_1_OR_GREATER
using Ssse3 = System.Runtime.Intrinsics.X86.Ssse3;
#endif
namespace Aaru.Checksums;
/// <inheritdoc />
/// <summary>Implements the Fletcher-32 algorithm</summary>
[SuppressMessage("ReSharper", "UnusedMethodReturnValue.Global")]
[SuppressMessage("ReSharper", "MemberCanBePrivate.Global")]
[SuppressMessage("ReSharper", "UnusedMember.Global")]
public sealed class Fletcher32Context : IChecksum
{
internal const ushort FLETCHER_MODULE = 0xFFFF;
internal const uint NMAX = 5552;
readonly IntPtr _nativeContext;
readonly bool _useNative;
ushort _sum1, _sum2;
/// <summary>Initializes the Fletcher-32 sums</summary>
public Fletcher32Context()
{
_sum1 = 0xFFFF;
_sum2 = 0xFFFF;
if(!Native.IsSupported)
return;
_nativeContext = fletcher32_init();
_useNative = _nativeContext != IntPtr.Zero;
}
#region IChecksum Members
/// <inheritdoc />
public string Name => "Fletcher-32";
/// <inheritdoc />
public Guid Id => new("0E51B39F-C5E6-4CED-9E59-BA5A42B3B2F4");
/// <inheritdoc />
public string Author => "Natalia Portillo";
/// <inheritdoc />
/// <summary>Updates the hash with data.</summary>
/// <param name="data">Data buffer.</param>
/// <param name="len">Length of buffer to hash.</param>
public void Update(byte[] data, uint len) => Step(ref _sum1, ref _sum2, data, len, _useNative, _nativeContext);
/// <inheritdoc />
/// <summary>Updates the hash with data.</summary>
/// <param name="data">Data buffer.</param>
public void Update(byte[] data) => Update(data, (uint)data.Length);
/// <inheritdoc />
/// <summary>Returns a byte array of the hash value.</summary>
public byte[] Final()
{
var finalSum = (uint)(_sum2 << 16 | _sum1);
if(!_useNative)
return BigEndianBitConverter.GetBytes(finalSum);
fletcher32_final(_nativeContext, ref finalSum);
fletcher32_free(_nativeContext);
return BigEndianBitConverter.GetBytes(finalSum);
}
/// <inheritdoc />
/// <summary>Returns a hexadecimal representation of the hash value.</summary>
public string End()
{
var finalSum = (uint)(_sum2 << 16 | _sum1);
if(_useNative)
{
fletcher32_final(_nativeContext, ref finalSum);
fletcher32_free(_nativeContext);
}
var fletcherOutput = new StringBuilder();
for(var i = 0; i < BigEndianBitConverter.GetBytes(finalSum).Length; i++)
fletcherOutput.Append(BigEndianBitConverter.GetBytes(finalSum)[i].ToString("x2"));
return fletcherOutput.ToString();
}
#endregion
[DllImport("libAaru.Checksums.Native", SetLastError = true)]
static extern IntPtr fletcher32_init();
[DllImport("libAaru.Checksums.Native", SetLastError = true)]
static extern int fletcher32_update(IntPtr ctx, byte[] data, uint len);
[DllImport("libAaru.Checksums.Native", SetLastError = true)]
static extern int fletcher32_final(IntPtr ctx, ref uint crc);
[DllImport("libAaru.Checksums.Native", SetLastError = true)]
static extern void fletcher32_free(IntPtr ctx);
static void Step(ref ushort previousSum1, ref ushort previousSum2, byte[] data, uint len, bool useNative,
IntPtr nativeContext)
{
if(useNative)
{
fletcher32_update(nativeContext, data, len);
return;
}
#if NETCOREAPP3_1_OR_GREATER
if(Ssse3.IsSupported)
{
Fletcher32.Ssse3.Step(ref previousSum1, ref previousSum2, data, len);
return;
}
#endif
#if NET5_0_OR_GREATER
if(AdvSimd.IsSupported)
{
Neon.Step(ref previousSum1, ref previousSum2, data, len);
return;
}
#endif
uint sum1 = previousSum1;
uint sum2 = previousSum2;
var dataOff = 0;
switch(len)
{
/* in case user likes doing a byte at a time, keep it fast */
case 1:
{
sum1 += data[dataOff];
if(sum1 >= FLETCHER_MODULE)
sum1 -= FLETCHER_MODULE;
sum2 += sum1;
if(sum2 >= FLETCHER_MODULE)
sum2 -= FLETCHER_MODULE;
previousSum1 = (ushort)(sum1 & 0xFFFF);
previousSum2 = (ushort)(sum2 & 0xFFFF);
return;
}
/* in case short lengths are provided, keep it somewhat fast */
case < 16:
{
while(len-- > 0)
{
sum1 += data[dataOff++];
sum2 += sum1;
}
if(sum1 >= FLETCHER_MODULE)
sum1 -= FLETCHER_MODULE;
sum2 %= FLETCHER_MODULE; /* only added so many FLETCHER_MODULE's */
previousSum1 = (ushort)(sum1 & 0xFFFF);
previousSum2 = (ushort)(sum2 & 0xFFFF);
return;
}
}
/* do length NMAX blocks -- requires just one modulo operation */
while(len >= NMAX)
{
len -= NMAX;
uint n = NMAX / 16;
do
{
sum1 += data[dataOff];
sum2 += sum1;
sum1 += data[dataOff + 1];
sum2 += sum1;
sum1 += data[dataOff + 2];
sum2 += sum1;
sum1 += data[dataOff + 2 + 1];
sum2 += sum1;
sum1 += data[dataOff + 4];
sum2 += sum1;
sum1 += data[dataOff + 4 + 1];
sum2 += sum1;
sum1 += data[dataOff + 4 + 2];
sum2 += sum1;
sum1 += data[dataOff + 4 + 2 + 1];
sum2 += sum1;
sum1 += data[dataOff + 8];
sum2 += sum1;
sum1 += data[dataOff + 8 + 1];
sum2 += sum1;
sum1 += data[dataOff + 8 + 2];
sum2 += sum1;
sum1 += data[dataOff + 8 + 2 + 1];
sum2 += sum1;
sum1 += data[dataOff + 8 + 4];
sum2 += sum1;
sum1 += data[dataOff + 8 + 4 + 1];
sum2 += sum1;
sum1 += data[dataOff + 8 + 4 + 2];
sum2 += sum1;
sum1 += data[dataOff + 8 + 4 + 2 + 1];
sum2 += sum1;
/* 16 sums unrolled */
dataOff += 16;
} while(--n != 0);
sum1 %= FLETCHER_MODULE;
sum2 %= FLETCHER_MODULE;
}
/* do remaining bytes (less than NMAX, still just one modulo) */
if(len != 0)
{
/* avoid modulos if none remaining */
while(len >= 16)
{
len -= 16;
sum1 += data[dataOff];
sum2 += sum1;
sum1 += data[dataOff + 1];
sum2 += sum1;
sum1 += data[dataOff + 2];
sum2 += sum1;
sum1 += data[dataOff + 2 + 1];
sum2 += sum1;
sum1 += data[dataOff + 4];
sum2 += sum1;
sum1 += data[dataOff + 4 + 1];
sum2 += sum1;
sum1 += data[dataOff + 4 + 2];
sum2 += sum1;
sum1 += data[dataOff + 4 + 2 + 1];
sum2 += sum1;
sum1 += data[dataOff + 8];
sum2 += sum1;
sum1 += data[dataOff + 8 + 1];
sum2 += sum1;
sum1 += data[dataOff + 8 + 2];
sum2 += sum1;
sum1 += data[dataOff + 8 + 2 + 1];
sum2 += sum1;
sum1 += data[dataOff + 8 + 4];
sum2 += sum1;
sum1 += data[dataOff + 8 + 4 + 1];
sum2 += sum1;
sum1 += data[dataOff + 8 + 4 + 2];
sum2 += sum1;
sum1 += data[dataOff + 8 + 4 + 2 + 1];
sum2 += sum1;
dataOff += 16;
}
while(len-- != 0)
{
sum1 += data[dataOff++];
sum2 += sum1;
}
sum1 %= FLETCHER_MODULE;
sum2 %= FLETCHER_MODULE;
}
previousSum1 = (ushort)(sum1 & 0xFFFF);
previousSum2 = (ushort)(sum2 & 0xFFFF);
}
/// <summary>Gets the hash of a file</summary>
/// <param name="filename">File path.</param>
public static byte[] File(string filename)
{
File(filename, out byte[] hash);
return hash;
}
/// <summary>Gets the hash of a file in hexadecimal and as a byte array.</summary>
/// <param name="filename">File path.</param>
/// <param name="hash">Byte array of the hash value.</param>
public static string File(string filename, out byte[] hash)
{
bool useNative = Native.IsSupported;
IntPtr nativeContext = IntPtr.Zero;
if(useNative)
{
nativeContext = fletcher32_init();
if(nativeContext == IntPtr.Zero)
useNative = false;
}
var fileStream = new FileStream(filename, FileMode.Open);
ushort localSum1 = 0xFFFF;
ushort localSum2 = 0xFFFF;
var buffer = new byte[65536];
int read = fileStream.EnsureRead(buffer, 0, 65536);
while(read > 0)
{
Step(ref localSum1, ref localSum2, buffer, (uint)read, useNative, nativeContext);
read = fileStream.EnsureRead(buffer, 0, 65536);
}
var finalSum = (uint)(localSum2 << 16 | localSum1);
if(useNative)
{
fletcher32_final(nativeContext, ref finalSum);
fletcher32_free(nativeContext);
}
hash = BigEndianBitConverter.GetBytes(finalSum);
var fletcherOutput = new StringBuilder();
foreach(byte h in hash)
fletcherOutput.Append(h.ToString("x2"));
fileStream.Close();
return fletcherOutput.ToString();
}
/// <summary>Gets the hash of the specified data buffer.</summary>
/// <param name="data">Data buffer.</param>
/// <param name="len">Length of the data buffer to hash.</param>
/// <param name="hash">Byte array of the hash value.</param>
public static string Data(byte[] data, uint len, out byte[] hash)
{
bool useNative = Native.IsSupported;
IntPtr nativeContext = IntPtr.Zero;
if(useNative)
{
nativeContext = fletcher32_init();
if(nativeContext == IntPtr.Zero)
useNative = false;
}
ushort localSum1 = 0xFFFF;
ushort localSum2 = 0xFFFF;
Step(ref localSum1, ref localSum2, data, len, useNative, nativeContext);
var finalSum = (uint)(localSum2 << 16 | localSum1);
if(useNative)
{
fletcher32_final(nativeContext, ref finalSum);
fletcher32_free(nativeContext);
}
hash = BigEndianBitConverter.GetBytes(finalSum);
var adlerOutput = new StringBuilder();
foreach(byte h in hash)
adlerOutput.Append(h.ToString("x2"));
return adlerOutput.ToString();
}
/// <summary>Gets the hash of the specified data buffer.</summary>
/// <param name="data">Data buffer.</param>
/// <param name="hash">Byte array of the hash value.</param>
public static string Data(byte[] data, out byte[] hash) => Data(data, (uint)data.Length, out hash);
}
/// <inheritdoc />
/// <summary>Implements the Fletcher-16 algorithm</summary>
[SuppressMessage("ReSharper", "UnusedMember.Global")]
[SuppressMessage("ReSharper", "MemberCanBePrivate.Global")]
[SuppressMessage("ReSharper", "UnusedMethodReturnValue.Global")]
public sealed class Fletcher16Context : IChecksum
{
const byte FLETCHER_MODULE = 0xFF;
const byte NMAX = 22;
readonly IntPtr _nativeContext;
readonly bool _useNative;
byte _sum1, _sum2;
/// <summary>Initializes the Fletcher-16 sums</summary>
public Fletcher16Context()
{
_sum1 = 0xFF;
_sum2 = 0xFF;
if(!Native.IsSupported)
return;
_nativeContext = fletcher16_init();
_useNative = _nativeContext != IntPtr.Zero;
}
#region IChecksum Members
/// <inheritdoc />
public string Name => "Fletcher-16";
/// <inheritdoc />
public Guid Id => new("80C51F1D-71F8-4741-A0CF-18FA8102EE4B");
/// <inheritdoc />
public string Author => "Natalia Portillo";
/// <inheritdoc />
/// <summary>Updates the hash with data.</summary>
/// <param name="data">Data buffer.</param>
/// <param name="len">Length of buffer to hash.</param>
public void Update(byte[] data, uint len) => Step(ref _sum1, ref _sum2, data, len, _useNative, _nativeContext);
/// <inheritdoc />
/// <summary>Updates the hash with data.</summary>
/// <param name="data">Data buffer.</param>
public void Update(byte[] data) => Update(data, (uint)data.Length);
/// <inheritdoc />
/// <summary>Returns a byte array of the hash value.</summary>
public byte[] Final()
{
var finalSum = (ushort)(_sum2 << 8 | _sum1);
if(!_useNative)
return BigEndianBitConverter.GetBytes(finalSum);
fletcher16_final(_nativeContext, ref finalSum);
fletcher16_free(_nativeContext);
return BigEndianBitConverter.GetBytes(finalSum);
}
/// <inheritdoc />
/// <summary>Returns a hexadecimal representation of the hash value.</summary>
public string End()
{
var finalSum = (ushort)(_sum2 << 8 | _sum1);
if(_useNative)
{
fletcher16_final(_nativeContext, ref finalSum);
fletcher16_free(_nativeContext);
}
var fletcherOutput = new StringBuilder();
for(var i = 0; i < BigEndianBitConverter.GetBytes(finalSum).Length; i++)
fletcherOutput.Append(BigEndianBitConverter.GetBytes(finalSum)[i].ToString("x2"));
return fletcherOutput.ToString();
}
#endregion
[DllImport("libAaru.Checksums.Native", SetLastError = true)]
static extern IntPtr fletcher16_init();
[DllImport("libAaru.Checksums.Native", SetLastError = true)]
static extern int fletcher16_update(IntPtr ctx, byte[] data, uint len);
[DllImport("libAaru.Checksums.Native", SetLastError = true)]
static extern int fletcher16_final(IntPtr ctx, ref ushort checksum);
[DllImport("libAaru.Checksums.Native", SetLastError = true)]
static extern void fletcher16_free(IntPtr ctx);
static void Step(ref byte previousSum1, ref byte previousSum2, byte[] data, uint len, bool useNative,
IntPtr nativeContext)
{
if(useNative)
{
fletcher16_update(nativeContext, data, len);
return;
}
uint sum1 = previousSum1;
uint sum2 = previousSum2;
var dataOff = 0;
switch(len)
{
/* in case user likes doing a byte at a time, keep it fast */
case 1:
{
sum1 += data[dataOff];
if(sum1 >= FLETCHER_MODULE)
sum1 -= FLETCHER_MODULE;
sum2 += sum1;
if(sum2 >= FLETCHER_MODULE)
sum2 -= FLETCHER_MODULE;
previousSum1 = (byte)(sum1 & 0xFF);
previousSum2 = (byte)(sum2 & 0xFF);
return;
}
/* in case short lengths are provided, keep it somewhat fast */
case < 11:
{
while(len-- > 0)
{
sum1 += data[dataOff++];
sum2 += sum1;
}
if(sum1 >= FLETCHER_MODULE)
sum1 -= FLETCHER_MODULE;
sum2 %= FLETCHER_MODULE; /* only added so many FLETCHER_MODULE's */
previousSum1 = (byte)(sum1 & 0xFF);
previousSum2 = (byte)(sum2 & 0xFF);
return;
}
}
/* do length NMAX blocks -- requires just one modulo operation */
while(len >= NMAX)
{
len -= NMAX;
uint n = NMAX / 11;
do
{
sum1 += data[dataOff];
sum2 += sum1;
sum1 += data[dataOff + 1];
sum2 += sum1;
sum1 += data[dataOff + 2];
sum2 += sum1;
sum1 += data[dataOff + 2 + 1];
sum2 += sum1;
sum1 += data[dataOff + 4];
sum2 += sum1;
sum1 += data[dataOff + 4 + 1];
sum2 += sum1;
sum1 += data[dataOff + 4 + 2];
sum2 += sum1;
sum1 += data[dataOff + 4 + 2 + 1];
sum2 += sum1;
sum1 += data[dataOff + 8];
sum2 += sum1;
sum1 += data[dataOff + 8 + 1];
sum2 += sum1;
sum1 += data[dataOff + 8 + 2];
sum2 += sum1;
/* 11 sums unrolled */
dataOff += 11;
} while(--n != 0);
sum1 %= FLETCHER_MODULE;
sum2 %= FLETCHER_MODULE;
}
/* do remaining bytes (less than NMAX, still just one modulo) */
if(len != 0)
{
/* avoid modulos if none remaining */
while(len >= 11)
{
len -= 11;
sum1 += data[dataOff];
sum2 += sum1;
sum1 += data[dataOff + 1];
sum2 += sum1;
sum1 += data[dataOff + 2];
sum2 += sum1;
sum1 += data[dataOff + 2 + 1];
sum2 += sum1;
sum1 += data[dataOff + 4];
sum2 += sum1;
sum1 += data[dataOff + 4 + 1];
sum2 += sum1;
sum1 += data[dataOff + 4 + 2];
sum2 += sum1;
sum1 += data[dataOff + 4 + 2 + 1];
sum2 += sum1;
sum1 += data[dataOff + 8];
sum2 += sum1;
sum1 += data[dataOff + 8 + 1];
sum2 += sum1;
sum1 += data[dataOff + 8 + 2];
sum2 += sum1;
dataOff += 11;
}
while(len-- != 0)
{
sum1 += data[dataOff++];
sum2 += sum1;
}
sum1 %= FLETCHER_MODULE;
sum2 %= FLETCHER_MODULE;
}
previousSum1 = (byte)(sum1 & 0xFF);
previousSum2 = (byte)(sum2 & 0xFF);
}
/// <summary>Gets the hash of a file</summary>
/// <param name="filename">File path.</param>
public static byte[] File(string filename)
{
File(filename, out byte[] hash);
return hash;
}
/// <summary>Gets the hash of a file in hexadecimal and as a byte array.</summary>
/// <param name="filename">File path.</param>
/// <param name="hash">Byte array of the hash value.</param>
public static string File(string filename, out byte[] hash)
{
bool useNative = Native.IsSupported;
IntPtr nativeContext = IntPtr.Zero;
if(useNative)
{
nativeContext = fletcher16_init();
if(nativeContext == IntPtr.Zero)
useNative = false;
}
var fileStream = new FileStream(filename, FileMode.Open);
byte localSum1 = 0xFF;
byte localSum2 = 0xFF;
var buffer = new byte[65536];
int read = fileStream.EnsureRead(buffer, 0, 65536);
while(read > 0)
{
Step(ref localSum1, ref localSum2, buffer, (uint)read, useNative, nativeContext);
read = fileStream.EnsureRead(buffer, 0, 65536);
}
var finalSum = (ushort)(localSum2 << 8 | localSum1);
if(useNative)
{
fletcher16_final(nativeContext, ref finalSum);
fletcher16_free(nativeContext);
}
hash = BigEndianBitConverter.GetBytes(finalSum);
var fletcherOutput = new StringBuilder();
foreach(byte h in hash)
fletcherOutput.Append(h.ToString("x2"));
fileStream.Close();
return fletcherOutput.ToString();
}
/// <summary>Gets the hash of the specified data buffer.</summary>
/// <param name="data">Data buffer.</param>
/// <param name="len">Length of the data buffer to hash.</param>
/// <param name="hash">Byte array of the hash value.</param>
public static string Data(byte[] data, uint len, out byte[] hash)
{
bool useNative = Native.IsSupported;
IntPtr nativeContext = IntPtr.Zero;
if(useNative)
{
nativeContext = fletcher16_init();
if(nativeContext == IntPtr.Zero)
useNative = false;
}
byte localSum1 = 0xFF;
byte localSum2 = 0xFF;
Step(ref localSum1, ref localSum2, data, len, useNative, nativeContext);
var finalSum = (ushort)(localSum2 << 8 | localSum1);
if(useNative)
{
fletcher16_final(nativeContext, ref finalSum);
fletcher16_free(nativeContext);
}
hash = BigEndianBitConverter.GetBytes(finalSum);
var adlerOutput = new StringBuilder();
foreach(byte h in hash)
adlerOutput.Append(h.ToString("x2"));
return adlerOutput.ToString();
}
/// <summary>Gets the hash of the specified data buffer.</summary>
/// <param name="data">Data buffer.</param>
/// <param name="hash">Byte array of the hash value.</param>
public static string Data(byte[] data, out byte[] hash) => Data(data, (uint)data.Length, out hash);
}

View File

@@ -0,0 +1,83 @@
// /***************************************************************************
// Aaru Data Preservation Suite
// ----------------------------------------------------------------------------
//
// Filename : Native.cs
// Author(s) : Natalia Portillo <claunia@claunia.com>
//
// Component : Checksums.
//
// --[ Description ] ----------------------------------------------------------
//
// Checks that Aaru.Checksums.Native library is available and usable.
//
// --[ License ] --------------------------------------------------------------
//
// This library is free software; you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as
// published by the Free Software Foundation; either version 2.1 of the
// License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, see <http://www.gnu.org/licenses/>.
//
// ----------------------------------------------------------------------------
// Copyright © 2011-2023 Natalia Portillo
// ****************************************************************************/
using System.Runtime.InteropServices;
namespace Aaru.Checksums;
/// <summary>Handles native implementations of compression algorithms</summary>
public static class Native
{
static bool _checked;
static bool _supported;
/// <summary>Set to return native as never supported</summary>
public static bool ForceManaged { get; set; }
/// <summary>
/// If set to <c>true</c> the native library was found and loaded correctly and its reported version is
/// compatible.
/// </summary>
public static bool IsSupported
{
get
{
if(ForceManaged)
return false;
if(_checked)
return _supported;
ulong version;
_checked = true;
try
{
version = get_acn_version();
}
catch
{
_supported = false;
return false;
}
// TODO: Check version compatibility
_supported = version >= 0x06000000;
return _supported;
}
}
[DllImport("libAaru.Checksums.Native", SetLastError = true)]
static extern ulong get_acn_version();
}

View File

@@ -0,0 +1,324 @@
// /***************************************************************************
// Aaru Data Preservation Suite
// ----------------------------------------------------------------------------
//
// Filename : BigEndianBitConverter.cs
// Author(s) : Natalia Portillo <claunia@claunia.com>
//
// Component : Helpers.
//
// --[ Description ] ----------------------------------------------------------
//
// Override of System.BitConverter that knows how to handle big-endian.
//
// --[ License ] --------------------------------------------------------------
//
// This library is free software; you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as
// published by the Free Software Foundation; either version 2.1 of the
// License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, see <http://www.gnu.org/licenses/>.
//
// ----------------------------------------------------------------------------
// Copyright © 2011-2023 Natalia Portillo
// ****************************************************************************/
using System;
using System.Linq;
namespace Aaru.Helpers
{
/// <summary>
/// Converts base data types to an array of bytes, and an array of bytes to base data types. All info taken from
/// the meta data of System.BitConverter. This implementation allows for Endianness consideration.
/// </summary>
public static class BigEndianBitConverter
{
/// <summary>Converts the specified double-precision floating point number to a 64-bit signed integer.</summary>
/// <param name="value">The number to convert.</param>
/// <returns>A 64-bit signed integer whose value is equivalent to value.</returns>
/// <exception cref="NotImplementedException">It is not currently implemented</exception>
public static long DoubleToInt64Bits(double value) => throw new NotImplementedException();
/// <summary>Returns the specified Boolean value as an array of bytes.</summary>
/// <param name="value">A Boolean value.</param>
/// <returns>An array of bytes with length 1.</returns>
public static byte[] GetBytes(bool value) => BitConverter.GetBytes(value).Reverse().ToArray();
/// <summary>Returns the specified Unicode character value as an array of bytes.</summary>
/// <param name="value">A character to convert.</param>
/// <returns>An array of bytes with length 2.</returns>
public static byte[] GetBytes(char value) => BitConverter.GetBytes(value).Reverse().ToArray();
/// <summary>Returns the specified double-precision floating point value as an array of bytes.</summary>
/// <param name="value">The number to convert.</param>
/// <returns>An array of bytes with length 8.</returns>
public static byte[] GetBytes(double value) => BitConverter.GetBytes(value).Reverse().ToArray();
/// <summary>Returns the specified single-precision floating point value as an array of bytes.</summary>
/// <param name="value">The number to convert.</param>
/// <returns>An array of bytes with length 4.</returns>
public static byte[] GetBytes(float value) => BitConverter.GetBytes(value).Reverse().ToArray();
/// <summary>Returns the specified 32-bit signed integer value as an array of bytes.</summary>
/// <param name="value">The number to convert.</param>
/// <returns>An array of bytes with length 4.</returns>
public static byte[] GetBytes(int value) => BitConverter.GetBytes(value).Reverse().ToArray();
/// <summary>Returns the specified 64-bit signed integer value as an array of bytes.</summary>
/// <param name="value">The number to convert.</param>
/// <returns>An array of bytes with length 8.</returns>
public static byte[] GetBytes(long value) => BitConverter.GetBytes(value).Reverse().ToArray();
/// <summary>Returns the specified 16-bit signed integer value as an array of bytes.</summary>
/// <param name="value">The number to convert.</param>
/// <returns>An array of bytes with length 2.</returns>
public static byte[] GetBytes(short value) => BitConverter.GetBytes(value).Reverse().ToArray();
/// <summary>Returns the specified 32-bit unsigned integer value as an array of bytes.</summary>
/// <param name="value">The number to convert.</param>
/// <returns>An array of bytes with length 4.</returns>
public static byte[] GetBytes(uint value) => BitConverter.GetBytes(value).Reverse().ToArray();
/// <summary>Returns the specified 64-bit unsigned integer value as an array of bytes.</summary>
/// <param name="value">The number to convert.</param>
/// <returns>An array of bytes with length 8.</returns>
public static byte[] GetBytes(ulong value) => BitConverter.GetBytes(value).Reverse().ToArray();
/// <summary>Returns the specified 16-bit unsigned integer value as an array of bytes.</summary>
/// <param name="value">The number to convert.</param>
/// <returns>An array of bytes with length 2.</returns>
public static byte[] GetBytes(ushort value) => BitConverter.GetBytes(value).Reverse().ToArray();
/// <summary>Converts the specified 64-bit signed integer to a double-precision floating point number.</summary>
/// <param name="value">The number to convert.</param>
/// <returns>A double-precision floating point number whose value is equivalent to value.</returns>
public static double Int64BitsToDouble(long value) => throw new NotImplementedException();
/// <summary>Returns a Boolean value converted from one byte at a specified position in a byte array.</summary>
/// <param name="value">An array of bytes.</param>
/// <param name="startIndex">The starting position within value.</param>
/// <returns>true if the byte at <see cref="startIndex" /> in value is nonzero; otherwise, false.</returns>
/// <exception cref="System.ArgumentNullException">value is null.</exception>
/// <exception cref="System.ArgumentOutOfRangeException">
/// <see cref="startIndex" /> is less than zero or greater than the
/// length of value minus 1.
/// </exception>
public static bool ToBoolean(byte[] value, int startIndex) => throw new NotImplementedException();
/// <summary>Returns a Unicode character converted from two bytes at a specified position in a byte array.</summary>
/// <param name="value">An array.</param>
/// <param name="startIndex">The starting position within value.</param>
/// <returns>A character formed by two bytes beginning at <see cref="startIndex" />.</returns>
/// <exception cref="System.ArgumentException"><see cref="startIndex" /> equals the length of value minus 1.</exception>
/// <exception cref="System.ArgumentNullException">value is null.</exception>
/// <exception cref="System.ArgumentOutOfRangeException">
/// <see cref="startIndex" /> is less than zero or greater than the
/// length of value minus 1.
/// </exception>
public static char ToChar(byte[] value, int startIndex) => throw new NotImplementedException();
/// <summary>
/// Returns a double-precision floating point number converted from eight bytes at a specified position in a byte
/// array.
/// </summary>
/// <param name="value">An array of bytes.</param>
/// <param name="startIndex">The starting position within value.</param>
/// <returns>A double precision floating point number formed by eight bytes beginning at <see cref="startIndex" />.</returns>
/// <exception cref="System.ArgumentException">
/// <see cref="startIndex" /> is greater than or equal to the length of value
/// minus 7, and is less than or equal to the length of value minus 1.
/// </exception>
/// <exception cref="System.ArgumentNullException">value is null.</exception>
/// <exception cref="System.ArgumentOutOfRangeException">
/// <see cref="startIndex" /> is less than zero or greater than the
/// length of value minus 1.
/// </exception>
public static double ToDouble(byte[] value, int startIndex) => throw new NotImplementedException();
/// <summary>Returns a 16-bit signed integer converted from two bytes at a specified position in a byte array.</summary>
/// <param name="value">An array of bytes.</param>
/// <param name="startIndex">The starting position within value.</param>
/// <returns>A 16-bit signed integer formed by two bytes beginning at <see cref="startIndex" />.</returns>
/// <exception cref="System.ArgumentException"><see cref="startIndex" /> equals the length of value minus 1.</exception>
/// <exception cref="System.ArgumentNullException">value is null.</exception>
/// <exception cref="System.ArgumentOutOfRangeException">
/// startIndex is less than zero or greater than the length of value
/// minus 1.
/// </exception>
public static short ToInt16(byte[] value, int startIndex) =>
BitConverter.ToInt16(value.Reverse().ToArray(), value.Length - sizeof(short) - startIndex);
/// <summary>Returns a 32-bit signed integer converted from four bytes at a specified position in a byte array.</summary>
/// <param name="value">An array of bytes.</param>
/// <param name="startIndex">The starting position within value.</param>
/// <returns>A 32-bit signed integer formed by four bytes beginning at <see cref="startIndex" />.</returns>
/// <exception cref="System.ArgumentException">
/// <see cref="startIndex" /> is greater than or equal to the length of value
/// minus 3, and is less than or equal to the length of value minus 1.
/// </exception>
/// <exception cref="System.ArgumentNullException">value is null.</exception>
/// <exception cref="System.ArgumentOutOfRangeException">
/// startIndex is less than zero or greater than the length of value
/// minus 1.
/// </exception>
public static int ToInt32(byte[] value, int startIndex) =>
BitConverter.ToInt32(value.Reverse().ToArray(), value.Length - sizeof(int) - startIndex);
/// <summary>Returns a 64-bit signed integer converted from eight bytes at a specified position in a byte array.</summary>
/// <param name="value">An array of bytes.</param>
/// <param name="startIndex">The starting position within value.</param>
/// <returns>A 64-bit signed integer formed by eight bytes beginning at <see cref="startIndex" />.</returns>
/// <exception cref="System.ArgumentException">
/// <see cref="startIndex" /> is greater than or equal to the length of value
/// minus 7, and is less than or equal to the length of value minus 1.
/// </exception>
/// <exception cref="System.ArgumentNullException">value is null.</exception>
/// <exception cref="System.ArgumentOutOfRangeException">
/// <see cref="startIndex" /> is less than zero or greater than the
/// length of value minus 1.
/// </exception>
public static long ToInt64(byte[] value, int startIndex) =>
BitConverter.ToInt64(value.Reverse().ToArray(), value.Length - sizeof(long) - startIndex);
/// <summary>
/// Returns a single-precision floating point number converted from four bytes at a specified position in a byte
/// array.
/// </summary>
/// <param name="value">An array of bytes.</param>
/// <param name="startIndex">The starting position within value.</param>
/// <returns>A single-precision floating point number formed by four bytes beginning at <see cref="startIndex" />.</returns>
/// <exception cref="System.ArgumentException">
/// <see cref="startIndex" /> is greater than or equal to the length of value
/// minus 3, and is less than or equal to the length of value minus 1.
/// </exception>
/// <exception cref="System.ArgumentNullException">value is null.</exception>
/// <exception cref="System.ArgumentOutOfRangeException">
/// <see cref="startIndex" /> is less than zero or greater than the
/// length of value minus 1.
/// </exception>
public static float ToSingle(byte[] value, int startIndex) =>
BitConverter.ToSingle(value.Reverse().ToArray(), value.Length - sizeof(float) - startIndex);
/// <summary>
/// Converts the numeric value of each element of a specified array of bytes to its equivalent hexadecimal string
/// representation.
/// </summary>
/// <param name="value">An array of bytes.</param>
/// <returns>
/// A System.String of hexadecimal pairs separated by hyphens, where each pair represents the corresponding
/// element in value; for example, "7F-2C-4A".
/// </returns>
/// <exception cref="System.ArgumentNullException">value is null.</exception>
public static string ToString(byte[] value) => BitConverter.ToString(value.Reverse().ToArray());
/// <summary>
/// Converts the numeric value of each element of a specified subarray of bytes to its equivalent hexadecimal
/// string representation.
/// </summary>
/// <param name="value">An array of bytes.</param>
/// <param name="startIndex">The starting position within value.</param>
/// <returns>
/// A System.String of hexadecimal pairs separated by hyphens, where each pair represents the corresponding
/// element in a subarray of value; for example, "7F-2C-4A".
/// </returns>
/// <exception cref="System.ArgumentNullException">value is null.</exception>
/// <exception cref="System.ArgumentOutOfRangeException">
/// startIndex is less than zero or greater than the length of value
/// minus 1.
/// </exception>
public static string ToString(byte[] value, int startIndex) =>
BitConverter.ToString(value.Reverse().ToArray(), startIndex);
/// <summary>
/// Converts the numeric value of each element of a specified subarray of bytes to its equivalent hexadecimal
/// string representation.
/// </summary>
/// <param name="value">An array of bytes.</param>
/// <param name="startIndex">The starting position within value.</param>
/// <param name="length">The number of array elements in value to convert.</param>
/// <returns>
/// A System.String of hexadecimal pairs separated by hyphens, where each pair represents the corresponding
/// element in a subarray of value; for example, "7F-2C-4A".
/// </returns>
/// <exception cref="System.ArgumentNullException">value is null.</exception>
/// <exception cref="System.ArgumentOutOfRangeException">
/// startIndex or length is less than zero. -or- startIndex is greater
/// than zero and is greater than or equal to the length of value.
/// </exception>
/// <exception cref="System.ArgumentException">
/// The combination of startIndex and length does not specify a position within
/// value; that is, the startIndex parameter is greater than the length of value minus the length parameter.
/// </exception>
public static string ToString(byte[] value, int startIndex, int length) =>
BitConverter.ToString(value.Reverse().ToArray(), startIndex, length);
/// <summary>Returns a 16-bit unsigned integer converted from two bytes at a specified position in a byte array.</summary>
/// <param name="value">The array of bytes.</param>
/// <param name="startIndex">The starting position within value.</param>
/// <returns>A 16-bit unsigned integer formed by two bytes beginning at startIndex.</returns>
/// <exception cref="System.ArgumentException">startIndex equals the length of value minus 1.</exception>
/// <exception cref="System.ArgumentNullException">value is null.</exception>
/// <exception cref="System.ArgumentOutOfRangeException">
/// startIndex is less than zero or greater than the length of value
/// minus 1.
/// </exception>
public static ushort ToUInt16(byte[] value, int startIndex) =>
BitConverter.ToUInt16(value.Reverse().ToArray(), value.Length - sizeof(ushort) - startIndex);
/// <summary>Returns a 32-bit unsigned integer converted from four bytes at a specified position in a byte array.</summary>
/// <param name="value">An array of bytes.</param>
/// <param name="startIndex">The starting position within value.</param>
/// <returns>A 32-bit unsigned integer formed by four bytes beginning at startIndex.</returns>
/// <exception cref="System.ArgumentException">
/// startIndex is greater than or equal to the length of value minus 3, and is
/// less than or equal to the length of value minus 1.
/// </exception>
/// <exception cref="System.ArgumentNullException">value is null.</exception>
/// <exception cref="System.ArgumentOutOfRangeException">
/// startIndex is less than zero or greater than the length of value
/// minus 1.
/// </exception>
public static uint ToUInt32(byte[] value, int startIndex) =>
BitConverter.ToUInt32(value.Reverse().ToArray(), value.Length - sizeof(uint) - startIndex);
/// <summary>Returns a 64-bit unsigned integer converted from eight bytes at a specified position in a byte array.</summary>
/// <param name="value">An array of bytes.</param>
/// <param name="startIndex">The starting position within value.</param>
/// <returns>A 64-bit unsigned integer formed by the eight bytes beginning at startIndex.</returns>
/// <exception cref="System.ArgumentException">
/// startIndex is greater than or equal to the length of value minus 7, and is
/// less than or equal to the length of value minus 1.
/// </exception>
/// <exception cref="System.ArgumentNullException">value is null.</exception>
/// <exception cref="System.ArgumentOutOfRangeException">
/// startIndex is less than zero or greater than the length of value
/// minus 1.
/// </exception>
public static ulong ToUInt64(byte[] value, int startIndex) =>
BitConverter.ToUInt64(value.Reverse().ToArray(), value.Length - sizeof(ulong) - startIndex);
/// <summary>Converts a big endian byte array representation of a GUID into the .NET Guid structure</summary>
/// <param name="value">Byte array containing a GUID in big endian</param>
/// <param name="startIndex">Start of the byte array to process</param>
/// <returns>Processed Guid</returns>
public static Guid ToGuid(byte[] value, int startIndex) => new Guid(ToUInt32(value, 0 + startIndex),
ToUInt16(value, 4 + startIndex),
ToUInt16(value, 6 + startIndex),
value[8 + startIndex + 0],
value[8 + startIndex + 1],
value[8 + startIndex + 2],
value[8 + startIndex + 3],
value[8 + startIndex + 5],
value[8 + startIndex + 5],
value[8 + startIndex + 6],
value[8 + startIndex + 7]);
}
}

View File

@@ -0,0 +1,72 @@
// /***************************************************************************
// Aaru Data Preservation Suite
// ----------------------------------------------------------------------------
//
// Filename : Extensions.cs
// Author(s) : Natalia Portillo <claunia@claunia.com>
//
// Component : Helpers.
//
// --[ Description ] ----------------------------------------------------------
//
// Provides class extensions.
//
// --[ License ] --------------------------------------------------------------
//
// This library is free software; you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as
// published by the Free Software Foundation; either version 2.1 of the
// License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, see <http://www.gnu.org/licenses/>.
//
// ----------------------------------------------------------------------------
// Copyright © 2011-2023 Natalia Portillo
// ****************************************************************************/
using System.IO;
namespace Aaru.Helpers;
public static class Extensions
{
/// <summary>
/// When overridden in a derived class, reads a sequence of bytes from the current stream and advances the
/// position within the stream by the number of bytes read.<br /> Guarantees the whole count of bytes is read or EOF is
/// found
/// </summary>
/// <param name="s">Stream to extend</param>
/// <param name="buffer">
/// An array of bytes. When this method returns, the buffer contains the specified byte array with the
/// values between <see cref="offset" /> and (<see cref="offset" /> + <see cref="count" /> - 1) replaced by the bytes
/// read from the current source.
/// </param>
/// <param name="offset">
/// The zero-based byte offset in <see cref="buffer" /> at which to begin storing the data read from
/// the current stream.
/// </param>
/// <param name="count">The maximum number of bytes to be read from the current stream.</param>
/// <returns>
/// The total number of bytes read into the buffer. This can be less than the number of bytes requested if the end
/// of the stream has been reached.
/// </returns>
public static int EnsureRead(this Stream s, byte[] buffer, int offset, int count)
{
var pos = 0;
int read;
do
{
read = s.Read(buffer, pos + offset, count - pos);
pos += read;
} while(read > 0);
return pos;
}
}

View File

@@ -0,0 +1,68 @@
using System;
namespace CRC32
{
public class NaiveCRC
{
private const uint kPoly = 0xEDB88320;
private const uint kInit = 0xFFFFFFFF;
private static readonly uint[] Table;
static NaiveCRC()
{
unchecked
{
Table = new uint[256];
for (uint i = 0; i < 256; i++)
{
uint r = i;
for (int j = 0; j < 8; j++)
r = (r >> 1) ^ (kPoly & ~((r & 1) - 1));
Table[i] = r;
}
}
}
private uint value;
public NaiveCRC()
{
Init();
}
public void Init()
{
value = kInit;
}
public int Value
{
get { return (int)~value; }
}
public void UpdateByte(byte b)
{
value = (value >> 8) ^ Table[(byte)value ^ b];
}
public void Update(byte[] data, int offset, int count)
{
if (count < 0) throw new ArgumentOutOfRangeException("count");
while (count-- != 0)
value = (value >> 8) ^ Table[(byte)value ^ data[offset++]];
}
static public int Compute(byte[] data, int offset, int count)
{
var crc = new NaiveCRC();
crc.Update(data, offset, count);
return crc.Value;
}
static public int Compute(byte[] data)
{
return Compute(data, 0, data.Length);
}
}
}

View File

@@ -1,54 +1,34 @@
/*
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.
*/
* Copyright (c) 2012-2015 Eugene Larchenko (el6345@gmail.com)
* This code is licensed under the MIT License.
* See the file LICENSE_MIT for the license details.
*/
using System;
namespace OptimizedCRC
namespace CRC32
{
internal class OptimizedCRC : IDisposable
public class OptimizedCRC
{
private const uint kCrcPoly = 0xEDB88320;
private const uint kInitial = 0xFFFFFFFF;
private const int CRC_NUM_TABLES = 8;
private const uint kPoly = 0xEDB88320;
private const uint kInit = 0xFFFFFFFF;
private const int NUM_TABLES = 8;
private static readonly uint[] Table;
static OptimizedCRC()
{
unchecked
{
Table = new uint[256 * CRC_NUM_TABLES];
Table = new uint[256 * 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));
}
r = (r >> 1) ^ (kPoly & ~((r & 1) - 1));
Table[i] = r;
}
for (; i < 256 * CRC_NUM_TABLES; i++)
for (; i < 256 * NUM_TABLES; i++)
{
uint r = Table[i - 256];
Table[i] = Table[r & 0xFF] ^ (r >> 8);
@@ -56,49 +36,37 @@ namespace OptimizedCRC
}
}
public uint UnsignedValue;
private uint value;
public OptimizedCRC()
{
Init();
}
/// <summary>
/// Reset CRC
/// </summary>
public void Init()
{
UnsignedValue = kInitial;
value = kInit;
}
public int Value
{
get { return (int)~UnsignedValue; }
get { return (int)~value; }
}
public void Update(byte[] data, int offset, int count)
{
new ArraySegment<byte>(data, offset, count); // check arguments
if (count == 0)
{
return;
}
new ArraySegment<byte>(data, offset, count); // check arguments
if (count <= 0) return;
var table = OptimizedCRC.Table;
uint crc = UnsignedValue;
uint crc = value;
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;
@@ -121,11 +89,9 @@ namespace OptimizedCRC
}
while (count-- != 0)
{
crc = (crc >> 8) ^ table[(byte)crc ^ data[offset++]];
}
UnsignedValue = crc;
value = crc;
}
static public int Compute(byte[] data, int offset, int count)
@@ -140,14 +106,5 @@ namespace OptimizedCRC
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;
}
}
}
}

View File

@@ -0,0 +1,302 @@
/*
* Copyright (c) 2012-2015 Eugene Larchenko (el6345@gmail.com)
* This code is licensed under the Microsoft Public License (MS-PL).
* See the file LICENSE_MSPL for the license details.
*/
using System;
using System.Threading;
using System.Collections.Generic;
using System.Linq;
namespace CRC32
{
public class ParallelCRC
{
private const uint kPoly = 0xEDB88320;
private const uint kInit = 0xFFFFFFFF;
private const int NUM_TABLES = 8;
private static readonly uint[] Table;
private const int ThreadCost = 512 * 1024;
private static readonly int ProcessorCount = Environment.ProcessorCount;
static ParallelCRC()
{
unchecked
{
Table = new uint[256 * NUM_TABLES];
int i;
for (i = 0; i < 256; i++)
{
uint r = (uint)i;
for (int j = 0; j < 8; j++)
r = (r >> 1) ^ (kPoly & ~((r & 1) - 1));
Table[i] = r;
}
for (; i < 256 * NUM_TABLES; i++)
{
uint r = Table[i - 256];
Table[i] = Table[r & 0xFF] ^ (r >> 8);
}
}
}
private uint value;
public ParallelCRC()
{
Init();
}
/// <summary>
/// Reset CRC
/// </summary>
public void Init()
{
value = kInit;
}
public int Value
{
get { return (int)~value; }
}
public void Update(byte[] data, int offset, int count)
{
new ArraySegment<byte>(data, offset, count); // check arguments
// quick elimination
if (count <= ThreadCost || ProcessorCount <= 1)
{
value = ProcessBlock(value, data, offset, count);
return;
}
// choose optimal number of threads to use
int threadCount = ProcessorCount;
L0:
int bytesPerThread = (count + threadCount - 1) / threadCount;
if (bytesPerThread < (ThreadCost >> 1))
{
threadCount--;
goto L0;
}
// create jobs chain
// threadCount >= 2
Job? lastJob = null;
while (count > bytesPerThread)
{
var job = new Job(new ArraySegment<byte>(data, offset, bytesPerThread), this, lastJob);
ThreadPool.QueueUserWorkItem(job.Start);
offset += bytesPerThread;
count -= bytesPerThread;
lastJob = job;
}
// lastJob != null
var lastBlockCRC = ProcessBlock(kInit, data, offset, count);
lastJob?.WaitAndDispose();
value = Combine(value, lastBlockCRC, count);
}
private static uint ProcessBlock(uint crc, byte[] data, int offset, int count)
{
/*
* A copy of OptimizedCRC.cs
*/
if (count < 0) throw new ArgumentOutOfRangeException("count");
if (count == 0) return crc;
var table = ParallelCRC.Table;
for (; (offset & 7) != 0 && count != 0; count--)
crc = (crc >> 8) ^ table[(byte)crc ^ data[offset++]];
if (count >= 8)
{
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++]];
return crc;
}
static public int Compute(byte[] data, int offset, int count)
{
var crc = new ParallelCRC();
crc.Update(data, offset, count);
return crc.Value;
}
static public int Compute(byte[] data)
{
return Compute(data, 0, data.Length);
}
#region Combining
// Copyright (c) 2011 Dino Chiesa.
// This module is (refactored) part of DotNetZip, a zipfile class library.
// This code is licensed under the Microsoft Public License.
// See the file LICENSE_MSPL for the license details.
// More info on: http://dotnetzip.codeplex.com
/// <summary>
/// Combine sums of two segments.
/// This function is thread-safe.
/// </summary>
private static uint Combine(uint crc1, uint crc2, int length2)
{
// Note: this function is thread-safe even though it references static fields
if (length2 <= 0) return crc1;
if (crc1 == kInit) return crc2;
if (even_cache == null)
{
Prepare_even_odd_Cache();
}
uint[] even = even_cache?.ToArray() ?? [];
uint[] odd = odd_cache?.ToArray() ?? [];
crc1 = ~crc1;
crc2 = ~crc2;
uint len2 = (uint)length2;
// apply len2 zeros to crc1 (first square will put the operator for one
// zero byte, eight zero bits, in even)
do
{
// apply zeros operator for this bit of len2
gf2_matrix_square(even, odd);
if ((len2 & 1) != 0) crc1 = gf2_matrix_times(even, crc1);
len2 >>= 1;
if (len2 == 0) break;
// another iteration of the loop with odd and even swapped
gf2_matrix_square(odd, even);
if ((len2 & 1) != 0) crc1 = gf2_matrix_times(odd, crc1);
len2 >>= 1;
} while (len2 != 0);
crc1 ^= crc2;
return ~crc1;
}
private static uint[]? even_cache = null;
private static uint[]? odd_cache;
private static void Prepare_even_odd_Cache()
{
var even = new uint[32]; // even-power-of-two zeros operator
var odd = new uint[32]; // odd-power-of-two zeros operator
// put operator for one zero bit in odd
odd[0] = kPoly; // the CRC-32 polynomial
for (int i = 1; i < 32; i++) odd[i] = 1U << (i - 1);
// put operator for two zero bits in even
gf2_matrix_square(even, odd);
// put operator for four zero bits in odd
gf2_matrix_square(odd, even);
odd_cache = odd;
even_cache = even;
}
/// <param name="matrix">will not be modified</param>
private static uint gf2_matrix_times(uint[] matrix, uint vec)
{
uint sum = 0;
int i = 0;
while (vec != 0)
{
if ((vec & 1) != 0) sum ^= matrix[i];
vec >>= 1;
i++;
}
return sum;
}
/// <param name="square">this array will be modified!</param>
/// <param name="mat">will not be modified</param>
private static void gf2_matrix_square(uint[] square, uint[] mat)
{
for (int i = 0; i < 32; i++)
square[i] = gf2_matrix_times(mat, mat[i]);
}
#endregion Combining
class Job
{
private ArraySegment<byte> data;
private Job? previousJob;
private ParallelCRC accumulator;
private ManualResetEvent? finished;
public Job(ArraySegment<byte> data, ParallelCRC accumulator, Job? previousJob)
{
this.data = data;
this.accumulator = accumulator;
this.previousJob = previousJob;
this.finished = new ManualResetEvent(false);
}
public void Start(object? arg)
{
var crc = ProcessBlock(kInit, data.Array!, data.Offset, data.Count);
if (previousJob != null) previousJob.WaitAndDispose();
accumulator.value = Combine(accumulator.value, crc, data.Count);
finished?.Set();
}
public void WaitAndDispose()
{
finished?.WaitOne();
Dispose();
}
public void Dispose()
{
if (finished != null) finished.Close();
finished = null;
}
}
}
}

View File

@@ -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();
}
}
}

View File

@@ -0,0 +1,76 @@
namespace SabreTools.Hashing
{
public static class Constants
{
#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
#region Hash string length constants
public const int CRCLength = 8;
public const int MD5Length = 32;
public const int SHA1Length = 40;
public const int SHA256Length = 64;
public const int SHA384Length = 96;
public const int SHA512Length = 128;
#endregion
}
}

View File

@@ -4,7 +4,6 @@ using System.IO;
#if NET40_OR_GREATER || NETCOREAPP
using System.Threading.Tasks;
#endif
using Compress.ThreadReaders;
namespace SabreTools.Hashing
{
@@ -46,18 +45,38 @@ namespace SabreTools.Hashing
public static Dictionary<HashType, string?>? GetFileHashes(string filename)
=> GetFileHashesAndSize(filename, out _);
/// <summary>
/// Get hashes from an input file path
/// </summary>
/// <param name="filename">Path to the input file</param>
/// <returns>Dictionary containing hashes on success, null on error</returns>
public static Dictionary<HashType, byte[]?>? GetFileHashArrays(string filename)
=> GetFileHashArraysAndSize(filename, out _);
/// <summary>
/// Get a hash from an input file path
/// </summary>
/// <param name="filename">Path to the input file</param>
/// <param name="hashType">Hash type to get from the file</param>
/// <returns>Dictionary containing hashes on success, null on error</returns>
/// <returns>Hash on success, null on error</returns>
public static string? GetFileHash(string filename, HashType hashType)
{
var hashes = GetFileHashes(filename, [hashType]);
return hashes?[hashType];
}
/// <summary>
/// Get a hash from an input file path
/// </summary>
/// <param name="filename">Path to the input file</param>
/// <param name="hashType">Hash type to get from the file</param>
/// <returns>Hash on success, null on error</returns>
public static byte[]? GetFileHashArray(string filename, HashType hashType)
{
var hashes = GetFileHashArrays(filename, [hashType]);
return hashes?[hashType];
}
/// <summary>
/// Get hashes from an input file path
/// </summary>
@@ -67,6 +86,15 @@ namespace SabreTools.Hashing
public static Dictionary<HashType, string?>? GetFileHashes(string filename, HashType[] hashTypes)
=> GetFileHashesAndSize(filename, hashTypes, out _);
/// <summary>
/// Get hashes from an input file path
/// </summary>
/// <param name="filename">Path to the input file</param>
/// <param name="hashTypes">Array of hash types to get from the file</param>
/// <returns>Dictionary containing hashes on success, null on error</returns>
public static Dictionary<HashType, byte[]?>? GetFileHashArrays(string filename, HashType[] hashTypes)
=> GetFileHashArraysAndSize(filename, hashTypes, out _);
#endregion
#region File Hashes With Size
@@ -85,18 +113,44 @@ namespace SabreTools.Hashing
return GetFileHashesAndSize(filename, hashTypes, out size);
}
/// <summary>
/// Get hashes and size from an input file path
/// </summary>
/// <param name="filename">Path to the input file</param>
/// <returns>Dictionary containing hashes on success, null on error</returns>
public static Dictionary<HashType, byte[]?>? GetFileHashArraysAndSize(string filename, out long size)
{
// Create a hash array for all entries
HashType[] hashTypes = (HashType[])Enum.GetValues(typeof(HashType));
// Return the hashes from the stream
return GetFileHashArraysAndSize(filename, hashTypes, out size);
}
/// <summary>
/// Get a hash and size from an input file path
/// </summary>
/// <param name="filename">Path to the input file</param>
/// <param name="hashType">Hash type to get from the file</param>
/// <returns>Dictionary containing hashes on success, null on error</returns>
/// <returns>Hash and size on success, null on error</returns>
public static string? GetFileHashAndSize(string filename, HashType hashType, out long size)
{
var hashes = GetFileHashesAndSize(filename, [hashType], out size);
return hashes?[hashType];
}
/// <summary>
/// Get a hash and size from an input file path
/// </summary>
/// <param name="filename">Path to the input file</param>
/// <param name="hashType">Hash type to get from the file</param>
/// <returns>Hash and size on success, null on error</returns>
public static byte[]? GetFileHashArrayAndSize(string filename, HashType hashType, out long size)
{
var hashes = GetFileHashArraysAndSize(filename, [hashType], out size);
return hashes?[hashType];
}
/// <summary>
/// Get hashes and size from an input file path
/// </summary>
@@ -122,6 +176,31 @@ namespace SabreTools.Hashing
return GetStreamHashes(input, hashTypes);
}
/// <summary>
/// Get hashes and size from an input file path
/// </summary>
/// <param name="filename">Path to the input file</param>
/// <param name="hashTypes">Array of hash types to get from the file</param>
/// <returns>Dictionary containing hashes on success, null on error</returns>
public static Dictionary<HashType, byte[]?>? GetFileHashArraysAndSize(string filename, HashType[] hashTypes, out long size)
{
// If the file doesn't exist, we can't do anything
if (!File.Exists(filename))
{
size = -1;
return null;
}
// Set the file size
size = new FileInfo(filename).Length;
// Open the input file
var input = File.OpenRead(filename);
// Return the hashes from the stream
return GetStreamHashArrays(input, hashTypes);
}
#endregion
#region Byte Array Hashes
@@ -140,18 +219,44 @@ namespace SabreTools.Hashing
return GetStreamHashes(new MemoryStream(input), hashTypes);
}
/// <summary>
/// Get hashes from an input byte array
/// </summary>
/// <param name="input">Byte array to hash</param>
/// <returns>Dictionary containing hashes on success, null on error</returns>
public static Dictionary<HashType, byte[]?>? GetByteArrayHashArrays(byte[] input)
{
// Create a hash array for all entries
HashType[] hashTypes = (HashType[])Enum.GetValues(typeof(HashType));
// Return the hashes from the stream
return GetStreamHashArrays(new MemoryStream(input), hashTypes);
}
/// <summary>
/// Get a hash from an input byte array
/// </summary>
/// <param name="input">Byte array to hash</param>
/// <param name="hashType">Hash type to get from the file</param>
/// <returns>Dictionary containing hashes on success, null on error</returns>
/// <returns>Hash on success, null on error</returns>
public static string? GetByteArrayHash(byte[] input, HashType hashType)
{
var hashes = GetStreamHashes(new MemoryStream(input), [hashType]);
return hashes?[hashType];
}
/// <summary>
/// Get a hash from an input byte array
/// </summary>
/// <param name="input">Byte array to hash</param>
/// <param name="hashType">Hash type to get from the file</param>
/// <returns>Hash on success, null on error</returns>
public static byte[]? GetByteArrayHashArray(byte[] input, HashType hashType)
{
var hashes = GetStreamHashArrays(new MemoryStream(input), [hashType]);
return hashes?[hashType];
}
/// <summary>
/// Get hashes from an input byte array
/// </summary>
@@ -161,6 +266,15 @@ namespace SabreTools.Hashing
public static Dictionary<HashType, string?>? GetByteArrayHashes(byte[] input, HashType[] hashTypes)
=> GetStreamHashes(new MemoryStream(input), hashTypes);
/// <summary>
/// Get hashes from an input byte array
/// </summary>
/// <param name="input">Byte array 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>
public static Dictionary<HashType, byte[]?>? GetByteArrayHashArrays(byte[] input, HashType[] hashTypes)
=> GetStreamHashArrays(new MemoryStream(input), hashTypes);
#endregion
#region Stream Hashes
@@ -170,13 +284,27 @@ namespace SabreTools.Hashing
/// </summary>
/// <param name="input">Stream to hash</param>
/// <returns>Dictionary containing hashes on success, null on error</returns>
public static Dictionary<HashType, string?>? GetStreamHashes(Stream input)
public static Dictionary<HashType, string?>? GetStreamHashes(Stream input, bool leaveOpen = false)
{
// Create a hash array for all entries
HashType[] hashTypes = (HashType[])Enum.GetValues(typeof(HashType));
// Get the output hashes
return GetStreamHashes(input, hashTypes);
return GetStreamHashes(input, hashTypes, leaveOpen);
}
/// <summary>
/// Get hashes from an input Stream
/// </summary>
/// <param name="input">Stream to hash</param>
/// <returns>Dictionary containing hashes on success, null on error</returns>
public static Dictionary<HashType, byte[]?>? GetStreamHashArrays(Stream input, bool leaveOpen = false)
{
// Create a hash array for all entries
HashType[] hashTypes = (HashType[])Enum.GetValues(typeof(HashType));
// Get the output hashes
return GetStreamHashArrays(input, hashTypes, leaveOpen);
}
/// <summary>
@@ -184,10 +312,22 @@ namespace SabreTools.Hashing
/// </summary>
/// <param name="input">Stream to hash</param>
/// <param name="hashType">Hash type to get from the file</param>
/// <returns>Dictionary containing hashes on success, null on error</returns>
public static string? GetStreamHash(Stream input, HashType hashType)
/// <returns>Hash on success, null on error</returns>
public static string? GetStreamHash(Stream input, HashType hashType, bool leaveOpen = false)
{
var hashes = GetStreamHashes(input, [hashType]);
var hashes = GetStreamHashes(input, [hashType], leaveOpen);
return hashes?[hashType];
}
/// <summary>
/// Get a hash and size from an input Stream
/// </summary>
/// <param name="input">Stream to hash</param>
/// <param name="hashType">Hash type to get from the file</param>
/// <returns>Hash on success, null on error</returns>
public static byte[]? GetStreamHashArray(Stream input, HashType hashType, bool leaveOpen = false)
{
var hashes = GetStreamHashArrays(input, [hashType], leaveOpen);
return hashes?[hashType];
}
@@ -197,7 +337,70 @@ 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>
public static Dictionary<HashType, string?>? GetStreamHashes(Stream input, HashType[] hashTypes)
public static Dictionary<HashType, string?>? GetStreamHashes(Stream input, HashType[] hashTypes, bool leaveOpen = false)
{
// Create the output dictionary
var hashDict = new Dictionary<HashType, string?>();
// 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.CurrentHashString;
}
// 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">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>
public static Dictionary<HashType, byte[]?>? GetStreamHashArrays(Stream input, HashType[] hashTypes, bool leaveOpen = false)
{
// Create the output dictionary
var hashDict = new Dictionary<HashType, byte[]?>();
// 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?>();
@@ -213,83 +416,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.CurrentHashString;
}
// Dispose of the hashers
loadBuffer.Dispose();
foreach (var hasher in hashers.Values)
{
hasher.Dispose();
}
return hashDict;
return hashers;
}
catch (IOException)
{
@@ -297,7 +461,8 @@ namespace SabreTools.Hashing
}
finally
{
input.Dispose();
if (!leaveOpen)
input.Dispose();
}
}

View File

@@ -5,23 +5,86 @@ 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
// <summary>
/// CRC 16-bit checksum using the CCITT polynomial
/// </summary>
CRC16_CCITT,
// <summary>
/// CRC 16-bit checksum using the IBM polynomial
/// </summary>
CRC16_IBM,
/// <summary>
/// CRC 32-bit checksum
/// </summary>
/// <remarks>Same as CRC32_ISO in .NET Framework 4.5.2 and lower</remarks>
CRC32,
#if NET462_OR_GREATER || NETCOREAPP
/// <summary>
/// CRC 64-bit checksum
/// CRC 32-bit checksum (ISO implementation)
/// </summary>
CRC32_ISO,
/// <summary>
/// CRC 32-bit checksum (NaiveCRC implementation)
/// </summary>
CRC32_Naive,
/// <summary>
/// CRC 32-bit checksum (OptimizedCRC implementation)
/// </summary>
CRC32_Optimized,
/// <summary>
/// CRC 32-bit checksum (ParallelCRC implementation)
/// </summary>
CRC32_Parallel,
/// <summary>
/// CRC 64-bit checksum (0x42F0E1EBA9EA3693 polynomial)
/// </summary>
CRC64,
#endif
/// <summary>
/// CRC 64-bit checksum (0xC96C5795D7870F42 polynomial)
/// </summary>
CRC64_Reversed,
/// <summary>
/// John G. Fletcher's 16-bit checksum
/// </summary>
Fletcher16,
/// <summary>
/// John G. Fletcher's 32-bit checksum
/// </summary>
Fletcher32,
/// <summary>
/// MD5 hash
/// </summary>
MD5,
#if NETFRAMEWORK
/// <summary>
/// RIPEMD160 hash
/// </summary>
RIPEMD160,
#endif
/// <summary>
/// SHA-1 hash
/// </summary>
@@ -42,6 +105,35 @@ 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
/// <summary>
/// spamsum fuzzy hash
/// </summary>

View File

@@ -2,12 +2,14 @@ using System;
#if NET462_OR_GREATER || NETCOREAPP
using System.IO.Hashing;
#endif
#if NET462_OR_GREATER || NETCOREAPP
using System.Linq;
#endif
using System.Security.Cryptography;
using Aaru.Checksums;
using Aaru.CommonTypes.Interfaces;
#if NET7_0_OR_GREATER
using Blake3;
#endif
using CRC32;
namespace SabreTools.Hashing
{
@@ -21,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
@@ -38,8 +36,15 @@ namespace SabreTools.Hashing
{
HashAlgorithm ha => ha.Hash,
IChecksum ic => ic.Final(),
NaiveCRC ncrc => BitConverter.GetBytes(ncrc.Value).Reverse().ToArray(),
#if NET462_OR_GREATER || NETCOREAPP
NonCryptographicHashAlgorithm ncha => ncha.GetCurrentHash().Reverse().ToArray(),
#endif
OptimizedCRC ocrc => BitConverter.GetBytes(ocrc.Value).Reverse().ToArray(),
ParallelCRC pcrc => BitConverter.GetBytes(pcrc.Value).Reverse().ToArray(),
#if NET8_0_OR_GREATER
Shake128 s128 => s128.GetCurrentHash(32),
Shake256 s256 => s256.GetCurrentHash(64),
#endif
_ => null,
};
@@ -71,6 +76,11 @@ namespace SabreTools.Hashing
/// <remarks>May be either a HashAlgorithm or NonCryptographicHashAlgorithm</remarks>
private object? _hasher;
/// <summary>
/// Non-reversed CRC-64 polynomial
/// </summary>
private const ulong CRC64_ECMA_POLY_NORMAL = 0x42F0E1EBA9EA3693;
#endregion
#region Constructors
@@ -92,17 +102,44 @@ namespace SabreTools.Hashing
{
_hasher = HashType switch
{
HashType.Adler32 => new Adler32Context(),
#if NET7_0_OR_GREATER
HashType.BLAKE3 => new Blake3HashAlgorithm(),
#endif
HashType.CRC16_CCITT => new CRC16CcittContext(),
HashType.CRC16_IBM => new CRC16IbmContext(),
#if NET462_OR_GREATER || NETCOREAPP
HashType.CRC32 => new Crc32(),
#else
HashType.CRC32 => new Crc32Context(),
#endif
HashType.CRC32_ISO => new Crc32Context(),
HashType.CRC32_Naive => new NaiveCRC(),
HashType.CRC32_Optimized => new OptimizedCRC(),
HashType.CRC32_Parallel => new ParallelCRC(),
#if NET462_OR_GREATER || NETCOREAPP
HashType.CRC64 => new Crc64(),
#else
HashType.CRC32 => new OptimizedCRC.OptimizedCRC(),
HashType.CRC64 => new Crc64Context(CRC64_ECMA_POLY_NORMAL, 0xFFFFFFFFFFFFFFFF),
#endif
HashType.CRC64_Reversed => new Crc64Context(),
HashType.Fletcher16 => new Fletcher16Context(),
HashType.Fletcher32 => new Fletcher32Context(),
HashType.MD5 => MD5.Create(),
#if NETFRAMEWORK
HashType.RIPEMD160 => RIPEMD160.Create(),
#endif
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(),
#if NET462_OR_GREATER || NETCOREAPP
HashType.XxHash32 => new XxHash32(),
@@ -141,15 +178,35 @@ namespace SabreTools.Hashing
ic.Update(icBuffer);
break;
case NaiveCRC nc:
nc.Update(buffer, offset, size);
break;
#if NET462_OR_GREATER || NETCOREAPP
case NonCryptographicHashAlgorithm ncha:
var nchaBufferSpan = new ReadOnlySpan<byte>(buffer, offset, size);
ncha.Append(nchaBufferSpan);
break;
#else
case OptimizedCRC.OptimizedCRC oc:
#endif
case OptimizedCRC oc:
oc.Update(buffer, offset, size);
break;
case ParallelCRC pc:
pc.Update(buffer, offset, size);
break;
#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
}
}
@@ -157,7 +214,7 @@ namespace SabreTools.Hashing
/// <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,11 +224,17 @@ namespace SabreTools.Hashing
ha.TransformFinalBlock(emptyBuffer, 0, 0);
break;
#if NET20_OR_GREATER || NETCOREAPP3_1 || NET5_0
case OptimizedCRC.OptimizedCRC oc:
case NaiveCRC nc:
nc.Update([], 0, 0);
break;
case OptimizedCRC oc:
oc.Update([], 0, 0);
break;
#endif
case ParallelCRC pc:
pc.Update([], 0, 0);
break;
}
}

View File

@@ -10,7 +10,8 @@
<Nullable>enable</Nullable>
<SuppressTfmSupportBuildWarnings>true</SuppressTfmSupportBuildWarnings>
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
<Version>1.1.2</Version>
<Version>1.2.2</Version>
<WarningsNotAsErrors>NU5104</WarningsNotAsErrors>
<!-- Package Properties -->
<Authors>Matt Nadareski</Authors>
@@ -28,6 +29,9 @@
</ItemGroup>
<!-- 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" />
@@ -39,5 +43,12 @@
<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`))">
<PackageReference Include="Blake3" Version="1.1.0" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Aaru.Checksums.Native" Version="6.0.0-alpha9"/>
</ItemGroup>
</Project>

View File

@@ -0,0 +1,524 @@
namespace SabreTools.Hashing.Tiger
{
/// <summary>
/// Tiger S boxes
/// </summary>
public static class SBoxes
{
public static readonly ulong[] Table =
[
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 */
];
}
}

View File

@@ -0,0 +1,185 @@
using System;
using System.Linq;
namespace SabreTools.Hashing.Tiger
{
/// <summary>
/// Reference implementation of the Tiger hash
/// </summary>
/// <see href="https://biham.cs.technion.ac.il/Reports/Tiger/"/>
public class TigerHash
{
/// <summary>
/// The number of passes of the hash function.
/// Three passes are recommended.
/// Use four passes when you need extra security.
/// Must be at least three.
/// </summary>
private const int PASSES = 3;
public void tiger(ulong[] str, ulong length)
{
ulong i, j;
byte[] temp = new byte[64];
ulong[] res =
[
0x0123456789ABCDEF,
0xFEDCBA9876543210,
0xF096A5B4C3B2E187
];
int strOffset = 0;
for (i = length; i >= 64; i -= 64)
{
Compress(str, strOffset, res);
strOffset += 8;
}
byte[] strBytes = new byte[str.Length * 8];
Array.ConstrainedCopy(str, 0, strBytes, 0, str.Length);
for (j = 0; j < i; j++)
{
temp[j] = strBytes[j];
}
temp[j++] = 0x01;
for (; (j & 7) > 0; j++)
{
temp[j] = 0;
}
if (j > 56)
{
for (; j < 64; j++)
{
temp[j] = 0;
}
Compress(ref temp, 0, res);
j = 0;
}
for (; j < 56; j++)
{
temp[j] = 0;
}
Compress(ref temp, 0, res, true, length);
}
private static bool Compress(ref byte[] str, int strOffset, ulong[] state, bool shouldSetSeven = false, ulong length = 0)
{
// Create the temp array
ulong[] temp = new ulong[str.Length / 8];
Array.ConstrainedCopy(str, 0, temp, 0, str.Length);
// Set index 7, if required
if (shouldSetSeven)
temp[7] = length << 3;
// Run the compression
bool success = Compress(temp, strOffset, state);
// Copy the values back
Array.ConstrainedCopy(temp, 0, str, 0, temp.Length);
return success;
}
private static bool Compress(ulong[] str, int strOffset, ulong[] state)
{
// Bounds checking
if (state.Length != 3)
return false;
if (str.Length < strOffset + 8)
return false;
ulong[] x = str.Skip(strOffset).Take(8).ToArray();
// save_abc
ulong aa = state[0];
ulong bb = state[1];
ulong cc = state[2];
for (int pass_no = 0; pass_no < PASSES; pass_no++)
{
if (pass_no != 0)
KeySchedule(x);
int mul = pass_no == 0 ? 5 : pass_no == 1 ? 7 : 9;
Pass(state, x, mul);
ulong temp = state[0]; state[0] = state[2]; state[2] = state[1]; state[1] = temp;
}
// feedforward
state[0] ^= aa;
state[1] -= bb;
state[2] += cc;
return true;
}
private static void KeySchedule(ulong[] x)
{
x[0] -= x[7] ^ 0xA5A5A5A5A5A5A5A5;
x[1] ^= x[0];
x[2] += x[1];
x[3] -= x[2] ^ ((~x[1]) << 19);
x[4] ^= x[3];
x[5] += x[4];
x[6] -= x[5] ^ ((~x[4]) >> 23);
x[7] ^= x[6];
x[0] += x[7];
x[1] -= x[0] ^ ((~x[7]) << 19);
x[2] ^= x[1];
x[3] += x[2];
x[4] -= x[3] ^ ((~x[2]) >> 23);
x[5] ^= x[4];
x[6] += x[5];
x[7] -= x[6] ^ 0x0123456789ABCDEF;
}
private static bool Pass(ulong[] state, ulong[] x, int mul)
{
// Bounds checking
if (state.Length != 3)
return false;
Round(state, 0, 1, 2, x[0], mul);
Round(state, 1, 2, 0, x[1], mul);
Round(state, 2, 0, 1, x[2], mul);
Round(state, 0, 1, 2, x[3], mul);
Round(state, 1, 2, 0, x[4], mul);
Round(state, 2, 0, 1, x[5], mul);
Round(state, 0, 1, 2, x[6], mul);
Round(state, 1, 2, 0, x[7], mul);
return true;
}
private static bool Round(ulong[] state, int a, int b, int c, ulong x, int mul)
{
// Bounds checking
if (state.Length != 3)
return false;
state[c] ^= x;
state[a] -= t1((byte)state[c])
^ t2((byte)(((uint)state[c]) >> (2 * 8)))
^ t3((byte)((state[c]) >> (4 * 8)))
^ t4((byte)(((uint)((state[c]) >> (4 * 8))) >> (2 * 8)));
state[b] += t4((byte)(((uint)state[c]) >> (1 * 8)))
^ t3((byte)(((uint)state[c]) >> (3 * 8)))
^ t2((byte)(((uint)((state[c]) >> (4 * 8))) >> (1 * 8)))
^ t1((byte)(((uint)((state[c]) >> (4 * 8))) >> (3 * 8)));
state[b] *= (ulong)mul;
return true;
}
private static ulong t1(int offset) => SBoxes.Table[offset];
private static ulong t2(int offset) => SBoxes.Table[offset + 256];
private static ulong t3(int offset) => SBoxes.Table[offset + 256 * 2];
private static ulong t4(int offset) => SBoxes.Table[offset + 256 * 3];
}
}

36
publish-nix.sh Normal file
View File

@@ -0,0 +1,36 @@
#! /bin/bash
# This batch file assumes the following:
# - .NET 8.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 "uba" 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
View File

@@ -0,0 +1,26 @@
# This batch file assumes the following:
# - .NET 8.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
}