如何计算字符串的 CRC32

Posted

技术标签:

【中文标题】如何计算字符串的 CRC32【英文标题】:How do I calculate CRC32 of a string 【发布时间】:2010-09-05 16:57:41 【问题描述】:

如何在 .NET 中计算字符串的 CRC32(循环冗余校验和)?

【问题讨论】:

【参考方案1】:

这家伙似乎有你的答案。

https://damieng.com/blog/2006/08/08/calculating_crc32_in_c_and_net

如果博客消失或破坏 url,这里是 github 链接:

https://github.com/damieng/DamienGKit/blob/master/CSharp/DamienG.Library/Security/Cryptography/Crc32.cs


博文中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 上找到源代码。我通常不会为每一件小事都包含依赖项,但这似乎是专业且合理的。【参考方案2】:

由于您似乎希望计算字符串(而不是文件)的 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/

【讨论】:

【参考方案3】:

使用上一个答案中的逻辑,这是我的看法:

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);
    

【讨论】:

以上是关于如何计算字符串的 CRC32的主要内容,如果未能解决你的问题,请参考以下文章

crc32 — 计算一个字符串的 crc32 多项式?

php crc32 计算字符串的 32 位 CRC(循环冗余校验)

如何用 Python 计算 CRC32 以匹配在线结果?

MySql crc32&&crc64函数提高字符串查询效率

一致性hash算法,采用哪种算法实现比较好,比如MD5,CRC32,或者其它

CRC16校验码如何计算