Groovy 产生不可预测结果的校验和算法

Groovy 产生不可预测结果的校验和算法,groovy,checksum,unsigned-integer,Groovy,Checksum,Unsigned Integer,我正在研究校验和算法,我遇到了一些问题。更重要的是,当我手工制作一个“假”消息时,它大大小于我收到的“真实”数据,我得到了一个正确的校验和。然而,针对实际数据,校验和不能正常工作 以下是有关传入数据/环境的一些信息: 这是一个groovy项目(参见下面的代码) 为了进行校验和计算,所有字节都将被视为无符号整数 你会注意到一些短线和长线的骗局,以使其发挥作用 实际数据的大小为491字节 我的示例数据(似乎添加正确)的大小为26字节 据我所知,我所有的十六进制到十进制的转换都不会产生负数 文件

我正在研究校验和算法,我遇到了一些问题。更重要的是,当我手工制作一个“假”消息时,它大大小于我收到的“真实”数据,我得到了一个正确的校验和。然而,针对实际数据,校验和不能正常工作

以下是有关传入数据/环境的一些信息:

  • 这是一个groovy项目(参见下面的代码)
  • 为了进行校验和计算,所有字节都将被视为无符号整数
    • 你会注意到一些短线和长线的骗局,以使其发挥作用
  • 实际数据的大小为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);
}
//将字节添加到校验和
public void addToChecksum(字节[]字节){
//如果未启用校验和,则不要添加
如果(!checksumEnabled){
返回;
}
long-previouschecksum=this.checksum;
for(int i=0;i

如果有人能在这个算法中找到任何可能导致偏离预期结果的东西,我将非常感谢您的帮助。我看不到您的代码中有一行重置了
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
import java.nio.ByteBuffer
短校验和=0
字节[]字节=新字节[491]
def计数=260
对于(defi=0;i
字节[]tmpBytes=新字节[2];
tmpBytes[0]=0x00;
tmpBytes[1]=b;
ByteBuffer tmpBuf=ByteBuffer.wrap(tmpBytes);
long computedBytes=tmpBuf.getShort();
校验和+=计算字节数
println“${b}:${computedBytes}”
}
println校验和+“!=”+255*计数

只需使用与输入长度相对应的“count”变量的值即可。

您的校验和将不断递增,直到它变为负(因为它是一个有符号长整数)

您还可以将方法缩短为:

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);
}
public void addToChecksum(字节[]字节){
//如果未启用校验和,则不要添加
如果(!checksumEnabled){
返回;
}
long-previouschecksum=this.checksum;
this.checksum+=bytes.inject(0L){tot,it->tot+=it&0xFF}
if(this.checksum

但这并不能阻止它转为负数。为了为每个要生成哈希的项目节省12字节,我仍然建议使用MD5之类的东西,它可能比你自己的要更好…但是我知道有时你必须坚持一些疯狂的要求…

快速问题。。。为什么不使用md5、sha或其他经过验证的哈希算法呢?即:在不深入了解实现细节的情况下,为什么不使用任何知名的、成熟的、足够好的校验和算法,如CRC、md5或sha(从微不足道到接近理想)?首先,让我声明,我无法确定使用哪种校验和算法。因此,这是一个没有意义的问题。我必须遵守协议-对此没有选择。其次,这样做是为了节省带宽。随着我们移动的数据量的增加,使用这种方法转换为实际的美元符号。这种方法只是更大类的一部分。而且是的,
这个。校验和
应该总是大于以前的校验和
。我有那行代码来检测我生成负数的可能性。这严格来说是一种调试策略。而且,
这个。校验和
是一个长的.491字节,不算太多。你已经打印了每次迭代的结果了吗n?嗯,491字节听上去可能不算多,但总共大约有80个命令。我很想和其他人分享,让他们检查我的数学,但这是专有的东西。:-\n是的,幸运的是,我没有遇到总和滚动的情况。当我做加法时,它只是比预期的要少,这令人难以置信地沮丧。@Matt您是否有导致所看到错误的字节数组示例?