2017-01-10 175 views
1

试图反向设计串行端口协议。我无法重新创建crc-16字节。C#中的CRC-CCITT Kermit 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个字节“5c b1”。根据文档,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(); 

    } 

回答

1

从这一个实例中,它似乎是X-25 16-bit CRC,而不是CCITT(柯密)16位CRC。有一个1/65536的机会,这是巧合,因为只有一个例子,所以你需要用更多的嗅探包来尝试它。

下面是一个简单,位在-A-时间C例程计算出CRC(与mem == NULL返回CRC初始值调用它):

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

通过crcany生成的代码,它也为表驱动版本生成代码,包括字节式和字面式。

+0

任何机会,你有C#代码? – user1698144

+0

不,它应该是直接翻译的。或者你可以修改你的问题中的代码。 'polynomial'是'0x8408'。 'crc'的初始值是'0xffff'而不是'0'。而不是'return crc;',放入'return crc^0xffff;'。这应该做到这一点。您发布的代码中没有多项式,因此您需要使用多项式初始化类。或者在代码中做一个常量会更好。 –

+0

仍然没有运气.. – user1698144