From 8400308a985550a93b77ed0ae2a91f21b05fe5ec Mon Sep 17 00:00:00 2001 From: Natalia Portillo Date: Sat, 11 Jan 2020 22:42:25 +0000 Subject: [PATCH] Move DiscImageChef.Checksums to a separate repository. --- .gitmodules | 3 + DiscImageChef.Checksums | 1 + DiscImageChef.Checksums/Adler32Context.cs | 178 ----- DiscImageChef.Checksums/CDChecksums.cs | 611 ----------------- DiscImageChef.Checksums/CRC16CCITTContext.cs | 63 -- DiscImageChef.Checksums/CRC16Context.cs | 226 ------- DiscImageChef.Checksums/CRC16IBMContext.cs | 64 -- DiscImageChef.Checksums/CRC32Context.cs | 237 ------- DiscImageChef.Checksums/CRC64Context.cs | 237 ------- .../DiscImageChef.Checksums.csproj | 120 ---- DiscImageChef.Checksums/FletcherContext.cs | 320 --------- DiscImageChef.Checksums/MD5Context.cs | 152 ----- DiscImageChef.Checksums/ReedSolomon.cs | 625 ------------------ DiscImageChef.Checksums/Register.cs | 71 -- DiscImageChef.Checksums/SHA1Context.cs | 152 ----- DiscImageChef.Checksums/SHA256Context.cs | 152 ----- DiscImageChef.Checksums/SHA384Context.cs | 152 ----- DiscImageChef.Checksums/SHA512Context.cs | 152 ----- DiscImageChef.Checksums/SpamSumContext.cs | 484 -------------- 19 files changed, 4 insertions(+), 3996 deletions(-) create mode 160000 DiscImageChef.Checksums delete mode 100644 DiscImageChef.Checksums/Adler32Context.cs delete mode 100644 DiscImageChef.Checksums/CDChecksums.cs delete mode 100644 DiscImageChef.Checksums/CRC16CCITTContext.cs delete mode 100644 DiscImageChef.Checksums/CRC16Context.cs delete mode 100644 DiscImageChef.Checksums/CRC16IBMContext.cs delete mode 100644 DiscImageChef.Checksums/CRC32Context.cs delete mode 100644 DiscImageChef.Checksums/CRC64Context.cs delete mode 100644 DiscImageChef.Checksums/DiscImageChef.Checksums.csproj delete mode 100644 DiscImageChef.Checksums/FletcherContext.cs delete mode 100644 DiscImageChef.Checksums/MD5Context.cs delete mode 100644 DiscImageChef.Checksums/ReedSolomon.cs delete mode 100644 DiscImageChef.Checksums/Register.cs delete mode 100644 DiscImageChef.Checksums/SHA1Context.cs delete mode 100644 DiscImageChef.Checksums/SHA256Context.cs delete mode 100644 DiscImageChef.Checksums/SHA384Context.cs delete mode 100644 DiscImageChef.Checksums/SHA512Context.cs delete mode 100644 DiscImageChef.Checksums/SpamSumContext.cs diff --git a/.gitmodules b/.gitmodules index 106f564fc..b692f2fe3 100644 --- a/.gitmodules +++ b/.gitmodules @@ -19,3 +19,6 @@ [submodule "DiscImageChef.Helpers"] path = DiscImageChef.Helpers url = https://github.com/discimagechef/DiscImageChef.Helpers.git +[submodule "DiscImageChef.Checksums"] + path = DiscImageChef.Checksums + url = https://github.com/discimagechef/DiscImageChef.Checksums.git diff --git a/DiscImageChef.Checksums b/DiscImageChef.Checksums new file mode 160000 index 000000000..b06fb9ec7 --- /dev/null +++ b/DiscImageChef.Checksums @@ -0,0 +1 @@ +Subproject commit b06fb9ec7b5bcc953ac21784b60812a170252f84 diff --git a/DiscImageChef.Checksums/Adler32Context.cs b/DiscImageChef.Checksums/Adler32Context.cs deleted file mode 100644 index 6ab855f81..000000000 --- a/DiscImageChef.Checksums/Adler32Context.cs +++ /dev/null @@ -1,178 +0,0 @@ -// /*************************************************************************** -// The Disc Image Chef -// ---------------------------------------------------------------------------- -// -// Filename : Adler32Context.cs -// Author(s) : Natalia Portillo -// -// Component : Checksums. -// -// --[ Description ] ---------------------------------------------------------- -// -// Implements an Adler-32 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 . -// -// ---------------------------------------------------------------------------- -// Copyright © 2011-2020 Natalia Portillo -// ****************************************************************************/ - -using System.IO; -using System.Text; -using DiscImageChef.CommonTypes.Interfaces; - -namespace DiscImageChef.Checksums -{ - /// - /// Implements the Adler-32 algorithm - /// - public class Adler32Context : IChecksum - { - const ushort ADLER_MODULE = 65521; - ushort sum1, sum2; - - /// - /// Initializes the Adler-32 sums - /// - public Adler32Context() - { - sum1 = 1; - sum2 = 0; - } - - /// - /// Updates the hash with data. - /// - /// Data buffer. - /// Length of buffer to hash. - public void Update(byte[] data, uint len) - { - for(int i = 0; i < len; i++) - { - sum1 = (ushort)((sum1 + data[i]) % ADLER_MODULE); - sum2 = (ushort)((sum2 + sum1) % ADLER_MODULE); - } - } - - /// - /// Updates the hash with data. - /// - /// Data buffer. - public void Update(byte[] data) - { - Update(data, (uint)data.Length); - } - - /// - /// Returns a byte array of the hash value. - /// - public byte[] Final() - { - uint finalSum = (uint)((sum2 << 16) | sum1); - return BigEndianBitConverter.GetBytes(finalSum); - } - - /// - /// Returns a hexadecimal representation of the hash value. - /// - public string End() - { - uint finalSum = (uint)((sum2 << 16) | sum1); - StringBuilder adlerOutput = new StringBuilder(); - - for(int i = 0; i < BigEndianBitConverter.GetBytes(finalSum).Length; i++) - adlerOutput.Append(BigEndianBitConverter.GetBytes(finalSum)[i].ToString("x2")); - - return adlerOutput.ToString(); - } - - /// - /// Gets the hash of a file - /// - /// File path. - public static byte[] File(string filename) - { - File(filename, out byte[] hash); - return hash; - } - - /// - /// Gets the hash of a file in hexadecimal and as a byte array. - /// - /// File path. - /// Byte array of the hash value. - public static string File(string filename, out byte[] hash) - { - FileStream fileStream = new FileStream(filename, FileMode.Open); - - ushort localSum1 = 1; - ushort localSum2 = 0; - - for(int i = 0; i < fileStream.Length; i++) - { - localSum1 = (ushort)((localSum1 + fileStream.ReadByte()) % ADLER_MODULE); - localSum2 = (ushort)((localSum2 + localSum1) % ADLER_MODULE); - } - - uint finalSum = (uint)((localSum2 << 16) | localSum1); - - hash = BigEndianBitConverter.GetBytes(finalSum); - - StringBuilder adlerOutput = new StringBuilder(); - - foreach(byte h in hash) adlerOutput.Append(h.ToString("x2")); - - fileStream.Close(); - - return adlerOutput.ToString(); - } - - /// - /// Gets the hash of the specified data buffer. - /// - /// Data buffer. - /// Length of the data buffer to hash. - /// Byte array of the hash value. - public static string Data(byte[] data, uint len, out byte[] hash) - { - ushort localSum1 = 1; - ushort localSum2 = 0; - - for(int i = 0; i < len; i++) - { - localSum1 = (ushort)((localSum1 + data[i]) % ADLER_MODULE); - localSum2 = (ushort)((localSum2 + localSum1) % ADLER_MODULE); - } - - uint finalSum = (uint)((localSum2 << 16) | localSum1); - - hash = BigEndianBitConverter.GetBytes(finalSum); - - StringBuilder adlerOutput = new StringBuilder(); - - foreach(byte h in hash) adlerOutput.Append(h.ToString("x2")); - - return adlerOutput.ToString(); - } - - /// - /// Gets the hash of the specified data buffer. - /// - /// Data buffer. - /// Byte array of the hash value. - public static string Data(byte[] data, out byte[] hash) => Data(data, (uint)data.Length, out hash); - } -} \ No newline at end of file diff --git a/DiscImageChef.Checksums/CDChecksums.cs b/DiscImageChef.Checksums/CDChecksums.cs deleted file mode 100644 index fb776502c..000000000 --- a/DiscImageChef.Checksums/CDChecksums.cs +++ /dev/null @@ -1,611 +0,0 @@ -// /*************************************************************************** -// The Disc Image Chef -// ---------------------------------------------------------------------------- -// -// Filename : CDChecksums.cs -// Author(s) : Natalia Portillo -// -// Component : Checksums. -// -// --[ Description ] ---------------------------------------------------------- -// -// Implements CD checksums. -// -// --[ License ] -------------------------------------------------------------- -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This program 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 General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program.If not, see. -// -// ---------------------------------------------------------------------------- -// Copyright © 2011-2020 Natalia Portillo -// ECC algorithm from ECM(c) 2002-2011 Neill Corlett -// ****************************************************************************/ - -using System; -using System.Collections.Generic; -using DiscImageChef.Console; - -namespace DiscImageChef.Checksums -{ - /// Implements ReedSolomon and CRC32 algorithms as used by CD-ROM - public static class CdChecksums - { - static byte[] eccFTable; - static byte[] eccBTable; - static uint[] edcTable; - - public static bool? CheckCdSector(byte[] buffer) - { - switch(buffer.Length) - { - case 2448: - { - byte[] subchannel = new byte[96]; - byte[] channel = new byte[2352]; - - Array.Copy(buffer, 0, channel, 0, 2352); - Array.Copy(buffer, 2352, subchannel, 0, 96); - - bool? channelStatus = CheckCdSectorChannel(channel); - bool? subchannelStatus = CheckCdSectorSubChannel(subchannel); - bool? status = null; - - if(channelStatus == false || - subchannelStatus == false) - status = false; - - switch(channelStatus) - { - case null when subchannelStatus == true: - status = true; - - break; - case true when subchannelStatus == null: - status = true; - - break; - } - - return status; - } - - case 2352: return CheckCdSectorChannel(buffer); - default: return null; - } - } - - static void EccInit() - { - eccFTable = new byte[256]; - eccBTable = new byte[256]; - edcTable = new uint[256]; - - for(uint i = 0; i < 256; i++) - { - uint edc = i; - uint j = (uint)((i << 1) ^ ((i & 0x80) == 0x80 ? 0x11D : 0)); - eccFTable[i] = (byte)j; - eccBTable[i ^ j] = (byte)i; - - for(j = 0; j < 8; j++) - edc = (edc >> 1) ^ ((edc & 1) > 0 ? 0xD8018001 : 0); - - edcTable[i] = edc; - } - } - - static bool CheckEcc(byte[] address, byte[] data, uint majorCount, uint minorCount, uint majorMult, - uint minorInc, byte[] ecc) - { - uint size = majorCount * minorCount; - uint major; - - for(major = 0; major < majorCount; major++) - { - uint index = ((major >> 1) * majorMult) + (major & 1); - byte eccA = 0; - byte eccB = 0; - uint minor; - - for(minor = 0; minor < minorCount; minor++) - { - byte temp = index < 4 ? address[index] : data[index - 4]; - index += minorInc; - - if(index >= size) - index -= size; - - eccA ^= temp; - eccB ^= temp; - eccA = eccFTable[eccA]; - } - - eccA = eccBTable[eccFTable[eccA] ^ eccB]; - - if(ecc[major] != eccA || - ecc[major + majorCount] != (eccA ^ eccB)) - return false; - } - - return true; - } - - static bool? CheckCdSectorChannel(byte[] channel) - { - EccInit(); - - if(channel[0x000] != 0x00 || - channel[0x001] != 0xFF || - channel[0x002] != 0xFF || - channel[0x003] != 0xFF || - channel[0x004] != 0xFF || - channel[0x005] != 0xFF || - channel[0x006] != 0xFF || - channel[0x007] != 0xFF || - channel[0x008] != 0xFF || - channel[0x009] != 0xFF || - channel[0x00A] != 0xFF || - channel[0x00B] != 0x00) - return null; - - //DicConsole.DebugWriteLine("CD checksums", "Data sector, address {0:X2}:{1:X2}:{2:X2}", channel[0x00C], - // channel[0x00D], channel[0x00E]); - - if(channel[0x00F] == 0x00) // mode (1 byte) - { - //DicConsole.DebugWriteLine("CD checksums", "Mode 0 sector at address {0:X2}:{1:X2}:{2:X2}", - // channel[0x00C], channel[0x00D], channel[0x00E]); - for(int i = 0x010; i < 0x930; i++) - if(channel[i] != 0x00) - { - DicConsole.DebugWriteLine("CD checksums", - "Mode 0 sector with error at address: {0:X2}:{1:X2}:{2:X2}", - channel[0x00C], channel[0x00D], channel[0x00E]); - - return false; - } - - return true; - } - - if(channel[0x00F] == 0x01) // mode (1 byte) - { - //DicConsole.DebugWriteLine("CD checksums", "Mode 1 sector at address {0:X2}:{1:X2}:{2:X2}", - // channel[0x00C], channel[0x00D], channel[0x00E]); - - if(channel[0x814] != 0x00 || // reserved (8 bytes) - channel[0x815] != 0x00 || - channel[0x816] != 0x00 || - channel[0x817] != 0x00 || - channel[0x818] != 0x00 || - channel[0x819] != 0x00 || - channel[0x81A] != 0x00 || - channel[0x81B] != 0x00) - { - DicConsole.DebugWriteLine("CD checksums", - "Mode 1 sector with data in reserved bytes at address: {0:X2}:{1:X2}:{2:X2}", - channel[0x00C], channel[0x00D], channel[0x00E]); - - return false; - } - - byte[] address = new byte[4]; - byte[] data = new byte[2060]; - byte[] data2 = new byte[2232]; - byte[] eccP = new byte[172]; - byte[] eccQ = new byte[104]; - - Array.Copy(channel, 0x0C, address, 0, 4); - Array.Copy(channel, 0x10, data, 0, 2060); - Array.Copy(channel, 0x10, data2, 0, 2232); - Array.Copy(channel, 0x81C, eccP, 0, 172); - Array.Copy(channel, 0x8C8, eccQ, 0, 104); - - bool failedEccP = !CheckEcc(address, data, 86, 24, 2, 86, eccP); - bool failedEccQ = !CheckEcc(address, data2, 52, 43, 86, 88, eccQ); - - if(failedEccP) - DicConsole.DebugWriteLine("CD checksums", - "Mode 1 sector at address: {0:X2}:{1:X2}:{2:X2}, fails ECC P check", - channel[0x00C], channel[0x00D], channel[0x00E]); - - if(failedEccQ) - DicConsole.DebugWriteLine("CD checksums", - "Mode 1 sector at address: {0:X2}:{1:X2}:{2:X2}, fails ECC Q check", - channel[0x00C], channel[0x00D], channel[0x00E]); - - uint storedEdc = BitConverter.ToUInt32(channel, 0x810); - uint calculatedEdc = ComputeEdc(0, channel, 0x810); - - if(calculatedEdc == storedEdc) - return!failedEccP && !failedEccQ; - - DicConsole.DebugWriteLine("CD checksums", - "Mode 1 sector at address: {0:X2}:{1:X2}:{2:X2}, got CRC 0x{3:X8} expected 0x{4:X8}", - channel[0x00C], channel[0x00D], channel[0x00E], calculatedEdc, storedEdc); - - return false; - } - - if(channel[0x00F] == 0x02) // mode (1 byte) - { - //DicConsole.DebugWriteLine("CD checksums", "Mode 2 sector at address {0:X2}:{1:X2}:{2:X2}", - // channel[0x00C], channel[0x00D], channel[0x00E]); - byte[] mode2Sector = new byte[channel.Length - 0x10]; - Array.Copy(channel, 0x10, mode2Sector, 0, mode2Sector.Length); - - if((channel[0x012] & 0x20) == 0x20) // mode 2 form 2 - { - if(channel[0x010] != channel[0x014] || - channel[0x011] != channel[0x015] || - channel[0x012] != channel[0x016] || - channel[0x013] != channel[0x017]) - DicConsole.DebugWriteLine("CD checksums", - "Subheader copies differ in mode 2 form 2 sector at address: {0:X2}:{1:X2}:{2:X2}", - channel[0x00C], channel[0x00D], channel[0x00E]); - - uint storedEdc = BitConverter.ToUInt32(mode2Sector, 0x91C); - - // No CRC stored! - if(storedEdc == 0x00000000) - return true; - - uint calculatedEdc = ComputeEdc(0, mode2Sector, 0x91C); - - if(calculatedEdc == storedEdc || - storedEdc == 0x00000000) - return true; - - DicConsole.DebugWriteLine("CD checksums", - "Mode 2 form 2 sector at address: {0:X2}:{1:X2}:{2:X2}, got CRC 0x{3:X8} expected 0x{4:X8}", - channel[0x00C], channel[0x00D], channel[0x00E], calculatedEdc, storedEdc); - - return false; - } - else - { - if(channel[0x010] != channel[0x014] || - channel[0x011] != channel[0x015] || - channel[0x012] != channel[0x016] || - channel[0x013] != channel[0x017]) - DicConsole.DebugWriteLine("CD checksums", - "Subheader copies differ in mode 2 form 1 sector at address: {0:X2}:{1:X2}:{2:X2}", - channel[0x00C], channel[0x00D], channel[0x00E]); - - byte[] address = new byte[4]; - byte[] eccP = new byte[172]; - byte[] eccQ = new byte[104]; - - Array.Copy(mode2Sector, 0x80C, eccP, 0, 172); - Array.Copy(mode2Sector, 0x8B8, eccQ, 0, 104); - - bool failedEccP = !CheckEcc(address, mode2Sector, 86, 24, 2, 86, eccP); - bool failedEccQ = !CheckEcc(address, mode2Sector, 52, 43, 86, 88, eccQ); - - if(failedEccP) - DicConsole.DebugWriteLine("CD checksums", - "Mode 2 form 1 sector at address: {0:X2}:{1:X2}:{2:X2}, fails ECC P check", - channel[0x00C], channel[0x00D], channel[0x00E]); - - if(failedEccQ) - DicConsole.DebugWriteLine("CD checksums", - "Mode 2 form 1 sector at address: {0:X2}:{1:X2}:{2:X2}, fails ECC Q check", - channel[0x00C], channel[0x00D], channel[0x00E]); - - uint storedEdc = BitConverter.ToUInt32(mode2Sector, 0x808); - uint calculatedEdc = ComputeEdc(0, mode2Sector, 0x808); - - if(calculatedEdc == storedEdc) - return!failedEccP && !failedEccQ; - - DicConsole.DebugWriteLine("CD checksums", - "Mode 1 sector at address: {0:X2}:{1:X2}:{2:X2}, got CRC 0x{3:X8} expected 0x{4:X8}", - channel[0x00C], channel[0x00D], channel[0x00E], calculatedEdc, storedEdc); - - return false; - } - } - - DicConsole.DebugWriteLine("CD checksums", "Unknown mode {0} sector at address: {1:X2}:{2:X2}:{3:X2}", - channel[0x00F], channel[0x00C], channel[0x00D], channel[0x00E]); - - return null; - } - - static uint ComputeEdc(uint edc, IReadOnlyList src, int size) - { - int pos = 0; - - for(; size > 0; size--) - edc = (edc >> 8) ^ edcTable[(edc ^ src[pos++]) & 0xFF]; - - return edc; - } - - static bool? CheckCdSectorSubChannel(IReadOnlyList subchannel) - { - bool? status = true; - byte[] qSubChannel = new byte[12]; - byte[] cdTextPack1 = new byte[18]; - byte[] cdTextPack2 = new byte[18]; - byte[] cdTextPack3 = new byte[18]; - byte[] cdTextPack4 = new byte[18]; - byte[] cdSubRwPack1 = new byte[24]; - byte[] cdSubRwPack2 = new byte[24]; - byte[] cdSubRwPack3 = new byte[24]; - byte[] cdSubRwPack4 = new byte[24]; - - int i = 0; - - for(int j = 0; j < 12; j++) - qSubChannel[j] = 0; - - for(int j = 0; j < 18; j++) - { - cdTextPack1[j] = 0; - cdTextPack2[j] = 0; - cdTextPack3[j] = 0; - cdTextPack4[j] = 0; - } - - for(int j = 0; j < 24; j++) - { - cdSubRwPack1[j] = 0; - cdSubRwPack2[j] = 0; - cdSubRwPack3[j] = 0; - cdSubRwPack4[j] = 0; - } - - for(int j = 0; j < 12; j++) - { - qSubChannel[j] = (byte)(qSubChannel[j] | ((subchannel[i++] & 0x40) << 1)); - qSubChannel[j] = (byte)(qSubChannel[j] | (subchannel[i++] & 0x40)); - qSubChannel[j] = (byte)(qSubChannel[j] | ((subchannel[i++] & 0x40) >> 1)); - qSubChannel[j] = (byte)(qSubChannel[j] | ((subchannel[i++] & 0x40) >> 2)); - qSubChannel[j] = (byte)(qSubChannel[j] | ((subchannel[i++] & 0x40) >> 3)); - qSubChannel[j] = (byte)(qSubChannel[j] | ((subchannel[i++] & 0x40) >> 4)); - qSubChannel[j] = (byte)(qSubChannel[j] | ((subchannel[i++] & 0x40) >> 5)); - qSubChannel[j] = (byte)(qSubChannel[j] | ((subchannel[i++] & 0x40) >> 6)); - } - - i = 0; - - for(int j = 0; j < 18; j++) - { - if(j < 18) - cdTextPack1[j] = (byte)(cdTextPack1[j] | ((subchannel[i++] & 0x3F) << 2)); - - if(j < 18) - cdTextPack1[j] = (byte)(cdTextPack1[j++] | ((subchannel[i] & 0xC0) >> 4)); - - if(j < 18) - cdTextPack1[j] = (byte)(cdTextPack1[j] | ((subchannel[i++] & 0x0F) << 4)); - - if(j < 18) - cdTextPack1[j] = (byte)(cdTextPack1[j++] | ((subchannel[i] & 0x3C) >> 2)); - - if(j < 18) - cdTextPack1[j] = (byte)(cdTextPack1[j] | ((subchannel[i++] & 0x03) << 6)); - - if(j < 18) - cdTextPack1[j] = (byte)(cdTextPack1[j] | (subchannel[i++] & 0x3F)); - } - - for(int j = 0; j < 18; j++) - { - if(j < 18) - cdTextPack2[j] = (byte)(cdTextPack2[j] | ((subchannel[i++] & 0x3F) << 2)); - - if(j < 18) - cdTextPack2[j] = (byte)(cdTextPack2[j++] | ((subchannel[i] & 0xC0) >> 4)); - - if(j < 18) - cdTextPack2[j] = (byte)(cdTextPack2[j] | ((subchannel[i++] & 0x0F) << 4)); - - if(j < 18) - cdTextPack2[j] = (byte)(cdTextPack2[j++] | ((subchannel[i] & 0x3C) >> 2)); - - if(j < 18) - cdTextPack2[j] = (byte)(cdTextPack2[j] | ((subchannel[i++] & 0x03) << 6)); - - if(j < 18) - cdTextPack2[j] = (byte)(cdTextPack2[j] | (subchannel[i++] & 0x3F)); - } - - for(int j = 0; j < 18; j++) - { - if(j < 18) - cdTextPack3[j] = (byte)(cdTextPack3[j] | ((subchannel[i++] & 0x3F) << 2)); - - if(j < 18) - cdTextPack3[j] = (byte)(cdTextPack3[j++] | ((subchannel[i] & 0xC0) >> 4)); - - if(j < 18) - cdTextPack3[j] = (byte)(cdTextPack3[j] | ((subchannel[i++] & 0x0F) << 4)); - - if(j < 18) - cdTextPack3[j] = (byte)(cdTextPack3[j++] | ((subchannel[i] & 0x3C) >> 2)); - - if(j < 18) - cdTextPack3[j] = (byte)(cdTextPack3[j] | ((subchannel[i++] & 0x03) << 6)); - - if(j < 18) - cdTextPack3[j] = (byte)(cdTextPack3[j] | (subchannel[i++] & 0x3F)); - } - - for(int j = 0; j < 18; j++) - { - if(j < 18) - cdTextPack4[j] = (byte)(cdTextPack4[j] | ((subchannel[i++] & 0x3F) << 2)); - - if(j < 18) - cdTextPack4[j] = (byte)(cdTextPack4[j++] | ((subchannel[i] & 0xC0) >> 4)); - - if(j < 18) - cdTextPack4[j] = (byte)(cdTextPack4[j] | ((subchannel[i++] & 0x0F) << 4)); - - if(j < 18) - cdTextPack4[j] = (byte)(cdTextPack4[j++] | ((subchannel[i] & 0x3C) >> 2)); - - if(j < 18) - cdTextPack4[j] = (byte)(cdTextPack4[j] | ((subchannel[i++] & 0x03) << 6)); - - if(j < 18) - cdTextPack4[j] = (byte)(cdTextPack4[j] | (subchannel[i++] & 0x3F)); - } - - i = 0; - - for(int j = 0; j < 24; j++) - cdSubRwPack1[j] = (byte)(subchannel[i++] & 0x3F); - - for(int j = 0; j < 24; j++) - cdSubRwPack2[j] = (byte)(subchannel[i++] & 0x3F); - - for(int j = 0; j < 24; j++) - cdSubRwPack3[j] = (byte)(subchannel[i++] & 0x3F); - - for(int j = 0; j < 24; j++) - cdSubRwPack4[j] = (byte)(subchannel[i++] & 0x3F); - - switch(cdSubRwPack1[0]) - { - case 0x00: - DicConsole.DebugWriteLine("CD checksums", "Detected Zero Pack in subchannel"); - - break; - case 0x08: - DicConsole.DebugWriteLine("CD checksums", "Detected Line Graphics Pack in subchannel"); - - break; - case 0x09: - DicConsole.DebugWriteLine("CD checksums", "Detected CD+G Pack in subchannel"); - - break; - case 0x0A: - DicConsole.DebugWriteLine("CD checksums", "Detected CD+EG Pack in subchannel"); - - break; - case 0x14: - DicConsole.DebugWriteLine("CD checksums", "Detected CD-TEXT Pack in subchannel"); - - break; - case 0x18: - DicConsole.DebugWriteLine("CD checksums", "Detected CD+MIDI Pack in subchannel"); - - break; - case 0x38: - DicConsole.DebugWriteLine("CD checksums", "Detected User Pack in subchannel"); - - break; - default: - DicConsole.DebugWriteLine("CD checksums", - "Detected unknown Pack type in subchannel: mode {0}, item {1}", - Convert.ToString(cdSubRwPack1[0] & 0x38, 2), - Convert.ToString(cdSubRwPack1[0] & 0x07, 2)); - - break; - } - - ushort qSubChannelCrc = BigEndianBitConverter.ToUInt16(qSubChannel, 10); - byte[] qSubChannelForCrc = new byte[10]; - Array.Copy(qSubChannel, 0, qSubChannelForCrc, 0, 10); - ushort calculatedQcrc = CRC16CCITTContext.Calculate(qSubChannelForCrc); - - if(qSubChannelCrc != calculatedQcrc) - { - DicConsole.DebugWriteLine("CD checksums", "Q subchannel CRC 0x{0:X4}, expected 0x{1:X4}", - calculatedQcrc, qSubChannelCrc); - - status = false; - } - - if((cdTextPack1[0] & 0x80) == 0x80) - { - ushort cdTextPack1Crc = BigEndianBitConverter.ToUInt16(cdTextPack1, 16); - byte[] cdTextPack1ForCrc = new byte[16]; - Array.Copy(cdTextPack1, 0, cdTextPack1ForCrc, 0, 16); - ushort calculatedCdtp1Crc = CRC16CCITTContext.Calculate(cdTextPack1ForCrc); - - if(cdTextPack1Crc != calculatedCdtp1Crc && - cdTextPack1Crc != 0) - { - DicConsole.DebugWriteLine("CD checksums", "CD-Text Pack 1 CRC 0x{0:X4}, expected 0x{1:X4}", - cdTextPack1Crc, calculatedCdtp1Crc); - - status = false; - } - } - - if((cdTextPack2[0] & 0x80) == 0x80) - { - ushort cdTextPack2Crc = BigEndianBitConverter.ToUInt16(cdTextPack2, 16); - byte[] cdTextPack2ForCrc = new byte[16]; - Array.Copy(cdTextPack2, 0, cdTextPack2ForCrc, 0, 16); - ushort calculatedCdtp2Crc = CRC16CCITTContext.Calculate(cdTextPack2ForCrc); - - DicConsole.DebugWriteLine("CD checksums", "Cyclic CDTP2 0x{0:X4}, Calc CDTP2 0x{1:X4}", cdTextPack2Crc, - calculatedCdtp2Crc); - - if(cdTextPack2Crc != calculatedCdtp2Crc && - cdTextPack2Crc != 0) - { - DicConsole.DebugWriteLine("CD checksums", "CD-Text Pack 2 CRC 0x{0:X4}, expected 0x{1:X4}", - cdTextPack2Crc, calculatedCdtp2Crc); - - status = false; - } - } - - if((cdTextPack3[0] & 0x80) == 0x80) - { - ushort cdTextPack3Crc = BigEndianBitConverter.ToUInt16(cdTextPack3, 16); - byte[] cdTextPack3ForCrc = new byte[16]; - Array.Copy(cdTextPack3, 0, cdTextPack3ForCrc, 0, 16); - ushort calculatedCdtp3Crc = CRC16CCITTContext.Calculate(cdTextPack3ForCrc); - - DicConsole.DebugWriteLine("CD checksums", "Cyclic CDTP3 0x{0:X4}, Calc CDTP3 0x{1:X4}", cdTextPack3Crc, - calculatedCdtp3Crc); - - if(cdTextPack3Crc != calculatedCdtp3Crc && - cdTextPack3Crc != 0) - { - DicConsole.DebugWriteLine("CD checksums", "CD-Text Pack 3 CRC 0x{0:X4}, expected 0x{1:X4}", - cdTextPack3Crc, calculatedCdtp3Crc); - - status = false; - } - } - - if((cdTextPack4[0] & 0x80) != 0x80) - return status; - - ushort cdTextPack4Crc = BigEndianBitConverter.ToUInt16(cdTextPack4, 16); - byte[] cdTextPack4ForCrc = new byte[16]; - Array.Copy(cdTextPack4, 0, cdTextPack4ForCrc, 0, 16); - ushort calculatedCdtp4Crc = CRC16CCITTContext.Calculate(cdTextPack4ForCrc); - - DicConsole.DebugWriteLine("CD checksums", "Cyclic CDTP4 0x{0:X4}, Calc CDTP4 0x{1:X4}", cdTextPack4Crc, - calculatedCdtp4Crc); - - if(cdTextPack4Crc == calculatedCdtp4Crc || - cdTextPack4Crc == 0) - return status; - - DicConsole.DebugWriteLine("CD checksums", "CD-Text Pack 4 CRC 0x{0:X4}, expected 0x{1:X4}", cdTextPack4Crc, - calculatedCdtp4Crc); - - return false; - } - } -} \ No newline at end of file diff --git a/DiscImageChef.Checksums/CRC16CCITTContext.cs b/DiscImageChef.Checksums/CRC16CCITTContext.cs deleted file mode 100644 index 808530538..000000000 --- a/DiscImageChef.Checksums/CRC16CCITTContext.cs +++ /dev/null @@ -1,63 +0,0 @@ -namespace DiscImageChef.Checksums -{ - public class CRC16CCITTContext : Crc16Context - { - public const ushort CRC16_CCITT_POLY = 0x8408; - public const ushort CRC16_CCITT_SEED = 0x0000; - static readonly ushort[] _ccittCrc16Table = - { - 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 - }; - - public CRC16CCITTContext() : base(CRC16_CCITT_POLY, CRC16_CCITT_SEED, _ccittCrc16Table, true) { } - - /// Gets the hash of a file - /// File path. - public static byte[] File(string filename) - { - File(filename, out byte[] hash); - - return hash; - } - - /// Gets the hash of a file in hexadecimal and as a byte array. - /// File path. - /// Byte array of the hash value. - public static string File(string filename, out byte[] hash) => - File(filename, out hash, CRC16_CCITT_POLY, CRC16_CCITT_SEED, _ccittCrc16Table, true); - - /// Gets the hash of the specified data buffer. - /// Data buffer. - /// Length of the data buffer to hash. - /// Byte array of the hash value. - public static string Data(byte[] data, uint len, out byte[] hash) => - Data(data, len, out hash, CRC16_CCITT_POLY, CRC16_CCITT_SEED, _ccittCrc16Table, true); - - /// Gets the hash of the specified data buffer. - /// Data buffer. - /// Byte array of the hash value. - public static string Data(byte[] data, out byte[] hash) => Data(data, (uint)data.Length, out hash); - - public static ushort Calculate(byte[] buffer) => - Calculate(buffer, CRC16_CCITT_POLY, CRC16_CCITT_SEED, _ccittCrc16Table, true); - } -} \ No newline at end of file diff --git a/DiscImageChef.Checksums/CRC16Context.cs b/DiscImageChef.Checksums/CRC16Context.cs deleted file mode 100644 index c9ff1df9a..000000000 --- a/DiscImageChef.Checksums/CRC16Context.cs +++ /dev/null @@ -1,226 +0,0 @@ -// /*************************************************************************** -// The Disc Image Chef -// ---------------------------------------------------------------------------- -// -// Filename : CRC16Context.cs -// Author(s) : Natalia Portillo -// -// 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 . -// -// ---------------------------------------------------------------------------- -// Copyright © 2011-2020 Natalia Portillo -// ****************************************************************************/ - -using System.IO; -using System.Linq; -using System.Text; -using DiscImageChef.CommonTypes.Interfaces; - -namespace DiscImageChef.Checksums -{ - /// Implements a CRC16 algorithm - public class Crc16Context : IChecksum - { - protected ushort _finalSeed; - protected ushort _hashInt; - protected bool _inverse; - - protected ushort[] _table; - - /// Initializes the CRC16 table with a custom polynomial and seed - public Crc16Context(ushort polynomial, ushort seed, ushort[] table, bool inverse) - { - _hashInt = seed; - _finalSeed = seed; - _inverse = inverse; - - _table = table ?? GenerateTable(polynomial, inverse); - } - - /// Updates the hash with data. - /// Data buffer. - /// Length of buffer to hash. - public void Update(byte[] data, uint len) - { - for(int i = 0; i < len; i++) - { - if(_inverse) - _hashInt = (ushort)(_table[(_hashInt >> 8) ^ data[i]] ^ (_hashInt << 8)); - else - _hashInt = (ushort)((_hashInt >> 8) ^ _table[data[i] ^ (_hashInt & 0xFF)]); - } - } - - /// Updates the hash with data. - /// Data buffer. - public void Update(byte[] data) => Update(data, (uint)data.Length); - - /// Returns a byte array of the hash value. - public byte[] Final() => BigEndianBitConverter.GetBytes((ushort)(_hashInt ^ _finalSeed)); - - /// Returns a hexadecimal representation of the hash value. - public string End() - { - var crc16Output = new StringBuilder(); - - ushort final = (ushort)(_hashInt ^ _finalSeed); - - if(_inverse) - final = (ushort)~final; - - byte[] finalBytes = BigEndianBitConverter.GetBytes(final); - - for(int i = 0; i < finalBytes.Length; i++) - crc16Output.Append(finalBytes[i].ToString("x2")); - - return crc16Output.ToString(); - } - - static ushort[] GenerateTable(ushort polynomial, bool inverseTable) - { - ushort[] table = new ushort[256]; - - if(!inverseTable) - for(uint i = 0; i < 256; i++) - { - uint entry = i; - - for(int j = 0; j < 8; j++) - if((entry & 1) == 1) - entry = (entry >> 1) ^ polynomial; - else - entry = entry >> 1; - - table[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[i] = (ushort)entry; - } - } - } - - return table; - } - - /// Gets the hash of a file in hexadecimal and as a byte array. - /// File path. - /// Byte array of the hash value. - public static string File(string filename, out byte[] hash, ushort polynomial, ushort seed, ushort[] table, - bool inverse) - { - var fileStream = new FileStream(filename, FileMode.Open); - - ushort localHashInt = seed; - - ushort[] localTable = table ?? GenerateTable(polynomial, inverse); - - for(int i = 0; i < fileStream.Length; i++) - if(inverse) - localHashInt = - (ushort)(localTable[(localHashInt >> 8) ^ fileStream.ReadByte()] ^ (localHashInt << 8)); - else - localHashInt = - (ushort)((localHashInt >> 8) ^ localTable[fileStream.ReadByte() ^ (localHashInt & 0xff)]); - - localHashInt ^= seed; - - if(inverse) - localHashInt = (ushort)~localHashInt; - - hash = BigEndianBitConverter.GetBytes(localHashInt); - - var crc16Output = new StringBuilder(); - - foreach(byte h in hash) - crc16Output.Append(h.ToString("x2")); - - fileStream.Close(); - - return crc16Output.ToString(); - } - - /// Gets the hash of the specified data buffer. - /// Data buffer. - /// Length of the data buffer to hash. - /// Byte array of the hash value. - /// CRC polynomial - /// CRC seed - public static string Data(byte[] data, uint len, out byte[] hash, ushort polynomial, ushort seed, - ushort[] table, bool inverse) - { - ushort localHashInt = seed; - - ushort[] localTable = table ?? GenerateTable(polynomial, inverse); - - for(int i = 0; i < len; i++) - if(inverse) - localHashInt = (ushort)(localTable[(localHashInt >> 8) ^ data[i]] ^ (localHashInt << 8)); - else - localHashInt = (ushort)((localHashInt >> 8) ^ localTable[data[i] ^ (localHashInt & 0xff)]); - - localHashInt ^= seed; - - if(inverse) - localHashInt = (ushort)~localHashInt; - - hash = BigEndianBitConverter.GetBytes(localHashInt); - - var crc16Output = new StringBuilder(); - - foreach(byte h in hash) - crc16Output.Append(h.ToString("x2")); - - return crc16Output.ToString(); - } - - public static ushort Calculate(byte[] buffer, ushort polynomial, ushort seed, ushort[] table, bool inverse) - { - ushort[] localTable = table ?? GenerateTable(polynomial, inverse); - - ushort crc16 = - buffer.Aggregate(0, - (current, b) => - inverse ? (ushort)(localTable[(current >> 8) ^ b] ^ (current << 8)) - : (ushort)((current >> 8) ^ - localTable[b ^ (current & 0xff)])); - - crc16 ^= seed; - - if(inverse) - crc16 = (ushort)~crc16; - - return crc16; - } - } -} \ No newline at end of file diff --git a/DiscImageChef.Checksums/CRC16IBMContext.cs b/DiscImageChef.Checksums/CRC16IBMContext.cs deleted file mode 100644 index 9626b1fe4..000000000 --- a/DiscImageChef.Checksums/CRC16IBMContext.cs +++ /dev/null @@ -1,64 +0,0 @@ -namespace DiscImageChef.Checksums -{ - public class CRC16IBMContext : Crc16Context - { - const ushort CRC16_IBM_POLY = 0xA001; - const ushort CRC16_IBM_SEED = 0x0000; - - static readonly ushort[] _ibmCrc16Table = - { - 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 - }; - - public CRC16IBMContext() : base(CRC16_IBM_POLY, CRC16_IBM_SEED, _ibmCrc16Table, false) { } - - /// Gets the hash of a file - /// File path. - public static byte[] File(string filename) - { - File(filename, out byte[] hash); - - return hash; - } - - /// Gets the hash of a file in hexadecimal and as a byte array. - /// File path. - /// Byte array of the hash value. - public static string File(string filename, out byte[] hash) => - File(filename, out hash, CRC16_IBM_POLY, CRC16_IBM_SEED, _ibmCrc16Table, false); - - /// Gets the hash of the specified data buffer. - /// Data buffer. - /// Length of the data buffer to hash. - /// Byte array of the hash value. - public static string Data(byte[] data, uint len, out byte[] hash) => - Data(data, len, out hash, CRC16_IBM_POLY, CRC16_IBM_SEED, _ibmCrc16Table, false); - - /// Gets the hash of the specified data buffer. - /// Data buffer. - /// Byte array of the hash value. - public static string Data(byte[] data, out byte[] hash) => Data(data, (uint)data.Length, out hash); - - public static ushort Calculate(byte[] buffer) => - Calculate(buffer, CRC16_IBM_POLY, CRC16_IBM_SEED, _ibmCrc16Table, false); - } -} \ No newline at end of file diff --git a/DiscImageChef.Checksums/CRC32Context.cs b/DiscImageChef.Checksums/CRC32Context.cs deleted file mode 100644 index 029b76f3d..000000000 --- a/DiscImageChef.Checksums/CRC32Context.cs +++ /dev/null @@ -1,237 +0,0 @@ -// /*************************************************************************** -// The Disc Image Chef -// ---------------------------------------------------------------------------- -// -// Filename : CRC32Context.cs -// Author(s) : Natalia Portillo -// -// 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 . -// -// ---------------------------------------------------------------------------- -// Copyright © 2011-2020 Natalia Portillo -// ****************************************************************************/ - -using System.IO; -using System.Text; -using DiscImageChef.CommonTypes.Interfaces; - -namespace DiscImageChef.Checksums -{ - /// - /// Implements a CRC32 algorithm - /// - public class Crc32Context : IChecksum - { - const uint CRC32_ISO_POLY = 0xEDB88320; - const uint CRC32_ISO_SEED = 0xFFFFFFFF; - const uint CRC32_CASTAGNOLI_POLY = 0x8F6E37A0; - const uint CRC32_CASTAGNOLI_SEED = 0xFFFFFFFF; - - readonly uint finalSeed; - readonly uint[] table; - uint hashInt; - - /// - /// Initializes the CRC32 table and seed as CRC32-ISO - /// - public Crc32Context() - { - hashInt = CRC32_ISO_SEED; - finalSeed = CRC32_ISO_SEED; - - table = new uint[256]; - for(int i = 0; i < 256; i++) - { - uint entry = (uint)i; - for(int j = 0; j < 8; j++) - if((entry & 1) == 1) entry = (entry >> 1) ^ CRC32_ISO_POLY; - else entry = entry >> 1; - - table[i] = entry; - } - } - - /// - /// Initializes the CRC32 table with a custom polynomial and seed - /// - public Crc32Context(uint polynomial, uint seed) - { - hashInt = seed; - finalSeed = seed; - - table = new uint[256]; - for(int i = 0; i < 256; i++) - { - uint entry = (uint)i; - for(int j = 0; j < 8; j++) - if((entry & 1) == 1) entry = (entry >> 1) ^ polynomial; - else entry = entry >> 1; - - table[i] = entry; - } - } - - /// - /// Updates the hash with data. - /// - /// Data buffer. - /// Length of buffer to hash. - public void Update(byte[] data, uint len) - { - for(int i = 0; i < len; i++) hashInt = (hashInt >> 8) ^ table[data[i] ^ (hashInt & 0xff)]; - } - - /// - /// Updates the hash with data. - /// - /// Data buffer. - public void Update(byte[] data) - { - Update(data, (uint)data.Length); - } - - /// - /// Returns a byte array of the hash value. - /// - public byte[] Final() => BigEndianBitConverter.GetBytes(hashInt ^ finalSeed); - - /// - /// Returns a hexadecimal representation of the hash value. - /// - public string End() - { - StringBuilder crc32Output = new StringBuilder(); - - for(int i = 0; i < BigEndianBitConverter.GetBytes(hashInt ^ finalSeed).Length; i++) - crc32Output.Append(BigEndianBitConverter.GetBytes(hashInt ^ finalSeed)[i].ToString("x2")); - - return crc32Output.ToString(); - } - - /// - /// Gets the hash of a file - /// - /// File path. - public static byte[] File(string filename) - { - File(filename, out byte[] hash); - return hash; - } - - /// - /// Gets the hash of a file in hexadecimal and as a byte array. - /// - /// File path. - /// Byte array of the hash value. - public static string File(string filename, out byte[] hash) => - File(filename, out hash, CRC32_ISO_POLY, CRC32_ISO_SEED); - - /// - /// Gets the hash of a file in hexadecimal and as a byte array. - /// - /// File path. - /// Byte array of the hash value. - public static string File(string filename, out byte[] hash, uint polynomial, uint seed) - { - FileStream fileStream = new FileStream(filename, FileMode.Open); - - uint localhashInt = seed; - - uint[] localTable = new uint[256]; - for(int i = 0; i < 256; i++) - { - uint entry = (uint)i; - for(int j = 0; j < 8; j++) - if((entry & 1) == 1) entry = (entry >> 1) ^ polynomial; - else entry = entry >> 1; - - localTable[i] = entry; - } - - for(int i = 0; i < fileStream.Length; i++) - localhashInt = (localhashInt >> 8) ^ localTable[fileStream.ReadByte() ^ (localhashInt & 0xff)]; - - localhashInt ^= seed; - hash = BigEndianBitConverter.GetBytes(localhashInt); - - StringBuilder crc32Output = new StringBuilder(); - - foreach(byte h in hash) crc32Output.Append(h.ToString("x2")); - - fileStream.Close(); - - return crc32Output.ToString(); - } - - /// - /// Gets the hash of the specified data buffer. - /// - /// Data buffer. - /// Length of the data buffer to hash. - /// Byte array of the hash value. - public static string Data(byte[] data, uint len, out byte[] hash) => - Data(data, len, out hash, CRC32_ISO_POLY, CRC32_ISO_SEED); - - /// - /// Gets the hash of the specified data buffer. - /// - /// Data buffer. - /// Length of the data buffer to hash. - /// Byte array of the hash value. - /// CRC polynomial - /// CRC seed - public static string Data(byte[] data, uint len, out byte[] hash, uint polynomial, uint seed) - { - uint localhashInt = seed; - - uint[] localTable = new uint[256]; - for(int i = 0; i < 256; i++) - { - uint entry = (uint)i; - for(int j = 0; j < 8; j++) - if((entry & 1) == 1) entry = (entry >> 1) ^ polynomial; - else entry = entry >> 1; - - localTable[i] = entry; - } - - for(int i = 0; i < len; i++) - localhashInt = (localhashInt >> 8) ^ localTable[data[i] ^ (localhashInt & 0xff)]; - - localhashInt ^= seed; - hash = BigEndianBitConverter.GetBytes(localhashInt); - - StringBuilder crc32Output = new StringBuilder(); - - foreach(byte h in hash) crc32Output.Append(h.ToString("x2")); - - return crc32Output.ToString(); - } - - /// - /// Gets the hash of the specified data buffer. - /// - /// Data buffer. - /// Byte array of the hash value. - public static string Data(byte[] data, out byte[] hash) => Data(data, (uint)data.Length, out hash); - } -} \ No newline at end of file diff --git a/DiscImageChef.Checksums/CRC64Context.cs b/DiscImageChef.Checksums/CRC64Context.cs deleted file mode 100644 index ada7cd9f6..000000000 --- a/DiscImageChef.Checksums/CRC64Context.cs +++ /dev/null @@ -1,237 +0,0 @@ -// /*************************************************************************** -// The Disc Image Chef -// ---------------------------------------------------------------------------- -// -// Filename : CRC64Context.cs -// Author(s) : Natalia Portillo -// -// 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 . -// -// ---------------------------------------------------------------------------- -// Copyright © 2011-2020 Natalia Portillo -// ****************************************************************************/ - -using System.IO; -using System.Text; -using DiscImageChef.CommonTypes.Interfaces; - -namespace DiscImageChef.Checksums -{ - /// - /// Implements a CRC64 algorithm - /// - public class Crc64Context : IChecksum - { - public const ulong CRC64_ECMA_POLY = 0xC96C5795D7870F42; - public const ulong CRC64_ECMA_SEED = 0xFFFFFFFFFFFFFFFF; - - readonly ulong finalSeed; - readonly ulong[] table; - ulong hashInt; - - /// - /// Initializes the CRC64 table and seed as CRC64-ECMA - /// - public Crc64Context() - { - hashInt = CRC64_ECMA_SEED; - - table = new ulong[256]; - for(int i = 0; i < 256; i++) - { - ulong entry = (ulong)i; - for(int j = 0; j < 8; j++) - if((entry & 1) == 1) entry = (entry >> 1) ^ CRC64_ECMA_POLY; - else entry = entry >> 1; - - table[i] = entry; - } - - finalSeed = CRC64_ECMA_SEED; - } - - /// - /// Initializes the CRC16 table with a custom polynomial and seed - /// - public Crc64Context(ulong polynomial, ulong seed) - { - hashInt = seed; - - table = new ulong[256]; - for(int i = 0; i < 256; i++) - { - ulong entry = (ulong)i; - for(int j = 0; j < 8; j++) - if((entry & 1) == 1) entry = (entry >> 1) ^ polynomial; - else entry = entry >> 1; - - table[i] = entry; - } - - finalSeed = seed; - } - - /// - /// Updates the hash with data. - /// - /// Data buffer. - /// Length of buffer to hash. - public void Update(byte[] data, uint len) - { - for(int i = 0; i < len; i++) hashInt = (hashInt >> 8) ^ table[data[i] ^ (hashInt & 0xff)]; - } - - /// - /// Updates the hash with data. - /// - /// Data buffer. - public void Update(byte[] data) - { - Update(data, (uint)data.Length); - } - - /// - /// Returns a byte array of the hash value. - /// - public byte[] Final() => BigEndianBitConverter.GetBytes(hashInt ^= finalSeed); - - /// - /// Returns a hexadecimal representation of the hash value. - /// - public string End() - { - StringBuilder crc64Output = new StringBuilder(); - - for(int i = 0; i < BigEndianBitConverter.GetBytes(hashInt ^= finalSeed).Length; i++) - crc64Output.Append(BigEndianBitConverter.GetBytes(hashInt ^= finalSeed)[i].ToString("x2")); - - return crc64Output.ToString(); - } - - /// - /// Gets the hash of a file - /// - /// File path. - public static byte[] File(string filename) - { - File(filename, out byte[] localHash); - return localHash; - } - - /// - /// Gets the hash of a file in hexadecimal and as a byte array. - /// - /// File path. - /// Byte array of the hash value. - public static string File(string filename, out byte[] hash) => - File(filename, out hash, CRC64_ECMA_POLY, CRC64_ECMA_SEED); - - /// - /// Gets the hash of a file in hexadecimal and as a byte array. - /// - /// File path. - /// Byte array of the hash value. - public static string File(string filename, out byte[] hash, ulong polynomial, ulong seed) - { - FileStream fileStream = new FileStream(filename, FileMode.Open); - - ulong localhashInt = seed; - - ulong[] localTable = new ulong[256]; - for(int i = 0; i < 256; i++) - { - ulong entry = (ulong)i; - for(int j = 0; j < 8; j++) - if((entry & 1) == 1) entry = (entry >> 1) ^ polynomial; - else entry = entry >> 1; - - localTable[i] = entry; - } - - for(int i = 0; i < fileStream.Length; i++) - localhashInt = (localhashInt >> 8) ^ localTable[(ulong)fileStream.ReadByte() ^ (localhashInt & 0xffL)]; - - localhashInt ^= seed; - hash = BigEndianBitConverter.GetBytes(localhashInt); - - StringBuilder crc64Output = new StringBuilder(); - - foreach(byte h in hash) crc64Output.Append(h.ToString("x2")); - - fileStream.Close(); - - return crc64Output.ToString(); - } - - /// - /// Gets the hash of the specified data buffer. - /// - /// Data buffer. - /// Length of the data buffer to hash. - /// Byte array of the hash value. - public static string Data(byte[] data, uint len, out byte[] hash) => - Data(data, len, out hash, CRC64_ECMA_POLY, CRC64_ECMA_SEED); - - /// - /// Gets the hash of the specified data buffer. - /// - /// Data buffer. - /// Length of the data buffer to hash. - /// Byte array of the hash value. - /// CRC polynomial - /// CRC seed - public static string Data(byte[] data, uint len, out byte[] hash, ulong polynomial, ulong seed) - { - ulong localhashInt = seed; - - ulong[] localTable = new ulong[256]; - for(int i = 0; i < 256; i++) - { - ulong entry = (ulong)i; - for(int j = 0; j < 8; j++) - if((entry & 1) == 1) entry = (entry >> 1) ^ polynomial; - else entry = entry >> 1; - - localTable[i] = entry; - } - - for(int i = 0; i < len; i++) - localhashInt = (localhashInt >> 8) ^ localTable[data[i] ^ (localhashInt & 0xff)]; - - localhashInt ^= seed; - hash = BigEndianBitConverter.GetBytes(localhashInt); - - StringBuilder crc64Output = new StringBuilder(); - - foreach(byte h in hash) crc64Output.Append(h.ToString("x2")); - - return crc64Output.ToString(); - } - - /// - /// Gets the hash of the specified data buffer. - /// - /// Data buffer. - /// Byte array of the hash value. - public static string Data(byte[] data, out byte[] hash) => Data(data, (uint)data.Length, out hash); - } -} \ No newline at end of file diff --git a/DiscImageChef.Checksums/DiscImageChef.Checksums.csproj b/DiscImageChef.Checksums/DiscImageChef.Checksums.csproj deleted file mode 100644 index 18f4d80aa..000000000 --- a/DiscImageChef.Checksums/DiscImageChef.Checksums.csproj +++ /dev/null @@ -1,120 +0,0 @@ - - - - Debug - AnyCPU - 2.0 - {CC48B324-A532-4A45-87A6-6F91F7141E8D} - Library - DiscImageChef.Checksums - DiscImageChef.Checksums - $(Version) - false - true - 4.5.99.1693 - Claunia.com - Copyright © 2011-2020 Natalia Portillo - The Disc Image Chef - DiscImageChef.Checksums - $(Version) - net461;netstandard2.0;netcoreapp2.0 - - - $(Version)-{chash:8} built by {mname} in $(Configuration){!:, modified} - true - true - - - true - full - false - bin\Debug - DEBUG; - prompt - 4 - false - - - full - true - bin\Release - prompt - 4 - false - - - - - - - - - - - - - - - - - - - - - - - - - - {F8BDF57B-1571-4CD0-84B3-B422088D359A} - DiscImageChef.Helpers - - - {CCAA7AFE-C094-4D82-A66D-630DE8A3F545} - DiscImageChef.Console - - - - - LICENSE.LGPL - - - LICENSE - - - - - - - - - - - - - - - - - - - - - /Library/Frameworks/Mono.framework/Versions/Current/lib/mono - /usr/lib/mono - /usr/local/lib/mono - - $(BaseFrameworkPathOverrideForMono)/4.0-api - $(BaseFrameworkPathOverrideForMono)/4.5-api - $(BaseFrameworkPathOverrideForMono)/4.5.1-api - $(BaseFrameworkPathOverrideForMono)/4.5.2-api - $(BaseFrameworkPathOverrideForMono)/4.6-api - $(BaseFrameworkPathOverrideForMono)/4.6.1-api - $(BaseFrameworkPathOverrideForMono)/4.6.2-api - $(BaseFrameworkPathOverrideForMono)/4.7-api - $(BaseFrameworkPathOverrideForMono)/4.7.1-api - true - - $(FrameworkPathOverride)/Facades;$(AssemblySearchPaths) - - \ No newline at end of file diff --git a/DiscImageChef.Checksums/FletcherContext.cs b/DiscImageChef.Checksums/FletcherContext.cs deleted file mode 100644 index d3fbba07a..000000000 --- a/DiscImageChef.Checksums/FletcherContext.cs +++ /dev/null @@ -1,320 +0,0 @@ -// /*************************************************************************** -// The Disc Image Chef -// ---------------------------------------------------------------------------- -// -// Filename : FletcherContext.cs -// Author(s) : Natalia Portillo -// -// 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 . -// -// ---------------------------------------------------------------------------- -// Copyright © 2011-2020 Natalia Portillo -// ****************************************************************************/ - -// Disabled because the speed is abnormally slow - -using System.IO; -using System.Text; -using DiscImageChef.CommonTypes.Interfaces; - -namespace DiscImageChef.Checksums -{ - /// - /// Implements the Fletcher-32 algorithm - /// - public class Fletcher32Context : IChecksum - { - const ushort FLETCHER_MODULE = 0xFFFF; - ushort sum1, sum2; - - /// - /// Initializes the Fletcher-32 sums - /// - public Fletcher32Context() - { - sum1 = 0xFFFF; - sum2 = 0xFFFF; - } - - /// - /// Updates the hash with data. - /// - /// Data buffer. - /// Length of buffer to hash. - public void Update(byte[] data, uint len) - { - for(int i = 0; i < len; i++) - { - sum1 = (ushort)((sum1 + data[i]) % FLETCHER_MODULE); - sum2 = (ushort)((sum2 + sum1) % FLETCHER_MODULE); - } - } - - /// - /// Updates the hash with data. - /// - /// Data buffer. - public void Update(byte[] data) - { - Update(data, (uint)data.Length); - } - - /// - /// Returns a byte array of the hash value. - /// - public byte[] Final() - { - uint finalSum = (uint)((sum2 << 16) | sum1); - return BigEndianBitConverter.GetBytes(finalSum); - } - - /// - /// Returns a hexadecimal representation of the hash value. - /// - public string End() - { - uint finalSum = (uint)((sum2 << 16) | sum1); - StringBuilder fletcherOutput = new StringBuilder(); - - for(int i = 0; i < BigEndianBitConverter.GetBytes(finalSum).Length; i++) - fletcherOutput.Append(BigEndianBitConverter.GetBytes(finalSum)[i].ToString("x2")); - - return fletcherOutput.ToString(); - } - - /// - /// Gets the hash of a file - /// - /// File path. - public static byte[] File(string filename) - { - File(filename, out byte[] hash); - return hash; - } - - /// - /// Gets the hash of a file in hexadecimal and as a byte array. - /// - /// File path. - /// Byte array of the hash value. - public static string File(string filename, out byte[] hash) - { - FileStream fileStream = new FileStream(filename, FileMode.Open); - - ushort localSum1 = 0xFFFF; - ushort localSum2 = 0xFFFF; - - for(int i = 0; i < fileStream.Length; i++) - { - localSum1 = (ushort)((localSum1 + fileStream.ReadByte()) % FLETCHER_MODULE); - localSum2 = (ushort)((localSum2 + localSum1) % FLETCHER_MODULE); - } - - uint finalSum = (uint)((localSum2 << 16) | localSum1); - - hash = BigEndianBitConverter.GetBytes(finalSum); - - StringBuilder fletcherOutput = new StringBuilder(); - - foreach(byte h in hash) fletcherOutput.Append(h.ToString("x2")); - - fileStream.Close(); - - return fletcherOutput.ToString(); - } - - /// - /// Gets the hash of the specified data buffer. - /// - /// Data buffer. - /// Length of the data buffer to hash. - /// Byte array of the hash value. - public static string Data(byte[] data, uint len, out byte[] hash) - { - ushort localSum1 = 0xFFFF; - ushort localSum2 = 0xFFFF; - - for(int i = 0; i < len; i++) - { - localSum1 = (ushort)((localSum1 + data[i]) % FLETCHER_MODULE); - localSum2 = (ushort)((localSum2 + localSum1) % FLETCHER_MODULE); - } - - uint finalSum = (uint)((localSum2 << 16) | localSum1); - - hash = BigEndianBitConverter.GetBytes(finalSum); - - StringBuilder adlerOutput = new StringBuilder(); - - foreach(byte h in hash) adlerOutput.Append(h.ToString("x2")); - - return adlerOutput.ToString(); - } - - /// - /// Gets the hash of the specified data buffer. - /// - /// Data buffer. - /// Byte array of the hash value. - public static string Data(byte[] data, out byte[] hash) => Data(data, (uint)data.Length, out hash); - } - - /// - /// Implements the Fletcher-16 algorithm - /// - public class Fletcher16Context : IChecksum - { - const byte FLETCHER_MODULE = 0xFF; - byte sum1, sum2; - - /// - /// Initializes the Fletcher-16 sums - /// - public Fletcher16Context() - { - sum1 = 0xFF; - sum2 = 0xFF; - } - - /// - /// Updates the hash with data. - /// - /// Data buffer. - /// Length of buffer to hash. - public void Update(byte[] data, uint len) - { - for(int i = 0; i < len; i++) - { - sum1 = (byte)((sum1 + data[i]) % FLETCHER_MODULE); - sum2 = (byte)((sum2 + sum1) % FLETCHER_MODULE); - } - } - - /// - /// Updates the hash with data. - /// - /// Data buffer. - public void Update(byte[] data) - { - Update(data, (uint)data.Length); - } - - /// - /// Returns a byte array of the hash value. - /// - public byte[] Final() - { - ushort finalSum = (ushort)((sum2 << 8) | sum1); - return BigEndianBitConverter.GetBytes(finalSum); - } - - /// - /// Returns a hexadecimal representation of the hash value. - /// - public string End() - { - ushort finalSum = (ushort)((sum2 << 8) | sum1); - StringBuilder fletcherOutput = new StringBuilder(); - - for(int i = 0; i < BigEndianBitConverter.GetBytes(finalSum).Length; i++) - fletcherOutput.Append(BigEndianBitConverter.GetBytes(finalSum)[i].ToString("x2")); - - return fletcherOutput.ToString(); - } - - /// - /// Gets the hash of a file - /// - /// File path. - public static byte[] File(string filename) - { - File(filename, out byte[] hash); - return hash; - } - - /// - /// Gets the hash of a file in hexadecimal and as a byte array. - /// - /// File path. - /// Byte array of the hash value. - public static string File(string filename, out byte[] hash) - { - FileStream fileStream = new FileStream(filename, FileMode.Open); - - byte localSum1 = 0xFF; - byte localSum2 = 0xFF; - - for(int i = 0; i < fileStream.Length; i++) - { - localSum1 = (byte)((localSum1 + fileStream.ReadByte()) % FLETCHER_MODULE); - localSum2 = (byte)((localSum2 + localSum1) % FLETCHER_MODULE); - } - - ushort finalSum = (ushort)((localSum2 << 8) | localSum1); - - hash = BigEndianBitConverter.GetBytes(finalSum); - - StringBuilder fletcherOutput = new StringBuilder(); - - foreach(byte h in hash) fletcherOutput.Append(h.ToString("x2")); - - fileStream.Close(); - - return fletcherOutput.ToString(); - } - - /// - /// Gets the hash of the specified data buffer. - /// - /// Data buffer. - /// Length of the data buffer to hash. - /// Byte array of the hash value. - public static string Data(byte[] data, uint len, out byte[] hash) - { - byte localSum1 = 0xFF; - byte localSum2 = 0xFF; - - for(int i = 0; i < len; i++) - { - localSum1 = (byte)((localSum1 + data[i]) % FLETCHER_MODULE); - localSum2 = (byte)((localSum2 + localSum1) % FLETCHER_MODULE); - } - - ushort finalSum = (ushort)((localSum2 << 8) | localSum1); - - hash = BigEndianBitConverter.GetBytes(finalSum); - - StringBuilder adlerOutput = new StringBuilder(); - - foreach(byte h in hash) adlerOutput.Append(h.ToString("x2")); - - return adlerOutput.ToString(); - } - - /// - /// Gets the hash of the specified data buffer. - /// - /// Data buffer. - /// Byte array of the hash value. - public static string Data(byte[] data, out byte[] hash) => Data(data, (uint)data.Length, out hash); - } -} \ No newline at end of file diff --git a/DiscImageChef.Checksums/MD5Context.cs b/DiscImageChef.Checksums/MD5Context.cs deleted file mode 100644 index 883d93d39..000000000 --- a/DiscImageChef.Checksums/MD5Context.cs +++ /dev/null @@ -1,152 +0,0 @@ -// /*************************************************************************** -// The Disc Image Chef -// ---------------------------------------------------------------------------- -// -// Filename : MD5Context.cs -// Author(s) : Natalia Portillo -// -// Component : Checksums. -// -// --[ Description ] ---------------------------------------------------------- -// -// Wraps up .NET MD5 implementation to a Init(), Update(), Final() context. -// -// --[ 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 . -// -// ---------------------------------------------------------------------------- -// Copyright © 2011-2020 Natalia Portillo -// ****************************************************************************/ - -using System.IO; -using System.Security.Cryptography; -using System.Text; -using DiscImageChef.CommonTypes.Interfaces; - -namespace DiscImageChef.Checksums -{ - /// - /// Wraps up .NET MD5 implementation to a Init(), Update(), Final() context. - /// - public class Md5Context : IChecksum - { - MD5 md5Provider; - - /// - /// Initializes the MD5 hash provider - /// - public Md5Context() - { - md5Provider = MD5.Create(); - } - - /// - /// Updates the hash with data. - /// - /// Data buffer. - /// Length of buffer to hash. - public void Update(byte[] data, uint len) - { - md5Provider.TransformBlock(data, 0, (int)len, data, 0); - } - - /// - /// Updates the hash with data. - /// - /// Data buffer. - public void Update(byte[] data) - { - Update(data, (uint)data.Length); - } - - /// - /// Returns a byte array of the hash value. - /// - public byte[] Final() - { - md5Provider.TransformFinalBlock(new byte[0], 0, 0); - return md5Provider.Hash; - } - - /// - /// Returns a hexadecimal representation of the hash value. - /// - public string End() - { - md5Provider.TransformFinalBlock(new byte[0], 0, 0); - StringBuilder md5Output = new StringBuilder(); - - foreach(byte h in md5Provider.Hash) md5Output.Append(h.ToString("x2")); - - return md5Output.ToString(); - } - - /// - /// Gets the hash of a file - /// - /// File path. - public static byte[] File(string filename) - { - MD5 localMd5Provider = MD5.Create(); - FileStream fileStream = new FileStream(filename, FileMode.Open); - byte[] result = localMd5Provider.ComputeHash(fileStream); - fileStream.Close(); - return result; - } - - /// - /// Gets the hash of a file in hexadecimal and as a byte array. - /// - /// File path. - /// Byte array of the hash value. - public static string File(string filename, out byte[] hash) - { - MD5 localMd5Provider = MD5.Create(); - FileStream fileStream = new FileStream(filename, FileMode.Open); - hash = localMd5Provider.ComputeHash(fileStream); - StringBuilder md5Output = new StringBuilder(); - - foreach(byte h in hash) md5Output.Append(h.ToString("x2")); - - fileStream.Close(); - - return md5Output.ToString(); - } - - /// - /// Gets the hash of the specified data buffer. - /// - /// Data buffer. - /// Length of the data buffer to hash. - /// Byte array of the hash value. - public static string Data(byte[] data, uint len, out byte[] hash) - { - MD5 localMd5Provider = MD5.Create(); - hash = localMd5Provider.ComputeHash(data, 0, (int)len); - StringBuilder md5Output = new StringBuilder(); - - foreach(byte h in hash) md5Output.Append(h.ToString("x2")); - - return md5Output.ToString(); - } - - /// - /// Gets the hash of the specified data buffer. - /// - /// Data buffer. - /// Byte array of the hash value. - public static string Data(byte[] data, out byte[] hash) => Data(data, (uint)data.Length, out hash); - } -} \ No newline at end of file diff --git a/DiscImageChef.Checksums/ReedSolomon.cs b/DiscImageChef.Checksums/ReedSolomon.cs deleted file mode 100644 index be2e5f60e..000000000 --- a/DiscImageChef.Checksums/ReedSolomon.cs +++ /dev/null @@ -1,625 +0,0 @@ -// /*************************************************************************** -// The Disc Image Chef -// ---------------------------------------------------------------------------- -// -// Filename : ReedSolomon.cs -// Author(s) : Natalia Portillo -// -// Component : Checksums. -// -// --[ Description ] ---------------------------------------------------------- -// -// Calculates a Reed-Solomon. -// -// --[ License ] -------------------------------------------------------------- -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program 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 General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . -// -// ---------------------------------------------------------------------------- -// Copyright © 2011-2020 Natalia Portillo -// Copyright (C) 1996 Phil Karn -// Copyright (C) 1995 Robert Morelos-Zaragoza -// Copyright (C) 1995 Hari Thirumoorthy -// ****************************************************************************/ - -/* - * Reed-Solomon coding and decoding - * Phil Karn (karn at ka9q.ampr.org) September 1996 - * - * This file is derived from the program "new_rs_erasures.c" by Robert - * Morelos-Zaragoza (robert at spectra.eng.hawaii.edu) and Hari Thirumoorthy - * (harit at spectra.eng.hawaii.edu), Aug 1995 - * - * I've made changes to improve performance, clean up the code and make it - * easier to follow. Data is now passed to the encoding and decoding functions - * through arguments rather than in global arrays. The decode function returns - * the number of corrected symbols, or -1 if the word is uncorrectable. - * - * This code supports a symbol size from 2 bits up to 16 bits, - * implying a block size of 3 2-bit symbols (6 bits) up to 65535 - * 16-bit symbols (1,048,560 bits). The code parameters are set in rs.h. - * - * Note that if symbols larger than 8 bits are used, the type of each - * data array element switches from unsigned char to unsigned int. The - * caller must ensure that elements larger than the symbol range are - * not passed to the encoder or decoder. - * - */ - -using System; -using DiscImageChef.Console; - -namespace DiscImageChef.Checksums -{ - /// - /// Implements the Reed-Solomon algorithm - /// - public class ReedSolomon - { - /// - /// Alpha exponent for the first root of the generator polynomial - /// - const int B0 = 1; - /// - /// No legal value in index form represents zero, so we need a special value for this purpose - /// - int a0; - /// - /// index->polynomial form conversion table - /// - int[] alpha_to; - /// - /// Generator polynomial g(x) Degree of g(x) = 2*TT has roots @**B0, @**(B0+1), ... ,@^(B0+2*TT-1) - /// - int[] gg; - /// - /// Polynomial->index form conversion table - /// - int[] index_of; - bool initialized; - int mm, kk, nn; - /// - /// Primitive polynomials - see Lin & Costello, Error Control Coding Appendix A, and Lee & Messerschmitt, Digital - /// Communication p. 453. - /// - int[] pp; - - /// - /// Initializes the Reed-Solomon with RS(n,k) with GF(2^m) - /// - public void InitRs(int n, int k, int m) - { - switch(m) - { - case 2: - pp = new[] {1, 1, 1}; - break; - case 3: - pp = new[] {1, 1, 0, 1}; - break; - case 4: - pp = new[] {1, 1, 0, 0, 1}; - break; - case 5: - pp = new[] {1, 0, 1, 0, 0, 1}; - break; - case 6: - pp = new[] {1, 1, 0, 0, 0, 0, 1}; - break; - case 7: - pp = new[] {1, 0, 0, 1, 0, 0, 0, 1}; - break; - case 8: - pp = new[] {1, 0, 1, 1, 1, 0, 0, 0, 1}; - break; - case 9: - pp = new[] {1, 0, 0, 0, 1, 0, 0, 0, 0, 1}; - break; - case 10: - pp = new[] {1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1}; - break; - case 11: - pp = new[] {1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1}; - break; - case 12: - pp = new[] {1, 1, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 1}; - break; - case 13: - pp = new[] {1, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1}; - break; - case 14: - pp = new[] {1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1}; - break; - case 15: - pp = new[] {1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}; - break; - case 16: - pp = new[] {1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1}; - break; - default: throw new ArgumentOutOfRangeException(nameof(m), "m must be between 2 and 16 inclusive"); - } - - mm = m; - kk = k; - nn = n; - a0 = n; - alpha_to = new int[n + 1]; - index_of = new int[n + 1]; - - gg = new int[nn - kk + 1]; - - generate_gf(); - gen_poly(); - - initialized = true; - } - - int Modnn(int x) - { - while(x >= nn) - { - x -= nn; - x = (x >> mm) + (x & nn); - } - - return x; - } - - static int Min(int a, int b) => a < b ? a : b; - - static void Clear(ref int[] a, int n) - { - int ci; - for(ci = n - 1; ci >= 0; ci--) a[ci] = 0; - } - - static void Copy(ref int[] a, ref int[] b, int n) - { - int ci; - for(ci = n - 1; ci >= 0; ci--) a[ci] = b[ci]; - } - - static void Copydown(ref int[] a, ref int[] b, int n) - { - int ci; - for(ci = n - 1; ci >= 0; ci--) a[ci] = b[ci]; - } - - /* generate GF(2**m) from the irreducible polynomial p(X) in p[0]..p[m] - lookup tables: index->polynomial form alpha_to[] contains j=alpha**i; - polynomial form -> index form index_of[j=alpha**i] = i - alpha=2 is the primitive element of GF(2**m) - HARI's COMMENT: (4/13/94) alpha_to[] can be used as follows: - Let @ represent the primitive element commonly called "alpha" that - is the root of the primitive polynomial p(x). Then in GF(2^m), for any - 0 <= i <= 2^m-2, - @^i = a(0) + a(1) @ + a(2) @^2 + ... + a(m-1) @^(m-1) - where the binary vector (a(0),a(1),a(2),...,a(m-1)) is the representation - of the integer "alpha_to[i]" with a(0) being the LSB and a(m-1) the MSB. Thus for - example the polynomial representation of @^5 would be given by the binary - representation of the integer "alpha_to[5]". - Similarily, index_of[] can be used as follows: - As above, let @ represent the primitive element of GF(2^m) that is - the root of the primitive polynomial p(x). In order to find the power - of @ (alpha) that has the polynomial representation - a(0) + a(1) @ + a(2) @^2 + ... + a(m-1) @^(m-1) - we consider the integer "i" whose binary representation with a(0) being LSB - and a(m-1) MSB is (a(0),a(1),...,a(m-1)) and locate the entry - "index_of[i]". Now, @^index_of[i] is that element whose polynomial - representation is (a(0),a(1),a(2),...,a(m-1)). - NOTE: - The element alpha_to[2^m-1] = 0 always signifying that the - representation of "@^infinity" = 0 is (0,0,0,...,0). - Similarily, the element index_of[0] = A0 always signifying - that the power of alpha which has the polynomial representation - (0,0,...,0) is "infinity". - - */ - void generate_gf() - { - int i; - - int mask = 1; - alpha_to[mm] = 0; - for(i = 0; i < mm; i++) - { - alpha_to[i] = mask; - index_of[alpha_to[i]] = i; - /* If Pp[i] == 1 then, term @^i occurs in poly-repr of @^MM */ - if(pp[i] != 0) alpha_to[mm] ^= mask; /* Bit-wise EXOR operation */ - mask <<= 1; /* single left-shift */ - } - - index_of[alpha_to[mm]] = mm; - /* - * Have obtained poly-repr of @^MM. Poly-repr of @^(i+1) is given by - * poly-repr of @^i shifted left one-bit and accounting for any @^MM - * term that may occur when poly-repr of @^i is shifted. - */ - mask >>= 1; - for(i = mm + 1; i < nn; i++) - { - if(alpha_to[i - 1] >= mask) alpha_to[i] = alpha_to[mm] ^ ((alpha_to[i - 1] ^ mask) << 1); - else alpha_to[i] = alpha_to[i - 1] << 1; - index_of[alpha_to[i]] = i; - } - - index_of[0] = a0; - alpha_to[nn] = 0; - } - - /* - * Obtain the generator polynomial of the TT-error correcting, length - * NN=(2**MM -1) Reed Solomon code from the product of (X+@**(B0+i)), i = 0, - * ... ,(2*TT-1) - * - * Examples: - * - * If B0 = 1, TT = 1. deg(g(x)) = 2*TT = 2. - * g(x) = (x+@) (x+@**2) - * - * If B0 = 0, TT = 2. deg(g(x)) = 2*TT = 4. - * g(x) = (x+1) (x+@) (x+@**2) (x+@**3) - */ - void gen_poly() - { - int i; - - gg[0] = alpha_to[B0]; - gg[1] = 1; /* g(x) = (X+@**B0) initially */ - for(i = 2; i <= nn - kk; i++) - { - gg[i] = 1; - /* - * Below multiply (Gg[0]+Gg[1]*x + ... +Gg[i]x^i) by - * (@**(B0+i-1) + x) - */ - for(int j = i - 1; j > 0; j--) - if(gg[j] != 0) - gg[j] = gg[j - 1] ^ alpha_to[Modnn(index_of[gg[j]] + B0 + i - 1)]; - else - gg[j] = gg[j - 1]; - /* Gg[0] can never be zero */ - gg[0] = alpha_to[Modnn(index_of[gg[0]] + B0 + i - 1)]; - } - - /* convert Gg[] to index form for quicker encoding */ - for(i = 0; i <= nn - kk; i++) gg[i] = index_of[gg[i]]; - } - - /* - * take the string of symbols in data[i], i=0..(k-1) and encode - * systematically to produce NN-KK parity symbols in bb[0]..bb[NN-KK-1] data[] - * is input and bb[] is output in polynomial form. Encoding is done by using - * a feedback shift register with appropriate connections specified by the - * elements of Gg[], which was generated above. Codeword is c(X) = - * data(X)*X**(NN-KK)+ b(X) - */ - /// - /// Takes the symbols in data to output parity in bb. - /// - /// Returns -1 if an illegal symbol is found. - /// Data symbols. - /// Outs parity symbols. - public int encode_rs(int[] data, out int[] bb) - { - if(!initialized) throw new UnauthorizedAccessException("Trying to calculate RS without initializing!"); - - int i; - bb = new int[nn - kk]; - - Clear(ref bb, nn - kk); - for(i = kk - 1; i >= 0; i--) - { - if(mm != 8) - if(data[i] > nn) - return -1; /* Illegal symbol */ - - int feedback = index_of[data[i] ^ bb[nn - kk - 1]]; - if(feedback != a0) - { - /* feedback term is non-zero */ - for(int j = nn - kk - 1; j > 0; j--) - if(gg[j] != a0) - bb[j] = bb[j - 1] ^ alpha_to[Modnn(gg[j] + feedback)]; - else - bb[j] = bb[j - 1]; - - bb[0] = alpha_to[Modnn(gg[0] + feedback)]; - } - else - { - /* feedback term is zero. encoder becomes a - * single-byte shifter */ - for(int j = nn - kk - 1; j > 0; j--) bb[j] = bb[j - 1]; - - bb[0] = 0; - } - } - - return 0; - } - - /* - * Performs ERRORS+ERASURES decoding of RS codes. If decoding is successful, - * writes the codeword into data[] itself. Otherwise data[] is unaltered. - * - * Return number of symbols corrected, or -1 if codeword is illegal - * or uncorrectable. - * - * First "no_eras" erasures are declared by the calling program. Then, the - * maximum # of errors correctable is t_after_eras = floor((NN-KK-no_eras)/2). - * If the number of channel errors is not greater than "t_after_eras" the - * transmitted codeword will be recovered. Details of algorithm can be found - * in R. Blahut's "Theory ... of Error-Correcting Codes". - */ - /// - /// Decodes the RS. If decoding is successful outputs corrected data symbols. - /// - /// Returns corrected symbols, -1 if illegal or uncorrectable - /// Data symbols. - /// Position of erasures. - /// Number of erasures. - public int eras_dec_rs(ref int[] data, out int[] erasPos, int noEras) - { - if(!initialized) throw new UnauthorizedAccessException("Trying to calculate RS without initializing!"); - - erasPos = new int[nn - kk]; - int i, j; - int q, tmp; - int[] recd = new int[nn]; - int[] lambda = new int[nn - kk + 1]; /* Err+Eras Locator poly */ - int[] s = new int[nn - kk + 1]; /* syndrome poly */ - int[] b = new int[nn - kk + 1]; - int[] t = new int[nn - kk + 1]; - int[] omega = new int[nn - kk + 1]; - int[] root = new int[nn - kk]; - int[] reg = new int[nn - kk + 1]; - int[] loc = new int[nn - kk]; - int count; - - /* data[] is in polynomial form, copy and convert to index form */ - for(i = nn - 1; i >= 0; i--) - { - if(mm != 8) - if(data[i] > nn) - return -1; /* Illegal symbol */ - - recd[i] = index_of[data[i]]; - } - - /* first form the syndromes; i.e., evaluate recd(x) at roots of g(x) - * namely @**(B0+i), i = 0, ... ,(NN-KK-1) - */ - int synError = 0; - for(i = 1; i <= nn - kk; i++) - { - tmp = 0; - for(j = 0; j < nn; j++) - if(recd[j] != a0) /* recd[j] in index form */ - tmp ^= alpha_to[Modnn(recd[j] + (B0 + i - 1) * j)]; - - synError |= tmp; /* set flag if non-zero syndrome => - * error */ - /* store syndrome in index form */ - s[i] = index_of[tmp]; - } - - if(synError == 0) return 0; - - Clear(ref lambda, nn - kk); - lambda[0] = 1; - if(noEras > 0) - { - /* Init lambda to be the erasure locator polynomial */ - lambda[1] = alpha_to[erasPos[0]]; - for(i = 1; i < noEras; i++) - { - int u = erasPos[i]; - for(j = i + 1; j > 0; j--) - { - tmp = index_of[lambda[j - 1]]; - if(tmp != a0) lambda[j] ^= alpha_to[Modnn(u + tmp)]; - } - } - - #if DEBUG - /* find roots of the erasure location polynomial */ - for(i = 1; i <= noEras; i++) reg[i] = index_of[lambda[i]]; - - count = 0; - for(i = 1; i <= nn; i++) - { - q = 1; - for(j = 1; j <= noEras; j++) - if(reg[j] != a0) - { - reg[j] = Modnn(reg[j] + j); - q ^= alpha_to[reg[j]]; - } - - if(q != 0) continue; - - /* store root and error location - * number indices - */ - root[count] = i; - loc[count] = nn - i; - count++; - } - - if(count != noEras) - { - DicConsole.DebugWriteLine("Reed Solomon", "\n lambda(x) is WRONG\n"); - return -1; - } - - DicConsole.DebugWriteLine("Reed Solomon", - "\n Erasure positions as determined by roots of Eras Loc Poly:\n"); - for(i = 0; i < count; i++) DicConsole.DebugWriteLine("Reed Solomon", "{0} ", loc[i]); - - DicConsole.DebugWriteLine("Reed Solomon", "\n"); - #endif - } - - for(i = 0; i < nn - kk + 1; i++) b[i] = index_of[lambda[i]]; - - /* - * Begin Berlekamp-Massey algorithm to determine error+erasure - * locator polynomial - */ - int r = noEras; - int el = noEras; - while(++r <= nn - kk) - { - /* r is the step number */ - /* Compute discrepancy at the r-th step in poly-form */ - int discrR = 0; - for(i = 0; i < r; i++) - if(lambda[i] != 0 && s[r - i] != a0) - discrR ^= alpha_to[Modnn(index_of[lambda[i]] + s[r - i])]; - - discrR = index_of[discrR]; /* Index form */ - if(discrR == a0) - { - /* 2 lines below: B(x) <-- x*B(x) */ - Copydown(ref b, ref b, nn - kk); - b[0] = a0; - } - else - { - /* 7 lines below: T(x) <-- lambda(x) - discr_r*x*b(x) */ - t[0] = lambda[0]; - for(i = 0; i < nn - kk; i++) - if(b[i] != a0) - t[i + 1] = lambda[i + 1] ^ alpha_to[Modnn(discrR + b[i])]; - else - t[i + 1] = lambda[i + 1]; - - if(2 * el <= r + noEras - 1) - { - el = r + noEras - el; - /* - * 2 lines below: B(x) <-- inv(discr_r) * - * lambda(x) - */ - for(i = 0; i <= nn - kk; i++) - b[i] = lambda[i] == 0 ? a0 : Modnn(index_of[lambda[i]] - discrR + nn); - } - else - { - /* 2 lines below: B(x) <-- x*B(x) */ - Copydown(ref b, ref b, nn - kk); - b[0] = a0; - } - - Copy(ref lambda, ref t, nn - kk + 1); - } - } - - /* Convert lambda to index form and compute deg(lambda(x)) */ - int degLambda = 0; - for(i = 0; i < nn - kk + 1; i++) - { - lambda[i] = index_of[lambda[i]]; - if(lambda[i] != a0) degLambda = i; - } - - /* - * Find roots of the error+erasure locator polynomial. By Chien - * Search - */ - int temp = reg[0]; - Copy(ref reg, ref lambda, nn - kk); - reg[0] = temp; - count = 0; /* Number of roots of lambda(x) */ - for(i = 1; i <= nn; i++) - { - q = 1; - for(j = degLambda; j > 0; j--) - if(reg[j] != a0) - { - reg[j] = Modnn(reg[j] + j); - q ^= alpha_to[reg[j]]; - } - - if(q != 0) continue; - - /* store root (index-form) and error location number */ - root[count] = i; - loc[count] = nn - i; - count++; - } - - #if DEBUG - DicConsole.DebugWriteLine("Reed Solomon", "\n Final error positions:\t"); - for(i = 0; i < count; i++) DicConsole.DebugWriteLine("Reed Solomon", "{0} ", loc[i]); - - DicConsole.DebugWriteLine("Reed Solomon", "\n"); - #endif - - if(degLambda != count) return -1; - - /* - * Compute err+eras evaluator poly omega(x) = s(x)*lambda(x) (modulo - * x**(NN-KK)). in index form. Also find deg(omega). - */ - int degOmega = 0; - for(i = 0; i < nn - kk; i++) - { - tmp = 0; - j = degLambda < i ? degLambda : i; - for(; j >= 0; j--) - if(s[i + 1 - j] != a0 && lambda[j] != a0) - tmp ^= alpha_to[Modnn(s[i + 1 - j] + lambda[j])]; - - if(tmp != 0) degOmega = i; - omega[i] = index_of[tmp]; - } - - omega[nn - kk] = a0; - - /* - * Compute error values in poly-form. num1 = omega(inv(X(l))), num2 = - * inv(X(l))**(B0-1) and den = lambda_pr(inv(X(l))) all in poly-form - */ - for(j = count - 1; j >= 0; j--) - { - int num1 = 0; - for(i = degOmega; i >= 0; i--) - if(omega[i] != a0) - num1 ^= alpha_to[Modnn(omega[i] + i * root[j])]; - - int num2 = alpha_to[Modnn(root[j] * (B0 - 1) + nn)]; - int den = 0; - - /* lambda[i+1] for i even is the formal derivative lambda_pr of lambda[i] */ - for(i = Min(degLambda, nn - kk - 1) & ~1; i >= 0; i -= 2) - if(lambda[i + 1] != a0) - den ^= alpha_to[Modnn(lambda[i + 1] + i * root[j])]; - - if(den == 0) - { - DicConsole.DebugWriteLine("Reed Solomon", "\n ERROR: denominator = 0\n"); - return -1; - } - - /* Apply error to data */ - if(num1 != 0) data[loc[j]] ^= alpha_to[Modnn(index_of[num1] + index_of[num2] + nn - index_of[den])]; - } - - return count; - } - } -} \ No newline at end of file diff --git a/DiscImageChef.Checksums/Register.cs b/DiscImageChef.Checksums/Register.cs deleted file mode 100644 index 7dcaa28d8..000000000 --- a/DiscImageChef.Checksums/Register.cs +++ /dev/null @@ -1,71 +0,0 @@ -// /*************************************************************************** -// The Disc Image Chef -// ---------------------------------------------------------------------------- -// -// Filename : Register.cs -// Author(s) : Natalia Portillo -// -// Component : Core algorithms. -// -// --[ Description ] ---------------------------------------------------------- -// -// Registers all plugins in this assembly. -// -// --[ License ] -------------------------------------------------------------- -// -// 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 © 2011-2020 Natalia Portillo -// ****************************************************************************/ - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Reflection; -using DiscImageChef.CommonTypes.Interfaces; - -namespace DiscImageChef.Checksums -{ - public class Register : IPluginRegister - { - public List GetAllChecksumPlugins() - { - return Assembly.GetExecutingAssembly().GetTypes().Where(t => t.GetInterfaces().Contains(typeof(IChecksum))) - .Where(t => t.IsClass).ToList(); - } - - public List GetAllFilesystemPlugins() => null; - - public List GetAllFilterPlugins() => null; - - public List GetAllFloppyImagePlugins() => null; - - public List GetAllMediaImagePlugins() => null; - - public List GetAllPartitionPlugins() => null; - - public List GetAllReadOnlyFilesystemPlugins() => null; - - public List GetAllWritableFloppyImagePlugins() => null; - - public List GetAllWritableImagePlugins() => null; - } -} \ No newline at end of file diff --git a/DiscImageChef.Checksums/SHA1Context.cs b/DiscImageChef.Checksums/SHA1Context.cs deleted file mode 100644 index ea81a8430..000000000 --- a/DiscImageChef.Checksums/SHA1Context.cs +++ /dev/null @@ -1,152 +0,0 @@ -// /*************************************************************************** -// The Disc Image Chef -// ---------------------------------------------------------------------------- -// -// Filename : SHA1Context.cs -// Author(s) : Natalia Portillo -// -// Component : Checksums. -// -// --[ Description ] ---------------------------------------------------------- -// -// Wraps up .NET SHA1 implementation to a Init(), Update(), Final() context. -// -// --[ 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 . -// -// ---------------------------------------------------------------------------- -// Copyright © 2011-2020 Natalia Portillo -// ****************************************************************************/ - -using System.IO; -using System.Security.Cryptography; -using System.Text; -using DiscImageChef.CommonTypes.Interfaces; - -namespace DiscImageChef.Checksums -{ - /// - /// Wraps up .NET SHA1 implementation to a Init(), Update(), Final() context. - /// - public class Sha1Context : IChecksum - { - SHA1 sha1Provider; - - /// - /// Initializes the SHA1 hash provider - /// - public Sha1Context() - { - sha1Provider = SHA1.Create(); - } - - /// - /// Updates the hash with data. - /// - /// Data buffer. - /// Length of buffer to hash. - public void Update(byte[] data, uint len) - { - sha1Provider.TransformBlock(data, 0, (int)len, data, 0); - } - - /// - /// Updates the hash with data. - /// - /// Data buffer. - public void Update(byte[] data) - { - Update(data, (uint)data.Length); - } - - /// - /// Returns a byte array of the hash value. - /// - public byte[] Final() - { - sha1Provider.TransformFinalBlock(new byte[0], 0, 0); - return sha1Provider.Hash; - } - - /// - /// Returns a hexadecimal representation of the hash value. - /// - public string End() - { - sha1Provider.TransformFinalBlock(new byte[0], 0, 0); - StringBuilder sha1Output = new StringBuilder(); - - foreach(byte h in sha1Provider.Hash) sha1Output.Append(h.ToString("x2")); - - return sha1Output.ToString(); - } - - /// - /// Gets the hash of a file - /// - /// File path. - public static byte[] File(string filename) - { - SHA1 localSha1Provider = SHA1.Create(); - FileStream fileStream = new FileStream(filename, FileMode.Open); - byte[] result = localSha1Provider.ComputeHash(fileStream); - fileStream.Close(); - return result; - } - - /// - /// Gets the hash of a file in hexadecimal and as a byte array. - /// - /// File path. - /// Byte array of the hash value. - public static string File(string filename, out byte[] hash) - { - SHA1 localSha1Provider = SHA1.Create(); - FileStream fileStream = new FileStream(filename, FileMode.Open); - hash = localSha1Provider.ComputeHash(fileStream); - StringBuilder sha1Output = new StringBuilder(); - - foreach(byte h in hash) sha1Output.Append(h.ToString("x2")); - - fileStream.Close(); - - return sha1Output.ToString(); - } - - /// - /// Gets the hash of the specified data buffer. - /// - /// Data buffer. - /// Length of the data buffer to hash. - /// Byte array of the hash value. - public static string Data(byte[] data, uint len, out byte[] hash) - { - SHA1 localSha1Provider = SHA1.Create(); - hash = localSha1Provider.ComputeHash(data, 0, (int)len); - StringBuilder sha1Output = new StringBuilder(); - - foreach(byte h in hash) sha1Output.Append(h.ToString("x2")); - - return sha1Output.ToString(); - } - - /// - /// Gets the hash of the specified data buffer. - /// - /// Data buffer. - /// Byte array of the hash value. - public static string Data(byte[] data, out byte[] hash) => Data(data, (uint)data.Length, out hash); - } -} \ No newline at end of file diff --git a/DiscImageChef.Checksums/SHA256Context.cs b/DiscImageChef.Checksums/SHA256Context.cs deleted file mode 100644 index 62406d068..000000000 --- a/DiscImageChef.Checksums/SHA256Context.cs +++ /dev/null @@ -1,152 +0,0 @@ -// /*************************************************************************** -// The Disc Image Chef -// ---------------------------------------------------------------------------- -// -// Filename : SHA256Context.cs -// Author(s) : Natalia Portillo -// -// Component : Checksums. -// -// --[ Description ] ---------------------------------------------------------- -// -// Wraps up .NET SHA256 implementation to a Init(), Update(), Final() context. -// -// --[ 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 . -// -// ---------------------------------------------------------------------------- -// Copyright © 2011-2020 Natalia Portillo -// ****************************************************************************/ - -using System.IO; -using System.Security.Cryptography; -using System.Text; -using DiscImageChef.CommonTypes.Interfaces; - -namespace DiscImageChef.Checksums -{ - /// - /// Wraps up .NET SHA256 implementation to a Init(), Update(), Final() context. - /// - public class Sha256Context : IChecksum - { - SHA256 sha256Provider; - - /// - /// Initializes the SHA256 hash provider - /// - public Sha256Context() - { - sha256Provider = SHA256.Create(); - } - - /// - /// Updates the hash with data. - /// - /// Data buffer. - /// Length of buffer to hash. - public void Update(byte[] data, uint len) - { - sha256Provider.TransformBlock(data, 0, (int)len, data, 0); - } - - /// - /// Updates the hash with data. - /// - /// Data buffer. - public void Update(byte[] data) - { - Update(data, (uint)data.Length); - } - - /// - /// Returns a byte array of the hash value. - /// - public byte[] Final() - { - sha256Provider.TransformFinalBlock(new byte[0], 0, 0); - return sha256Provider.Hash; - } - - /// - /// Returns a hexadecimal representation of the hash value. - /// - public string End() - { - sha256Provider.TransformFinalBlock(new byte[0], 0, 0); - StringBuilder sha256Output = new StringBuilder(); - - foreach(byte h in sha256Provider.Hash) sha256Output.Append(h.ToString("x2")); - - return sha256Output.ToString(); - } - - /// - /// Gets the hash of a file - /// - /// File path. - public static byte[] File(string filename) - { - SHA256 localSha256Provider = SHA256.Create(); - FileStream fileStream = new FileStream(filename, FileMode.Open); - byte[] result = localSha256Provider.ComputeHash(fileStream); - fileStream.Close(); - return result; - } - - /// - /// Gets the hash of a file in hexadecimal and as a byte array. - /// - /// File path. - /// Byte array of the hash value. - public static string File(string filename, out byte[] hash) - { - SHA256 localSha256Provider = SHA256.Create(); - FileStream fileStream = new FileStream(filename, FileMode.Open); - hash = localSha256Provider.ComputeHash(fileStream); - StringBuilder sha256Output = new StringBuilder(); - - foreach(byte h in hash) sha256Output.Append(h.ToString("x2")); - - fileStream.Close(); - - return sha256Output.ToString(); - } - - /// - /// Gets the hash of the specified data buffer. - /// - /// Data buffer. - /// Length of the data buffer to hash. - /// Byte array of the hash value. - public static string Data(byte[] data, uint len, out byte[] hash) - { - SHA256 localSha256Provider = SHA256.Create(); - hash = localSha256Provider.ComputeHash(data, 0, (int)len); - StringBuilder sha256Output = new StringBuilder(); - - foreach(byte h in hash) sha256Output.Append(h.ToString("x2")); - - return sha256Output.ToString(); - } - - /// - /// Gets the hash of the specified data buffer. - /// - /// Data buffer. - /// Byte array of the hash value. - public static string Data(byte[] data, out byte[] hash) => Data(data, (uint)data.Length, out hash); - } -} \ No newline at end of file diff --git a/DiscImageChef.Checksums/SHA384Context.cs b/DiscImageChef.Checksums/SHA384Context.cs deleted file mode 100644 index 2939a0952..000000000 --- a/DiscImageChef.Checksums/SHA384Context.cs +++ /dev/null @@ -1,152 +0,0 @@ -// /*************************************************************************** -// The Disc Image Chef -// ---------------------------------------------------------------------------- -// -// Filename : SHA384Context.cs -// Author(s) : Natalia Portillo -// -// Component : Checksums. -// -// --[ Description ] ---------------------------------------------------------- -// -// Wraps up .NET SHA384 implementation to a Init(), Update(), Final() context. -// -// --[ 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 . -// -// ---------------------------------------------------------------------------- -// Copyright © 2011-2020 Natalia Portillo -// ****************************************************************************/ - -using System.IO; -using System.Security.Cryptography; -using System.Text; -using DiscImageChef.CommonTypes.Interfaces; - -namespace DiscImageChef.Checksums -{ - /// - /// Wraps up .NET SHA384 implementation to a Init(), Update(), Final() context. - /// - public class Sha384Context : IChecksum - { - SHA384 sha384Provider; - - /// - /// Initializes the SHA384 hash provider - /// - public Sha384Context() - { - sha384Provider = SHA384.Create(); - } - - /// - /// Updates the hash with data. - /// - /// Data buffer. - /// Length of buffer to hash. - public void Update(byte[] data, uint len) - { - sha384Provider.TransformBlock(data, 0, (int)len, data, 0); - } - - /// - /// Updates the hash with data. - /// - /// Data buffer. - public void Update(byte[] data) - { - Update(data, (uint)data.Length); - } - - /// - /// Returns a byte array of the hash value. - /// - public byte[] Final() - { - sha384Provider.TransformFinalBlock(new byte[0], 0, 0); - return sha384Provider.Hash; - } - - /// - /// Returns a hexadecimal representation of the hash value. - /// - public string End() - { - sha384Provider.TransformFinalBlock(new byte[0], 0, 0); - StringBuilder sha384Output = new StringBuilder(); - - foreach(byte h in sha384Provider.Hash) sha384Output.Append(h.ToString("x2")); - - return sha384Output.ToString(); - } - - /// - /// Gets the hash of a file - /// - /// File path. - public static byte[] File(string filename) - { - SHA384 localSha384Provider = SHA384.Create(); - FileStream fileStream = new FileStream(filename, FileMode.Open); - byte[] result = localSha384Provider.ComputeHash(fileStream); - fileStream.Close(); - return result; - } - - /// - /// Gets the hash of a file in hexadecimal and as a byte array. - /// - /// File path. - /// Byte array of the hash value. - public static string File(string filename, out byte[] hash) - { - SHA384 localSha384Provider = SHA384.Create(); - FileStream fileStream = new FileStream(filename, FileMode.Open); - hash = localSha384Provider.ComputeHash(fileStream); - StringBuilder sha384Output = new StringBuilder(); - - foreach(byte h in hash) sha384Output.Append(h.ToString("x2")); - - fileStream.Close(); - - return sha384Output.ToString(); - } - - /// - /// Gets the hash of the specified data buffer. - /// - /// Data buffer. - /// Length of the data buffer to hash. - /// Byte array of the hash value. - public static string Data(byte[] data, uint len, out byte[] hash) - { - SHA384 localSha384Provider = SHA384.Create(); - hash = localSha384Provider.ComputeHash(data, 0, (int)len); - StringBuilder sha384Output = new StringBuilder(); - - foreach(byte h in hash) sha384Output.Append(h.ToString("x2")); - - return sha384Output.ToString(); - } - - /// - /// Gets the hash of the specified data buffer. - /// - /// Data buffer. - /// Byte array of the hash value. - public static string Data(byte[] data, out byte[] hash) => Data(data, (uint)data.Length, out hash); - } -} \ No newline at end of file diff --git a/DiscImageChef.Checksums/SHA512Context.cs b/DiscImageChef.Checksums/SHA512Context.cs deleted file mode 100644 index 2f1c57ed3..000000000 --- a/DiscImageChef.Checksums/SHA512Context.cs +++ /dev/null @@ -1,152 +0,0 @@ -// /*************************************************************************** -// The Disc Image Chef -// ---------------------------------------------------------------------------- -// -// Filename : SHA512Context.cs -// Author(s) : Natalia Portillo -// -// Component : Checksums. -// -// --[ Description ] ---------------------------------------------------------- -// -// Wraps up .NET SHA512 implementation to a Init(), Update(), Final() context. -// -// --[ 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 . -// -// ---------------------------------------------------------------------------- -// Copyright © 2011-2020 Natalia Portillo -// ****************************************************************************/ - -using System.IO; -using System.Security.Cryptography; -using System.Text; -using DiscImageChef.CommonTypes.Interfaces; - -namespace DiscImageChef.Checksums -{ - /// - /// Wraps up .NET SHA512 implementation to a Init(), Update(), Final() context. - /// - public class Sha512Context : IChecksum - { - SHA512 sha512Provider; - - /// - /// Initializes the SHA512 hash provider - /// - public Sha512Context() - { - sha512Provider = SHA512.Create(); - } - - /// - /// Updates the hash with data. - /// - /// Data buffer. - /// Length of buffer to hash. - public void Update(byte[] data, uint len) - { - sha512Provider.TransformBlock(data, 0, (int)len, data, 0); - } - - /// - /// Updates the hash with data. - /// - /// Data buffer. - public void Update(byte[] data) - { - Update(data, (uint)data.Length); - } - - /// - /// Returns a byte array of the hash value. - /// - public byte[] Final() - { - sha512Provider.TransformFinalBlock(new byte[0], 0, 0); - return sha512Provider.Hash; - } - - /// - /// Returns a hexadecimal representation of the hash value. - /// - public string End() - { - sha512Provider.TransformFinalBlock(new byte[0], 0, 0); - StringBuilder sha512Output = new StringBuilder(); - - foreach(byte h in sha512Provider.Hash) sha512Output.Append(h.ToString("x2")); - - return sha512Output.ToString(); - } - - /// - /// Gets the hash of a file - /// - /// File path. - public static byte[] File(string filename) - { - SHA512 localSha512Provider = SHA512.Create(); - FileStream fileStream = new FileStream(filename, FileMode.Open); - byte[] result = localSha512Provider.ComputeHash(fileStream); - fileStream.Close(); - return result; - } - - /// - /// Gets the hash of a file in hexadecimal and as a byte array. - /// - /// File path. - /// Byte array of the hash value. - public static string File(string filename, out byte[] hash) - { - SHA512 localSha512Provider = SHA512.Create(); - FileStream fileStream = new FileStream(filename, FileMode.Open); - hash = localSha512Provider.ComputeHash(fileStream); - StringBuilder sha512Output = new StringBuilder(); - - foreach(byte h in hash) sha512Output.Append(h.ToString("x2")); - - fileStream.Close(); - - return sha512Output.ToString(); - } - - /// - /// Gets the hash of the specified data buffer. - /// - /// Data buffer. - /// Length of the data buffer to hash. - /// Byte array of the hash value. - public static string Data(byte[] data, uint len, out byte[] hash) - { - SHA512 localSha512Provider = SHA512.Create(); - hash = localSha512Provider.ComputeHash(data, 0, (int)len); - StringBuilder sha512Output = new StringBuilder(); - - foreach(byte h in hash) sha512Output.Append(h.ToString("x2")); - - return sha512Output.ToString(); - } - - /// - /// Gets the hash of the specified data buffer. - /// - /// Data buffer. - /// Byte array of the hash value. - public static string Data(byte[] data, out byte[] hash) => Data(data, (uint)data.Length, out hash); - } -} \ No newline at end of file diff --git a/DiscImageChef.Checksums/SpamSumContext.cs b/DiscImageChef.Checksums/SpamSumContext.cs deleted file mode 100644 index 5b551e90e..000000000 --- a/DiscImageChef.Checksums/SpamSumContext.cs +++ /dev/null @@ -1,484 +0,0 @@ -// /*************************************************************************** -// The Disc Image Chef -// ---------------------------------------------------------------------------- -// -// Filename : SpamSumContext.cs -// Author(s) : Natalia Portillo -// -// Component : Checksums. -// -// --[ Description ] ---------------------------------------------------------- -// -// Implements the SpamSum fuzzy hashing 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 . -// -// ---------------------------------------------------------------------------- -// Copyright © 2011-2020 Natalia Portillo -// ****************************************************************************/ - -// Based on ssdeep -// Copyright (C) 2002 Andrew Tridgell -// Copyright (C) 2006 ManTech International Corporation -// Copyright (C) 2013 Helmut Grohne -// -// Earlier versions of this code were named fuzzy.c and can be found at: -// http://www.samba.org/ftp/unpacked/junkcode/spamsum/ -// http://ssdeep.sf.net/ - -using System; -using System.Runtime.CompilerServices; -using System.Text; -using DiscImageChef.CommonTypes.Interfaces; - -namespace DiscImageChef.Checksums -{ - /// - /// Implements the SpamSum fuzzy hashing algorithm. - /// - public class SpamSumContext : IChecksum - { - const uint ROLLING_WINDOW = 7; - const uint MIN_BLOCKSIZE = 3; - const uint HASH_PRIME = 0x01000193; - const uint HASH_INIT = 0x28021967; - const uint NUM_BLOCKHASHES = 31; - const uint SPAMSUM_LENGTH = 64; - const uint FUZZY_MAX_RESULT = 2 * SPAMSUM_LENGTH + 20; - //"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; - readonly byte[] b64 = - { - 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50, 0x51, - 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, - 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, - 0x7A, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x2B, 0x2F - }; - - FuzzyState self; - - /// - /// Initializes the SpamSum structures - /// - public SpamSumContext() - { - self = new FuzzyState {Bh = new BlockhashContext[NUM_BLOCKHASHES]}; - for(int i = 0; i < NUM_BLOCKHASHES; i++) self.Bh[i].Digest = new byte[SPAMSUM_LENGTH]; - - self.Bhstart = 0; - self.Bhend = 1; - self.Bh[0].H = HASH_INIT; - self.Bh[0].Halfh = HASH_INIT; - self.Bh[0].Digest[0] = 0; - self.Bh[0].Halfdigest = 0; - self.Bh[0].Dlen = 0; - self.TotalSize = 0; - roll_init(); - } - - /// - /// Updates the hash with data. - /// - /// Data buffer. - /// Length of buffer to hash. - public void Update(byte[] data, uint len) - { - self.TotalSize += len; - for(int i = 0; i < len; i++) fuzzy_engine_step(data[i]); - } - - /// - /// Updates the hash with data. - /// - /// Data buffer. - public void Update(byte[] data) - { - Update(data, (uint)data.Length); - } - - /// - /// Returns a byte array of the hash value. - /// - public byte[] Final() => throw new NotImplementedException("SpamSum does not have a binary representation."); - - /// - /// Returns a base64 representation of the hash value. - /// - public string End() - { - FuzzyDigest(out byte[] result); - - return CToString(result); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - void roll_init() - { - self.Roll = new RollState {Window = new byte[ROLLING_WINDOW]}; - } - - /* - * a rolling hash, based on the Adler checksum. By using a rolling hash - * we can perform auto resynchronisation after inserts/deletes - - * internally, h1 is the sum of the bytes in the window and h2 - * is the sum of the bytes times the index - - * h3 is a shift/xor based rolling hash, and is mostly needed to ensure that - * we can cope with large blocksize values - */ - [MethodImpl(MethodImplOptions.AggressiveInlining)] - void roll_hash(byte c) - { - self.Roll.H2 -= self.Roll.H1; - self.Roll.H2 += ROLLING_WINDOW * c; - - self.Roll.H1 += c; - self.Roll.H1 -= self.Roll.Window[self.Roll.N % ROLLING_WINDOW]; - - self.Roll.Window[self.Roll.N % ROLLING_WINDOW] = c; - self.Roll.N++; - - /* The original spamsum AND'ed this value with 0xFFFFFFFF which - * in theory should have no effect. This AND has been removed - * for performance (jk) */ - self.Roll.H3 <<= 5; - self.Roll.H3 ^= c; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - uint roll_sum() => self.Roll.H1 + self.Roll.H2 + self.Roll.H3; - - /* A simple non-rolling hash, based on the FNV hash. */ - [MethodImpl(MethodImplOptions.AggressiveInlining)] - static uint sum_hash(byte c, uint h) => (h * HASH_PRIME) ^ c; - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - static uint SSDEEP_BS(uint index) => MIN_BLOCKSIZE << (int)index; - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - void fuzzy_try_fork_blockhash() - { - if(self.Bhend >= NUM_BLOCKHASHES) return; - - if(self.Bhend == 0) // assert - throw new Exception("Assertion failed"); - - uint obh = self.Bhend - 1; - uint nbh = self.Bhend; - self.Bh[nbh].H = self.Bh[obh].H; - self.Bh[nbh].Halfh = self.Bh[obh].Halfh; - self.Bh[nbh].Digest[0] = 0; - self.Bh[nbh].Halfdigest = 0; - self.Bh[nbh].Dlen = 0; - ++self.Bhend; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - void fuzzy_try_reduce_blockhash() - { - if(self.Bhstart >= self.Bhend) throw new Exception("Assertion failed"); - - if(self.Bhend - self.Bhstart < 2) - /* Need at least two working hashes. */ return; - if((ulong)SSDEEP_BS(self.Bhstart) * SPAMSUM_LENGTH >= self.TotalSize) - /* Initial blocksize estimate would select this or a smaller - * blocksize. */ return; - if(self.Bh[self.Bhstart + 1].Dlen < SPAMSUM_LENGTH / 2) - /* Estimate adjustment would select this blocksize. */ return; - - /* At this point we are clearly no longer interested in the - * start_blocksize. Get rid of it. */ - ++self.Bhstart; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - void fuzzy_engine_step(byte c) - { - uint i; - /* At each character we update the rolling hash and the normal hashes. - * When the rolling hash hits a reset value then we emit a normal hash - * as a element of the signature and reset the normal hash. */ - roll_hash(c); - ulong h = roll_sum(); - - for(i = self.Bhstart; i < self.Bhend; ++i) - { - self.Bh[i].H = sum_hash(c, self.Bh[i].H); - self.Bh[i].Halfh = sum_hash(c, self.Bh[i].Halfh); - } - - for(i = self.Bhstart; i < self.Bhend; ++i) - { - /* With growing blocksize almost no runs fail the next test. */ - if(h % SSDEEP_BS(i) != SSDEEP_BS(i) - 1) - /* Once this condition is false for one bs, it is - * automatically false for all further bs. I.e. if - * h === -1 (mod 2*bs) then h === -1 (mod bs). */ break; - - /* We have hit a reset point. We now emit hashes which are - * based on all characters in the piece of the message between - * the last reset point and this one */ - if(0 == self.Bh[i].Dlen) fuzzy_try_fork_blockhash(); - self.Bh[i].Digest[self.Bh[i].Dlen] = b64[self.Bh[i].H % 64]; - self.Bh[i].Halfdigest = b64[self.Bh[i].Halfh % 64]; - if(self.Bh[i].Dlen < SPAMSUM_LENGTH - 1) - { - /* We can have a problem with the tail overflowing. The - * easiest way to cope with this is to only reset the - * normal hash if we have room for more characters in - * our signature. This has the effect of combining the - * last few pieces of the message into a single piece - * */ - self.Bh[i].Digest[++self.Bh[i].Dlen] = 0; - self.Bh[i].H = HASH_INIT; - if(self.Bh[i].Dlen >= SPAMSUM_LENGTH / 2) continue; - - self.Bh[i].Halfh = HASH_INIT; - self.Bh[i].Halfdigest = 0; - } - else fuzzy_try_reduce_blockhash(); - } - } - - // CLAUNIA: Flags seems to never be used in ssdeep, so I just removed it for code simplicity - [MethodImpl(MethodImplOptions.AggressiveInlining)] - uint FuzzyDigest(out byte[] result) - { - StringBuilder sb = new StringBuilder(); - uint bi = self.Bhstart; - uint h = roll_sum(); - int remain = (int)(FUZZY_MAX_RESULT - 1); /* Exclude terminating '\0'. */ - result = new byte[FUZZY_MAX_RESULT]; - /* Verify that our elimination was not overeager. */ - if(!(bi == 0 || (ulong)SSDEEP_BS(bi) / 2 * SPAMSUM_LENGTH < self.TotalSize)) - throw new Exception("Assertion failed"); - - int resultOff = 0; - - /* Initial blocksize guess. */ - while((ulong)SSDEEP_BS(bi) * SPAMSUM_LENGTH < self.TotalSize) - { - ++bi; - if(bi >= NUM_BLOCKHASHES) throw new OverflowException("The input exceeds data types."); - } - - /* Adapt blocksize guess to actual digest length. */ - while(bi >= self.Bhend) --bi; - while(bi > self.Bhstart && self.Bh[bi].Dlen < SPAMSUM_LENGTH / 2) --bi; - - if(bi > 0 && self.Bh[bi].Dlen < SPAMSUM_LENGTH / 2) throw new Exception("Assertion failed"); - - sb.AppendFormat("{0}:", SSDEEP_BS(bi)); - int i = Encoding.ASCII.GetBytes(sb.ToString()).Length; - if(i <= 0) - /* Maybe snprintf has set errno here? */ throw new OverflowException("The input exceeds data types."); - if(i >= remain) throw new Exception("Assertion failed"); - - remain -= i; - - Array.Copy(Encoding.ASCII.GetBytes(sb.ToString()), 0, result, 0, i); - - resultOff += i; - - i = (int)self.Bh[bi].Dlen; - if(i > remain) throw new Exception("Assertion failed"); - - Array.Copy(self.Bh[bi].Digest, 0, result, resultOff, i); - resultOff += i; - remain -= i; - if(h != 0) - { - if(remain <= 0) throw new Exception("Assertion failed"); - - result[resultOff] = b64[self.Bh[bi].H % 64]; - if(i < 3 || result[resultOff] != result[resultOff - 1] || - result[resultOff] != result[resultOff - 2] || - result[resultOff] != result[resultOff - 3]) - { - ++resultOff; - --remain; - } - } - else if(self.Bh[bi].Digest[i] != 0) - { - if(remain <= 0) throw new Exception("Assertion failed"); - - result[resultOff] = self.Bh[bi].Digest[i]; - if(i < 3 || result[resultOff] != result[resultOff - 1] || - result[resultOff] != result[resultOff - 2] || - result[resultOff] != result[resultOff - 3]) - { - ++resultOff; - --remain; - } - } - - if(remain <= 0) throw new Exception("Assertion failed"); - - result[resultOff++] = 0x3A; // ':' - --remain; - if(bi < self.Bhend - 1) - { - ++bi; - i = (int)self.Bh[bi].Dlen; - if(i > remain) throw new Exception("Assertion failed"); - - Array.Copy(self.Bh[bi].Digest, 0, result, resultOff, i); - resultOff += i; - remain -= i; - - if(h != 0) - { - if(remain <= 0) throw new Exception("Assertion failed"); - - h = self.Bh[bi].Halfh; - result[resultOff] = b64[h % 64]; - if(i < 3 || result[resultOff] != result[resultOff - 1] || - result[resultOff] != result[resultOff - 2] || - result[resultOff] != result[resultOff - 3]) - { - ++resultOff; - --remain; - } - } - else - { - i = self.Bh[bi].Halfdigest; - if(i != 0) - { - if(remain <= 0) throw new Exception("Assertion failed"); - - result[resultOff] = (byte)i; - if(i < 3 || result[resultOff] != result[resultOff - 1] || - result[resultOff] != result[resultOff - 2] || - result[resultOff] != result[resultOff - 3]) - { - ++resultOff; - --remain; - } - } - } - } - else if(h != 0) - { - if(self.Bh[bi].Dlen != 0) throw new Exception("Assertion failed"); - if(remain <= 0) throw new Exception("Assertion failed"); - - result[resultOff++] = b64[self.Bh[bi].H % 64]; - /* No need to bother with FUZZY_FLAG_ELIMSEQ, because this - * digest has length 1. */ - --remain; - } - - result[resultOff] = 0; - return 0; - } - - /// - /// Gets the hash of a file - /// - /// File path. - public static byte[] File(string filename) => - throw new NotImplementedException("SpamSum does not have a binary representation."); - - /// - /// Gets the hash of a file in hexadecimal and as a byte array. - /// - /// File path. - /// Byte array of the hash value. - public static string File(string filename, out byte[] hash) => - throw new NotImplementedException("Not yet implemented."); - - /// - /// Gets the hash of the specified data buffer. - /// - /// Data buffer. - /// Length of the data buffer to hash. - /// null - /// Base64 representation of SpamSum $blocksize:$hash:$hash - public static string Data(byte[] data, uint len, out byte[] hash) - { - SpamSumContext fuzzyContext = new SpamSumContext(); - - fuzzyContext.Update(data, len); - - hash = null; - - return fuzzyContext.End(); - } - - /// - /// Gets the hash of the specified data buffer. - /// - /// Data buffer. - /// null - /// Base64 representation of SpamSum $blocksize:$hash:$hash - public static string Data(byte[] data, out byte[] hash) => Data(data, (uint)data.Length, out hash); - - // Converts an ASCII null-terminated string to .NET string - [MethodImpl(MethodImplOptions.AggressiveInlining)] - static string CToString(byte[] cString) - { - int count = 0; - - // ReSharper disable once LoopCanBeConvertedToQuery - // LINQ is six times slower - foreach(byte c in cString) - { - if(c == 0) break; - - count++; - } - - return Encoding.ASCII.GetString(cString, 0, count); - } - - struct RollState - { - public byte[] Window; - // ROLLING_WINDOW - public uint H1; - public uint H2; - public uint H3; - public uint N; - } - - /* A blockhash contains a signature state for a specific (implicit) blocksize. - * The blocksize is given by SSDEEP_BS(index). The h and halfh members are the - * FNV hashes, where halfh stops to be reset after digest is SPAMSUM_LENGTH/2 - * long. The halfh hash is needed be able to truncate digest for the second - * output hash to stay compatible with ssdeep output. */ - struct BlockhashContext - { - public uint H; - public uint Halfh; - public byte[] Digest; - // SPAMSUM_LENGTH - public byte Halfdigest; - public uint Dlen; - } - - struct FuzzyState - { - public uint Bhstart; - public uint Bhend; - public BlockhashContext[] Bh; - //NUM_BLOCKHASHES - public ulong TotalSize; - public RollState Roll; - } - } -} \ No newline at end of file