Алгоритм контрольной суммы дает непредсказуемые результаты

Я работаю над алгоритмом контрольной суммы, и у меня возникли проблемы. Проблема в том, что когда я вручную создаю «фальшивое» сообщение, которое существенно меньше «реальных» данных, которые я получаю, я получаю правильную контрольную сумму. Однако вопреки реальным данным - контрольная сумма работает некорректно.

Вот некоторая информация о входящих данных / среде:

  • Это отличный проект (см. Код ниже)
  • 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.
  • Размер реальных данных составляет 491 байт.
  • Размер моих данных образца (который, кажется, складывается правильно) составляет 26 байт.
  • Насколько я могу судить, ни одно из моих преобразований из шестнадцатеричного в десятичное не дает отрицательного числа.
  • Некоторые байты в файле не добавляются к контрольной сумме. Я проверил, что переключатель для них работает правильно, и когда он должен работать - так что проблема не в этом.
  • Моя вычисленная контрольная сумма и контрольная сумма, упакованная с реальной передачей, всегда различаются на одинаковую величину.
  • Я вручную проверил, что контрольная сумма, содержащая реальные данные, верна.

Вот код:

// 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);
}

Если кто-нибудь может найти в этом алгоритме что-либо, что может вызвать отклонение от ожидаемого результата, я был бы очень признателен за вашу помощь в отслеживании этого.


person Matt Farmer    schedule 07.09.2011    source источник
comment
Быстрый вопрос ... Почему бы не использовать md5, sha или какой-нибудь другой проверенный алгоритм хеширования? То есть: groovyconsole.appspot.com/script/256001.   -  person tim_yates    schedule 07.09.2011
comment
Не вдаваясь в детали вашей реализации, почему вы не используете какие-либо хорошо известные, отработанные и достаточно хорошие алгоритмы контрольной суммы, такие как CRC, MD5 или SHA (от тривиального до близкого к идеальному)?   -  person Tomasz Nurkiewicz    schedule 07.09.2011
comment
Что ж, сначала позвольте мне заявить, что я не могу определить, какой алгоритм контрольной суммы используется. Так что это спорный вопрос. Я должен подчиняться протоколу - с этим ничего не остается. Во-вторых, это было сделано для экономии полосы пропускания. С учетом объема данных, которые мы перемещаем - использование этого метода переводится в реальные знаки доллара.   -  person Matt Farmer    schedule 07.09.2011


Ответы (2)


Я не вижу в вашем коде строчки, где вы сбрасываете свой this.checksum.

Таким образом, вы всегда должны получить this.checksum > previouschecksum, верно? Это предназначено?

В противном случае я не смогу найти недостаток в приведенном выше коде. Возможно, ваш 'this.checksum' имеет неправильный тип (например, сокращенный). Это может привести к опрокидыванию и получению отрицательных значений.

вот пример такого поведения

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

просто поиграйте со значением переменной count, которое так или иначе соответствует длине вашего ввода.

person rdmueller    schedule 07.09.2011
comment
Этот метод является лишь частью более крупного класса. И да, this.checksum должен всегда быть больше previouschecksum. У меня была эта строка, чтобы определить вероятность того, что я генерировал отрицательные числа. Это была строго отладочная тактика. Кроме того, this.checksum является длинным. - person Matt Farmer; 08.09.2011
comment
491 байт - это немного. Вы уже println просмотрели результаты каждой итерации? - person rdmueller; 08.09.2011
comment
Что ж, 491 байт может показаться не таким уж большим, но это примерно 80 команд. Я бы хотел поделиться, чтобы кто-то другой проверил мою математику, но это проприетарный материал. : - \ - person Matt Farmer; 08.09.2011

Ваша контрольная сумма будет увеличиваться до тех пор, пока не станет отрицательной (поскольку это длинное целое число со знаком)

Вы также можете сократить свой метод до:

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);
}

Но это не остановит его переход в отрицательную форму. Ради экономии 12 байтов на элемент, для которого вы генерируете хэш, я бы все же предложил что-то вроде MD5, который, как известно, работает, вероятно, лучше, чем катить свой собственный ... Однако я понимаю, что иногда есть сумасшедшие требования, которые вы должны выполнить придерживаться ...

person tim_yates    schedule 07.09.2011
comment
Да, к счастью, я не сталкиваюсь с ситуацией, когда сумма увеличивается. Когда я добавляю, оно оказывается меньше, чем должно быть, что невероятно расстраивает. - person Matt Farmer; 08.09.2011
comment
@Matt у вас есть пример массива байтов, который вызывает ошибку, которую вы видите? - person tim_yates; 08.09.2011