Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Checksum calculation - two’s complement sum of all bytes

I have instructions on creating a checksum of a message described like this:

The checksum consists of a single byte equal to the two’s complement sum of all bytes starting from the “message type” word up to the end of the message block (excluding the transmitted checksum). Carry from the most significant bit is ignored.

Another description I found was: The checksum value contains the twos complement of the modulo 256 sum of the other words in the data message (i.e., message type, message length, and data words). The receiving equipment may calculate the modulo 256 sum of the received words and add this sum to the received checksum word. A result of zero generally indicates that the message was correctly received.

I understand this to mean that I sum the value of all bytes in message (excl checksum), get modulo 256 of this number. get twos complement of this number and that is my checksum.

But I am having trouble with an example message example (from design doc so I must assume it has been encoded correctly).

unsigned char arr[] = {0x80,0x15,0x1,0x8,0x30,0x33,0x31,0x35,0x31,0x30,0x33,0x30,0x2,0x8,0x30,0x33,0x35,0x31,0x2d,0x33,0x32,0x31,0x30,0xe};

So the last byte, 0xE, is the checksum. My code to calculate the checksum is as follows:

bool isMsgValid(unsigned char arr[], int len) {
   int sum = 0;
   for(int i = 0; i < (len-1); ++i) {
      sum += arr[i];
   }
   //modulo 256 sum
   sum %= 256;

   char ch = sum;

   //twos complement
   unsigned char twoscompl = ~ch + 1;

   return arr[len-1] == twoscompl;
}


int main(int argc, char* argv[])
{
   unsigned char arr[] = {0x80,0x15,0x1,0x8,0x30,0x33,0x31,0x35,0x31,0x30,0x33,0x30,0x2,0x8,0x30,0x33,0x35,0x31,0x2d,0x33,0x32,0x31,0x30,0xe};
   int arrsize = sizeof(arr) / sizeof(arr[0]);

   bool ret = isMsgValid(arr, arrsize);

   return 0;
}

The spec is here:= http://www.sinet.bt.com/227v3p5.pdf

I assume I have misunderstood the algorithm required. Any idea how to create this checksum?

Flippin spec writer made a mistake in their data example. Just spotted this then came back on here and found others spotted too. Sorry if I wasted your time. I will study responses because it looks like some useful comments for improving my code.

like image 248
Angus Comber Avatar asked Feb 19 '23 07:02

Angus Comber


1 Answers

You miscopied the example message from the pdf you linked. The second parameter length is 9 bytes, but you used 0x08 in your code.

The document incorrectly states "8 bytes" in the third column when there are really 9 bytes in the parameter. The second column correctly states "00001001".

In other words, your test message should be:

{0x80,0x15,0x1,0x8,0x30,0x33,0x31,0x35,0x31,0x30,0x33,0x30, // param1
 0x2,0x9,0x30,0x33,0x35,0x31,0x2d,0x33,0x32,0x31,0x30,0xe}  // param2
     ^^^

With the correct message array, ret == true when I try your program.

like image 180
Emile Cormier Avatar answered Mar 05 '23 00:03

Emile Cormier