From ebdb8de6b39dca7195122519b80a28f3ca023da7 Mon Sep 17 00:00:00 2001 From: Matt Nadareski Date: Wed, 4 Oct 2023 16:37:33 -0400 Subject: [PATCH] Use System.IO.Hashing for CRC32 --- CHANGELIST.md | 1 + MPF.Core/Hashing/Hasher.cs | 28 +++--- MPF.Core/Hashing/OptimizedCRC.cs | 154 ------------------------------- MPF.Core/MPF.Core.csproj | 1 + MPF.Modules/BaseParameters.cs | 4 +- 5 files changed, 19 insertions(+), 169 deletions(-) delete mode 100644 MPF.Core/Hashing/OptimizedCRC.cs diff --git a/CHANGELIST.md b/CHANGELIST.md index 04f042cd..0590cb94 100644 --- a/CHANGELIST.md +++ b/CHANGELIST.md @@ -7,6 +7,7 @@ - Job number not build ID - Fix errant space in variable name - Build number not job number +- Use System.IO.Hashing for CRC32 ### 2.6.6 (2023-10-04) diff --git a/MPF.Core/Hashing/Hasher.cs b/MPF.Core/Hashing/Hasher.cs index d5bd35c4..182f7bfa 100644 --- a/MPF.Core/Hashing/Hasher.cs +++ b/MPF.Core/Hashing/Hasher.cs @@ -1,4 +1,5 @@ using System; +using System.IO.Hashing; using System.Linq; using System.Security.Cryptography; @@ -10,7 +11,7 @@ namespace MPF.Core.Hashing [Flags] public enum Hash { - CRC = 1 << 0, + CRC32 = 1 << 0, MD5 = 1 << 1, SHA1 = 1 << 2, SHA256 = 1 << 3, @@ -18,8 +19,8 @@ namespace MPF.Core.Hashing SHA512 = 1 << 5, // Special combinations - Standard = CRC | MD5 | SHA1, - All = CRC | MD5 | SHA1 | SHA256 | SHA384 | SHA512, + Standard = CRC32 | MD5 | SHA1, + All = CRC32 | MD5 | SHA1 | SHA256 | SHA384 | SHA512, } /// @@ -28,7 +29,7 @@ namespace MPF.Core.Hashing public class Hasher { public Hash HashType { get; private set; } - private IDisposable _hasher; + private object _hasher; public Hasher(Hash hashType) { @@ -43,8 +44,8 @@ namespace MPF.Core.Hashing { switch (HashType) { - case Hash.CRC: - _hasher = new OptimizedCRC(); + case Hash.CRC32: + _hasher = new Crc32(); break; case Hash.MD5: @@ -71,7 +72,8 @@ namespace MPF.Core.Hashing public void Dispose() { - _hasher.Dispose(); + if (_hasher is IDisposable disposable) + disposable.Dispose(); } /// @@ -81,8 +83,8 @@ namespace MPF.Core.Hashing { switch (HashType) { - case Hash.CRC: - (_hasher as OptimizedCRC).Update(buffer, 0, size); + case Hash.CRC32: + (_hasher as NonCryptographicHashAlgorithm).Append(buffer); break; case Hash.MD5: @@ -103,8 +105,8 @@ namespace MPF.Core.Hashing byte[] emptyBuffer = new byte[0]; switch (HashType) { - case Hash.CRC: - (_hasher as OptimizedCRC).Update(emptyBuffer, 0, 0); + case Hash.CRC32: + (_hasher as NonCryptographicHashAlgorithm).Append(emptyBuffer); break; case Hash.MD5: @@ -124,8 +126,8 @@ namespace MPF.Core.Hashing { switch (HashType) { - case Hash.CRC: - return BitConverter.GetBytes((_hasher as OptimizedCRC).Value).Reverse().ToArray(); + case Hash.CRC32: + return (_hasher as NonCryptographicHashAlgorithm).GetCurrentHash().Reverse().ToArray(); case Hash.MD5: case Hash.SHA1: diff --git a/MPF.Core/Hashing/OptimizedCRC.cs b/MPF.Core/Hashing/OptimizedCRC.cs deleted file mode 100644 index 1e3e7a6a..00000000 --- a/MPF.Core/Hashing/OptimizedCRC.cs +++ /dev/null @@ -1,154 +0,0 @@ -/* - - Copyright (c) 2012-2015 Eugene Larchenko (spct@mail.ru) - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - THE SOFTWARE. - -*/ - -using System; - -//namespace OptimizedCRC -namespace MPF.Core.Hashing -{ - internal class OptimizedCRC : IDisposable - { - private const uint kCrcPoly = 0xEDB88320; - private const uint kInitial = 0xFFFFFFFF; - private const int CRC_NUM_TABLES = 8; - private static readonly uint[] Table; - - static OptimizedCRC() - { - unchecked - { - Table = new uint[256 * CRC_NUM_TABLES]; - int i; - for (i = 0; i < 256; i++) - { - uint r = (uint)i; - for (int j = 0; j < 8; j++) - { - r = (r >> 1) ^ (kCrcPoly & ~((r & 1) - 1)); - } - Table[i] = r; - } - for (; i < 256 * CRC_NUM_TABLES; i++) - { - uint r = Table[i - 256]; - Table[i] = Table[r & 0xFF] ^ (r >> 8); - } - } - } - - public uint UnsignedValue; - - public OptimizedCRC() - { - Init(); - } - - /// - /// Reset CRC - /// - public void Init() - { - UnsignedValue = kInitial; - } - - public int Value - { - get { return (int)~UnsignedValue; } - } - - public void Update(byte[] data, int offset, int count) - { - new ArraySegment(data, offset, count); // check arguments - if (count == 0) - { - return; - } - - var table = OptimizedCRC.Table; - - uint crc = UnsignedValue; - - for (; (offset & 7) != 0 && count != 0; count--) - { - crc = (crc >> 8) ^ table[(byte)crc ^ data[offset++]]; - } - - if (count >= 8) - { - /* - * Idea from 7-zip project sources (http://7-zip.org/sdk.html) - */ - - int end = (count - 8) & ~7; - count -= end; - end += offset; - - while (offset != end) - { - crc ^= (uint)(data[offset] + (data[offset + 1] << 8) + (data[offset + 2] << 16) + (data[offset + 3] << 24)); - uint high = (uint)(data[offset + 4] + (data[offset + 5] << 8) + (data[offset + 6] << 16) + (data[offset + 7] << 24)); - offset += 8; - - crc = table[(byte)crc + 0x700] - ^ table[(byte)(crc >>= 8) + 0x600] - ^ table[(byte)(crc >>= 8) + 0x500] - ^ table[/*(byte)*/(crc >> 8) + 0x400] - ^ table[(byte)(high) + 0x300] - ^ table[(byte)(high >>= 8) + 0x200] - ^ table[(byte)(high >>= 8) + 0x100] - ^ table[/*(byte)*/(high >> 8) + 0x000]; - } - } - - while (count-- != 0) - { - crc = (crc >> 8) ^ table[(byte)crc ^ data[offset++]]; - } - - UnsignedValue = crc; - } - - static public int Compute(byte[] data, int offset, int count) - { - var crc = new OptimizedCRC(); - crc.Update(data, offset, count); - return crc.Value; - } - - static public int Compute(byte[] data) - { - return Compute(data, 0, data.Length); - } - - static public int Compute(ArraySegment block) - { - return Compute(block.Array, block.Offset, block.Count); - } - - public void Dispose() - { - UnsignedValue = 0; - } - } -} \ No newline at end of file diff --git a/MPF.Core/MPF.Core.csproj b/MPF.Core/MPF.Core.csproj index ed67d6e4..955cef51 100644 --- a/MPF.Core/MPF.Core.csproj +++ b/MPF.Core/MPF.Core.csproj @@ -36,6 +36,7 @@ + diff --git a/MPF.Modules/BaseParameters.cs b/MPF.Modules/BaseParameters.cs index eec435ea..55663234 100644 --- a/MPF.Modules/BaseParameters.cs +++ b/MPF.Modules/BaseParameters.cs @@ -1204,7 +1204,7 @@ namespace MPF.Modules // Get a list of hashers to run over the buffer var hashers = new List { - new Hasher(Hash.CRC), + new Hasher(Hash.CRC32), new Hasher(Hash.MD5), new Hasher(Hash.SHA1), new Hasher(Hash.SHA256), @@ -1261,7 +1261,7 @@ namespace MPF.Modules Parallel.ForEach(hashers, h => h.Terminate()); // Get the results - crc32 = hashers.First(h => h.HashType == Hash.CRC).GetHashString(); + crc32 = hashers.First(h => h.HashType == Hash.CRC32).GetHashString(); md5 = hashers.First(h => h.HashType == Hash.MD5).GetHashString(); sha1 = hashers.First(h => h.HashType == Hash.SHA1).GetHashString(); //sha256 = hashers.First(h => h.HashType == Hash.SHA256).GetHashString();