Search code examples
ioschecksum

How to calculate binary checksum?


I'm working on an app of hardware communication that I send or require data from an external hardware. I have the require data part done.

And I just find out I could use some help to calculate the checksum.

A package is created as NSMutableData, then it will be converted in to Byte Array before sending out. A package looks like this:

0x1E 0x2D 0x2F DATA checksum

I'm thinking I can convert hex into binary to calculate them one by one. But I don't know if it's a good idea. Please let me know if this is the only way to do it, or there are some built in functions I don't know. Any suggestions will be appreciated.

BTW, I just found the code for C# from other's post, I'll try to make it work in my app. If I can, I'll share it with you. Still any suggestions will be appreciated.

package org.example.checksum;

public class InternetChecksum {

  /**
   * Calculate the Internet Checksum of a buffer (RFC 1071 -     http://www.faqs.org/rfcs/rfc1071.html)
   * Algorithm is
   * 1) apply a 16-bit 1's complement sum over all octets (adjacent 8-bit pairs [A,B], final odd length is [A,0])
   * 2) apply 1's complement to this final sum
   *
   * Notes:
   * 1's complement is bitwise NOT of positive value.
   * Ensure that any carry bits are added back to avoid off-by-one errors
   *
   *
   * @param buf The message
   * @return The checksum
   */
  public long calculateChecksum(byte[] buf) {
int length = buf.length;
int i = 0;

long sum = 0;
long data;

// Handle all pairs
while (length > 1) {
  // Corrected to include @Andy's edits and various comments on Stack Overflow
  data = (((buf[i] << 8) & 0xFF00) | ((buf[i + 1]) & 0xFF));
  sum += data;
  // 1's complement carry bit correction in 16-bits (detecting sign extension)
  if ((sum & 0xFFFF0000) > 0) {
    sum = sum & 0xFFFF;
    sum += 1;
  }

  i += 2;
  length -= 2;
}

// Handle remaining byte in odd length buffers
if (length > 0) {
  // Corrected to include @Andy's edits and various comments on Stack Overflow
  sum += (buf[i] << 8 & 0xFF00);
  // 1's complement carry bit correction in 16-bits (detecting sign extension)
  if ((sum & 0xFFFF0000) > 0) {
    sum = sum & 0xFFFF;
    sum += 1;
  }
}

// Final 1's complement value correction to 16-bits
sum = ~sum;
sum = sum & 0xFFFF;
return sum;

  }

}

Solution

  • When I post this question a year ago, I was still quite new to Objective-C. It turned out to be something very easy to do.

    The way you calculate checksum is based on how checksum is defined in your communication protocol. In my case, checksum is just the sum of all the previous bytes sent or the data you want to send.

    So if I have a NSMutableData *cmd that has five bytes:

    0x10 0x14 0xE1 0xA4 0x32

    checksum is the last byte of 0x10+0x14+0xE1+0xA4+0x32

    So the sum is 01DB, checksum is 0xDB.

    Code:

    //i is the length of cmd
    - (Byte)CalcCheckSum:(Byte)i data:(NSMutableData *)cmd
    {   Byte * cmdByte = (Byte *)malloc(i);
        memcpy(cmdByte, [cmd bytes], i);
        Byte local_cs = 0;
        int j = 0;
        while (i>0) {
            local_cs += cmdByte[j];
            i--;
            j++;
        };
        local_cs = local_cs&0xff;
        return local_cs;
    }
    

    To use it:

    Byte checkSum = [self CalcCheckSum:[command length] data:command];
    

    Hope it helps.