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

View File

@@ -228,7 +228,7 @@ namespace Aaru.Checksums
uint calculatedEdc = ComputeEdc(0, channel, 0x810);
if(calculatedEdc == storedEdc)
return!failedEccP && !failedEccQ;
return !failedEccP && !failedEccQ;
AaruConsole.DebugWriteLine("CD checksums",
"Mode 1 sector at address: {0:X2}:{1:X2}:{2:X2}, got CRC 0x{3:X8} expected 0x{4:X8}",
@@ -268,7 +268,8 @@ namespace Aaru.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}",
channel[0x00C], channel[0x00D], channel[0x00E], calculatedEdc, storedEdc);
channel[0x00C], channel[0x00D], channel[0x00E], calculatedEdc,
storedEdc);
return false;
}
@@ -306,11 +307,12 @@ namespace Aaru.Checksums
uint calculatedEdc = ComputeEdc(0, mode2Sector, 0x808);
if(calculatedEdc == storedEdc)
return!failedEccP && !failedEccQ;
return !failedEccP && !failedEccQ;
AaruConsole.DebugWriteLine("CD checksums",
"Mode 1 sector at address: {0:X2}:{1:X2}:{2:X2}, got CRC 0x{3:X8} expected 0x{4:X8}",
channel[0x00C], channel[0x00D], channel[0x00E], calculatedEdc, storedEdc);
channel[0x00C], channel[0x00D], channel[0x00E], calculatedEdc,
storedEdc);
return false;
}

View File

@@ -28,7 +28,7 @@ namespace Aaru.Checksums
0x9ff8, 0x6e17, 0x7e36, 0x4e55, 0x5e74, 0x2e93, 0x3eb2, 0x0ed1, 0x1ef0
};
public CRC16CCITTContext() : base(CRC16_CCITT_POLY, CRC16_CCITT_SEED, _ccittCrc16Table, true) { }
public CRC16CCITTContext() : base(CRC16_CCITT_POLY, CRC16_CCITT_SEED, _ccittCrc16Table, true) {}
/// <summary>Gets the hash of a file</summary>
/// <param name="filename">File path.</param>

View File

@@ -29,7 +29,7 @@ namespace Aaru.Checksums
0x8641, 0x8201, 0x42C0, 0x4380, 0x8341, 0x4100, 0x81C1, 0x8081, 0x4040
};
public CRC16IBMContext() : base(CRC16_IBM_POLY, CRC16_IBM_SEED, _ibmCrc16Table, false) { }
public CRC16IBMContext() : base(CRC16_IBM_POLY, CRC16_IBM_SEED, _ibmCrc16Table, false) {}
/// <summary>Gets the hash of a file</summary>
/// <param name="filename">File path.</param>

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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