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

ZIP CRC32 Static Method and Values

By , 30 Jun 2008
 

Introduction

What! Another Crc32 routine? Well, I like small, fast, and lightweight solutions ... especially the kind having a quick copy and paste solution.

Using the Code

Copy and paste the following into your class or struct... and add overloads as you wish. I've put some overloads into the download code.

//*****************************************************************************
#region Crc32 ESSENTIAL STATIC METHOD AND POLYVALS (where all THE WORK IS DONE)
    internal static uint Crc32  // The only moving part (method) 
        ( uint theStartingCRC
        , byte[] theBytes
        , int theStartingIndex
        , int forCount
        )
    {
        uint iCursor = ~theStartingCRC;
        int iTop = theStartingIndex + forCount;
        for (int i = theStartingIndex; i < iTop; i++)
        {
            iCursor = (((uint)(iCursor / 256)) & 0xFFFFFF)
                ^ Crc32_PolyVals[(int)((iCursor ^ theBytes[i]) & 0xFF)]; 
        }
        return ~iCursor;
    }
    // NOTE: No PolyVals dynamic build! 
    // Weighing dynamic generation code bytes=<whatever> 
    // versus 1024 static bytes, we suggest the savings(if any) of dynamic generation 
    // are not significant and static storage never has to be 
    // dynamically generated (grin).
    // We consider less heap motion (allocation/collection) a good thing.
    private static readonly uint[] Crc32_PolyVals = 
    {
<small>        0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, 0x076DC419, 0x706AF48F, 0xE963A535, 0x9E6495A3,
        0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988, 0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91,
        0x1DB71064, 0x6AB020F2, 0xF3B97148, 0x84BE41DE, 0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7,
        0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC, 0x14015C4F, 0x63066CD9, 0xFA0F3D63, 0x8D080DF5,
        0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172, 0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B,
        0x35B5A8FA, 0x42B2986C, 0xDBBBC9D6, 0xACBCF940, 0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59,
        0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116, 0x21B4F4B5, 0x56B3C423, 0xCFBA9599, 0xB8BDA50F,
        0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924, 0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D,
        0x76DC4190, 0x01DB7106, 0x98D220BC, 0xEFD5102A, 0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433,
        0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818, 0x7F6A0DBB, 0x086D3D2D, 0x91646C97, 0xE6635C01,
        0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E, 0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457,
        0x65B0D9C6, 0x12B7E950, 0x8BBEB8EA, 0xFCB9887C, 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65,
        0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2, 0x4ADFA541, 0x3DD895D7, 0xA4D1C46D, 0xD3D6F4FB,
        0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0, 0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9,
        0x5005713C, 0x270241AA, 0xBE0B1010, 0xC90C2086, 0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F,
        0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4, 0x59B33D17, 0x2EB40D81, 0xB7BD5C3B, 0xC0BA6CAD,
        0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A, 0xEAD54739, 0x9DD277AF, 0x04DB2615, 0x73DC1683,
        0xE3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8, 0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1,
        0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE, 0xF762575D, 0x806567CB, 0x196C3671, 0x6E6B06E7,
        0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC, 0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5,
        0xD6D6A3E8, 0xA1D1937E, 0x38D8C2C4, 0x4FDFF252, 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B,
        0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60, 0xDF60EFC3, 0xA867DF55, 0x316E8EEF, 0x4669BE79,
        0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236, 0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F,
        0xC5BA3BBE, 0xB2BD0B28, 0x2BB45A92, 0x5CB36A04, 0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D,
        0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A, 0x9C0906A9, 0xEB0E363F, 0x72076785, 0x05005713,
        0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38, 0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21,
        0x86D3D2D4, 0xF1D4E242, 0x68DDB3F8, 0x1FDA836E, 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777,
        0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C, 0x8F659EFF, 0xF862AE69, 0x616BFFD3, 0x166CCF45,
        0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2, 0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB,
        0xAED16A4A, 0xD9D65ADC, 0x40DF0B66, 0x37D83BF0, 0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9,
        0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6, 0xBAD03605, 0xCDD70693, 0x54DE5729, 0x23D967BF,
        0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94, 0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D,</small>
     };

#endregion Crc32 ESSENTIAL STATIC METHOD AND POLYVALS

History

  • 27th December, 2007: Initial post
  • 27th June, 2008: Corrected the "stream overload" example in the download file

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

About the Author

G.Franklin
United States United States
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  Layout  Per page   
QuestionCan you code a dynamic hash function?memberTushar Arora20 Aug '10 - 8:19 
Hi!
 
I do not know how to create a hashing function which can roll back to previous hash, into which I could be able to merge (dissolve) new hashes. Like patterns, limitless patterns, which can be rolled back to give the previous pattern state. Can you help me? Thank you.
 
Tushar
Tushar Arora
Tushar Arora

GeneralMy vote of 1memberDizZ5 May '10 - 5:31 
No comment or explanation. What is the theStartingCRC? When the author was asked, the response was "theStartingCRC is the starting CRC".
QuestionBug in stream implementation?memberSteve Pritchard27 Jun '08 - 0:10 
Hi,
 
I think there's a bug in the stream implementation in the commented out code. It seems to have a redundant for loop. I think the code should look like this:
 
            uint iCrc = 0;
            byte[] xBuf = (theOptionalReusableBuffer != null)
                ? theOptionalReusableBuffer : new byte[1024];
            int iRead;
            while ( 0 < (iRead = theStream.Read(xBuf, 0, xBuf.Length)))
            {
                iCrc = Crc32(iCrc, xBuf, 0, iRead);
            }
            theStream.Dispose(); 
rather than like this:
 
            uint iCrc = 0;
            byte[] xBuf = (theOptionalReusableBuffer != null)
                ? theOptionalReusableBuffer : new byte[1024];
            int iRead;
            while (0 < (iRead = theStream.Read(xBuf, 0, xBuf.Length)))
            {
                for (int i = 0; i < iRead; i++)
                    iCrc = Crc32(iCrc, xBuf, 0, iRead);
            }
            theStream.Dispose(); 
 
Cheers,
 
Steve.
AnswerRe: Bug in stream implementation?memberg.CoderCat27 Jun '08 - 6:49 
Steve ... you are exactly right. Thank you.
 
In my library, I implement the "stream overload" as a directly accessing the Crc32_PolyVals ... a copy of what is in for loop of the "Essential Static Method". This gets rid of the need to do
"uint iCursor = ~theStartingCRC;"
on every buffer read, as well as giving the JIT more options of optimization.
 
In copying the "stream method" from my library and rushing to simplify it as an "example overload", I failed to delete the "for line".
 
Hey, now I have some history.
 
Thanks again.
 
g.CoderCat

QuestionWhat is your polynomial generator?memberMember 122027 Dec '07 - 21:06 
The question is in the title!
This might be important as there are many possible polynoms that can be used to generate the static table.
 
Thanks.
 
Didier.

AnswerRe: What is your polynomial generator?memberg.CoderCat29 Feb '08 - 7:16 
The values specified are the same poly values you would get from any dynamic generator.
 
The only thing we do is to declare them statically, rather than calculate them dynamically (IE dynamically producing exactly the same table at runtime versus compile time).
 
My preference for static allocation of the “poly vals” is that if you put in code to dynamically generate them, that code itself will take up program space. Who knows how much, but I say it’s not worth it … because the savings of memory (if any) would not be worth the cost of runtime allocation on the heap. By keeping it all static, all processing occurs on the stack. There is minimal memory (heap) motion.
 
The download code has an example of usage, plus additional “overloads” … including one that streams in a file.
 
While I could have gone on and on about CRC32 calculations … the point of this "article" was quick “copy and paste” ... grab it and use it ... showing the absolute mimimum code needed for any CRC32 "calucation suite". There are plenty of articles on the details of CRC32 caluclation, involving many pages and much dialog.
 
Of course you have to trust this code … which is mainly a process of trusting that the hex values are “correct”. The download code has a full example of how to use the static CRC32 method to generate CRC32 on files (IE buffers), as well as some “overloads” for those that want them. The example produces CRC32 values for files in folders. You can compare those values with a what a known program (such as WinZip) generates to get that confidence.
 
When/if you get that confidence ... the code becomes "frozen" ... and a simple copy and paste when/where needed.
 
Sorry for the delay in responding.
 
g.CoderCat

GeneralRe: What is your polynomial generator?memberTobiasP9 Jul '08 - 1:38 
I'm sure your code works just fine, but the question of which polynomial was used is a valid one as there are several different variants for how a CRC checksum can be calculated - see for example Wikipedia: Computation of CRC[^], where one can read "One of the most commonly encountered CRC algorithms is known as CRC-32, used by (among others) Ethernet, FDDI, ZIP and other archive formats, and PNG image format. Its polynomial can be written msbit-first as 0x04C11DB7, or lsbit-first as 0xEDB88320". Therefore, as there are several variants of CRC-32, the article would benefit from having the exact variant specified.
GeneralRe: What is your polynomial generator?memberg.CoderCat9 Jul '08 - 10:35 
It's the same CRC32 used by ZIP files ... and PNG files and ethernet, etc. I think of it as "The CRC32" because these days it is almost as visible and accepted as just another file attribute ... like size or name or date written.
 
I have little use for CRCs as strong error detection mechanisms. But I do need a routine that "computes what the other guys compute".
 
The download software computes "ZIP CRCS" on the files in any directory. If you want a real test, do it on the System32 folder. Within the test, we suggest comparing the results to what WinZip would generate.
 
In addition, the test will compute each file's CRC using various buffer sizes, with associated tick totals for each buffer size used.
 
You are right. Sorry Didier. Thanks for the feedback. I will ammend the article sometime soon.
 
See also: Spoofing the Wily Zip CRC
http://www.codeproject.com/kb/security/crcspoof.aspx
 
g.CoderCat

GeneralSuggestions...memberMichael Moreno27 Dec '07 - 19:36 
Hello,
 
None of the parameters are commented and personally, not being familiar with crc32 methods I simply could not use the code. I know what a crc32 function is supposed to do, but that neither tells me what the parameters are nor how to call the function nor why on earth it is marked as private!
Besides the static allocation of the Crc32_PolyVals seems a poor choice. It may suit a particular project but not all the projects and having to check all those values for bugs is very tedious in my opinion.
 
All the best,
MM
GeneralRe: Suggestions...memberg.CoderCat29 Feb '08 - 7:33 
MM, as I indicated in my previous message … the point of this was a quick copy and paste of the absolute minimum code for CRC32 calculation. Depending on your situation, you may want to add your own desired “overloads” such as the ones in the download code, or none at all.
 
As far as parameter comments …
theStartingCRC is the starting CRC
theBytes is the byte array that the CRC is being calculated on
theStartingIndex is the starting index in that byte array to start calculation
forCount is the count of bytes to process from theStartingIndex
 
We usually calculate CRC over many buffers of bytes. This code is the absolute minimum needed to generate CRC32, where you start with a CRC of zero, and as you calculate each buffer, you supply as theStartingCRC, the last calculated CRC).
 
In the download code, I give full examples of usage, as well as suggest some “overloads” you might want to have.
 
Again, sorry for the delay in responding.
 
g.CoderCat

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

Permalink | Advertise | Privacy | Mobile
Web03 | 2.6.130523.1 | Last Updated 30 Jun 2008
Article Copyright 2007 by G.Franklin
Everything else Copyright © CodeProject, 1999-2013
Terms of Use
Layout: fixed | fluid