mirror of
https://github.com/aaru-dps/Aaru.Checksums.git
synced 2025-12-16 19:24:29 +00:00
Code restyling.
This commit is contained in:
@@ -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);
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|||||||
107
CRC32Context.cs
107
CRC32Context.cs
@@ -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);
|
||||||
|
|||||||
107
CRC64Context.cs
107
CRC64Context.cs
@@ -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);
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
277
ReedSolomon.cs
277
ReedSolomon.cs
@@ -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;
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
Reference in New Issue
Block a user