Click here to Skip to main content
Click here to Skip to main content

Cyclic Redundancy Check (CRC32) HashAlgorithm

By , 4 Oct 2002
 

Sample Image - CRC32_DotNet1.jpg

Sample Image - CRC32_DotNet1.jpg

Caution

As Paul Ravier mentioned, this class should NOT be used for security purposes. The CRC32 algorithm can easily be brute forced in minutes. For security applications use MD5, SHA1, SHA256, SHA384, or SHA512 in the System.Security.Cryptography namespace.

Introduction

The System.Security.Cryptography contains the HashAlgorithm. The HashAlgorithm class represents the base class from which all implementations of cryptographic hash algorithms must derive. Although I don't believe the Cyclic Redundancy Check algorithm is considered a true cryptographic hash algorithm, it does fit into the HashAlgorithm pattern.

The CRC32 algorithm is initialized using a 32-bit unsigned integer. This unsigned integer is known the polynomial. Different polynomials produce different check sums. The polynomial is used to generate a 256 element table that speeds the calculation. Normal applications will use the same polynomial throughout it's life-time. Due to this, the default behavior of the CRC32 class caches the table on first use. This behavior can be changed by setting the AutoCache property to false

Sample Usage

// Generic function using HashAlgorithm 
public void HashData(HashAlgorithm hashAlg, string str )
{
    byte[] rawBytes = System.Text.ASCIIEncoding.ASCII.GetBytes( str );
    byte[] hashData = hashAlg.ComputeHash( rawBytes );
    Console.WriteLine( BitConverter.ToString( hashData ) );
}

// Example showing that both functions can be used
public void Example()
{
    string str = "A lazy brown dog..."; // data to hash

    MD5 md5 = new MD5CryptoServiceProvider();
    HashData( md5, str); // Sample of the MD5 algorithm 

    CRC32 crc = new CRC32(); // equivalent to new CRC32(CRC32.DefaultPolynomial);
    HashData( crc, str); // Compute the default CRC32 value for a string
}

Conclusion

Although the MD5, SHA1, SHA256, SHA384, and SHA512 are more accurate than the CRC32 algorithm, sometimes you do not have a choice due various reasons. This class can be used without modification anywhere other HashAlgorithm classes can.

History

6 Oct 2002 - updated source

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here

About the Author

Phil Bolduc
Web Developer
Canada Canada
Member
No Biography provided

Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
You must Sign In to use this message board.
Search this forum  
    Spacing  Noise  Layout  Per page   
GeneralRe: This CRC32 algorithm is brokenmemberWillemM10 May '04 - 5:07 
If I hash the text "Compad 5" two times, I get different results using your CRC32 CryptoService Provider.
 
Greetings.... Smile | :)


Questionnew public byte[] ComputeHash ---> necessary?membercuynen20 Nov '03 - 7:46 
redefining ComputeHash and all its overloads isn't necessary
 
HashAlgorithm contains implementations which internally use
+ Initialize
+ HashCore
+ HashFinal
 
nevertheless, you could still override ComputeHash, e.g. to optimize a Stream buffer
GeneralCRC calcsmemberTim Kohler21 Oct '03 - 4:00 
Hey, I've always used CRCs to do data validation checks on both ends of a communications channel.
You can CRC on the send end and send the value to the client along with the data. The client can then CRC and if the values match you can be very sure (althought not 100%) you got good data. If the client calc's a different CRC than the server's value you need to have the server resend.
 
I think CRC is used for this purpose, not cryptography.
 

GeneralClarification of statementmemberTom Archer9 Sep '03 - 9:44 
You make the following point in your Conclusion:
 
Although the MD5, SHA1, SHA256, SHA384, and SHA512 are more accurate than the CRC32 algorithm, sometimes you do not have a choice due various reasons. This class can be used without modification anywhere other HashAlgorithm classes can.
 
What are examples of these situations?
 
Cheers,
Tom Archer
Inside C#,
Extending MFC Applications with the .NET Framework
It's better to listen to others than to speak, because I already know what I'm going to say anyway. - friend of Jörgen Sigvardsson
GeneralRe: Clarification of statementmemberMika15 Dec '03 - 10:25 
Well I can think of one off the top of my head - Integrating some code with current code - for example when you ZIP some files, the ZIP stores the CRC's of the compressed files to check whether they have been corrupted after un-zipping.
 
Maybe not used for security but definitely has a place.

 
Mladen Mihajlovic
http://mladen.nata.co.za

QuestionHow I could hash a file?memberdomain_gr19 Jun '03 - 3:13 
Please tell me how I could hash a file using C# code.
 
Thank you... Smile | :)
 
Reply at dkolettis@Symmetrics.gr
 
Dimitris
GeneralCompatibility with other CRC32'smembermmthomas7 Jan '03 - 16:06 
In order to be compatible with more common CRC32 implementations, some small changes need to be made.   PKZIP, Ethernet, FDDI, etc, all use a "reflected" form.
 
For further info, see Ross Williams' excellent treatise "A Painless Guide to CRC Error Detection Algorithms" at ftp://ftp.rocksoft.com/papers/crc_v3.txt.
 
The following code should be changed in the class CRC32:
 
/// <summary>
/// Builds a reflected form 32-bit CRC table given a polynomial
/// </summary>
/// <param name="polynomial">The polynomial to use for the table.</param>
/// <returns>The crc table.</returns>
protected static uint[] BuildCRC32Table(uint polynomial)
{
     // 256 entries, one for each possible byte value
     const int length = 256;
     uint[] table = new uint[length];
     for (int i = 0; i < length; i++)
     {
          uint r = Reflect((uint)i, 8) << 24;
 
          for (int j = 8; j > 0; j--)
          {
               const uint topbit = (uint)1 << 31;
               if ((r & topbit) != 0)
                    r = (r << 1) ^ polynomial;
               else
                    r <<= 1;
          }
 
          table[i] = Reflect(r, 32);
     }
     return table;
}
 
/// <summary>
/// Reflects a value's lowest count bits.
/// </summary>
/// <param name="value">The value to reflect.</param>
/// <param name="count">The number of bits to reflect.</param>
/// <returns>The reflected value.</returns>
protected static uint Reflect(uint value, int count)
{
     uint t = value;
     for (int i = 0; i < count; i++)  
     {     
          if ((t & 1) != 0)
               value |=   (uint)(   1 << ((count - 1) - i));     
          else        
               value &=   (uint)(~(1 << ((count - 1) - i)));     
          t >>= 1;  
     }
     return value;
}

GeneralRe: Compatibility with other CRC32'smemberwhosit1 Apr '03 - 9:35 
I am coming up with a value different than WinZip, i believe it is because i have a different polynomial value. The DefaultPolynomial that i have is 0x04C11DB7. Can you tell me what the polynomial you need to use for WinZip/PKZip compatability is?
 
For a given file, with your code im currently getting a CRC of:
 
0xfb40c1b6
 
But WinZip gives me a value for the CRC of
 
0x4317c6d4
 
Any idea? Does it make any diff (i should hope not) that im using the ComputeHash overload that takes a Stream as its argument?
 
Thanks!
GeneralRe: Compatibility with other CRC32'smembermmthomas1 Apr '03 - 11:07 
I'm not sure what part of the file the CRC for PKZIP is being calculated on... whether or not it includes any additional information either before or after compression.
 
Anyone else know when the PKZIP CRC is calculated?
 
-Monroe
GeneralRe: Compatibility with other CRC32'smemberwhosit1 Apr '03 - 11:13 
Actually, i figured out my problem. I did in fact have the right polynomial. What im doing is integrating this CRC code with one of the examples for ColumnHandlers in explorer to give myself a WinZip CRC column in my explorer detail views.
 
The project was set to debug by launching a new instance of explorer. I didnt realize this would also be integrated then into PREVIOUS explorer sessions (including the shell). I thought that would wait until i genned a setup project.
 
So by killing ALL explorer sessions, then recompiling, then reloading explorer, i got it to work. Of course, it would be nice if the IDE would warn you that it wasnt able to update the destination file because it was in use.... then i couldve avoided this whole question.
 
Oh well, c'est la vie. It works now, so all's peachy.

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Permalink | Advertise | Privacy | Mobile
Web01 | 2.6.130523.1 | Last Updated 5 Oct 2002
Article Copyright 2002 by Phil Bolduc
Everything else Copyright © CodeProject, 1999-2013
Terms of Use
Layout: fixed | fluid