CRC-16 and CRC-32 Checks

本文关键字:Checks CRC-32 and CRC-16 | 更新日期: 2023-09-27 18:10:13

我需要帮助试图验证CRC-16值(也需要帮助与CRC-32值)。我试着坐下来了解CRC是如何工作的,但我却一片空白。

我的第一个问题是当试图使用在线计算器计算消息"BD001325E032091B94C412AC"到CRC16 = 12AC时。文档指出,最后两个八位字节是CRC16值,因此我将"BD001325E032091B94C4"输入站点http://www.lammertbies.nl/comm/info/crc-calculation.html,并收到5A90作为结果,而不是12AC。

有没有人知道为什么这些值是不同的,我在哪里可以找到如何计算CRC16和CRC32值的代码(我计划以后学习如何做到这一点,但时间不允许现在)?

更多的消息如下:

16000040FFFFFFFF00015FCB  
3C00003144010405E57022C7  
BA00001144010101B970F0ED  
3900010101390401B3049FF1  
09900C800000000000008CF3  
8590000000000000000035F7  
00900259025902590259EBC9  
0200002B00080191014BF5A2  
BB0000BEE0014401B970E51E  
3D000322D0320A2510A263A0  
2C0001440000D60000D65E54

——编辑——

我已经包含了更多的信息。我引用的文件是TIA-102。BAAA-A(来自TIA标准)。以下是文档的说明(尽可能避免侵犯版权):

包中的最后一个块由用户信息和/或的几个八位字节组成pad字节,然后是4字节的CRC奇偶校验。这被称为包CRC。

数据包CRC是对所有数据进行编码的4字节循环冗余校验中间块中包含的字节数和用户信息的字节数最后一块。具体计算如下:

设k为该数据包所覆盖的用户信息和填充位的总数计算CRC。将k个消息位视为a的系数阶为k-1的多项式M(x),关联第0条消息的MSB具有x^ k-1的octet和具有x^0的最后一个消息octet的LSB。定义生成多项式GM(x)和反转多项式IM(x).

通用(x) = x ^ 32 + x ^ 26 + x x ^ ^ 23 + 22 + 16 + x x ^ ^ 12 + x ^ 11 + x x ^ ^ 10 + 8 + x ^ ^ 5 + 7 + xX ^4 + X ^2 + X + 1

IM(x) = x^31 + x^30 + x^29 +…+ x^2 + x +1

包CRC多项式FM(x),然后从下面的公式计算。

调频(x) = (x ^ 32 M (x)国防部通用(x)) + IM (x),,,,,,,,,,,,模2,即在GF(2)

FM(x)的系数放在CRC域中,MSB为第0位x^31对应的CRC的八位字节和CRC的第三个八位字节的LSB对应于x^0

在上面的引用,我已经把^显示权力,因为格式不保持不变时引用。我不确定什么是什么,但这有帮助吗?

CRC-16 and CRC-32 Checks

我有一个类我从一个c++转换我在互联网上发现,它使用一个长计算一个CRC32。它坚持标准,是PKZIP, WinZip和以太网使用的一个。为了测试它,使用Winzip压缩一个文件,然后用这个类计算相同的文件,它应该返回相同的CRC。我喜欢。

public class CRC32
{
    private int[] iTable;
    public CRC32() {
       this.iTable = new int[256];
       Init();
    }
    /**
     * Initialize the iTable aplying the polynomial used by PKZIP, WINZIP and Ethernet.
     */
    private void Init()
    {
       // 0x04C11DB7 is the official polynomial used by PKZip, WinZip and Ethernet.
       int iPolynomial = 0x04C11DB7;
       // 256 values representing ASCII character codes.
       for (int iAscii = 0; iAscii <= 0xFF; iAscii++)
       {
          this.iTable[iAscii] = this.Reflect(iAscii, (byte) 8) << 24;
          for (int i = 0; i <= 7; i++)
          {
             if ((this.iTable[iAscii] & 0x80000000L) == 0) this.iTable[iAscii] = (this.iTable[iAscii] << 1) ^ 0;
             else this.iTable[iAscii] = (this.iTable[iAscii] << 1) ^ iPolynomial;
          }
          this.iTable[iAscii] = this.Reflect(this.iTable[iAscii], (byte) 32);
       }
    }
    /**
     * Reflection is a requirement for the official CRC-32 standard. Note that you can create CRC without it,
     * but it won't conform to the standard.
     *
     * @param iReflect
     *           value to apply the reflection
     * @param iValue
     * @return the calculated value
     */
    private int Reflect(int iReflect, int iValue)
    {
       int iReturned = 0;
       // Swap bit 0 for bit 7, bit 1 For bit 6, etc....
       for (int i = 1; i < (iValue + 1); i++)
       {
          if ((iReflect & 1) != 0)
          {
             iReturned |= (1 << (iValue - i));
          }
          iReflect >>= 1;
       }
       return iReturned;
    }
    /**
     * PartialCRC caculates the CRC32 by looping through each byte in sData
     *
     * @param lCRC
     *           the variable to hold the CRC. It must have been initialize.
     *           <p>
     *           See fullCRC for an example
     *           </p>
     * @param sData
     *           array of byte to calculate the CRC
     * @param iDataLength
     *           the length of the data
     * @return the new caculated CRC
     */
    public long CalculateCRC(long lCRC, byte[] sData, int iDataLength)
    {
       for (int i = 0; i < iDataLength; i++)
       {
          lCRC = (lCRC >> 8) ^ (long) (this.iTable[(int) (lCRC & 0xFF) ^ (int) (sData[i] & 0xff)] & 0xffffffffL);
       }
       return lCRC;
    }
    /**
     * Caculates the CRC32 for the given Data
     *
     * @param sData
     *           the data to calculate the CRC
     * @param iDataLength
     *           then length of the data
     * @return the calculated CRC32
     */
    public long FullCRC(byte[] sData, int iDataLength)
    {
       long lCRC = 0xffffffffL;
       lCRC = this.CalculateCRC(lCRC, sData, iDataLength);
       return (lCRC /*& 0xffffffffL)*/^ 0xffffffffL);
    }
    /**
     * Calculates the CRC32 of a file
     *
     * @param sFileName
     *           The complete file path
     * @param context
     *           The context to open the files.
     * @return the calculated CRC32 or -1 if an error occurs (file not found).
     */
    long FileCRC(String sFileName, Context context)
    {
          long iOutCRC = 0xffffffffL; // Initilaize the CRC.
          int iBytesRead = 0;
          int buffSize = 32 * 1024;
          FileInputStream isFile = null;
          try
          {
             byte[] data = new byte[buffSize]; // buffer de 32Kb
             isFile = context.openFileInput(sFileName);
             try
             {
                while ((iBytesRead = isFile.read(data, 0, buffSize)) > 0)
                {
                   iOutCRC = this.CalculateCRC(iOutCRC, data, iBytesRead);
                }
                return (iOutCRC ^ 0xffffffffL); // Finalize the CRC.
             }
             catch (Exception e)
             {
                // Error reading file
             }
             finally
             {
                isFile.close();
             }
          }
          catch (Exception e)
          {
             // file not found
          }
          return -1l;
       }
 }
  1. 阅读Ross Williams关于CRC的教程,以更好地理解CRC,什么定义了一个特定的CRC,以及它们的实现。

  2. 复仇网站有一个很好的已知CRC目录,对于每个测试字符串的CRC(九个字节:"123456789"在ASCII/UTF-8)。注意,这里定义了22个不同的16位crc 。

同一站点上的复仇软件可用于对多项式、初始化、后处理和位反转进行逆向工程,给出了一些16位CRC的示例。(因此得名"复仇"。)我把你的数据看了一遍,得到:

./reveng -w 16 -s 16000040FFFFFFFF00015FCB 3C00003144010405E57022C7 BA00001144010101B970F0ED 3900010101390401B3049FF1 09900C800000000000008CF3 8590000000000000000035F7 00900259025902590259EBC9 0200002B00080191014BF5A2 BB0000BEE0014401B970E51E 3D000322D0320A2510A263A0 2C0001440000D60000D65E54
width=16  poly=0x1021  init=0xc921  refin=false  refout=false  xorout=0x0000  check=0x2fcf  name=(none)

如"(none)"所示,该16位CRC不是revenge上列出的22个CRC中的任何一个,尽管它与其中几个相似,只是初始化不同。

您提供的附加信息是针对32位CRC的,复仇目录中的CRC-32或CRC-32/BZIP,取决于比特是否反转。

CRC计算有相当多的参数:多项式,初始值,最终异或…详情请参阅维基百科。你的CRC似乎不适合你使用的网站,但你可以尝试从你的文档中找到正确的参数,并使用不同的计算器,例如这个(虽然我担心它不支持十六进制输入)。

要记住的一件事是CRC-16通常是在应该被校验和的数据上计算的加上两个零字节,例如,您可能正在寻找CRC16函数,其中CRC16(BD001325E032091B94C40000) == 12AC。这样计算校验和后,加了校验和的数据的CRC值为0,便于检查,如CRC16(BD001325E032091B94C412AC) == 0000