50

How do I calculate the CRC32 (Cyclic Redundancy Checksum) of a string in .NET?

Nick Berardi
  • 54,393
  • 15
  • 113
  • 135

3 Answers3

43

This guy seems to have your answer.

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

And in case the blog ever goes away or breaks the url, here's the github link:

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


Usage of the Crc32 class from the blog post:

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);
DamienG
  • 6,575
  • 27
  • 43
Pete
  • 3,991
  • 3
  • 31
  • 30
  • 1
    Good answer and the code at that link looks solid. Thanks Pete! – Erick Brown Oct 04 '14 at 21:01
  • This code is now broken it would seem. The `Crc32` class does not have a base constructor that his code sample calls. – mellis481 Aug 28 '17 at 15:41
  • 7
    There is a NuGet package that will handle this for you Install-Package Crc32.NET. It actually implements the algorithm (and purports to be considerably faster than other alternatives). You can run the above NuGet command or find the source on GitHub at https://github.com/force-net/Crc32.NET. I'm not normally for including dependencies for every little thing, but this seems specialized and reasonable. – Pete Aug 29 '17 at 13:14
14

Since you seem to be looking to calculate the CRC32 of a string (rather than a file) there's a good example here: https://rosettacode.org/wiki/CRC-32#C.23

The code, should it ever disappear:

/// <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
}

and to use it:

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

You can test the input / output values here: https://crccalc.com/

SharpC
  • 6,974
  • 4
  • 45
  • 40
2

Using the logic from the previous answer, this was my take:

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);
    }
}
spludlow
  • 131
  • 4