




Кажется, у этого парня есть твой ответ.
https://damieng.com/blog/2006/08/08/calculating_crc32_in_c_and_net
И на случай, если блог когда-нибудь исчезнет или сломается URL-адрес, вот ссылка на github:
Использование класса Crc32 из сообщения в блоге:
Crc32 crc32 = new Crc32();
String hash = String.Empty;
using (FileStream fs = File.Open("c:\myfile.txt", FileMode.Open))
foreach (byte b in crc32.ComputeHash(fs)) hash += b.ToString("x2").ToLower();
Console.WriteLine("CRC-32 is {0}", hash);
Казалось бы, этот код сейчас не работает. Класс Crc32 не имеет базового конструктора, который вызывается в его образце кода.
Существует пакет NuGet, который сделает это за вас. Install-Package Crc32.NET. Он фактически реализует алгоритм (и претендует на то, чтобы быть значительно быстрее, чем другие альтернативы). Вы можете запустить указанную выше команду NuGet или найти источник на GitHub по адресу github.com/force-net/Crc32.NET. Обычно я не включаю зависимости для каждой мелочи, но это кажется специализированным и разумным.
Поскольку вы, кажется, хотите вычислить CRC32 строки (а не файла), здесь есть хороший пример: https://rosettacode.org/wiki/CRC-32#C.23
Код, если он когда-нибудь исчезнет:
/// <summary>
/// Performs 32-bit reversed cyclic redundancy checks.
/// </summary>
public class Crc32
{
#region Constants
/// <summary>
/// Generator polynomial (modulo 2) for the reversed CRC32 algorithm.
/// </summary>
private const UInt32 s_generator = 0xEDB88320;
#endregion
#region Constructors
/// <summary>
/// Creates a new instance of the Crc32 class.
/// </summary>
public Crc32()
{
// Constructs the checksum lookup table. Used to optimize the checksum.
m_checksumTable = Enumerable.Range(0, 256).Select(i =>
{
var tableEntry = (uint)i;
for (var j = 0; j < 8; ++j)
{
tableEntry = ((tableEntry & 1) != 0)
? (s_generator ^ (tableEntry >> 1))
: (tableEntry >> 1);
}
return tableEntry;
}).ToArray();
}
#endregion
#region Methods
/// <summary>
/// Calculates the checksum of the byte stream.
/// </summary>
/// <param name = "byteStream">The byte stream to calculate the checksum for.</param>
/// <returns>A 32-bit reversed checksum.</returns>
public UInt32 Get<T>(IEnumerable<T> byteStream)
{
try
{
// Initialize checksumRegister to 0xFFFFFFFF and calculate the checksum.
return ~byteStream.Aggregate(0xFFFFFFFF, (checksumRegister, currentByte) =>
(m_checksumTable[(checksumRegister & 0xFF) ^ Convert.ToByte(currentByte)] ^ (checksumRegister >> 8)));
}
catch (FormatException e)
{
throw new CrcException("Could not read the stream out as bytes.", e);
}
catch (InvalidCastException e)
{
throw new CrcException("Could not read the stream out as bytes.", e);
}
catch (OverflowException e)
{
throw new CrcException("Could not read the stream out as bytes.", e);
}
}
#endregion
#region Fields
/// <summary>
/// Contains a cache of calculated checksum chunks.
/// </summary>
private readonly UInt32[] m_checksumTable;
#endregion
}
и использовать его:
var arrayOfBytes = Encoding.ASCII.GetBytes("The quick brown fox jumps over the lazy dog");
var crc32 = new Crc32();
Console.WriteLine(crc32.Get(arrayOfBytes).ToString("X"));
Здесь вы можете проверить значения ввода / вывода: https://crccalc.com/
Используя логику из предыдущего ответа, я сделал следующее:
public class CRC32
{
private readonly uint[] ChecksumTable;
private readonly uint Polynomial = 0xEDB88320;
public CRC32()
{
ChecksumTable = new uint[0x100];
for (uint index = 0; index < 0x100; ++index)
{
uint item = index;
for (int bit = 0; bit < 8; ++bit)
item = ((item & 1) != 0) ? (Polynomial ^ (item >> 1)) : (item >> 1);
ChecksumTable[index] = item;
}
}
public byte[] ComputeHash(Stream stream)
{
uint result = 0xFFFFFFFF;
int current;
while ((current = stream.ReadByte()) != -1)
result = ChecksumTable[(result & 0xFF) ^ (byte)current] ^ (result >> 8);
byte[] hash = BitConverter.GetBytes(~result);
Array.Reverse(hash);
return hash;
}
public byte[] ComputeHash(byte[] data)
{
using (MemoryStream stream = new MemoryStream(data))
return ComputeHash(stream);
}
}
Хороший ответ, и код по этой ссылке выглядит надежным. Спасибо, Пит!