A C-language program is included which produces CRC values which conform to this specification. The program also includes a routine which demonstrates how an incorrect “check value” which has been found on the web may be generated.
Important features of a standard CRC are that it:
Can be used to validate data Is reproducible by others
The first feature above is easy to realize in a closed system if corruption of data is infrequent (but substantial when it occurs). The term “closed system” refers to a situation where the CRC need not be communicated to others. A correct implementation of a 16-bit CRC will detect a change in a single bit in a message of over 8000 bytes. An erroneous CRC implementation may not be able to detect such subtle errors. If errors are usually both rare and large (affecting several bits), then a faulty 16-bit CRC implementation may still be adequate in a closed system.
The second feature above — that the CRC is reproducible by others — is crucial in an open system; that is, when the CRC must be communicated to others. If the integrity of data passed between two applications is to be verified using a CRC defined by a particular standard, then the implementation of that standard must produce the same result in both applications — otherwise, valid data will be reported as corrupt.
Reproducibility may be satisfied by even a botched implementation of a standard CRC in most cases — if everyone uses the same erroneous implementation of the standard. But this approach:
It appears that some CRC implementations available on the web produce incorrect values for the 16-bit CRC-CCITT. How to tell if a CRC16-CCITT implementation was botched? By calculating the CRC for a reference string.
The CRC value for the 9-byte reference string, “123456789” is 0xE5CC. Some web pages report that the value for reference string should be 0x29B1 — but this value is returned by an implementation which does NOT conform to the specification above. CRC values for other reference strings are listed elsewhere in this document.
The bolding and italics above are used to emphasize the correct value and distort the incorrect value in the hope that it will discourage propagation of the incorrect value.
Why focus on the 16-bit CRC-CCITT (polynomial 0x1021) and not CRC16 (polynomial 0x8005), which appears to have wider use? Because the 16-bit CRC-CCITT:
The following CRC values were produced by the program whose source code is listed elsewhere in this document. The “Good_CRC” values are in accordance with the CRC-CCITT specification as defined at the top of this document. The “Bad_CRC” values are produced by an implementation which reports the incorrect check value that is reported on some web pages for the reference string “123456789”. The validity of the “Good_CRC” values below is demonstrated elsewhere in this document.
Message |
Good_CRC |
Bad_CRC |
Message Length (bytes) |
|
|
|
|
|
|
|
|
|
|
|
|
A string of 256 upper case “A”
characters with no line breaks |
|
|
|
Among the problems with the “Bad_CRC” implementation is that it does not augment a zero-length message with 16 zero bits, as is required (either implicitly or explicitly) when calculating the standard CRC. Thus, it reports a CRC of 0xFFFF — not 0x1D0F — for a zero-length message.
The purpose of this section is to demonstrate that the
“Good_CRC” values listed in the previous section do, in
fact, conform to the CRC-CCITT specification as defined at the top of this document.
Calculation of the 16-bit CRC-CCITT for a one-byte message consisting
of the letter “A”:
Quotient= 111100001110111101011001
|
Conversion of the binary value above to hexadecimal by segmenting
the bits to nibbles:
binary nibbles 1001 0100 0111 1001 hexadecimal 9 4 7 9 |
/*
demonstrates how the incorrect check value of 0x29B1 may be reported for the test string “123456789” when it should be 0xE5CC. */ #include <stdio.h>
#define poly 0x1021 /* crc-ccitt mask */ /* global variables */
int main(void)
sprintf(text, "%s", "");
sprintf(text, "%s", "A");
sprintf(text, "%s", "123456789");
repeat_character(65, 256);
return 0;
void go(void)
unsigned short ch, i; good_crc = 0xffff;
void repeat_character(unsigned char ch, unsigned short n)
void update_good_crc(unsigned short ch)
/*
for (i=0; i<8; i++)
if (ch & v)
if (xor_flag)
/*
void augment_message_for_good_crc()
for (i=0; i<16; i++)
if (xor_flag)
void update_bad_crc(unsigned short ch)
unsigned short i, xor_flag; /*
for(i=0; i<8; i++)
|
The following web pages were among those which were helpful in developing the text and program in this document:
To begin with, I have yet to see a specific reference to an ITU (formerly CCITT) document that clearly identifies exactly where “the” algorithm for the CRC16-CCITT is given. If anyone can cite “chapter and verse”, please let me know where the official specification may be found.
At this point, I'm left with what I can find on the web and what seems most credible to me. The article by Ross Williams, cited above, seems to have stood the test of time and explains things in a way that (eventually) make sense to me. I count it as very credible.
The snippets of C code scattered around the web which claim to produce a CRC16-CCITT have taken on a life of their own, whether they are actually doing what they advertise or not.
I have not yet made a thorough investigation into everything that will be said below, so it may be subject to extensive revision once I find time to do so.
It seems that most of the CRC code on the web actually does implement some form of CRC algorithm — as opposed to some less-robust kind of checksum. It is questionable in some cases whether their algorithm actually implements the CRC that they claim it does.
Assuming that an algorithm is actually implementing some kind of CRC, certain features of that algorithm are crucial when accurately implementing a particular CRC:
There seems to be no controversy that the “correct” (truncated) polynomial is for the CRC16-CCITT is 0x1021.
According to the document by Ross Williams, the initial value for “the” CRC16-CCITT is 0xFFFF. There seems to be little controversy over this, either.
It is usually the case that no one really wants to explicitly append “zero” bits to the end of a message to calculate a CRC. The mathematics of calculating a CRC do allow a shortcut to avoid this time-wasting exercise — but if the shortcut is taken without making a corresponding change in the initial value, then the result is a different CRC.
The question at this point is:
Does the official specification for the CRC16-CCITT say that initial value of 0xFFFF applies to a message with or without “zero” bits explicitly appended to the message?
It makes sense to me that the initial value of 0xFFFF applies to a message with “zero” bits explicitly appended to the message. Why? Because the purpose of a CRC is to detect errors, not necessarily to be implemented in a compact algorithm or to have parameters that are easy to remember.
Whatever clever technique is used to calculate a CRC, it is always emulating a simple implementation in which “zero” bit are explicitly appended to the message. I think it unlikely that the official specification for the CRC16-CCITT would be in terms of anything but the most basic implementation.
The paper by Ross Williams says:
“In theory (i.e. with no assumptions about the message), the initial value has no affect on the strength of the CRC algorithm”
But did the committee that designed the CRC16-CCITT make no assumptions about the message? I suspect that they made one or more assumptions about the kinds of messages that were important to them. If the “correct” check value for message, “123456789”, using “the” CRC16-CCITT is 0x29B1, why would they choose an initial value of 0x84CF (see table below) for the initial value? Remember, the ultimate definition of a CRC requires “zero” bits to be explicitly added to the end of the message — all other implementations use tricks (clever techniques) to accomplish an equivalent calculation. Why would the CCITT (now ITU) want to specify an initial value of 0x84CF to error-check the kinds of messages that were important to them?
It seems that the same CRC can be calculated using the parameters below:
Initial Value | “Zero” bits explicitly
appended to message |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Which is “the” CRC16-CCITT? I think it is 0xE5CC.
Because I haven't seen “chapter and verse” from an ITU document clearly calling for some “shortcut” algorithm using the 0xFFFF initial value, I remain convinced that the “correct” check value for message, “123456789”, using “the” CRC16-CCITT is 0xE5CC — not 0x29B1, as is more widely claimed.
Is this spitting into the wind? Probably so. I don't imagine that publishing this page is going to cause the “incorrect” implementations to disappear. It is offered mainly to help others avoid the frustration that I experienced — what almost everyone else said was the “correct” check value doesn't seem to be correct when trying to calculate the CRC16-CCITT from first principles. This page attempts to provide information which may be helpful in resolving this issue.
As Sven Reifegerste pointed out to me, the “correct” check value for the CRC32 seems to be calculated in a way that is similar to most implementations of the CRC16-CCITT — everyone seems to calculate CRC32 with an initial value of 0xFFFFFFFF but without “zero” bits explicitly appended to the message. The CRC32 is much more widely used — it is calculated and stored for each file that is archived in a .zip (compressed) file. I'm not prepared to spit into that hurricane. And I think that those who are trying to come to grips with exactly how to implement a CRC calculation will find that beginning with a 16-bit CRC, such as CRC16-CCITT, may be more manageable than wrestling with a 32-bit CRC algorithm.
Thank you to the several people who responded to the request for “chapter and verse” where the official specification may be found for “the” CRC16-CCITT.
The ITU (formerly CCITT) documents that have come to my attention so far are:
ITU allows three free downloads (another page on their site says three free downloads per year?) of their standards, as mentioned here:
http://www.itu.int/publications/index.html
Do be careful to follow the instructions as they are presented — I wasted a free download by not doing so.
All three documents mentioned above use the same truncated polynomial — 0x1021.
Recommendation V.41 seems to specify an initial value of “zero” — which differs from the usual implementations of CRC16-CCITT.
Recommendation X.25 seems to:
The result from the X.25 calculation may be mathematically equivalent to a usual implementation of CRC16-CCITT, but that isn't clear to me at this point.
Recommendation T.30 seems to:
Thus, T.30 seems to depart from usual implementations of CRC16-CCITT in that it requires performing one's complement.
There seems to be relatively good agreement among the routines found on the web concerning some parts of “the” CRC16-CCITT specification. But at this point (July 2003), I am not aware of an ITU/CCITT document that agrees with other parts of “the” CRC16-CCITT specification (as it is normally rendered in routines found on the web), and:
Perhaps I missed something in one of the documents mentioned above?
It is also becoming less clear to me that the ITU/CCITT intended or documented the calculation of a stand-alone CRC. Their documents seem to be more focused on a FCS (Frame Check Sequence) that can be used to validate a serial transmission immediately upon receipt rather than being concerned about ensuring that disk files (static data) are intact or unmodified (to the extent that a CRC is good for such a purpose) after a period of months or years.
Copyright © 2001-2007 Joe Geluso
All disclaimers apply — use at your own risk.
This page may reproduced only if it is not altered and it is reproduced
in its entirety — including the link to the author's web site (now gone).