#include #include #include #define BYTE_WIDTH 8 #define REMAINDER_WIDTH 8 #define MESSAGE_LENGTH 3 // Define a boolean type as an enumeration. typedef enum { FALSE = 0, TRUE = 1 } Bool; const unsigned char PowersOfTwo[REMAINDER_WIDTH] = {1, 2, 4, 8, 16, 32, 64, 128}; // This truncated "Divisor", when displayed in binary, looks like this (11010101). const unsigned char Poly = 213; // This function performs the clearest type of modulo-2 bitwise long-division on "NumberOfBytes" Bytes, starting at "DataMessage". // The divisor used is defined in the constant "Poly". // The value returned by the function is the "FinalRemainder", or CRC-Digest. unsigned char ClearCrc(const unsigned char *DataMessage, unsigned int NumberOfBytes){ unsigned int X; unsigned char CurrentRemainder = 0; unsigned int NextMessageBit; unsigned int NextMessageByte; // Load the first Byte of "DataMessage" into the "CurrentRemainder". memcpy(&CurrentRemainder, DataMessage, sizeof(unsigned char)); NextMessageByte = sizeof(unsigned char); NextMessageBit = (BYTE_WIDTH - 1); // This loop eliminates "1"s in the "MSB" position of "CurrentRemainder" using bit-shifting and the "XOR" operation with "Poly". while ( TRUE ) { // This loop left-shifts "0"s out of the "CurrentRemainder". // The process continues until a "1" is found, or the final message bit is pulled in from the right-hand-side. while ( !(CurrentRemainder & PowersOfTwo[REMAINDER_WIDTH - 1]) ) { CurrentRemainder <<= 1; CurrentRemainder += (DataMessage[NextMessageByte] & PowersOfTwo[NextMessageBit])? 1: 0; // Increment the "NextMessageByte" when we have just pulled bit zero into the "CurrentRemainder". // Exit when there are no more bytes left to process. if ( !NextMessageBit ) { NextMessageByte +=1; // End Event #1. if ( NextMessageByte == NumberOfBytes ) { printf("End Event #1\n"); return CurrentRemainder; } NextMessageBit = (BYTE_WIDTH - 1); } else NextMessageBit -= 1; } CurrentRemainder <<= 1; CurrentRemainder += (DataMessage[NextMessageByte] & PowersOfTwo[NextMessageBit])? 1: 0; // The pivotal "XOR" operation. CurrentRemainder ^= Poly; if ( !NextMessageBit ) { NextMessageByte +=1; // End Event #2 if ( NextMessageByte == NumberOfBytes ) { printf("End Event #2\n"); return CurrentRemainder; } NextMessageBit = (BYTE_WIDTH - 1); } else NextMessageBit -= 1; } } // Simply print out "ThisByte" using "1"s and "0"s. void PrintByteInBinary(unsigned char ThisByte){ unsigned int X; char HoldOut[BYTE_WIDTH + 1]; for ( X = 0; X < BYTE_WIDTH; X++ ) HoldOut[X] = (ThisByte & PowersOfTwo[BYTE_WIDTH - 1 - X])? '1': '0'; HoldOut[BYTE_WIDTH] = '\0'; printf("%s", HoldOut); } int main(){ unsigned int X; // Include an extra Byte in the message to test the trailing-zeros CRC property. unsigned char DemonstrationMessage[MESSAGE_LENGTH + 1] = {202, 45, 166, 0}; unsigned char TheDigest; printf("\n---------------------------------------------------------------------------------\n"); printf("\nBehold the |%d| Byte DataMessage - |", MESSAGE_LENGTH); for ( X = 0; X < MESSAGE_LENGTH; X++ ) { PrintByteInBinary(DemonstrationMessage[X]); printf("|"); } printf("\n\n"); TheDigest = ClearCrc(DemonstrationMessage, MESSAGE_LENGTH*sizeof(unsigned char)); printf("Behold TheDigest-|%d|-|", TheDigest); PrintByteInBinary(TheDigest); printf("|\n"); printf("\n---------------------------------------------------------------------------------\n"); // Calculate "TheDigest" with appended zeros, and then replace the trailing zeros with this number. // Recalculate "TheDigest", and this time the digest should compute to zero. printf("\nAppend \"W\" zeros to the DataMessage - |"); for ( X = 0; X < (MESSAGE_LENGTH + 1); X++ ) { PrintByteInBinary(DemonstrationMessage[X]); printf("|"); } printf("\n\n"); TheDigest = ClearCrc(DemonstrationMessage, MESSAGE_LENGTH*sizeof(unsigned char) + 1); printf("Behold TheDigest-|%d|-|", TheDigest); PrintByteInBinary(TheDigest); printf("|\n"); printf("\n---------------------------------------------------------------------------------\n"); DemonstrationMessage[MESSAGE_LENGTH] = TheDigest; printf("\n\"TheDigest\" of this DataMessage should be zero - |"); for ( X = 0; X < (MESSAGE_LENGTH + 1); X++ ) { PrintByteInBinary(DemonstrationMessage[X]); printf("|"); } printf("\n\n"); TheDigest = ClearCrc(DemonstrationMessage, MESSAGE_LENGTH*sizeof(unsigned char) + 1); printf("Behold TheDigest-|%d|-|", TheDigest); PrintByteInBinary(TheDigest); printf("|\n"); printf("\n---------------------------------------------------------------------------------\n"); printf("\n"); return 0; }