CRC-CCITT Kermit 16英寸C#

CRC-CCITT Kermit 16英寸C#,c#,crc,crc16,C#,Crc,Crc16,正在尝试对串行端口协议进行反向工程。我无法重新创建crc-16字节 根据文档,这是数据包的格式 48 45 4c 4f // HELO 01 00 00 01 // ARG 1 00 00 00 00 // ARG 2 00 00 00 00 // ARG 3 00 00 00 00 // ARG 4 00 00 00 00 // REQUEST BODY 5c b1 00 00 // CRC-16 b7 ba b3 b0 // Bit-wise inversion of HELO comma

正在尝试对串行端口协议进行反向工程。我无法重新创建crc-16字节

根据文档,这是数据包的格式

48 45 4c 4f // HELO
01 00 00 01 // ARG 1
00 00 00 00 // ARG 2
00 00 00 00 // ARG 3
00 00 00 00 // ARG 4
00 00 00 00 // REQUEST BODY
5c b1 00 00 // CRC-16
b7 ba b3 b0  // Bit-wise inversion of HELO command
这是从串行监控中嗅出的写入命令

48 45 4c 4f 01 00 00 01 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 5c b1 00 00 b7 ba b3 b0   
我能够很好地重新创建数据包,除了2个字节的“5cb1”。根据文档,5c b1字节是数据包上的crc-ccit16,crc-16插槽中有零。CRC16函数不返回5C字节,但不返回b1

我使用以下代码计算crc:

  public class Crc16
{
    static ushort[] table = new ushort[256];

    public ushort ComputeChecksum(params byte[] bytes)
    {
        ushort crc = 0;
        for (int i = 0; i < bytes.Length; ++i)
        {
            byte index = (byte)(crc ^ bytes[i]);
            crc = (ushort)((crc >> 8) ^ table[index]);
        }
        return crc;
    }

    public byte[] ComputeChecksumBytes(params byte[] bytes)
    {
        ushort crc = ComputeChecksum(bytes);
        return BitConverter.GetBytes(crc);
    }

    public Crc16(Crc16Mode mode)
    {
        ushort polynomial = (ushort)mode;
        ushort value;
        ushort temp;
        for (ushort i = 0; i < table.Length; ++i)
        {
            value = 0;
            temp = i;
            for (byte j = 0; j < 8; ++j)
            {
                if (((value ^ temp) & 0x0001) != 0)
                {
                    value = (ushort)((value >> 1) ^ polynomial);
                }
                else {
                    value >>= 1;
                }
                temp >>= 1;
            }
            table[i] = value;
        }
    }
}

       public byte[] getPreCRC16Bytes()
    {
            byte[] x = new byte[28];
            byte[] cmdBytes = Encoding.ASCII.GetBytes(this.cmd.ToString());
            byte[] arg1Bytes = (byte[])this.arg1;
            byte[] arg2Bytes = (byte[])this.arg2;
            byte[] arg3Bytes = (byte[])this.arg3;
            byte[] arg4Bytes = (byte[])this.arg4;
            byte[] bodyLen = { 0x00, 0x00, 0x00, 0x00 };
            byte[] emptyCRC = { 0x00, 0x00, 0x00, 0x00 };
            byte[] checksum = Encoding.ASCII.GetBytes(this.checksum);
            var list = new List<byte>();
            list.AddRange(cmdBytes);
            list.AddRange(arg1Bytes);
            list.AddRange(arg2Bytes);
            list.AddRange(arg3Bytes);
            list.AddRange(arg4Bytes);
            list.AddRange(bodyLen);
            list.AddRange(emptyCRC);
            list.AddRange(checksum);
            var xx = list.ToArray();

        string hex = BitConverter.ToString(cmdBytes).Replace("-", "");

        return list.ToArray();

    }
公共类Crc16
{
静态ushort[]表=新ushort[256];
公共ushort ComputeChecksum(参数字节[]字节)
{
ushort crc=0;
for(int i=0;i>8)^表[索引];
}
返回crc;
}
公共字节[]ComputeChecksumBytes(参数字节[]字节)
{
ushort crc=计算中心(字节);
返回位转换器.GetBytes(crc);
}
公共Crc16(Crc16Mode模式)
{
ushort多项式=(ushort)模式;
ushort值;
乌斯波特温度;
对于(ushort i=0;i>1)^多项式);
}
否则{
值>>=1;
}
温度>>=1;
}
表[i]=数值;
}
}
}
公共字节[]getPreCRC16Bytes()
{
字节[]x=新字节[28];
byte[]cmdBytes=Encoding.ASCII.GetBytes(this.cmd.ToString());
字节[]arg1Bytes=(字节[])this.arg1;
字节[]arg2字节=(字节[])this.arg2;
字节[]arg3Bytes=(字节[])this.arg3;
字节[]arg4Bytes=(字节[])this.arg4;
字节[]bodyLen={0x00,0x00,0x00,0x00};
字节[]emptyCRC={0x00,0x00,0x00,0x00};
字节[]校验和=Encoding.ASCII.GetBytes(this.checksum);
var list=新列表();
list.AddRange(cmdBytes);
list.AddRange(arg1字节);
list.AddRange(arg2字节);
list.AddRange(arg3字节);
list.AddRange(arg4字节);
列表.添加范围(bodyLen);
list.AddRange(emptyCRC);
list.AddRange(校验和);
var xx=list.ToArray();
字符串十六进制=位转换器.ToString(cmdBytes).Replace(“-”,”);
return list.ToArray();
}

从这个例子来看,它似乎是CCITT,而不是CCITT(Kermit)16位CRC。这有1/65536的可能是巧合,因为只有一个示例,所以您需要尝试使用多个嗅探数据包

下面是一个简单的逐位C例程,用于计算CRC(使用
mem==NULL调用它,返回CRC的初始值):

unsigned crc16x_25_位(unsigned crc,void const*mem,size_t len){
无符号字符常量*data=mem;
如果(数据==NULL)
返回0;
crc=~crc;
crc&=0xffff;
而(len--){
crc^=*数据++;
for(无符号k=0;k<8;k++)
crc=crc&1?(crc>>1)^0x8408:crc>>1;
}
crc^=0xffff;
返回crc;
}

该代码是由生成的,它还为表驱动版本生成代码,包括字节版本和单词版本。

不,翻译起来应该很简单。或者,您可以修改问题中的代码<代码>多项式
0x8408
crc
的初始值是
0xffff
,而不是
0
。而不是
返回crc
,输入
返回crc^0xffff。应该这样做。您发布的代码中没有多项式,因此需要使用多项式初始化类。或者最好在代码中把它设为常量。
unsigned crc16x_25_bit(unsigned crc, void const *mem, size_t len) {
    unsigned char const *data = mem;
    if (data == NULL)
        return 0;
    crc = ~crc;
    crc &= 0xffff;
    while (len--) {
        crc ^= *data++;
        for (unsigned k = 0; k < 8; k++)
            crc = crc & 1 ? (crc >> 1) ^ 0x8408 : crc >> 1;
    }
    crc ^= 0xffff;
    return crc;
}