2017-01-10 63 views
1

シリアルポートプロトコルをリバースエンジニアリングしようとしています。私はcrc-16バイトを再現することができません。CRC-CCITT Kermit 16 in C#

は、ドキュメントによると、これは

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-16スロットに0が入ったパケット上のcrc-ccit16です。 CRC16関数は、5Cバイトを返しますが、b1は返しません。私は、CRCを計算するために以下のコードを使用しています

:その1つの例から

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つの例しかないので、これは偶然であるという確率は1/65536であるため、いくつかのパケットをスニッフィングして試してみる必要があります。ここ

は、CRCは、(mem == NULLとそれを呼び出すと、CRCの初期値を返す)と計算単純なビット・アット・タイムCルーチンである:

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

いいえ、翻訳するのは簡単です。あるいは、あなたの質問のコードを変更するだけでよいのです。 '多項式'は '0x8408'です。 'crc'の初期値は' 0'ではなく '0xffff'です。 'return crc;'の代わりに 'return crc^0xffff;'を入れてください。それはそれを行う必要があります。投稿されたコードには多項式が含まれていないため、多項式でクラスを初期化する必要があります。あるいは、コード内で定数を作るだけの方がいいでしょう。 –

+0

まだ運がいい.. – user1698144