Проверки CRC-16 и CRC-32
Мне нужна помощь, чтобы проверить значения 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). Ниже приводится то, что говорится в документации (чтобы максимально избежать нарушения авторских прав):
Последний блок в пакете содержит несколько октетов пользовательской информации и / или октетов пэда, за которыми следует проверка четности CRC с 4 октетами. Это называется CRC пакета.
CRC пакета представляет собой 4-октетную циклическую проверку избыточности, закодированную по всем октетам данных, включенным в промежуточные блоки, и октетам пользовательской информации последнего блока. Конкретный расчет заключается в следующем.
Пусть k будет общим количеством пользовательской информации и битов заполнителя, по которым должен рассчитываться CRC пакета. Рассмотрим k битов сообщения как коэффициенты полинома M(x) степени k–1, связывая MSB нулевого октета сообщения с x^k–1 и младший бит последнего октета сообщения с x^0. Определите генераторный полином GM(x) и инверсионный полином IM(x).
GM(x) = x ^ 32 + x ^ 26 + x ^ 23 + x ^ 22 + x ^ 16 + x ^ 12 + x ^ 11 + x ^ 10 + x ^ 8 + x ^ 7 + x ^ 5 + x ^ 4 + х ^2 + х + 1
IM(x) = x^31 + x ^ 30 + x ^ 29 +... + x ^2 + x +1
Полином CRC пакета, FM(x), затем вычисляется по следующей формуле.
FM(x) = (x ^ 32 M(x) mod GM(x)) + IM(x) по модулю 2, т. Е. В GF(2)
Коэффициенты FM(x) помещаются в поле CRC, где MSB нулевого октета CRC соответствует x^31, а младший бит третьего октета CRC соответствует x^0.
В приведенной выше цитате я положил ^
показывать полномочия, так как форматирование не осталось прежним при цитировании. Я не уверен, что к чему идет, но помогает ли это?
3 ответа
Прочитайте руководство Росса Уильямса по CRC, чтобы лучше понять CRC, что определяет конкретный CRC и их реализации.
На сайте ревангов есть отличный каталог известных 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 не является ни одним из 22, перечисленных в реванге, хотя он похож на несколько из них, отличающихся только инициализацией.
Предоставленная вами дополнительная информация относится к 32-битному CRC, CRC-32 или CRC-32/BZIP в каталоге мести, в зависимости от того, обращены ли эти биты в обратном порядке или нет.
У меня есть класс, который я конвертировал из C++, который я нашел в интернете, он использует long для вычисления CRC32. Он соответствует стандарту и используется PKZIP, WinZip и Ethernet. Чтобы проверить это, используйте 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;
}
}
Существует довольно много параметров для расчета CRC: полином, начальное значение, окончательное значение XOR... подробности см. В Википедии. Похоже, ваш CRC не соответствует тем, которые вы использовали на сайте, который вы использовали, но вы можете попытаться найти правильные параметры в вашей документации и использовать другой калькулятор, например, этот (хотя, боюсь, он не поддерживает ввод в HEX),
Следует иметь в виду, что CRC-16 обычно рассчитывается по данным, которые должны быть проверены, плюс два нулевых байта, например, вы, вероятно, ищете CRC16
функция где CRC16(BD001325E032091B94C40000) == 12AC
, С контрольными суммами, рассчитанными таким образом, CRC данных с добавленной контрольной суммой сработает до 0, что облегчает проверку, например CRC16(BD001325E032091B94C412AC) == 0000