开发者

Checksum Algorithm Producing Unpredictable Results

I'm working on a checksum algorithm, and I'm having some issues. The kicker is, when I hand craft a "fake" message, that is substantially smaller than the "real" data I'm receiving, I get a correct checksum. However, against the real data - the checksum does not work properly.

Here's some information on the incoming data/environment:

  • This is a groovy project (see code below)
  • All bytes are to be treated as unsigned integers for the purpose of checksum calculation
    • You'll notice some finagling with shorts and longs in order to make that work.
  • The size 开发者_运维百科of the real data is 491 bytes.
  • The size of my sample data (which appears to add correctly) is 26 bytes
  • None of my hex-to-decimal conversions are producing a negative number, as best I can tell
  • Some bytes in the file are not added to the checksum. I've verified that the switch for these is working properly, and when it is supposed to - so that's not the issue.
  • My calculated checksum, and the checksum packaged with the real transmission always differ by the same amount.
  • I have manually verified that the checksum packaged with the real data is correct.

Here is the code:

// add bytes to checksum
public void addToChecksum( byte[] bytes) {
    //if the checksum isn't enabled, don't add
    if(!checksumEnabled) {
        return;
    }

    long previouschecksum =  this.checksum;

    for(int i = 0; i < bytes.length; i++) {
        byte[] tmpBytes = new byte[2];
        tmpBytes[0] = 0x00;
        tmpBytes[1] = bytes[i];

        ByteBuffer tmpBuf = ByteBuffer.wrap(tmpBytes);

        long computedBytes = tmpBuf.getShort();
        logger.info(getHex(bytes[i]) + " = " + computedBytes);
        this.checksum += computedBytes;
    }

    if(this.checksum < previouschecksum) {
        logger.error("Checksum DECREASED: " + this.checksum);
    }
    //logger.info("Checksum: " + this.checksum);
}

If anyone can find anything in this algorithm that could be causing drift from the expected result, I would greatly appreciate your help in tracking this down.


I don't see a line in your code where you reset your this.checksum.

This way, you should alway get a this.checksum > previouschecksum, right? Is this intended?

Otherwise I can't find a flaw in your above code. Maybe your 'this.checksum' is of the wrong type (short for instance). This could rollover so that you get negative values.

here is an example for such a behaviour

import java.nio.ByteBuffer
short checksum = 0
byte[] bytes = new byte[491]
def count = 260
for (def i=0;i<count;i++) {
    bytes[i]=255
}
bytes.each { b ->
    byte[] tmpBytes = new byte[2];
    tmpBytes[0] = 0x00;
    tmpBytes[1] = b;
    ByteBuffer tmpBuf = ByteBuffer.wrap(tmpBytes);
    long computedBytes = tmpBuf.getShort();
    checksum += computedBytes
    println "${b} : ${computedBytes}"
}
println checksum +"!=" + 255*count

just play around with the value of the 'count' variable which somehow corresponds to the lenght of your input.


Your checksum will keep incrementing until it rolls over to being negative (as it is a signed long integer)

You can also shorten your method to:

public void addToChecksum( byte[] bytes) {
  //if the checksum isn't enabled, don't add
  if(!checksumEnabled) {
    return;
  }

  long previouschecksum =  this.checksum;
  this.checksum += bytes.inject( 0L ) { tot, it -> tot += it & 0xFF }

  if(this.checksum < previouschecksum) {
    logger.error("Checksum DECREASED: " + this.checksum);
  }
  //logger.info("Checksum: " + this.checksum);
}

But that won't stop it rolling over to being negative. For the sake of saving 12 bytes per item that you are generating a hash for, I would still suggest something like MD5 which is know to work is probably better than rolling your own... However I understand sometimes there are crazy requirements you have to stick to...

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜