Code restyling.

This commit is contained in:
2020-02-29 18:03:33 +00:00
parent 2d5bc1f8ed
commit 5f2ddad918
15 changed files with 690 additions and 739 deletions

View File

@@ -36,26 +36,20 @@ using Aaru.CommonTypes.Interfaces;
namespace Aaru.Checksums namespace Aaru.Checksums
{ {
/// <summary> /// <summary>Implements the Adler-32 algorithm</summary>
/// Implements the Adler-32 algorithm
/// </summary>
public class Adler32Context : IChecksum public class Adler32Context : IChecksum
{ {
const ushort ADLER_MODULE = 65521; const ushort ADLER_MODULE = 65521;
ushort sum1, sum2; ushort sum1, sum2;
/// <summary> /// <summary>Initializes the Adler-32 sums</summary>
/// Initializes the Adler-32 sums
/// </summary>
public Adler32Context() public Adler32Context()
{ {
sum1 = 1; sum1 = 1;
sum2 = 0; sum2 = 0;
} }
/// <summary> /// <summary>Updates the hash with data.</summary>
/// Updates the hash with data.
/// </summary>
/// <param name="data">Data buffer.</param> /// <param name="data">Data buffer.</param>
/// <param name="len">Length of buffer to hash.</param> /// <param name="len">Length of buffer to hash.</param>
public void Update(byte[] data, uint len) public void Update(byte[] data, uint len)
@@ -67,31 +61,23 @@ namespace Aaru.Checksums
} }
} }
/// <summary> /// <summary>Updates the hash with data.</summary>
/// Updates the hash with data.
/// </summary>
/// <param name="data">Data buffer.</param> /// <param name="data">Data buffer.</param>
public void Update(byte[] data) public void Update(byte[] data) => Update(data, (uint)data.Length);
{
Update(data, (uint)data.Length);
}
/// <summary> /// <summary>Returns a byte array of the hash value.</summary>
/// Returns a byte array of the hash value.
/// </summary>
public byte[] Final() public byte[] Final()
{ {
uint finalSum = (uint)((sum2 << 16) | sum1); uint finalSum = (uint)((sum2 << 16) | sum1);
return BigEndianBitConverter.GetBytes(finalSum); return BigEndianBitConverter.GetBytes(finalSum);
} }
/// <summary> /// <summary>Returns a hexadecimal representation of the hash value.</summary>
/// Returns a hexadecimal representation of the hash value.
/// </summary>
public string End() public string End()
{ {
uint finalSum = (uint)((sum2 << 16) | sum1); uint finalSum = (uint)((sum2 << 16) | sum1);
StringBuilder adlerOutput = new StringBuilder(); var adlerOutput = new StringBuilder();
for(int i = 0; i < BigEndianBitConverter.GetBytes(finalSum).Length; i++) for(int i = 0; i < BigEndianBitConverter.GetBytes(finalSum).Length; i++)
adlerOutput.Append(BigEndianBitConverter.GetBytes(finalSum)[i].ToString("x2")); adlerOutput.Append(BigEndianBitConverter.GetBytes(finalSum)[i].ToString("x2"));
@@ -99,24 +85,21 @@ namespace Aaru.Checksums
return adlerOutput.ToString(); return adlerOutput.ToString();
} }
/// <summary> /// <summary>Gets the hash of a file</summary>
/// Gets the hash of a file
/// </summary>
/// <param name="filename">File path.</param> /// <param name="filename">File path.</param>
public static byte[] File(string filename) public static byte[] File(string filename)
{ {
File(filename, out byte[] hash); File(filename, out byte[] hash);
return hash; return hash;
} }
/// <summary> /// <summary>Gets the hash of a file in hexadecimal and as a byte array.</summary>
/// Gets the hash of a file in hexadecimal and as a byte array.
/// </summary>
/// <param name="filename">File path.</param> /// <param name="filename">File path.</param>
/// <param name="hash">Byte array of the hash value.</param> /// <param name="hash">Byte array of the hash value.</param>
public static string File(string filename, out byte[] hash) public static string File(string filename, out byte[] hash)
{ {
FileStream fileStream = new FileStream(filename, FileMode.Open); var fileStream = new FileStream(filename, FileMode.Open);
ushort localSum1 = 1; ushort localSum1 = 1;
ushort localSum2 = 0; ushort localSum2 = 0;
@@ -131,18 +114,17 @@ namespace Aaru.Checksums
hash = BigEndianBitConverter.GetBytes(finalSum); hash = BigEndianBitConverter.GetBytes(finalSum);
StringBuilder adlerOutput = new StringBuilder(); var adlerOutput = new StringBuilder();
foreach(byte h in hash) adlerOutput.Append(h.ToString("x2")); foreach(byte h in hash)
adlerOutput.Append(h.ToString("x2"));
fileStream.Close(); fileStream.Close();
return adlerOutput.ToString(); return adlerOutput.ToString();
} }
/// <summary> /// <summary>Gets the hash of the specified data buffer.</summary>
/// Gets the hash of the specified data buffer.
/// </summary>
/// <param name="data">Data buffer.</param> /// <param name="data">Data buffer.</param>
/// <param name="len">Length of the data buffer to hash.</param> /// <param name="len">Length of the data buffer to hash.</param>
/// <param name="hash">Byte array of the hash value.</param> /// <param name="hash">Byte array of the hash value.</param>
@@ -161,16 +143,15 @@ namespace Aaru.Checksums
hash = BigEndianBitConverter.GetBytes(finalSum); hash = BigEndianBitConverter.GetBytes(finalSum);
StringBuilder adlerOutput = new StringBuilder(); var adlerOutput = new StringBuilder();
foreach(byte h in hash) adlerOutput.Append(h.ToString("x2")); foreach(byte h in hash)
adlerOutput.Append(h.ToString("x2"));
return adlerOutput.ToString(); return adlerOutput.ToString();
} }
/// <summary> /// <summary>Gets the hash of the specified data buffer.</summary>
/// Gets the hash of the specified data buffer.
/// </summary>
/// <param name="data">Data buffer.</param> /// <param name="data">Data buffer.</param>
/// <param name="hash">Byte array of the hash value.</param> /// <param name="hash">Byte array of the hash value.</param>
public static string Data(byte[] data, out byte[] hash) => Data(data, (uint)data.Length, out hash); public static string Data(byte[] data, out byte[] hash) => Data(data, (uint)data.Length, out hash);

View File

@@ -268,7 +268,8 @@ namespace Aaru.Checksums
AaruConsole.DebugWriteLine("CD checksums", AaruConsole.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}", "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); channel[0x00C], channel[0x00D], channel[0x00E], calculatedEdc,
storedEdc);
return false; return false;
} }
@@ -310,7 +311,8 @@ namespace Aaru.Checksums
AaruConsole.DebugWriteLine("CD checksums", AaruConsole.DebugWriteLine("CD checksums",
"Mode 1 sector at address: {0:X2}:{1:X2}:{2:X2}, got CRC 0x{3:X8} expected 0x{4:X8}", "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); channel[0x00C], channel[0x00D], channel[0x00E], calculatedEdc,
storedEdc);
return false; return false;
} }

View File

@@ -36,9 +36,7 @@ using Aaru.CommonTypes.Interfaces;
namespace Aaru.Checksums namespace Aaru.Checksums
{ {
/// <summary> /// <summary>Implements a CRC32 algorithm</summary>
/// Implements a CRC32 algorithm
/// </summary>
public class Crc32Context : IChecksum public class Crc32Context : IChecksum
{ {
const uint CRC32_ISO_POLY = 0xEDB88320; const uint CRC32_ISO_POLY = 0xEDB88320;
@@ -50,76 +48,70 @@ namespace Aaru.Checksums
readonly uint[] table; readonly uint[] table;
uint hashInt; uint hashInt;
/// <summary> /// <summary>Initializes the CRC32 table and seed as CRC32-ISO</summary>
/// Initializes the CRC32 table and seed as CRC32-ISO
/// </summary>
public Crc32Context() public Crc32Context()
{ {
hashInt = CRC32_ISO_SEED; hashInt = CRC32_ISO_SEED;
finalSeed = CRC32_ISO_SEED; finalSeed = CRC32_ISO_SEED;
table = new uint[256]; table = new uint[256];
for(int i = 0; i < 256; i++) for(int i = 0; i < 256; i++)
{ {
uint entry = (uint)i; uint entry = (uint)i;
for(int j = 0; j < 8; j++) for(int j = 0; j < 8; j++)
if((entry & 1) == 1) entry = (entry >> 1) ^ CRC32_ISO_POLY; if((entry & 1) == 1)
else entry = entry >> 1; entry = (entry >> 1) ^ CRC32_ISO_POLY;
else
entry = entry >> 1;
table[i] = entry; table[i] = entry;
} }
} }
/// <summary> /// <summary>Initializes the CRC32 table with a custom polynomial and seed</summary>
/// Initializes the CRC32 table with a custom polynomial and seed
/// </summary>
public Crc32Context(uint polynomial, uint seed) public Crc32Context(uint polynomial, uint seed)
{ {
hashInt = seed; hashInt = seed;
finalSeed = seed; finalSeed = seed;
table = new uint[256]; table = new uint[256];
for(int i = 0; i < 256; i++) for(int i = 0; i < 256; i++)
{ {
uint entry = (uint)i; uint entry = (uint)i;
for(int j = 0; j < 8; j++) for(int j = 0; j < 8; j++)
if((entry & 1) == 1) entry = (entry >> 1) ^ polynomial; if((entry & 1) == 1)
else entry = entry >> 1; entry = (entry >> 1) ^ polynomial;
else
entry = entry >> 1;
table[i] = entry; table[i] = entry;
} }
} }
/// <summary> /// <summary>Updates the hash with data.</summary>
/// Updates the hash with data.
/// </summary>
/// <param name="data">Data buffer.</param> /// <param name="data">Data buffer.</param>
/// <param name="len">Length of buffer to hash.</param> /// <param name="len">Length of buffer to hash.</param>
public void Update(byte[] data, uint len) public void Update(byte[] data, uint len)
{ {
for(int i = 0; i < len; i++) hashInt = (hashInt >> 8) ^ table[data[i] ^ (hashInt & 0xff)]; for(int i = 0; i < len; i++)
hashInt = (hashInt >> 8) ^ table[data[i] ^ (hashInt & 0xff)];
} }
/// <summary> /// <summary>Updates the hash with data.</summary>
/// Updates the hash with data.
/// </summary>
/// <param name="data">Data buffer.</param> /// <param name="data">Data buffer.</param>
public void Update(byte[] data) public void Update(byte[] data) => Update(data, (uint)data.Length);
{
Update(data, (uint)data.Length);
}
/// <summary> /// <summary>Returns a byte array of the hash value.</summary>
/// Returns a byte array of the hash value.
/// </summary>
public byte[] Final() => BigEndianBitConverter.GetBytes(hashInt ^ finalSeed); public byte[] Final() => BigEndianBitConverter.GetBytes(hashInt ^ finalSeed);
/// <summary> /// <summary>Returns a hexadecimal representation of the hash value.</summary>
/// Returns a hexadecimal representation of the hash value.
/// </summary>
public string End() public string End()
{ {
StringBuilder crc32Output = new StringBuilder(); var crc32Output = new StringBuilder();
for(int i = 0; i < BigEndianBitConverter.GetBytes(hashInt ^ finalSeed).Length; i++) for(int i = 0; i < BigEndianBitConverter.GetBytes(hashInt ^ finalSeed).Length; i++)
crc32Output.Append(BigEndianBitConverter.GetBytes(hashInt ^ finalSeed)[i].ToString("x2")); crc32Output.Append(BigEndianBitConverter.GetBytes(hashInt ^ finalSeed)[i].ToString("x2"));
@@ -127,42 +119,41 @@ namespace Aaru.Checksums
return crc32Output.ToString(); return crc32Output.ToString();
} }
/// <summary> /// <summary>Gets the hash of a file</summary>
/// Gets the hash of a file
/// </summary>
/// <param name="filename">File path.</param> /// <param name="filename">File path.</param>
public static byte[] File(string filename) public static byte[] File(string filename)
{ {
File(filename, out byte[] hash); File(filename, out byte[] hash);
return hash; return hash;
} }
/// <summary> /// <summary>Gets the hash of a file in hexadecimal and as a byte array.</summary>
/// Gets the hash of a file in hexadecimal and as a byte array.
/// </summary>
/// <param name="filename">File path.</param> /// <param name="filename">File path.</param>
/// <param name="hash">Byte array of the hash value.</param> /// <param name="hash">Byte array of the hash value.</param>
public static string File(string filename, out byte[] hash) => public static string File(string filename, out byte[] hash) =>
File(filename, out hash, CRC32_ISO_POLY, CRC32_ISO_SEED); File(filename, out hash, CRC32_ISO_POLY, CRC32_ISO_SEED);
/// <summary> /// <summary>Gets the hash of a file in hexadecimal and as a byte array.</summary>
/// Gets the hash of a file in hexadecimal and as a byte array.
/// </summary>
/// <param name="filename">File path.</param> /// <param name="filename">File path.</param>
/// <param name="hash">Byte array of the hash value.</param> /// <param name="hash">Byte array of the hash value.</param>
public static string File(string filename, out byte[] hash, uint polynomial, uint seed) public static string File(string filename, out byte[] hash, uint polynomial, uint seed)
{ {
FileStream fileStream = new FileStream(filename, FileMode.Open); var fileStream = new FileStream(filename, FileMode.Open);
uint localhashInt = seed; uint localhashInt = seed;
uint[] localTable = new uint[256]; uint[] localTable = new uint[256];
for(int i = 0; i < 256; i++) for(int i = 0; i < 256; i++)
{ {
uint entry = (uint)i; uint entry = (uint)i;
for(int j = 0; j < 8; j++) for(int j = 0; j < 8; j++)
if((entry & 1) == 1) entry = (entry >> 1) ^ polynomial; if((entry & 1) == 1)
else entry = entry >> 1; entry = (entry >> 1) ^ polynomial;
else
entry = entry >> 1;
localTable[i] = entry; localTable[i] = entry;
} }
@@ -173,27 +164,24 @@ namespace Aaru.Checksums
localhashInt ^= seed; localhashInt ^= seed;
hash = BigEndianBitConverter.GetBytes(localhashInt); hash = BigEndianBitConverter.GetBytes(localhashInt);
StringBuilder crc32Output = new StringBuilder(); var crc32Output = new StringBuilder();
foreach(byte h in hash) crc32Output.Append(h.ToString("x2")); foreach(byte h in hash)
crc32Output.Append(h.ToString("x2"));
fileStream.Close(); fileStream.Close();
return crc32Output.ToString(); return crc32Output.ToString();
} }
/// <summary> /// <summary>Gets the hash of the specified data buffer.</summary>
/// Gets the hash of the specified data buffer.
/// </summary>
/// <param name="data">Data buffer.</param> /// <param name="data">Data buffer.</param>
/// <param name="len">Length of the data buffer to hash.</param> /// <param name="len">Length of the data buffer to hash.</param>
/// <param name="hash">Byte array of the hash value.</param> /// <param name="hash">Byte array of the hash value.</param>
public static string Data(byte[] data, uint len, out byte[] hash) => public static string Data(byte[] data, uint len, out byte[] hash) =>
Data(data, len, out hash, CRC32_ISO_POLY, CRC32_ISO_SEED); Data(data, len, out hash, CRC32_ISO_POLY, CRC32_ISO_SEED);
/// <summary> /// <summary>Gets the hash of the specified data buffer.</summary>
/// Gets the hash of the specified data buffer.
/// </summary>
/// <param name="data">Data buffer.</param> /// <param name="data">Data buffer.</param>
/// <param name="len">Length of the data buffer to hash.</param> /// <param name="len">Length of the data buffer to hash.</param>
/// <param name="hash">Byte array of the hash value.</param> /// <param name="hash">Byte array of the hash value.</param>
@@ -204,12 +192,16 @@ namespace Aaru.Checksums
uint localhashInt = seed; uint localhashInt = seed;
uint[] localTable = new uint[256]; uint[] localTable = new uint[256];
for(int i = 0; i < 256; i++) for(int i = 0; i < 256; i++)
{ {
uint entry = (uint)i; uint entry = (uint)i;
for(int j = 0; j < 8; j++) for(int j = 0; j < 8; j++)
if((entry & 1) == 1) entry = (entry >> 1) ^ polynomial; if((entry & 1) == 1)
else entry = entry >> 1; entry = (entry >> 1) ^ polynomial;
else
entry = entry >> 1;
localTable[i] = entry; localTable[i] = entry;
} }
@@ -220,16 +212,15 @@ namespace Aaru.Checksums
localhashInt ^= seed; localhashInt ^= seed;
hash = BigEndianBitConverter.GetBytes(localhashInt); hash = BigEndianBitConverter.GetBytes(localhashInt);
StringBuilder crc32Output = new StringBuilder(); var crc32Output = new StringBuilder();
foreach(byte h in hash) crc32Output.Append(h.ToString("x2")); foreach(byte h in hash)
crc32Output.Append(h.ToString("x2"));
return crc32Output.ToString(); return crc32Output.ToString();
} }
/// <summary> /// <summary>Gets the hash of the specified data buffer.</summary>
/// Gets the hash of the specified data buffer.
/// </summary>
/// <param name="data">Data buffer.</param> /// <param name="data">Data buffer.</param>
/// <param name="hash">Byte array of the hash value.</param> /// <param name="hash">Byte array of the hash value.</param>
public static string Data(byte[] data, out byte[] hash) => Data(data, (uint)data.Length, out hash); public static string Data(byte[] data, out byte[] hash) => Data(data, (uint)data.Length, out hash);

View File

@@ -36,9 +36,7 @@ using Aaru.CommonTypes.Interfaces;
namespace Aaru.Checksums namespace Aaru.Checksums
{ {
/// <summary> /// <summary>Implements a CRC64 algorithm</summary>
/// Implements a CRC64 algorithm
/// </summary>
public class Crc64Context : IChecksum public class Crc64Context : IChecksum
{ {
public const ulong CRC64_ECMA_POLY = 0xC96C5795D7870F42; public const ulong CRC64_ECMA_POLY = 0xC96C5795D7870F42;
@@ -48,20 +46,22 @@ namespace Aaru.Checksums
readonly ulong[] table; readonly ulong[] table;
ulong hashInt; ulong hashInt;
/// <summary> /// <summary>Initializes the CRC64 table and seed as CRC64-ECMA</summary>
/// Initializes the CRC64 table and seed as CRC64-ECMA
/// </summary>
public Crc64Context() public Crc64Context()
{ {
hashInt = CRC64_ECMA_SEED; hashInt = CRC64_ECMA_SEED;
table = new ulong[256]; table = new ulong[256];
for(int i = 0; i < 256; i++) for(int i = 0; i < 256; i++)
{ {
ulong entry = (ulong)i; ulong entry = (ulong)i;
for(int j = 0; j < 8; j++) for(int j = 0; j < 8; j++)
if((entry & 1) == 1) entry = (entry >> 1) ^ CRC64_ECMA_POLY; if((entry & 1) == 1)
else entry = entry >> 1; entry = (entry >> 1) ^ CRC64_ECMA_POLY;
else
entry = entry >> 1;
table[i] = entry; table[i] = entry;
} }
@@ -69,20 +69,22 @@ namespace Aaru.Checksums
finalSeed = CRC64_ECMA_SEED; finalSeed = CRC64_ECMA_SEED;
} }
/// <summary> /// <summary>Initializes the CRC16 table with a custom polynomial and seed</summary>
/// Initializes the CRC16 table with a custom polynomial and seed
/// </summary>
public Crc64Context(ulong polynomial, ulong seed) public Crc64Context(ulong polynomial, ulong seed)
{ {
hashInt = seed; hashInt = seed;
table = new ulong[256]; table = new ulong[256];
for(int i = 0; i < 256; i++) for(int i = 0; i < 256; i++)
{ {
ulong entry = (ulong)i; ulong entry = (ulong)i;
for(int j = 0; j < 8; j++) for(int j = 0; j < 8; j++)
if((entry & 1) == 1) entry = (entry >> 1) ^ polynomial; if((entry & 1) == 1)
else entry = entry >> 1; entry = (entry >> 1) ^ polynomial;
else
entry = entry >> 1;
table[i] = entry; table[i] = entry;
} }
@@ -90,36 +92,26 @@ namespace Aaru.Checksums
finalSeed = seed; finalSeed = seed;
} }
/// <summary> /// <summary>Updates the hash with data.</summary>
/// Updates the hash with data.
/// </summary>
/// <param name="data">Data buffer.</param> /// <param name="data">Data buffer.</param>
/// <param name="len">Length of buffer to hash.</param> /// <param name="len">Length of buffer to hash.</param>
public void Update(byte[] data, uint len) public void Update(byte[] data, uint len)
{ {
for(int i = 0; i < len; i++) hashInt = (hashInt >> 8) ^ table[data[i] ^ (hashInt & 0xff)]; for(int i = 0; i < len; i++)
hashInt = (hashInt >> 8) ^ table[data[i] ^ (hashInt & 0xff)];
} }
/// <summary> /// <summary>Updates the hash with data.</summary>
/// Updates the hash with data.
/// </summary>
/// <param name="data">Data buffer.</param> /// <param name="data">Data buffer.</param>
public void Update(byte[] data) public void Update(byte[] data) => Update(data, (uint)data.Length);
{
Update(data, (uint)data.Length);
}
/// <summary> /// <summary>Returns a byte array of the hash value.</summary>
/// Returns a byte array of the hash value.
/// </summary>
public byte[] Final() => BigEndianBitConverter.GetBytes(hashInt ^= finalSeed); public byte[] Final() => BigEndianBitConverter.GetBytes(hashInt ^= finalSeed);
/// <summary> /// <summary>Returns a hexadecimal representation of the hash value.</summary>
/// Returns a hexadecimal representation of the hash value.
/// </summary>
public string End() public string End()
{ {
StringBuilder crc64Output = new StringBuilder(); var crc64Output = new StringBuilder();
for(int i = 0; i < BigEndianBitConverter.GetBytes(hashInt ^= finalSeed).Length; i++) for(int i = 0; i < BigEndianBitConverter.GetBytes(hashInt ^= finalSeed).Length; i++)
crc64Output.Append(BigEndianBitConverter.GetBytes(hashInt ^= finalSeed)[i].ToString("x2")); crc64Output.Append(BigEndianBitConverter.GetBytes(hashInt ^= finalSeed)[i].ToString("x2"));
@@ -127,42 +119,41 @@ namespace Aaru.Checksums
return crc64Output.ToString(); return crc64Output.ToString();
} }
/// <summary> /// <summary>Gets the hash of a file</summary>
/// Gets the hash of a file
/// </summary>
/// <param name="filename">File path.</param> /// <param name="filename">File path.</param>
public static byte[] File(string filename) public static byte[] File(string filename)
{ {
File(filename, out byte[] localHash); File(filename, out byte[] localHash);
return localHash; return localHash;
} }
/// <summary> /// <summary>Gets the hash of a file in hexadecimal and as a byte array.</summary>
/// Gets the hash of a file in hexadecimal and as a byte array.
/// </summary>
/// <param name="filename">File path.</param> /// <param name="filename">File path.</param>
/// <param name="hash">Byte array of the hash value.</param> /// <param name="hash">Byte array of the hash value.</param>
public static string File(string filename, out byte[] hash) => public static string File(string filename, out byte[] hash) =>
File(filename, out hash, CRC64_ECMA_POLY, CRC64_ECMA_SEED); File(filename, out hash, CRC64_ECMA_POLY, CRC64_ECMA_SEED);
/// <summary> /// <summary>Gets the hash of a file in hexadecimal and as a byte array.</summary>
/// Gets the hash of a file in hexadecimal and as a byte array.
/// </summary>
/// <param name="filename">File path.</param> /// <param name="filename">File path.</param>
/// <param name="hash">Byte array of the hash value.</param> /// <param name="hash">Byte array of the hash value.</param>
public static string File(string filename, out byte[] hash, ulong polynomial, ulong seed) public static string File(string filename, out byte[] hash, ulong polynomial, ulong seed)
{ {
FileStream fileStream = new FileStream(filename, FileMode.Open); var fileStream = new FileStream(filename, FileMode.Open);
ulong localhashInt = seed; ulong localhashInt = seed;
ulong[] localTable = new ulong[256]; ulong[] localTable = new ulong[256];
for(int i = 0; i < 256; i++) for(int i = 0; i < 256; i++)
{ {
ulong entry = (ulong)i; ulong entry = (ulong)i;
for(int j = 0; j < 8; j++) for(int j = 0; j < 8; j++)
if((entry & 1) == 1) entry = (entry >> 1) ^ polynomial; if((entry & 1) == 1)
else entry = entry >> 1; entry = (entry >> 1) ^ polynomial;
else
entry = entry >> 1;
localTable[i] = entry; localTable[i] = entry;
} }
@@ -173,27 +164,24 @@ namespace Aaru.Checksums
localhashInt ^= seed; localhashInt ^= seed;
hash = BigEndianBitConverter.GetBytes(localhashInt); hash = BigEndianBitConverter.GetBytes(localhashInt);
StringBuilder crc64Output = new StringBuilder(); var crc64Output = new StringBuilder();
foreach(byte h in hash) crc64Output.Append(h.ToString("x2")); foreach(byte h in hash)
crc64Output.Append(h.ToString("x2"));
fileStream.Close(); fileStream.Close();
return crc64Output.ToString(); return crc64Output.ToString();
} }
/// <summary> /// <summary>Gets the hash of the specified data buffer.</summary>
/// Gets the hash of the specified data buffer.
/// </summary>
/// <param name="data">Data buffer.</param> /// <param name="data">Data buffer.</param>
/// <param name="len">Length of the data buffer to hash.</param> /// <param name="len">Length of the data buffer to hash.</param>
/// <param name="hash">Byte array of the hash value.</param> /// <param name="hash">Byte array of the hash value.</param>
public static string Data(byte[] data, uint len, out byte[] hash) => public static string Data(byte[] data, uint len, out byte[] hash) =>
Data(data, len, out hash, CRC64_ECMA_POLY, CRC64_ECMA_SEED); Data(data, len, out hash, CRC64_ECMA_POLY, CRC64_ECMA_SEED);
/// <summary> /// <summary>Gets the hash of the specified data buffer.</summary>
/// Gets the hash of the specified data buffer.
/// </summary>
/// <param name="data">Data buffer.</param> /// <param name="data">Data buffer.</param>
/// <param name="len">Length of the data buffer to hash.</param> /// <param name="len">Length of the data buffer to hash.</param>
/// <param name="hash">Byte array of the hash value.</param> /// <param name="hash">Byte array of the hash value.</param>
@@ -204,12 +192,16 @@ namespace Aaru.Checksums
ulong localhashInt = seed; ulong localhashInt = seed;
ulong[] localTable = new ulong[256]; ulong[] localTable = new ulong[256];
for(int i = 0; i < 256; i++) for(int i = 0; i < 256; i++)
{ {
ulong entry = (ulong)i; ulong entry = (ulong)i;
for(int j = 0; j < 8; j++) for(int j = 0; j < 8; j++)
if((entry & 1) == 1) entry = (entry >> 1) ^ polynomial; if((entry & 1) == 1)
else entry = entry >> 1; entry = (entry >> 1) ^ polynomial;
else
entry = entry >> 1;
localTable[i] = entry; localTable[i] = entry;
} }
@@ -220,16 +212,15 @@ namespace Aaru.Checksums
localhashInt ^= seed; localhashInt ^= seed;
hash = BigEndianBitConverter.GetBytes(localhashInt); hash = BigEndianBitConverter.GetBytes(localhashInt);
StringBuilder crc64Output = new StringBuilder(); var crc64Output = new StringBuilder();
foreach(byte h in hash) crc64Output.Append(h.ToString("x2")); foreach(byte h in hash)
crc64Output.Append(h.ToString("x2"));
return crc64Output.ToString(); return crc64Output.ToString();
} }
/// <summary> /// <summary>Gets the hash of the specified data buffer.</summary>
/// Gets the hash of the specified data buffer.
/// </summary>
/// <param name="data">Data buffer.</param> /// <param name="data">Data buffer.</param>
/// <param name="hash">Byte array of the hash value.</param> /// <param name="hash">Byte array of the hash value.</param>
public static string Data(byte[] data, out byte[] hash) => Data(data, (uint)data.Length, out hash); public static string Data(byte[] data, out byte[] hash) => Data(data, (uint)data.Length, out hash);

View File

@@ -38,26 +38,20 @@ using Aaru.CommonTypes.Interfaces;
namespace Aaru.Checksums namespace Aaru.Checksums
{ {
/// <summary> /// <summary>Implements the Fletcher-32 algorithm</summary>
/// Implements the Fletcher-32 algorithm
/// </summary>
public class Fletcher32Context : IChecksum public class Fletcher32Context : IChecksum
{ {
const ushort FLETCHER_MODULE = 0xFFFF; const ushort FLETCHER_MODULE = 0xFFFF;
ushort sum1, sum2; ushort sum1, sum2;
/// <summary> /// <summary>Initializes the Fletcher-32 sums</summary>
/// Initializes the Fletcher-32 sums
/// </summary>
public Fletcher32Context() public Fletcher32Context()
{ {
sum1 = 0xFFFF; sum1 = 0xFFFF;
sum2 = 0xFFFF; sum2 = 0xFFFF;
} }
/// <summary> /// <summary>Updates the hash with data.</summary>
/// Updates the hash with data.
/// </summary>
/// <param name="data">Data buffer.</param> /// <param name="data">Data buffer.</param>
/// <param name="len">Length of buffer to hash.</param> /// <param name="len">Length of buffer to hash.</param>
public void Update(byte[] data, uint len) public void Update(byte[] data, uint len)
@@ -69,31 +63,23 @@ namespace Aaru.Checksums
} }
} }
/// <summary> /// <summary>Updates the hash with data.</summary>
/// Updates the hash with data.
/// </summary>
/// <param name="data">Data buffer.</param> /// <param name="data">Data buffer.</param>
public void Update(byte[] data) public void Update(byte[] data) => Update(data, (uint)data.Length);
{
Update(data, (uint)data.Length);
}
/// <summary> /// <summary>Returns a byte array of the hash value.</summary>
/// Returns a byte array of the hash value.
/// </summary>
public byte[] Final() public byte[] Final()
{ {
uint finalSum = (uint)((sum2 << 16) | sum1); uint finalSum = (uint)((sum2 << 16) | sum1);
return BigEndianBitConverter.GetBytes(finalSum); return BigEndianBitConverter.GetBytes(finalSum);
} }
/// <summary> /// <summary>Returns a hexadecimal representation of the hash value.</summary>
/// Returns a hexadecimal representation of the hash value.
/// </summary>
public string End() public string End()
{ {
uint finalSum = (uint)((sum2 << 16) | sum1); uint finalSum = (uint)((sum2 << 16) | sum1);
StringBuilder fletcherOutput = new StringBuilder(); var fletcherOutput = new StringBuilder();
for(int i = 0; i < BigEndianBitConverter.GetBytes(finalSum).Length; i++) for(int i = 0; i < BigEndianBitConverter.GetBytes(finalSum).Length; i++)
fletcherOutput.Append(BigEndianBitConverter.GetBytes(finalSum)[i].ToString("x2")); fletcherOutput.Append(BigEndianBitConverter.GetBytes(finalSum)[i].ToString("x2"));
@@ -101,24 +87,21 @@ namespace Aaru.Checksums
return fletcherOutput.ToString(); return fletcherOutput.ToString();
} }
/// <summary> /// <summary>Gets the hash of a file</summary>
/// Gets the hash of a file
/// </summary>
/// <param name="filename">File path.</param> /// <param name="filename">File path.</param>
public static byte[] File(string filename) public static byte[] File(string filename)
{ {
File(filename, out byte[] hash); File(filename, out byte[] hash);
return hash; return hash;
} }
/// <summary> /// <summary>Gets the hash of a file in hexadecimal and as a byte array.</summary>
/// Gets the hash of a file in hexadecimal and as a byte array.
/// </summary>
/// <param name="filename">File path.</param> /// <param name="filename">File path.</param>
/// <param name="hash">Byte array of the hash value.</param> /// <param name="hash">Byte array of the hash value.</param>
public static string File(string filename, out byte[] hash) public static string File(string filename, out byte[] hash)
{ {
FileStream fileStream = new FileStream(filename, FileMode.Open); var fileStream = new FileStream(filename, FileMode.Open);
ushort localSum1 = 0xFFFF; ushort localSum1 = 0xFFFF;
ushort localSum2 = 0xFFFF; ushort localSum2 = 0xFFFF;
@@ -133,18 +116,17 @@ namespace Aaru.Checksums
hash = BigEndianBitConverter.GetBytes(finalSum); hash = BigEndianBitConverter.GetBytes(finalSum);
StringBuilder fletcherOutput = new StringBuilder(); var fletcherOutput = new StringBuilder();
foreach(byte h in hash) fletcherOutput.Append(h.ToString("x2")); foreach(byte h in hash)
fletcherOutput.Append(h.ToString("x2"));
fileStream.Close(); fileStream.Close();
return fletcherOutput.ToString(); return fletcherOutput.ToString();
} }
/// <summary> /// <summary>Gets the hash of the specified data buffer.</summary>
/// Gets the hash of the specified data buffer.
/// </summary>
/// <param name="data">Data buffer.</param> /// <param name="data">Data buffer.</param>
/// <param name="len">Length of the data buffer to hash.</param> /// <param name="len">Length of the data buffer to hash.</param>
/// <param name="hash">Byte array of the hash value.</param> /// <param name="hash">Byte array of the hash value.</param>
@@ -163,41 +145,34 @@ namespace Aaru.Checksums
hash = BigEndianBitConverter.GetBytes(finalSum); hash = BigEndianBitConverter.GetBytes(finalSum);
StringBuilder adlerOutput = new StringBuilder(); var adlerOutput = new StringBuilder();
foreach(byte h in hash) adlerOutput.Append(h.ToString("x2")); foreach(byte h in hash)
adlerOutput.Append(h.ToString("x2"));
return adlerOutput.ToString(); return adlerOutput.ToString();
} }
/// <summary> /// <summary>Gets the hash of the specified data buffer.</summary>
/// Gets the hash of the specified data buffer.
/// </summary>
/// <param name="data">Data buffer.</param> /// <param name="data">Data buffer.</param>
/// <param name="hash">Byte array of the hash value.</param> /// <param name="hash">Byte array of the hash value.</param>
public static string Data(byte[] data, out byte[] hash) => Data(data, (uint)data.Length, out hash); public static string Data(byte[] data, out byte[] hash) => Data(data, (uint)data.Length, out hash);
} }
/// <summary> /// <summary>Implements the Fletcher-16 algorithm</summary>
/// Implements the Fletcher-16 algorithm
/// </summary>
public class Fletcher16Context : IChecksum public class Fletcher16Context : IChecksum
{ {
const byte FLETCHER_MODULE = 0xFF; const byte FLETCHER_MODULE = 0xFF;
byte sum1, sum2; byte sum1, sum2;
/// <summary> /// <summary>Initializes the Fletcher-16 sums</summary>
/// Initializes the Fletcher-16 sums
/// </summary>
public Fletcher16Context() public Fletcher16Context()
{ {
sum1 = 0xFF; sum1 = 0xFF;
sum2 = 0xFF; sum2 = 0xFF;
} }
/// <summary> /// <summary>Updates the hash with data.</summary>
/// Updates the hash with data.
/// </summary>
/// <param name="data">Data buffer.</param> /// <param name="data">Data buffer.</param>
/// <param name="len">Length of buffer to hash.</param> /// <param name="len">Length of buffer to hash.</param>
public void Update(byte[] data, uint len) public void Update(byte[] data, uint len)
@@ -209,31 +184,23 @@ namespace Aaru.Checksums
} }
} }
/// <summary> /// <summary>Updates the hash with data.</summary>
/// Updates the hash with data.
/// </summary>
/// <param name="data">Data buffer.</param> /// <param name="data">Data buffer.</param>
public void Update(byte[] data) public void Update(byte[] data) => Update(data, (uint)data.Length);
{
Update(data, (uint)data.Length);
}
/// <summary> /// <summary>Returns a byte array of the hash value.</summary>
/// Returns a byte array of the hash value.
/// </summary>
public byte[] Final() public byte[] Final()
{ {
ushort finalSum = (ushort)((sum2 << 8) | sum1); ushort finalSum = (ushort)((sum2 << 8) | sum1);
return BigEndianBitConverter.GetBytes(finalSum); return BigEndianBitConverter.GetBytes(finalSum);
} }
/// <summary> /// <summary>Returns a hexadecimal representation of the hash value.</summary>
/// Returns a hexadecimal representation of the hash value.
/// </summary>
public string End() public string End()
{ {
ushort finalSum = (ushort)((sum2 << 8) | sum1); ushort finalSum = (ushort)((sum2 << 8) | sum1);
StringBuilder fletcherOutput = new StringBuilder(); var fletcherOutput = new StringBuilder();
for(int i = 0; i < BigEndianBitConverter.GetBytes(finalSum).Length; i++) for(int i = 0; i < BigEndianBitConverter.GetBytes(finalSum).Length; i++)
fletcherOutput.Append(BigEndianBitConverter.GetBytes(finalSum)[i].ToString("x2")); fletcherOutput.Append(BigEndianBitConverter.GetBytes(finalSum)[i].ToString("x2"));
@@ -241,24 +208,21 @@ namespace Aaru.Checksums
return fletcherOutput.ToString(); return fletcherOutput.ToString();
} }
/// <summary> /// <summary>Gets the hash of a file</summary>
/// Gets the hash of a file
/// </summary>
/// <param name="filename">File path.</param> /// <param name="filename">File path.</param>
public static byte[] File(string filename) public static byte[] File(string filename)
{ {
File(filename, out byte[] hash); File(filename, out byte[] hash);
return hash; return hash;
} }
/// <summary> /// <summary>Gets the hash of a file in hexadecimal and as a byte array.</summary>
/// Gets the hash of a file in hexadecimal and as a byte array.
/// </summary>
/// <param name="filename">File path.</param> /// <param name="filename">File path.</param>
/// <param name="hash">Byte array of the hash value.</param> /// <param name="hash">Byte array of the hash value.</param>
public static string File(string filename, out byte[] hash) public static string File(string filename, out byte[] hash)
{ {
FileStream fileStream = new FileStream(filename, FileMode.Open); var fileStream = new FileStream(filename, FileMode.Open);
byte localSum1 = 0xFF; byte localSum1 = 0xFF;
byte localSum2 = 0xFF; byte localSum2 = 0xFF;
@@ -273,18 +237,17 @@ namespace Aaru.Checksums
hash = BigEndianBitConverter.GetBytes(finalSum); hash = BigEndianBitConverter.GetBytes(finalSum);
StringBuilder fletcherOutput = new StringBuilder(); var fletcherOutput = new StringBuilder();
foreach(byte h in hash) fletcherOutput.Append(h.ToString("x2")); foreach(byte h in hash)
fletcherOutput.Append(h.ToString("x2"));
fileStream.Close(); fileStream.Close();
return fletcherOutput.ToString(); return fletcherOutput.ToString();
} }
/// <summary> /// <summary>Gets the hash of the specified data buffer.</summary>
/// Gets the hash of the specified data buffer.
/// </summary>
/// <param name="data">Data buffer.</param> /// <param name="data">Data buffer.</param>
/// <param name="len">Length of the data buffer to hash.</param> /// <param name="len">Length of the data buffer to hash.</param>
/// <param name="hash">Byte array of the hash value.</param> /// <param name="hash">Byte array of the hash value.</param>
@@ -303,16 +266,15 @@ namespace Aaru.Checksums
hash = BigEndianBitConverter.GetBytes(finalSum); hash = BigEndianBitConverter.GetBytes(finalSum);
StringBuilder adlerOutput = new StringBuilder(); var adlerOutput = new StringBuilder();
foreach(byte h in hash) adlerOutput.Append(h.ToString("x2")); foreach(byte h in hash)
adlerOutput.Append(h.ToString("x2"));
return adlerOutput.ToString(); return adlerOutput.ToString();
} }
/// <summary> /// <summary>Gets the hash of the specified data buffer.</summary>
/// Gets the hash of the specified data buffer.
/// </summary>
/// <param name="data">Data buffer.</param> /// <param name="data">Data buffer.</param>
/// <param name="hash">Byte array of the hash value.</param> /// <param name="hash">Byte array of the hash value.</param>
public static string Data(byte[] data, out byte[] hash) => Data(data, (uint)data.Length, out hash); public static string Data(byte[] data, out byte[] hash) => Data(data, (uint)data.Length, out hash);

View File

@@ -37,114 +37,90 @@ using Aaru.CommonTypes.Interfaces;
namespace Aaru.Checksums namespace Aaru.Checksums
{ {
/// <summary> /// <summary>Wraps up .NET MD5 implementation to a Init(), Update(), Final() context.</summary>
/// Wraps up .NET MD5 implementation to a Init(), Update(), Final() context.
/// </summary>
public class Md5Context : IChecksum public class Md5Context : IChecksum
{ {
MD5 md5Provider; readonly MD5 md5Provider;
/// <summary> /// <summary>Initializes the MD5 hash provider</summary>
/// Initializes the MD5 hash provider public Md5Context() => md5Provider = MD5.Create();
/// </summary>
public Md5Context()
{
md5Provider = MD5.Create();
}
/// <summary> /// <summary>Updates the hash with data.</summary>
/// Updates the hash with data.
/// </summary>
/// <param name="data">Data buffer.</param> /// <param name="data">Data buffer.</param>
/// <param name="len">Length of buffer to hash.</param> /// <param name="len">Length of buffer to hash.</param>
public void Update(byte[] data, uint len) public void Update(byte[] data, uint len) => md5Provider.TransformBlock(data, 0, (int)len, data, 0);
{
md5Provider.TransformBlock(data, 0, (int)len, data, 0);
}
/// <summary> /// <summary>Updates the hash with data.</summary>
/// Updates the hash with data.
/// </summary>
/// <param name="data">Data buffer.</param> /// <param name="data">Data buffer.</param>
public void Update(byte[] data) public void Update(byte[] data) => Update(data, (uint)data.Length);
{
Update(data, (uint)data.Length);
}
/// <summary> /// <summary>Returns a byte array of the hash value.</summary>
/// Returns a byte array of the hash value.
/// </summary>
public byte[] Final() public byte[] Final()
{ {
md5Provider.TransformFinalBlock(new byte[0], 0, 0); md5Provider.TransformFinalBlock(new byte[0], 0, 0);
return md5Provider.Hash; return md5Provider.Hash;
} }
/// <summary> /// <summary>Returns a hexadecimal representation of the hash value.</summary>
/// Returns a hexadecimal representation of the hash value.
/// </summary>
public string End() public string End()
{ {
md5Provider.TransformFinalBlock(new byte[0], 0, 0); md5Provider.TransformFinalBlock(new byte[0], 0, 0);
StringBuilder md5Output = new StringBuilder(); var md5Output = new StringBuilder();
foreach(byte h in md5Provider.Hash) md5Output.Append(h.ToString("x2")); foreach(byte h in md5Provider.Hash)
md5Output.Append(h.ToString("x2"));
return md5Output.ToString(); return md5Output.ToString();
} }
/// <summary> /// <summary>Gets the hash of a file</summary>
/// Gets the hash of a file
/// </summary>
/// <param name="filename">File path.</param> /// <param name="filename">File path.</param>
public static byte[] File(string filename) public static byte[] File(string filename)
{ {
MD5 localMd5Provider = MD5.Create(); var localMd5Provider = MD5.Create();
FileStream fileStream = new FileStream(filename, FileMode.Open); var fileStream = new FileStream(filename, FileMode.Open);
byte[] result = localMd5Provider.ComputeHash(fileStream); byte[] result = localMd5Provider.ComputeHash(fileStream);
fileStream.Close(); fileStream.Close();
return result; return result;
} }
/// <summary> /// <summary>Gets the hash of a file in hexadecimal and as a byte array.</summary>
/// Gets the hash of a file in hexadecimal and as a byte array.
/// </summary>
/// <param name="filename">File path.</param> /// <param name="filename">File path.</param>
/// <param name="hash">Byte array of the hash value.</param> /// <param name="hash">Byte array of the hash value.</param>
public static string File(string filename, out byte[] hash) public static string File(string filename, out byte[] hash)
{ {
MD5 localMd5Provider = MD5.Create(); var localMd5Provider = MD5.Create();
FileStream fileStream = new FileStream(filename, FileMode.Open); var fileStream = new FileStream(filename, FileMode.Open);
hash = localMd5Provider.ComputeHash(fileStream); hash = localMd5Provider.ComputeHash(fileStream);
StringBuilder md5Output = new StringBuilder(); var md5Output = new StringBuilder();
foreach(byte h in hash) md5Output.Append(h.ToString("x2")); foreach(byte h in hash)
md5Output.Append(h.ToString("x2"));
fileStream.Close(); fileStream.Close();
return md5Output.ToString(); return md5Output.ToString();
} }
/// <summary> /// <summary>Gets the hash of the specified data buffer.</summary>
/// Gets the hash of the specified data buffer.
/// </summary>
/// <param name="data">Data buffer.</param> /// <param name="data">Data buffer.</param>
/// <param name="len">Length of the data buffer to hash.</param> /// <param name="len">Length of the data buffer to hash.</param>
/// <param name="hash">Byte array of the hash value.</param> /// <param name="hash">Byte array of the hash value.</param>
public static string Data(byte[] data, uint len, out byte[] hash) public static string Data(byte[] data, uint len, out byte[] hash)
{ {
MD5 localMd5Provider = MD5.Create(); var localMd5Provider = MD5.Create();
hash = localMd5Provider.ComputeHash(data, 0, (int)len); hash = localMd5Provider.ComputeHash(data, 0, (int)len);
StringBuilder md5Output = new StringBuilder(); var md5Output = new StringBuilder();
foreach(byte h in hash) md5Output.Append(h.ToString("x2")); foreach(byte h in hash)
md5Output.Append(h.ToString("x2"));
return md5Output.ToString(); return md5Output.ToString();
} }
/// <summary> /// <summary>Gets the hash of the specified data buffer.</summary>
/// Gets the hash of the specified data buffer.
/// </summary>
/// <param name="data">Data buffer.</param> /// <param name="data">Data buffer.</param>
/// <param name="hash">Byte array of the hash value.</param> /// <param name="hash">Byte array of the hash value.</param>
public static string Data(byte[] data, out byte[] hash) => Data(data, (uint)data.Length, out hash); public static string Data(byte[] data, out byte[] hash) => Data(data, (uint)data.Length, out hash);

View File

@@ -62,30 +62,18 @@ using Aaru.Console;
namespace Aaru.Checksums namespace Aaru.Checksums
{ {
/// <summary> /// <summary>Implements the Reed-Solomon algorithm</summary>
/// Implements the Reed-Solomon algorithm
/// </summary>
public class ReedSolomon public class ReedSolomon
{ {
/// <summary> /// <summary>Alpha exponent for the first root of the generator polynomial</summary>
/// Alpha exponent for the first root of the generator polynomial
/// </summary>
const int B0 = 1; const int B0 = 1;
/// <summary> /// <summary>No legal value in index form represents zero, so we need a special value for this purpose</summary>
/// No legal value in index form represents zero, so we need a special value for this purpose
/// </summary>
int a0; int a0;
/// <summary> /// <summary>index->polynomial form conversion table</summary>
/// index->polynomial form conversion table
/// </summary>
int[] alpha_to; int[] alpha_to;
/// <summary> /// <summary>Generator polynomial g(x) Degree of g(x) = 2*TT has roots @**B0, @**(B0+1), ... ,@^(B0+2*TT-1)</summary>
/// Generator polynomial g(x) Degree of g(x) = 2*TT has roots @**B0, @**(B0+1), ... ,@^(B0+2*TT-1)
/// </summary>
int[] gg; int[] gg;
/// <summary> /// <summary>Polynomial->index form conversion table</summary>
/// Polynomial->index form conversion table
/// </summary>
int[] index_of; int[] index_of;
bool initialized; bool initialized;
int mm, kk, nn; int mm, kk, nn;
@@ -95,57 +83,115 @@ namespace Aaru.Checksums
/// </summary> /// </summary>
int[] pp; int[] pp;
/// <summary> /// <summary>Initializes the Reed-Solomon with RS(n,k) with GF(2^m)</summary>
/// Initializes the Reed-Solomon with RS(n,k) with GF(2^m)
/// </summary>
public void InitRs(int n, int k, int m) public void InitRs(int n, int k, int m)
{ {
switch(m) switch(m)
{ {
case 2: case 2:
pp = new[] {1, 1, 1}; pp = new[]
{
1, 1, 1
};
break; break;
case 3: case 3:
pp = new[] {1, 1, 0, 1}; pp = new[]
{
1, 1, 0, 1
};
break; break;
case 4: case 4:
pp = new[] {1, 1, 0, 0, 1}; pp = new[]
{
1, 1, 0, 0, 1
};
break; break;
case 5: case 5:
pp = new[] {1, 0, 1, 0, 0, 1}; pp = new[]
{
1, 0, 1, 0, 0, 1
};
break; break;
case 6: case 6:
pp = new[] {1, 1, 0, 0, 0, 0, 1}; pp = new[]
{
1, 1, 0, 0, 0, 0, 1
};
break; break;
case 7: case 7:
pp = new[] {1, 0, 0, 1, 0, 0, 0, 1}; pp = new[]
{
1, 0, 0, 1, 0, 0, 0, 1
};
break; break;
case 8: case 8:
pp = new[] {1, 0, 1, 1, 1, 0, 0, 0, 1}; pp = new[]
{
1, 0, 1, 1, 1, 0, 0, 0, 1
};
break; break;
case 9: case 9:
pp = new[] {1, 0, 0, 0, 1, 0, 0, 0, 0, 1}; pp = new[]
{
1, 0, 0, 0, 1, 0, 0, 0, 0, 1
};
break; break;
case 10: case 10:
pp = new[] {1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1}; pp = new[]
{
1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1
};
break; break;
case 11: case 11:
pp = new[] {1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1}; pp = new[]
{
1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1
};
break; break;
case 12: case 12:
pp = new[] {1, 1, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 1}; pp = new[]
{
1, 1, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 1
};
break; break;
case 13: case 13:
pp = new[] {1, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1}; pp = new[]
{
1, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1
};
break; break;
case 14: case 14:
pp = new[] {1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1}; pp = new[]
{
1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1
};
break; break;
case 15: case 15:
pp = new[] {1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}; pp = new[]
{
1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1
};
break; break;
case 16: case 16:
pp = new[] {1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1}; pp = new[]
{
1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1
};
break; break;
default: throw new ArgumentOutOfRangeException(nameof(m), "m must be between 2 and 16 inclusive"); default: throw new ArgumentOutOfRangeException(nameof(m), "m must be between 2 and 16 inclusive");
} }
@@ -157,7 +203,7 @@ namespace Aaru.Checksums
alpha_to = new int[n + 1]; alpha_to = new int[n + 1];
index_of = new int[n + 1]; index_of = new int[n + 1];
gg = new int[nn - kk + 1]; gg = new int[(nn - kk) + 1];
generate_gf(); generate_gf();
gen_poly(); gen_poly();
@@ -181,19 +227,25 @@ namespace Aaru.Checksums
static void Clear(ref int[] a, int n) static void Clear(ref int[] a, int n)
{ {
int ci; int ci;
for(ci = n - 1; ci >= 0; ci--) a[ci] = 0;
for(ci = n - 1; ci >= 0; ci--)
a[ci] = 0;
} }
static void Copy(ref int[] a, ref int[] b, int n) static void Copy(ref int[] a, ref int[] b, int n)
{ {
int ci; int ci;
for(ci = n - 1; ci >= 0; ci--) a[ci] = b[ci];
for(ci = n - 1; ci >= 0; ci--)
a[ci] = b[ci];
} }
static void Copydown(ref int[] a, ref int[] b, int n) static void Copydown(ref int[] a, ref int[] b, int n)
{ {
int ci; int ci;
for(ci = n - 1; ci >= 0; ci--) a[ci] = b[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] /* generate GF(2**m) from the irreducible polynomial p(X) in p[0]..p[m]
@@ -232,12 +284,16 @@ namespace Aaru.Checksums
int mask = 1; int mask = 1;
alpha_to[mm] = 0; alpha_to[mm] = 0;
for(i = 0; i < mm; i++) for(i = 0; i < mm; i++)
{ {
alpha_to[i] = mask; alpha_to[i] = mask;
index_of[alpha_to[i]] = i; index_of[alpha_to[i]] = i;
/* If Pp[i] == 1 then, term @^i occurs in poly-repr of @^MM */ /* 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 */ if(pp[i] != 0)
alpha_to[mm] ^= mask; /* Bit-wise EXOR operation */
mask <<= 1; /* single left-shift */ mask <<= 1; /* single left-shift */
} }
@@ -248,10 +304,14 @@ namespace Aaru.Checksums
* term that may occur when poly-repr of @^i is shifted. * term that may occur when poly-repr of @^i is shifted.
*/ */
mask >>= 1; mask >>= 1;
for(i = mm + 1; i < nn; i++) 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); if(alpha_to[i - 1] >= mask)
else alpha_to[i] = alpha_to[i - 1] << 1; 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[alpha_to[i]] = i;
} }
@@ -278,24 +338,28 @@ namespace Aaru.Checksums
gg[0] = alpha_to[B0]; gg[0] = alpha_to[B0];
gg[1] = 1; /* g(x) = (X+@**B0) initially */ gg[1] = 1; /* g(x) = (X+@**B0) initially */
for(i = 2; i <= nn - kk; i++) for(i = 2; i <= nn - kk; i++)
{ {
gg[i] = 1; gg[i] = 1;
/* /*
* Below multiply (Gg[0]+Gg[1]*x + ... +Gg[i]x^i) by * Below multiply (Gg[0]+Gg[1]*x + ... +Gg[i]x^i) by
* (@**(B0+i-1) + x) * (@**(B0+i-1) + x)
*/ */
for(int j = i - 1; j > 0; j--) for(int j = i - 1; j > 0; j--)
if(gg[j] != 0) if(gg[j] != 0)
gg[j] = gg[j - 1] ^ alpha_to[Modnn(index_of[gg[j]] + B0 + i - 1)]; gg[j] = gg[j - 1] ^ alpha_to[Modnn((index_of[gg[j]] + B0 + i) - 1)];
else else
gg[j] = gg[j - 1]; gg[j] = gg[j - 1];
/* Gg[0] can never be zero */ /* Gg[0] can never be zero */
gg[0] = alpha_to[Modnn(index_of[gg[0]] + B0 + i - 1)]; gg[0] = alpha_to[Modnn((index_of[gg[0]] + B0 + i) - 1)];
} }
/* convert Gg[] to index form for quicker encoding */ /* convert Gg[] to index form for quicker encoding */
for(i = 0; i <= nn - kk; i++) gg[i] = index_of[gg[i]]; for(i = 0; i <= nn - kk; i++)
gg[i] = index_of[gg[i]];
} }
/* /*
@@ -306,20 +370,20 @@ namespace Aaru.Checksums
* elements of Gg[], which was generated above. Codeword is c(X) = * elements of Gg[], which was generated above. Codeword is c(X) =
* data(X)*X**(NN-KK)+ b(X) * data(X)*X**(NN-KK)+ b(X)
*/ */
/// <summary> /// <summary>Takes the symbols in data to output parity in bb.</summary>
/// Takes the symbols in data to output parity in bb.
/// </summary>
/// <returns>Returns -1 if an illegal symbol is found.</returns> /// <returns>Returns -1 if an illegal symbol is found.</returns>
/// <param name="data">Data symbols.</param> /// <param name="data">Data symbols.</param>
/// <param name="bb">Outs parity symbols.</param> /// <param name="bb">Outs parity symbols.</param>
public int encode_rs(int[] data, out int[] bb) public int encode_rs(int[] data, out int[] bb)
{ {
if(!initialized) throw new UnauthorizedAccessException("Trying to calculate RS without initializing!"); if(!initialized)
throw new UnauthorizedAccessException("Trying to calculate RS without initializing!");
int i; int i;
bb = new int[nn - kk]; bb = new int[nn - kk];
Clear(ref bb, nn - kk); Clear(ref bb, nn - kk);
for(i = kk - 1; i >= 0; i--) for(i = kk - 1; i >= 0; i--)
{ {
if(mm != 8) if(mm != 8)
@@ -327,6 +391,7 @@ namespace Aaru.Checksums
return -1; /* Illegal symbol */ return -1; /* Illegal symbol */
int feedback = index_of[data[i] ^ bb[nn - kk - 1]]; int feedback = index_of[data[i] ^ bb[nn - kk - 1]];
if(feedback != a0) if(feedback != a0)
{ {
/* feedback term is non-zero */ /* feedback term is non-zero */
@@ -342,7 +407,8 @@ namespace Aaru.Checksums
{ {
/* feedback term is zero. encoder becomes a /* feedback term is zero. encoder becomes a
* single-byte shifter */ * single-byte shifter */
for(int j = nn - kk - 1; j > 0; j--) bb[j] = bb[j - 1]; for(int j = nn - kk - 1; j > 0; j--)
bb[j] = bb[j - 1];
bb[0] = 0; bb[0] = 0;
} }
@@ -364,28 +430,27 @@ namespace Aaru.Checksums
* transmitted codeword will be recovered. Details of algorithm can be found * transmitted codeword will be recovered. Details of algorithm can be found
* in R. Blahut's "Theory ... of Error-Correcting Codes". * in R. Blahut's "Theory ... of Error-Correcting Codes".
*/ */
/// <summary> /// <summary>Decodes the RS. If decoding is successful outputs corrected data symbols.</summary>
/// Decodes the RS. If decoding is successful outputs corrected data symbols.
/// </summary>
/// <returns>Returns corrected symbols, -1 if illegal or uncorrectable</returns> /// <returns>Returns corrected symbols, -1 if illegal or uncorrectable</returns>
/// <param name="data">Data symbols.</param> /// <param name="data">Data symbols.</param>
/// <param name="erasPos">Position of erasures.</param> /// <param name="erasPos">Position of erasures.</param>
/// <param name="noEras">Number of erasures.</param> /// <param name="noEras">Number of erasures.</param>
public int eras_dec_rs(ref int[] data, out int[] erasPos, int noEras) public int eras_dec_rs(ref int[] data, out int[] erasPos, int noEras)
{ {
if(!initialized) throw new UnauthorizedAccessException("Trying to calculate RS without initializing!"); if(!initialized)
throw new UnauthorizedAccessException("Trying to calculate RS without initializing!");
erasPos = new int[nn - kk]; erasPos = new int[nn - kk];
int i, j; int i, j;
int q, tmp; int q, tmp;
int[] recd = new int[nn]; int[] recd = new int[nn];
int[] lambda = new int[nn - kk + 1]; /* Err+Eras Locator poly */ int[] lambda = new int[(nn - kk) + 1]; /* Err+Eras Locator poly */
int[] s = new int[nn - kk + 1]; /* syndrome poly */ int[] s = new int[(nn - kk) + 1]; /* syndrome poly */
int[] b = new int[nn - kk + 1]; int[] b = new int[(nn - kk) + 1];
int[] t = new int[nn - kk + 1]; int[] t = new int[(nn - kk) + 1];
int[] omega = new int[nn - kk + 1]; int[] omega = new int[(nn - kk) + 1];
int[] root = new int[nn - kk]; int[] root = new int[nn - kk];
int[] reg = new int[nn - kk + 1]; int[] reg = new int[(nn - kk) + 1];
int[] loc = new int[nn - kk]; int[] loc = new int[nn - kk];
int count; int count;
@@ -403,45 +468,57 @@ namespace Aaru.Checksums
* namely @**(B0+i), i = 0, ... ,(NN-KK-1) * namely @**(B0+i), i = 0, ... ,(NN-KK-1)
*/ */
int synError = 0; int synError = 0;
for(i = 1; i <= nn - kk; i++) for(i = 1; i <= nn - kk; i++)
{ {
tmp = 0; tmp = 0;
for(j = 0; j < nn; j++) for(j = 0; j < nn; j++)
if(recd[j] != a0) /* recd[j] in index form */ if(recd[j] != a0) /* recd[j] in index form */
tmp ^= alpha_to[Modnn(recd[j] + (B0 + i - 1) * j)]; tmp ^= alpha_to[Modnn(recd[j] + (((B0 + i) - 1) * j))];
synError |= tmp; /* set flag if non-zero syndrome => synError |= tmp; /* set flag if non-zero syndrome =>
* error */ * error */
/* store syndrome in index form */ /* store syndrome in index form */
s[i] = index_of[tmp]; s[i] = index_of[tmp];
} }
if(synError == 0) return 0; if(synError == 0)
return 0;
Clear(ref lambda, nn - kk); Clear(ref lambda, nn - kk);
lambda[0] = 1; lambda[0] = 1;
if(noEras > 0) if(noEras > 0)
{ {
/* Init lambda to be the erasure locator polynomial */ /* Init lambda to be the erasure locator polynomial */
lambda[1] = alpha_to[erasPos[0]]; lambda[1] = alpha_to[erasPos[0]];
for(i = 1; i < noEras; i++) for(i = 1; i < noEras; i++)
{ {
int u = erasPos[i]; int u = erasPos[i];
for(j = i + 1; j > 0; j--) for(j = i + 1; j > 0; j--)
{ {
tmp = index_of[lambda[j - 1]]; tmp = index_of[lambda[j - 1]];
if(tmp != a0) lambda[j] ^= alpha_to[Modnn(u + tmp)];
if(tmp != a0)
lambda[j] ^= alpha_to[Modnn(u + tmp)];
} }
} }
#if DEBUG #if DEBUG
/* find roots of the erasure location polynomial */ /* find roots of the erasure location polynomial */
for(i = 1; i <= noEras; i++) reg[i] = index_of[lambda[i]]; for(i = 1; i <= noEras; i++)
reg[i] = index_of[lambda[i]];
count = 0; count = 0;
for(i = 1; i <= nn; i++) for(i = 1; i <= nn; i++)
{ {
q = 1; q = 1;
for(j = 1; j <= noEras; j++) for(j = 1; j <= noEras; j++)
if(reg[j] != a0) if(reg[j] != a0)
{ {
@@ -449,7 +526,8 @@ namespace Aaru.Checksums
q ^= alpha_to[reg[j]]; q ^= alpha_to[reg[j]];
} }
if(q != 0) continue; if(q != 0)
continue;
/* store root and error location /* store root and error location
* number indices * number indices
@@ -462,18 +540,22 @@ namespace Aaru.Checksums
if(count != noEras) if(count != noEras)
{ {
AaruConsole.DebugWriteLine("Reed Solomon", "\n lambda(x) is WRONG\n"); AaruConsole.DebugWriteLine("Reed Solomon", "\n lambda(x) is WRONG\n");
return -1; return -1;
} }
AaruConsole.DebugWriteLine("Reed Solomon", AaruConsole.DebugWriteLine("Reed Solomon",
"\n Erasure positions as determined by roots of Eras Loc Poly:\n"); "\n Erasure positions as determined by roots of Eras Loc Poly:\n");
for(i = 0; i < count; i++) AaruConsole.DebugWriteLine("Reed Solomon", "{0} ", loc[i]);
for(i = 0; i < count; i++)
AaruConsole.DebugWriteLine("Reed Solomon", "{0} ", loc[i]);
AaruConsole.DebugWriteLine("Reed Solomon", "\n"); AaruConsole.DebugWriteLine("Reed Solomon", "\n");
#endif #endif
} }
for(i = 0; i < nn - kk + 1; i++) b[i] = index_of[lambda[i]]; for(i = 0; i < (nn - kk) + 1; i++)
b[i] = index_of[lambda[i]];
/* /*
* Begin Berlekamp-Massey algorithm to determine error+erasure * Begin Berlekamp-Massey algorithm to determine error+erasure
@@ -481,16 +563,20 @@ namespace Aaru.Checksums
*/ */
int r = noEras; int r = noEras;
int el = noEras; int el = noEras;
while(++r <= nn - kk) while(++r <= nn - kk)
{ {
/* r is the step number */ /* r is the step number */
/* Compute discrepancy at the r-th step in poly-form */ /* Compute discrepancy at the r-th step in poly-form */
int discrR = 0; int discrR = 0;
for(i = 0; i < r; i++) for(i = 0; i < r; i++)
if(lambda[i] != 0 && s[r - i] != a0) if(lambda[i] != 0 &&
s[r - i] != a0)
discrR ^= alpha_to[Modnn(index_of[lambda[i]] + s[r - i])]; discrR ^= alpha_to[Modnn(index_of[lambda[i]] + s[r - i])];
discrR = index_of[discrR]; /* Index form */ discrR = index_of[discrR]; /* Index form */
if(discrR == a0) if(discrR == a0)
{ {
/* 2 lines below: B(x) <-- x*B(x) */ /* 2 lines below: B(x) <-- x*B(x) */
@@ -501,21 +587,23 @@ namespace Aaru.Checksums
{ {
/* 7 lines below: T(x) <-- lambda(x) - discr_r*x*b(x) */ /* 7 lines below: T(x) <-- lambda(x) - discr_r*x*b(x) */
t[0] = lambda[0]; t[0] = lambda[0];
for(i = 0; i < nn - kk; i++) for(i = 0; i < nn - kk; i++)
if(b[i] != a0) if(b[i] != a0)
t[i + 1] = lambda[i + 1] ^ alpha_to[Modnn(discrR + b[i])]; t[i + 1] = lambda[i + 1] ^ alpha_to[Modnn(discrR + b[i])];
else else
t[i + 1] = lambda[i + 1]; t[i + 1] = lambda[i + 1];
if(2 * el <= r + noEras - 1) if(2 * el <= (r + noEras) - 1)
{ {
el = r + noEras - el; el = (r + noEras) - el;
/* /*
* 2 lines below: B(x) <-- inv(discr_r) * * 2 lines below: B(x) <-- inv(discr_r) *
* lambda(x) * lambda(x)
*/ */
for(i = 0; i <= nn - kk; i++) for(i = 0; i <= nn - kk; i++)
b[i] = lambda[i] == 0 ? a0 : Modnn(index_of[lambda[i]] - discrR + nn); b[i] = lambda[i] == 0 ? a0 : Modnn((index_of[lambda[i]] - discrR) + nn);
} }
else else
{ {
@@ -524,16 +612,19 @@ namespace Aaru.Checksums
b[0] = a0; b[0] = a0;
} }
Copy(ref lambda, ref t, nn - kk + 1); Copy(ref lambda, ref t, (nn - kk) + 1);
} }
} }
/* Convert lambda to index form and compute deg(lambda(x)) */ /* Convert lambda to index form and compute deg(lambda(x)) */
int degLambda = 0; int degLambda = 0;
for(i = 0; i < nn - kk + 1; i++)
for(i = 0; i < (nn - kk) + 1; i++)
{ {
lambda[i] = index_of[lambda[i]]; lambda[i] = index_of[lambda[i]];
if(lambda[i] != a0) degLambda = i;
if(lambda[i] != a0)
degLambda = i;
} }
/* /*
@@ -544,9 +635,11 @@ namespace Aaru.Checksums
Copy(ref reg, ref lambda, nn - kk); Copy(ref reg, ref lambda, nn - kk);
reg[0] = temp; reg[0] = temp;
count = 0; /* Number of roots of lambda(x) */ count = 0; /* Number of roots of lambda(x) */
for(i = 1; i <= nn; i++) for(i = 1; i <= nn; i++)
{ {
q = 1; q = 1;
for(j = degLambda; j > 0; j--) for(j = degLambda; j > 0; j--)
if(reg[j] != a0) if(reg[j] != a0)
{ {
@@ -554,7 +647,8 @@ namespace Aaru.Checksums
q ^= alpha_to[reg[j]]; q ^= alpha_to[reg[j]];
} }
if(q != 0) continue; if(q != 0)
continue;
/* store root (index-form) and error location number */ /* store root (index-form) and error location number */
root[count] = i; root[count] = i;
@@ -564,27 +658,35 @@ namespace Aaru.Checksums
#if DEBUG #if DEBUG
AaruConsole.DebugWriteLine("Reed Solomon", "\n Final error positions:\t"); AaruConsole.DebugWriteLine("Reed Solomon", "\n Final error positions:\t");
for(i = 0; i < count; i++) AaruConsole.DebugWriteLine("Reed Solomon", "{0} ", loc[i]);
for(i = 0; i < count; i++)
AaruConsole.DebugWriteLine("Reed Solomon", "{0} ", loc[i]);
AaruConsole.DebugWriteLine("Reed Solomon", "\n"); AaruConsole.DebugWriteLine("Reed Solomon", "\n");
#endif #endif
if(degLambda != count) return -1; if(degLambda != count)
return -1;
/* /*
* Compute err+eras evaluator poly omega(x) = s(x)*lambda(x) (modulo * Compute err+eras evaluator poly omega(x) = s(x)*lambda(x) (modulo
* x**(NN-KK)). in index form. Also find deg(omega). * x**(NN-KK)). in index form. Also find deg(omega).
*/ */
int degOmega = 0; int degOmega = 0;
for(i = 0; i < nn - kk; i++) for(i = 0; i < nn - kk; i++)
{ {
tmp = 0; tmp = 0;
j = degLambda < i ? degLambda : i; 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; 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[i] = index_of[tmp];
} }
@@ -597,26 +699,29 @@ namespace Aaru.Checksums
for(j = count - 1; j >= 0; j--) for(j = count - 1; j >= 0; j--)
{ {
int num1 = 0; int num1 = 0;
for(i = degOmega; i >= 0; i--) for(i = degOmega; i >= 0; i--)
if(omega[i] != a0) if(omega[i] != a0)
num1 ^= alpha_to[Modnn(omega[i] + i * root[j])]; num1 ^= alpha_to[Modnn(omega[i] + (i * root[j]))];
int num2 = alpha_to[Modnn(root[j] * (B0 - 1) + nn)]; int num2 = alpha_to[Modnn((root[j] * (B0 - 1)) + nn)];
int den = 0; int den = 0;
/* lambda[i+1] for i even is the formal derivative lambda_pr of lambda[i] */ /* 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) for(i = Min(degLambda, nn - kk - 1) & ~1; i >= 0; i -= 2)
if(lambda[i + 1] != a0) if(lambda[i + 1] != a0)
den ^= alpha_to[Modnn(lambda[i + 1] + i * root[j])]; den ^= alpha_to[Modnn(lambda[i + 1] + (i * root[j]))];
if(den == 0) if(den == 0)
{ {
AaruConsole.DebugWriteLine("Reed Solomon", "\n ERROR: denominator = 0\n"); AaruConsole.DebugWriteLine("Reed Solomon", "\n ERROR: denominator = 0\n");
return -1; return -1;
} }
/* Apply error to data */ /* Apply error to data */
if(num1 != 0) data[loc[j]] ^= alpha_to[Modnn(index_of[num1] + index_of[num2] + nn - index_of[den])]; if(num1 != 0)
data[loc[j]] ^= alpha_to[Modnn((index_of[num1] + index_of[num2] + nn) - index_of[den])];
} }
return count; return count;

View File

@@ -46,11 +46,10 @@ namespace Aaru.Checksums
{ {
public class Register : IPluginRegister public class Register : IPluginRegister
{ {
public List<Type> GetAllChecksumPlugins() public List<Type> GetAllChecksumPlugins() => Assembly.
{ GetExecutingAssembly().GetTypes().
return Assembly.GetExecutingAssembly().GetTypes().Where(t => t.GetInterfaces().Contains(typeof(IChecksum))) Where(t => t.GetInterfaces().Contains(typeof(IChecksum))).
.Where(t => t.IsClass).ToList(); Where(t => t.IsClass).ToList();
}
public List<Type> GetAllFilesystemPlugins() => null; public List<Type> GetAllFilesystemPlugins() => null;

View File

@@ -37,114 +37,90 @@ using Aaru.CommonTypes.Interfaces;
namespace Aaru.Checksums namespace Aaru.Checksums
{ {
/// <summary> /// <summary>Wraps up .NET SHA1 implementation to a Init(), Update(), Final() context.</summary>
/// Wraps up .NET SHA1 implementation to a Init(), Update(), Final() context.
/// </summary>
public class Sha1Context : IChecksum public class Sha1Context : IChecksum
{ {
SHA1 sha1Provider; readonly SHA1 sha1Provider;
/// <summary> /// <summary>Initializes the SHA1 hash provider</summary>
/// Initializes the SHA1 hash provider public Sha1Context() => sha1Provider = SHA1.Create();
/// </summary>
public Sha1Context()
{
sha1Provider = SHA1.Create();
}
/// <summary> /// <summary>Updates the hash with data.</summary>
/// Updates the hash with data.
/// </summary>
/// <param name="data">Data buffer.</param> /// <param name="data">Data buffer.</param>
/// <param name="len">Length of buffer to hash.</param> /// <param name="len">Length of buffer to hash.</param>
public void Update(byte[] data, uint len) public void Update(byte[] data, uint len) => sha1Provider.TransformBlock(data, 0, (int)len, data, 0);
{
sha1Provider.TransformBlock(data, 0, (int)len, data, 0);
}
/// <summary> /// <summary>Updates the hash with data.</summary>
/// Updates the hash with data.
/// </summary>
/// <param name="data">Data buffer.</param> /// <param name="data">Data buffer.</param>
public void Update(byte[] data) public void Update(byte[] data) => Update(data, (uint)data.Length);
{
Update(data, (uint)data.Length);
}
/// <summary> /// <summary>Returns a byte array of the hash value.</summary>
/// Returns a byte array of the hash value.
/// </summary>
public byte[] Final() public byte[] Final()
{ {
sha1Provider.TransformFinalBlock(new byte[0], 0, 0); sha1Provider.TransformFinalBlock(new byte[0], 0, 0);
return sha1Provider.Hash; return sha1Provider.Hash;
} }
/// <summary> /// <summary>Returns a hexadecimal representation of the hash value.</summary>
/// Returns a hexadecimal representation of the hash value.
/// </summary>
public string End() public string End()
{ {
sha1Provider.TransformFinalBlock(new byte[0], 0, 0); sha1Provider.TransformFinalBlock(new byte[0], 0, 0);
StringBuilder sha1Output = new StringBuilder(); var sha1Output = new StringBuilder();
foreach(byte h in sha1Provider.Hash) sha1Output.Append(h.ToString("x2")); foreach(byte h in sha1Provider.Hash)
sha1Output.Append(h.ToString("x2"));
return sha1Output.ToString(); return sha1Output.ToString();
} }
/// <summary> /// <summary>Gets the hash of a file</summary>
/// Gets the hash of a file
/// </summary>
/// <param name="filename">File path.</param> /// <param name="filename">File path.</param>
public static byte[] File(string filename) public static byte[] File(string filename)
{ {
SHA1 localSha1Provider = SHA1.Create(); var localSha1Provider = SHA1.Create();
FileStream fileStream = new FileStream(filename, FileMode.Open); var fileStream = new FileStream(filename, FileMode.Open);
byte[] result = localSha1Provider.ComputeHash(fileStream); byte[] result = localSha1Provider.ComputeHash(fileStream);
fileStream.Close(); fileStream.Close();
return result; return result;
} }
/// <summary> /// <summary>Gets the hash of a file in hexadecimal and as a byte array.</summary>
/// Gets the hash of a file in hexadecimal and as a byte array.
/// </summary>
/// <param name="filename">File path.</param> /// <param name="filename">File path.</param>
/// <param name="hash">Byte array of the hash value.</param> /// <param name="hash">Byte array of the hash value.</param>
public static string File(string filename, out byte[] hash) public static string File(string filename, out byte[] hash)
{ {
SHA1 localSha1Provider = SHA1.Create(); var localSha1Provider = SHA1.Create();
FileStream fileStream = new FileStream(filename, FileMode.Open); var fileStream = new FileStream(filename, FileMode.Open);
hash = localSha1Provider.ComputeHash(fileStream); hash = localSha1Provider.ComputeHash(fileStream);
StringBuilder sha1Output = new StringBuilder(); var sha1Output = new StringBuilder();
foreach(byte h in hash) sha1Output.Append(h.ToString("x2")); foreach(byte h in hash)
sha1Output.Append(h.ToString("x2"));
fileStream.Close(); fileStream.Close();
return sha1Output.ToString(); return sha1Output.ToString();
} }
/// <summary> /// <summary>Gets the hash of the specified data buffer.</summary>
/// Gets the hash of the specified data buffer.
/// </summary>
/// <param name="data">Data buffer.</param> /// <param name="data">Data buffer.</param>
/// <param name="len">Length of the data buffer to hash.</param> /// <param name="len">Length of the data buffer to hash.</param>
/// <param name="hash">Byte array of the hash value.</param> /// <param name="hash">Byte array of the hash value.</param>
public static string Data(byte[] data, uint len, out byte[] hash) public static string Data(byte[] data, uint len, out byte[] hash)
{ {
SHA1 localSha1Provider = SHA1.Create(); var localSha1Provider = SHA1.Create();
hash = localSha1Provider.ComputeHash(data, 0, (int)len); hash = localSha1Provider.ComputeHash(data, 0, (int)len);
StringBuilder sha1Output = new StringBuilder(); var sha1Output = new StringBuilder();
foreach(byte h in hash) sha1Output.Append(h.ToString("x2")); foreach(byte h in hash)
sha1Output.Append(h.ToString("x2"));
return sha1Output.ToString(); return sha1Output.ToString();
} }
/// <summary> /// <summary>Gets the hash of the specified data buffer.</summary>
/// Gets the hash of the specified data buffer.
/// </summary>
/// <param name="data">Data buffer.</param> /// <param name="data">Data buffer.</param>
/// <param name="hash">Byte array of the hash value.</param> /// <param name="hash">Byte array of the hash value.</param>
public static string Data(byte[] data, out byte[] hash) => Data(data, (uint)data.Length, out hash); public static string Data(byte[] data, out byte[] hash) => Data(data, (uint)data.Length, out hash);

View File

@@ -37,114 +37,90 @@ using Aaru.CommonTypes.Interfaces;
namespace Aaru.Checksums namespace Aaru.Checksums
{ {
/// <summary> /// <summary>Wraps up .NET SHA256 implementation to a Init(), Update(), Final() context.</summary>
/// Wraps up .NET SHA256 implementation to a Init(), Update(), Final() context.
/// </summary>
public class Sha256Context : IChecksum public class Sha256Context : IChecksum
{ {
SHA256 sha256Provider; readonly SHA256 sha256Provider;
/// <summary> /// <summary>Initializes the SHA256 hash provider</summary>
/// Initializes the SHA256 hash provider public Sha256Context() => sha256Provider = SHA256.Create();
/// </summary>
public Sha256Context()
{
sha256Provider = SHA256.Create();
}
/// <summary> /// <summary>Updates the hash with data.</summary>
/// Updates the hash with data.
/// </summary>
/// <param name="data">Data buffer.</param> /// <param name="data">Data buffer.</param>
/// <param name="len">Length of buffer to hash.</param> /// <param name="len">Length of buffer to hash.</param>
public void Update(byte[] data, uint len) public void Update(byte[] data, uint len) => sha256Provider.TransformBlock(data, 0, (int)len, data, 0);
{
sha256Provider.TransformBlock(data, 0, (int)len, data, 0);
}
/// <summary> /// <summary>Updates the hash with data.</summary>
/// Updates the hash with data.
/// </summary>
/// <param name="data">Data buffer.</param> /// <param name="data">Data buffer.</param>
public void Update(byte[] data) public void Update(byte[] data) => Update(data, (uint)data.Length);
{
Update(data, (uint)data.Length);
}
/// <summary> /// <summary>Returns a byte array of the hash value.</summary>
/// Returns a byte array of the hash value.
/// </summary>
public byte[] Final() public byte[] Final()
{ {
sha256Provider.TransformFinalBlock(new byte[0], 0, 0); sha256Provider.TransformFinalBlock(new byte[0], 0, 0);
return sha256Provider.Hash; return sha256Provider.Hash;
} }
/// <summary> /// <summary>Returns a hexadecimal representation of the hash value.</summary>
/// Returns a hexadecimal representation of the hash value.
/// </summary>
public string End() public string End()
{ {
sha256Provider.TransformFinalBlock(new byte[0], 0, 0); sha256Provider.TransformFinalBlock(new byte[0], 0, 0);
StringBuilder sha256Output = new StringBuilder(); var sha256Output = new StringBuilder();
foreach(byte h in sha256Provider.Hash) sha256Output.Append(h.ToString("x2")); foreach(byte h in sha256Provider.Hash)
sha256Output.Append(h.ToString("x2"));
return sha256Output.ToString(); return sha256Output.ToString();
} }
/// <summary> /// <summary>Gets the hash of a file</summary>
/// Gets the hash of a file
/// </summary>
/// <param name="filename">File path.</param> /// <param name="filename">File path.</param>
public static byte[] File(string filename) public static byte[] File(string filename)
{ {
SHA256 localSha256Provider = SHA256.Create(); var localSha256Provider = SHA256.Create();
FileStream fileStream = new FileStream(filename, FileMode.Open); var fileStream = new FileStream(filename, FileMode.Open);
byte[] result = localSha256Provider.ComputeHash(fileStream); byte[] result = localSha256Provider.ComputeHash(fileStream);
fileStream.Close(); fileStream.Close();
return result; return result;
} }
/// <summary> /// <summary>Gets the hash of a file in hexadecimal and as a byte array.</summary>
/// Gets the hash of a file in hexadecimal and as a byte array.
/// </summary>
/// <param name="filename">File path.</param> /// <param name="filename">File path.</param>
/// <param name="hash">Byte array of the hash value.</param> /// <param name="hash">Byte array of the hash value.</param>
public static string File(string filename, out byte[] hash) public static string File(string filename, out byte[] hash)
{ {
SHA256 localSha256Provider = SHA256.Create(); var localSha256Provider = SHA256.Create();
FileStream fileStream = new FileStream(filename, FileMode.Open); var fileStream = new FileStream(filename, FileMode.Open);
hash = localSha256Provider.ComputeHash(fileStream); hash = localSha256Provider.ComputeHash(fileStream);
StringBuilder sha256Output = new StringBuilder(); var sha256Output = new StringBuilder();
foreach(byte h in hash) sha256Output.Append(h.ToString("x2")); foreach(byte h in hash)
sha256Output.Append(h.ToString("x2"));
fileStream.Close(); fileStream.Close();
return sha256Output.ToString(); return sha256Output.ToString();
} }
/// <summary> /// <summary>Gets the hash of the specified data buffer.</summary>
/// Gets the hash of the specified data buffer.
/// </summary>
/// <param name="data">Data buffer.</param> /// <param name="data">Data buffer.</param>
/// <param name="len">Length of the data buffer to hash.</param> /// <param name="len">Length of the data buffer to hash.</param>
/// <param name="hash">Byte array of the hash value.</param> /// <param name="hash">Byte array of the hash value.</param>
public static string Data(byte[] data, uint len, out byte[] hash) public static string Data(byte[] data, uint len, out byte[] hash)
{ {
SHA256 localSha256Provider = SHA256.Create(); var localSha256Provider = SHA256.Create();
hash = localSha256Provider.ComputeHash(data, 0, (int)len); hash = localSha256Provider.ComputeHash(data, 0, (int)len);
StringBuilder sha256Output = new StringBuilder(); var sha256Output = new StringBuilder();
foreach(byte h in hash) sha256Output.Append(h.ToString("x2")); foreach(byte h in hash)
sha256Output.Append(h.ToString("x2"));
return sha256Output.ToString(); return sha256Output.ToString();
} }
/// <summary> /// <summary>Gets the hash of the specified data buffer.</summary>
/// Gets the hash of the specified data buffer.
/// </summary>
/// <param name="data">Data buffer.</param> /// <param name="data">Data buffer.</param>
/// <param name="hash">Byte array of the hash value.</param> /// <param name="hash">Byte array of the hash value.</param>
public static string Data(byte[] data, out byte[] hash) => Data(data, (uint)data.Length, out hash); public static string Data(byte[] data, out byte[] hash) => Data(data, (uint)data.Length, out hash);

View File

@@ -37,114 +37,90 @@ using Aaru.CommonTypes.Interfaces;
namespace Aaru.Checksums namespace Aaru.Checksums
{ {
/// <summary> /// <summary>Wraps up .NET SHA384 implementation to a Init(), Update(), Final() context.</summary>
/// Wraps up .NET SHA384 implementation to a Init(), Update(), Final() context.
/// </summary>
public class Sha384Context : IChecksum public class Sha384Context : IChecksum
{ {
SHA384 sha384Provider; readonly SHA384 sha384Provider;
/// <summary> /// <summary>Initializes the SHA384 hash provider</summary>
/// Initializes the SHA384 hash provider public Sha384Context() => sha384Provider = SHA384.Create();
/// </summary>
public Sha384Context()
{
sha384Provider = SHA384.Create();
}
/// <summary> /// <summary>Updates the hash with data.</summary>
/// Updates the hash with data.
/// </summary>
/// <param name="data">Data buffer.</param> /// <param name="data">Data buffer.</param>
/// <param name="len">Length of buffer to hash.</param> /// <param name="len">Length of buffer to hash.</param>
public void Update(byte[] data, uint len) public void Update(byte[] data, uint len) => sha384Provider.TransformBlock(data, 0, (int)len, data, 0);
{
sha384Provider.TransformBlock(data, 0, (int)len, data, 0);
}
/// <summary> /// <summary>Updates the hash with data.</summary>
/// Updates the hash with data.
/// </summary>
/// <param name="data">Data buffer.</param> /// <param name="data">Data buffer.</param>
public void Update(byte[] data) public void Update(byte[] data) => Update(data, (uint)data.Length);
{
Update(data, (uint)data.Length);
}
/// <summary> /// <summary>Returns a byte array of the hash value.</summary>
/// Returns a byte array of the hash value.
/// </summary>
public byte[] Final() public byte[] Final()
{ {
sha384Provider.TransformFinalBlock(new byte[0], 0, 0); sha384Provider.TransformFinalBlock(new byte[0], 0, 0);
return sha384Provider.Hash; return sha384Provider.Hash;
} }
/// <summary> /// <summary>Returns a hexadecimal representation of the hash value.</summary>
/// Returns a hexadecimal representation of the hash value.
/// </summary>
public string End() public string End()
{ {
sha384Provider.TransformFinalBlock(new byte[0], 0, 0); sha384Provider.TransformFinalBlock(new byte[0], 0, 0);
StringBuilder sha384Output = new StringBuilder(); var sha384Output = new StringBuilder();
foreach(byte h in sha384Provider.Hash) sha384Output.Append(h.ToString("x2")); foreach(byte h in sha384Provider.Hash)
sha384Output.Append(h.ToString("x2"));
return sha384Output.ToString(); return sha384Output.ToString();
} }
/// <summary> /// <summary>Gets the hash of a file</summary>
/// Gets the hash of a file
/// </summary>
/// <param name="filename">File path.</param> /// <param name="filename">File path.</param>
public static byte[] File(string filename) public static byte[] File(string filename)
{ {
SHA384 localSha384Provider = SHA384.Create(); var localSha384Provider = SHA384.Create();
FileStream fileStream = new FileStream(filename, FileMode.Open); var fileStream = new FileStream(filename, FileMode.Open);
byte[] result = localSha384Provider.ComputeHash(fileStream); byte[] result = localSha384Provider.ComputeHash(fileStream);
fileStream.Close(); fileStream.Close();
return result; return result;
} }
/// <summary> /// <summary>Gets the hash of a file in hexadecimal and as a byte array.</summary>
/// Gets the hash of a file in hexadecimal and as a byte array.
/// </summary>
/// <param name="filename">File path.</param> /// <param name="filename">File path.</param>
/// <param name="hash">Byte array of the hash value.</param> /// <param name="hash">Byte array of the hash value.</param>
public static string File(string filename, out byte[] hash) public static string File(string filename, out byte[] hash)
{ {
SHA384 localSha384Provider = SHA384.Create(); var localSha384Provider = SHA384.Create();
FileStream fileStream = new FileStream(filename, FileMode.Open); var fileStream = new FileStream(filename, FileMode.Open);
hash = localSha384Provider.ComputeHash(fileStream); hash = localSha384Provider.ComputeHash(fileStream);
StringBuilder sha384Output = new StringBuilder(); var sha384Output = new StringBuilder();
foreach(byte h in hash) sha384Output.Append(h.ToString("x2")); foreach(byte h in hash)
sha384Output.Append(h.ToString("x2"));
fileStream.Close(); fileStream.Close();
return sha384Output.ToString(); return sha384Output.ToString();
} }
/// <summary> /// <summary>Gets the hash of the specified data buffer.</summary>
/// Gets the hash of the specified data buffer.
/// </summary>
/// <param name="data">Data buffer.</param> /// <param name="data">Data buffer.</param>
/// <param name="len">Length of the data buffer to hash.</param> /// <param name="len">Length of the data buffer to hash.</param>
/// <param name="hash">Byte array of the hash value.</param> /// <param name="hash">Byte array of the hash value.</param>
public static string Data(byte[] data, uint len, out byte[] hash) public static string Data(byte[] data, uint len, out byte[] hash)
{ {
SHA384 localSha384Provider = SHA384.Create(); var localSha384Provider = SHA384.Create();
hash = localSha384Provider.ComputeHash(data, 0, (int)len); hash = localSha384Provider.ComputeHash(data, 0, (int)len);
StringBuilder sha384Output = new StringBuilder(); var sha384Output = new StringBuilder();
foreach(byte h in hash) sha384Output.Append(h.ToString("x2")); foreach(byte h in hash)
sha384Output.Append(h.ToString("x2"));
return sha384Output.ToString(); return sha384Output.ToString();
} }
/// <summary> /// <summary>Gets the hash of the specified data buffer.</summary>
/// Gets the hash of the specified data buffer.
/// </summary>
/// <param name="data">Data buffer.</param> /// <param name="data">Data buffer.</param>
/// <param name="hash">Byte array of the hash value.</param> /// <param name="hash">Byte array of the hash value.</param>
public static string Data(byte[] data, out byte[] hash) => Data(data, (uint)data.Length, out hash); public static string Data(byte[] data, out byte[] hash) => Data(data, (uint)data.Length, out hash);

View File

@@ -37,114 +37,90 @@ using Aaru.CommonTypes.Interfaces;
namespace Aaru.Checksums namespace Aaru.Checksums
{ {
/// <summary> /// <summary>Wraps up .NET SHA512 implementation to a Init(), Update(), Final() context.</summary>
/// Wraps up .NET SHA512 implementation to a Init(), Update(), Final() context.
/// </summary>
public class Sha512Context : IChecksum public class Sha512Context : IChecksum
{ {
SHA512 sha512Provider; readonly SHA512 sha512Provider;
/// <summary> /// <summary>Initializes the SHA512 hash provider</summary>
/// Initializes the SHA512 hash provider public Sha512Context() => sha512Provider = SHA512.Create();
/// </summary>
public Sha512Context()
{
sha512Provider = SHA512.Create();
}
/// <summary> /// <summary>Updates the hash with data.</summary>
/// Updates the hash with data.
/// </summary>
/// <param name="data">Data buffer.</param> /// <param name="data">Data buffer.</param>
/// <param name="len">Length of buffer to hash.</param> /// <param name="len">Length of buffer to hash.</param>
public void Update(byte[] data, uint len) public void Update(byte[] data, uint len) => sha512Provider.TransformBlock(data, 0, (int)len, data, 0);
{
sha512Provider.TransformBlock(data, 0, (int)len, data, 0);
}
/// <summary> /// <summary>Updates the hash with data.</summary>
/// Updates the hash with data.
/// </summary>
/// <param name="data">Data buffer.</param> /// <param name="data">Data buffer.</param>
public void Update(byte[] data) public void Update(byte[] data) => Update(data, (uint)data.Length);
{
Update(data, (uint)data.Length);
}
/// <summary> /// <summary>Returns a byte array of the hash value.</summary>
/// Returns a byte array of the hash value.
/// </summary>
public byte[] Final() public byte[] Final()
{ {
sha512Provider.TransformFinalBlock(new byte[0], 0, 0); sha512Provider.TransformFinalBlock(new byte[0], 0, 0);
return sha512Provider.Hash; return sha512Provider.Hash;
} }
/// <summary> /// <summary>Returns a hexadecimal representation of the hash value.</summary>
/// Returns a hexadecimal representation of the hash value.
/// </summary>
public string End() public string End()
{ {
sha512Provider.TransformFinalBlock(new byte[0], 0, 0); sha512Provider.TransformFinalBlock(new byte[0], 0, 0);
StringBuilder sha512Output = new StringBuilder(); var sha512Output = new StringBuilder();
foreach(byte h in sha512Provider.Hash) sha512Output.Append(h.ToString("x2")); foreach(byte h in sha512Provider.Hash)
sha512Output.Append(h.ToString("x2"));
return sha512Output.ToString(); return sha512Output.ToString();
} }
/// <summary> /// <summary>Gets the hash of a file</summary>
/// Gets the hash of a file
/// </summary>
/// <param name="filename">File path.</param> /// <param name="filename">File path.</param>
public static byte[] File(string filename) public static byte[] File(string filename)
{ {
SHA512 localSha512Provider = SHA512.Create(); var localSha512Provider = SHA512.Create();
FileStream fileStream = new FileStream(filename, FileMode.Open); var fileStream = new FileStream(filename, FileMode.Open);
byte[] result = localSha512Provider.ComputeHash(fileStream); byte[] result = localSha512Provider.ComputeHash(fileStream);
fileStream.Close(); fileStream.Close();
return result; return result;
} }
/// <summary> /// <summary>Gets the hash of a file in hexadecimal and as a byte array.</summary>
/// Gets the hash of a file in hexadecimal and as a byte array.
/// </summary>
/// <param name="filename">File path.</param> /// <param name="filename">File path.</param>
/// <param name="hash">Byte array of the hash value.</param> /// <param name="hash">Byte array of the hash value.</param>
public static string File(string filename, out byte[] hash) public static string File(string filename, out byte[] hash)
{ {
SHA512 localSha512Provider = SHA512.Create(); var localSha512Provider = SHA512.Create();
FileStream fileStream = new FileStream(filename, FileMode.Open); var fileStream = new FileStream(filename, FileMode.Open);
hash = localSha512Provider.ComputeHash(fileStream); hash = localSha512Provider.ComputeHash(fileStream);
StringBuilder sha512Output = new StringBuilder(); var sha512Output = new StringBuilder();
foreach(byte h in hash) sha512Output.Append(h.ToString("x2")); foreach(byte h in hash)
sha512Output.Append(h.ToString("x2"));
fileStream.Close(); fileStream.Close();
return sha512Output.ToString(); return sha512Output.ToString();
} }
/// <summary> /// <summary>Gets the hash of the specified data buffer.</summary>
/// Gets the hash of the specified data buffer.
/// </summary>
/// <param name="data">Data buffer.</param> /// <param name="data">Data buffer.</param>
/// <param name="len">Length of the data buffer to hash.</param> /// <param name="len">Length of the data buffer to hash.</param>
/// <param name="hash">Byte array of the hash value.</param> /// <param name="hash">Byte array of the hash value.</param>
public static string Data(byte[] data, uint len, out byte[] hash) public static string Data(byte[] data, uint len, out byte[] hash)
{ {
SHA512 localSha512Provider = SHA512.Create(); var localSha512Provider = SHA512.Create();
hash = localSha512Provider.ComputeHash(data, 0, (int)len); hash = localSha512Provider.ComputeHash(data, 0, (int)len);
StringBuilder sha512Output = new StringBuilder(); var sha512Output = new StringBuilder();
foreach(byte h in hash) sha512Output.Append(h.ToString("x2")); foreach(byte h in hash)
sha512Output.Append(h.ToString("x2"));
return sha512Output.ToString(); return sha512Output.ToString();
} }
/// <summary> /// <summary>Gets the hash of the specified data buffer.</summary>
/// Gets the hash of the specified data buffer.
/// </summary>
/// <param name="data">Data buffer.</param> /// <param name="data">Data buffer.</param>
/// <param name="hash">Byte array of the hash value.</param> /// <param name="hash">Byte array of the hash value.</param>
public static string Data(byte[] data, out byte[] hash) => Data(data, (uint)data.Length, out hash); public static string Data(byte[] data, out byte[] hash) => Data(data, (uint)data.Length, out hash);

View File

@@ -46,9 +46,7 @@ using Aaru.CommonTypes.Interfaces;
namespace Aaru.Checksums namespace Aaru.Checksums
{ {
/// <summary> /// <summary>Implements the SpamSum fuzzy hashing algorithm.</summary>
/// Implements the SpamSum fuzzy hashing algorithm.
/// </summary>
public class SpamSumContext : IChecksum public class SpamSumContext : IChecksum
{ {
const uint ROLLING_WINDOW = 7; const uint ROLLING_WINDOW = 7;
@@ -57,25 +55,29 @@ namespace Aaru.Checksums
const uint HASH_INIT = 0x28021967; const uint HASH_INIT = 0x28021967;
const uint NUM_BLOCKHASHES = 31; const uint NUM_BLOCKHASHES = 31;
const uint SPAMSUM_LENGTH = 64; const uint SPAMSUM_LENGTH = 64;
const uint FUZZY_MAX_RESULT = 2 * SPAMSUM_LENGTH + 20; const uint FUZZY_MAX_RESULT = (2 * SPAMSUM_LENGTH) + 20;
//"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; //"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
readonly byte[] b64 = readonly byte[] b64 =
{ {
0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50, 0x51, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50, 0x51, 0x52,
0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6A,
0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A, 0x30, 0x31,
0x7A, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x2B, 0x2F 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x2B, 0x2F
}; };
FuzzyState self; FuzzyState self;
/// <summary> /// <summary>Initializes the SpamSum structures</summary>
/// Initializes the SpamSum structures
/// </summary>
public SpamSumContext() public SpamSumContext()
{ {
self = new FuzzyState {Bh = new BlockhashContext[NUM_BLOCKHASHES]}; self = new FuzzyState
for(int i = 0; i < NUM_BLOCKHASHES; i++) self.Bh[i].Digest = new byte[SPAMSUM_LENGTH]; {
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.Bhstart = 0;
self.Bhend = 1; self.Bhend = 1;
@@ -88,34 +90,25 @@ namespace Aaru.Checksums
roll_init(); roll_init();
} }
/// <summary> /// <summary>Updates the hash with data.</summary>
/// Updates the hash with data.
/// </summary>
/// <param name="data">Data buffer.</param> /// <param name="data">Data buffer.</param>
/// <param name="len">Length of buffer to hash.</param> /// <param name="len">Length of buffer to hash.</param>
public void Update(byte[] data, uint len) public void Update(byte[] data, uint len)
{ {
self.TotalSize += len; self.TotalSize += len;
for(int i = 0; i < len; i++) fuzzy_engine_step(data[i]);
for(int i = 0; i < len; i++)
fuzzy_engine_step(data[i]);
} }
/// <summary> /// <summary>Updates the hash with data.</summary>
/// Updates the hash with data.
/// </summary>
/// <param name="data">Data buffer.</param> /// <param name="data">Data buffer.</param>
public void Update(byte[] data) public void Update(byte[] data) => Update(data, (uint)data.Length);
{
Update(data, (uint)data.Length);
}
/// <summary> /// <summary>Returns a byte array of the hash value.</summary>
/// Returns a byte array of the hash value.
/// </summary>
public byte[] Final() => throw new NotImplementedException("SpamSum does not have a binary representation."); public byte[] Final() => throw new NotImplementedException("SpamSum does not have a binary representation.");
/// <summary> /// <summary>Returns a base64 representation of the hash value.</summary>
/// Returns a base64 representation of the hash value.
/// </summary>
public string End() public string End()
{ {
FuzzyDigest(out byte[] result); FuzzyDigest(out byte[] result);
@@ -124,10 +117,10 @@ namespace Aaru.Checksums
} }
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
void roll_init() void roll_init() => self.Roll = new RollState
{ {
self.Roll = new RollState {Window = new byte[ROLLING_WINDOW]}; Window = new byte[ROLLING_WINDOW]
} };
/* /*
* a rolling hash, based on the Adler checksum. By using a rolling hash * a rolling hash, based on the Adler checksum. By using a rolling hash
@@ -171,7 +164,8 @@ namespace Aaru.Checksums
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
void fuzzy_try_fork_blockhash() void fuzzy_try_fork_blockhash()
{ {
if(self.Bhend >= NUM_BLOCKHASHES) return; if(self.Bhend >= NUM_BLOCKHASHES)
return;
if(self.Bhend == 0) // assert if(self.Bhend == 0) // assert
throw new Exception("Assertion failed"); throw new Exception("Assertion failed");
@@ -189,15 +183,21 @@ namespace Aaru.Checksums
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
void fuzzy_try_reduce_blockhash() void fuzzy_try_reduce_blockhash()
{ {
if(self.Bhstart >= self.Bhend) throw new Exception("Assertion failed"); if(self.Bhstart >= self.Bhend)
throw new Exception("Assertion failed");
if(self.Bhend - self.Bhstart < 2) if(self.Bhend - self.Bhstart < 2)
/* Need at least two working hashes. */ return; /* Need at least two working hashes. */
return;
if((ulong)SSDEEP_BS(self.Bhstart) * SPAMSUM_LENGTH >= self.TotalSize) if((ulong)SSDEEP_BS(self.Bhstart) * SPAMSUM_LENGTH >= self.TotalSize)
/* Initial blocksize estimate would select this or a smaller /* Initial blocksize estimate would select this or a smaller
* blocksize. */ return; * blocksize. */
return;
if(self.Bh[self.Bhstart + 1].Dlen < SPAMSUM_LENGTH / 2) if(self.Bh[self.Bhstart + 1].Dlen < SPAMSUM_LENGTH / 2)
/* Estimate adjustment would select this blocksize. */ return; /* Estimate adjustment would select this blocksize. */
return;
/* At this point we are clearly no longer interested in the /* At this point we are clearly no longer interested in the
* start_blocksize. Get rid of it. */ * start_blocksize. Get rid of it. */
@@ -226,14 +226,18 @@ namespace Aaru.Checksums
if(h % SSDEEP_BS(i) != SSDEEP_BS(i) - 1) if(h % SSDEEP_BS(i) != SSDEEP_BS(i) - 1)
/* Once this condition is false for one bs, it is /* Once this condition is false for one bs, it is
* automatically false for all further bs. I.e. if * automatically false for all further bs. I.e. if
* h === -1 (mod 2*bs) then h === -1 (mod bs). */ break; * h === -1 (mod 2*bs) then h === -1 (mod bs). */
break;
/* We have hit a reset point. We now emit hashes which are /* We have hit a reset point. We now emit hashes which are
* based on all characters in the piece of the message between * based on all characters in the piece of the message between
* the last reset point and this one */ * the last reset point and this one */
if(0 == self.Bh[i].Dlen) fuzzy_try_fork_blockhash(); 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].Digest[self.Bh[i].Dlen] = b64[self.Bh[i].H % 64];
self.Bh[i].Halfdigest = b64[self.Bh[i].Halfh % 64]; self.Bh[i].Halfdigest = b64[self.Bh[i].Halfh % 64];
if(self.Bh[i].Dlen < SPAMSUM_LENGTH - 1) if(self.Bh[i].Dlen < SPAMSUM_LENGTH - 1)
{ {
/* We can have a problem with the tail overflowing. The /* We can have a problem with the tail overflowing. The
@@ -244,12 +248,15 @@ namespace Aaru.Checksums
* */ * */
self.Bh[i].Digest[++self.Bh[i].Dlen] = 0; self.Bh[i].Digest[++self.Bh[i].Dlen] = 0;
self.Bh[i].H = HASH_INIT; self.Bh[i].H = HASH_INIT;
if(self.Bh[i].Dlen >= SPAMSUM_LENGTH / 2) continue;
if(self.Bh[i].Dlen >= SPAMSUM_LENGTH / 2)
continue;
self.Bh[i].Halfh = HASH_INIT; self.Bh[i].Halfh = HASH_INIT;
self.Bh[i].Halfdigest = 0; self.Bh[i].Halfdigest = 0;
} }
else fuzzy_try_reduce_blockhash(); else
fuzzy_try_reduce_blockhash();
} }
} }
@@ -257,13 +264,14 @@ namespace Aaru.Checksums
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
uint FuzzyDigest(out byte[] result) uint FuzzyDigest(out byte[] result)
{ {
StringBuilder sb = new StringBuilder(); var sb = new StringBuilder();
uint bi = self.Bhstart; uint bi = self.Bhstart;
uint h = roll_sum(); uint h = roll_sum();
int remain = (int)(FUZZY_MAX_RESULT - 1); /* Exclude terminating '\0'. */ int remain = (int)(FUZZY_MAX_RESULT - 1); /* Exclude terminating '\0'. */
result = new byte[FUZZY_MAX_RESULT]; result = new byte[FUZZY_MAX_RESULT];
/* Verify that our elimination was not overeager. */ /* Verify that our elimination was not overeager. */
if(!(bi == 0 || (ulong)SSDEEP_BS(bi) / 2 * SPAMSUM_LENGTH < self.TotalSize)) if(!(bi == 0 || ((ulong)SSDEEP_BS(bi) / 2) * SPAMSUM_LENGTH < self.TotalSize))
throw new Exception("Assertion failed"); throw new Exception("Assertion failed");
int resultOff = 0; int resultOff = 0;
@@ -272,20 +280,32 @@ namespace Aaru.Checksums
while((ulong)SSDEEP_BS(bi) * SPAMSUM_LENGTH < self.TotalSize) while((ulong)SSDEEP_BS(bi) * SPAMSUM_LENGTH < self.TotalSize)
{ {
++bi; ++bi;
if(bi >= NUM_BLOCKHASHES) throw new OverflowException("The input exceeds data types.");
if(bi >= NUM_BLOCKHASHES)
throw new OverflowException("The input exceeds data types.");
} }
/* Adapt blocksize guess to actual digest length. */ /* Adapt blocksize guess to actual digest length. */
while(bi >= self.Bhend) --bi; while(bi >= self.Bhend)
while(bi > self.Bhstart && self.Bh[bi].Dlen < SPAMSUM_LENGTH / 2) --bi; --bi;
if(bi > 0 && self.Bh[bi].Dlen < SPAMSUM_LENGTH / 2) throw new Exception("Assertion failed"); 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)); sb.AppendFormat("{0}:", SSDEEP_BS(bi));
int i = Encoding.ASCII.GetBytes(sb.ToString()).Length; int i = Encoding.ASCII.GetBytes(sb.ToString()).Length;
if(i <= 0) if(i <= 0)
/* Maybe snprintf has set errno here? */ throw new OverflowException("The input exceeds data types."); /* Maybe snprintf has set errno here? */
if(i >= remain) throw new Exception("Assertion failed"); throw new OverflowException("The input exceeds data types.");
if(i >= remain)
throw new Exception("Assertion failed");
remain -= i; remain -= i;
@@ -294,17 +314,23 @@ namespace Aaru.Checksums
resultOff += i; resultOff += i;
i = (int)self.Bh[bi].Dlen; i = (int)self.Bh[bi].Dlen;
if(i > remain) throw new Exception("Assertion failed");
if(i > remain)
throw new Exception("Assertion failed");
Array.Copy(self.Bh[bi].Digest, 0, result, resultOff, i); Array.Copy(self.Bh[bi].Digest, 0, result, resultOff, i);
resultOff += i; resultOff += i;
remain -= i; remain -= i;
if(h != 0) if(h != 0)
{ {
if(remain <= 0) throw new Exception("Assertion failed"); if(remain <= 0)
throw new Exception("Assertion failed");
result[resultOff] = b64[self.Bh[bi].H % 64]; result[resultOff] = b64[self.Bh[bi].H % 64];
if(i < 3 || result[resultOff] != result[resultOff - 1] ||
if(i < 3 ||
result[resultOff] != result[resultOff - 1] ||
result[resultOff] != result[resultOff - 2] || result[resultOff] != result[resultOff - 2] ||
result[resultOff] != result[resultOff - 3]) result[resultOff] != result[resultOff - 3])
{ {
@@ -314,10 +340,13 @@ namespace Aaru.Checksums
} }
else if(self.Bh[bi].Digest[i] != 0) else if(self.Bh[bi].Digest[i] != 0)
{ {
if(remain <= 0) throw new Exception("Assertion failed"); if(remain <= 0)
throw new Exception("Assertion failed");
result[resultOff] = self.Bh[bi].Digest[i]; result[resultOff] = self.Bh[bi].Digest[i];
if(i < 3 || result[resultOff] != result[resultOff - 1] ||
if(i < 3 ||
result[resultOff] != result[resultOff - 1] ||
result[resultOff] != result[resultOff - 2] || result[resultOff] != result[resultOff - 2] ||
result[resultOff] != result[resultOff - 3]) result[resultOff] != result[resultOff - 3])
{ {
@@ -326,15 +355,19 @@ namespace Aaru.Checksums
} }
} }
if(remain <= 0) throw new Exception("Assertion failed"); if(remain <= 0)
throw new Exception("Assertion failed");
result[resultOff++] = 0x3A; // ':' result[resultOff++] = 0x3A; // ':'
--remain; --remain;
if(bi < self.Bhend - 1) if(bi < self.Bhend - 1)
{ {
++bi; ++bi;
i = (int)self.Bh[bi].Dlen; i = (int)self.Bh[bi].Dlen;
if(i > remain) throw new Exception("Assertion failed");
if(i > remain)
throw new Exception("Assertion failed");
Array.Copy(self.Bh[bi].Digest, 0, result, resultOff, i); Array.Copy(self.Bh[bi].Digest, 0, result, resultOff, i);
resultOff += i; resultOff += i;
@@ -342,11 +375,14 @@ namespace Aaru.Checksums
if(h != 0) if(h != 0)
{ {
if(remain <= 0) throw new Exception("Assertion failed"); if(remain <= 0)
throw new Exception("Assertion failed");
h = self.Bh[bi].Halfh; h = self.Bh[bi].Halfh;
result[resultOff] = b64[h % 64]; result[resultOff] = b64[h % 64];
if(i < 3 || result[resultOff] != result[resultOff - 1] ||
if(i < 3 ||
result[resultOff] != result[resultOff - 1] ||
result[resultOff] != result[resultOff - 2] || result[resultOff] != result[resultOff - 2] ||
result[resultOff] != result[resultOff - 3]) result[resultOff] != result[resultOff - 3])
{ {
@@ -357,12 +393,16 @@ namespace Aaru.Checksums
else else
{ {
i = self.Bh[bi].Halfdigest; i = self.Bh[bi].Halfdigest;
if(i != 0) if(i != 0)
{ {
if(remain <= 0) throw new Exception("Assertion failed"); if(remain <= 0)
throw new Exception("Assertion failed");
result[resultOff] = (byte)i; result[resultOff] = (byte)i;
if(i < 3 || result[resultOff] != result[resultOff - 1] ||
if(i < 3 ||
result[resultOff] != result[resultOff - 1] ||
result[resultOff] != result[resultOff - 2] || result[resultOff] != result[resultOff - 2] ||
result[resultOff] != result[resultOff - 3]) result[resultOff] != result[resultOff - 3])
{ {
@@ -374,8 +414,11 @@ namespace Aaru.Checksums
} }
else if(h != 0) else if(h != 0)
{ {
if(self.Bh[bi].Dlen != 0) throw new Exception("Assertion failed"); if(self.Bh[bi].Dlen != 0)
if(remain <= 0) throw new Exception("Assertion failed"); throw new Exception("Assertion failed");
if(remain <= 0)
throw new Exception("Assertion failed");
result[resultOff++] = b64[self.Bh[bi].H % 64]; result[resultOff++] = b64[self.Bh[bi].H % 64];
/* No need to bother with FUZZY_FLAG_ELIMSEQ, because this /* No need to bother with FUZZY_FLAG_ELIMSEQ, because this
@@ -384,34 +427,29 @@ namespace Aaru.Checksums
} }
result[resultOff] = 0; result[resultOff] = 0;
return 0; return 0;
} }
/// <summary> /// <summary>Gets the hash of a file</summary>
/// Gets the hash of a file
/// </summary>
/// <param name="filename">File path.</param> /// <param name="filename">File path.</param>
public static byte[] File(string filename) => public static byte[] File(string filename) =>
throw new NotImplementedException("SpamSum does not have a binary representation."); throw new NotImplementedException("SpamSum does not have a binary representation.");
/// <summary> /// <summary>Gets the hash of a file in hexadecimal and as a byte array.</summary>
/// Gets the hash of a file in hexadecimal and as a byte array.
/// </summary>
/// <param name="filename">File path.</param> /// <param name="filename">File path.</param>
/// <param name="hash">Byte array of the hash value.</param> /// <param name="hash">Byte array of the hash value.</param>
public static string File(string filename, out byte[] hash) => public static string File(string filename, out byte[] hash) =>
throw new NotImplementedException("Not yet implemented."); throw new NotImplementedException("Not yet implemented.");
/// <summary> /// <summary>Gets the hash of the specified data buffer.</summary>
/// Gets the hash of the specified data buffer.
/// </summary>
/// <param name="data">Data buffer.</param> /// <param name="data">Data buffer.</param>
/// <param name="len">Length of the data buffer to hash.</param> /// <param name="len">Length of the data buffer to hash.</param>
/// <param name="hash">null</param> /// <param name="hash">null</param>
/// <returns>Base64 representation of SpamSum $blocksize:$hash:$hash</returns> /// <returns>Base64 representation of SpamSum $blocksize:$hash:$hash</returns>
public static string Data(byte[] data, uint len, out byte[] hash) public static string Data(byte[] data, uint len, out byte[] hash)
{ {
SpamSumContext fuzzyContext = new SpamSumContext(); var fuzzyContext = new SpamSumContext();
fuzzyContext.Update(data, len); fuzzyContext.Update(data, len);
@@ -420,9 +458,7 @@ namespace Aaru.Checksums
return fuzzyContext.End(); return fuzzyContext.End();
} }
/// <summary> /// <summary>Gets the hash of the specified data buffer.</summary>
/// Gets the hash of the specified data buffer.
/// </summary>
/// <param name="data">Data buffer.</param> /// <param name="data">Data buffer.</param>
/// <param name="hash">null</param> /// <param name="hash">null</param>
/// <returns>Base64 representation of SpamSum $blocksize:$hash:$hash</returns> /// <returns>Base64 representation of SpamSum $blocksize:$hash:$hash</returns>
@@ -438,7 +474,8 @@ namespace Aaru.Checksums
// LINQ is six times slower // LINQ is six times slower
foreach(byte c in cString) foreach(byte c in cString)
{ {
if(c == 0) break; if(c == 0)
break;
count++; count++;
} }
@@ -449,6 +486,7 @@ namespace Aaru.Checksums
struct RollState struct RollState
{ {
public byte[] Window; public byte[] Window;
// ROLLING_WINDOW // ROLLING_WINDOW
public uint H1; public uint H1;
public uint H2; public uint H2;
@@ -466,6 +504,7 @@ namespace Aaru.Checksums
public uint H; public uint H;
public uint Halfh; public uint Halfh;
public byte[] Digest; public byte[] Digest;
// SPAMSUM_LENGTH // SPAMSUM_LENGTH
public byte Halfdigest; public byte Halfdigest;
public uint Dlen; public uint Dlen;
@@ -476,6 +515,7 @@ namespace Aaru.Checksums
public uint Bhstart; public uint Bhstart;
public uint Bhend; public uint Bhend;
public BlockhashContext[] Bh; public BlockhashContext[] Bh;
//NUM_BLOCKHASHES //NUM_BLOCKHASHES
public ulong TotalSize; public ulong TotalSize;
public RollState Roll; public RollState Roll;