C# 基本的CRC32维基百科实现不同于在线看到的标准CRC32
我有一个基本的CRC32实现,遵循维基百科的。我认为我做得对,修改后的余数多项式使用n位寄存器,而不是如示例所示使用n+1位寄存器 我得到的结果与在线CRC32实施结果不同。在我的实现中,我必须改变什么 请忽略用于逻辑的Console.Writeline语句C# 基本的CRC32维基百科实现不同于在线看到的标准CRC32,c#,crc,crc32,C#,Crc,Crc32,我有一个基本的CRC32实现,遵循维基百科的。我认为我做得对,修改后的余数多项式使用n位寄存器,而不是如示例所示使用n+1位寄存器 我得到的结果与在线CRC32实施结果不同。在我的实现中,我必须改变什么 请忽略用于逻辑的Console.Writeline语句 const UInt32 poly = 0x04C11DB7; public static UInt32 GenerateCRC_32(byte[] message) { byte[] augmen
const UInt32 poly = 0x04C11DB7;
public static UInt32 GenerateCRC_32(byte[] message)
{
byte[] augmentedMsg = new byte[message.Length + 4];
message.CopyTo(augmentedMsg, 0);
UInt32 remainder = Convert.ToUInt32(augmentedMsg[0]) << 24 |
Convert.ToUInt32(augmentedMsg[1]) << 16 |
Convert.ToUInt32(augmentedMsg[2]) << 8 |
Convert.ToUInt32(augmentedMsg[3]);
for (Int32 i = 4; i < augmentedMsg.Length; i++)
{
for (int bit = 0; bit < 8; bit++)
{
UInt32 nextBit = ((UInt32)augmentedMsg[i] >> (7 - bit)) & 0x01;
if ((remainder & 0x80000000) > 0)
{
Console.WriteLine("---------------DO XOR --------------------");
Console.WriteLine(Convert.ToString(((remainder << 1) | nextBit), 2).PadLeft(32, '0'));
Console.WriteLine(Convert.ToString(poly, 2).PadLeft(32, '0'));
Console.WriteLine("------------------------------------------");
remainder = ((remainder << 1) | nextBit) ^ poly;
Console.WriteLine(Convert.ToString(remainder, 2).PadLeft(32, '0'));
Console.WriteLine("------------------------------------------");
}
else
{
remainder = (remainder << 1) | nextBit;
Console.WriteLine("--------------NO---------------------");
Console.WriteLine(Convert.ToString(remainder, 2).PadLeft(32, '0'));
Console.WriteLine("------------------------------------------");
}
}
}
Console.WriteLine(Convert.ToString(remainder, 2).PadLeft(32, '0'));
Console.WriteLine(remainder.ToString("X"));
return remainder;
}
十六进制的最后一行:0x30476DC0
@Mark Adler评论的后续行动:**
const UInt32 poly32 = 0x04C11DB7;
public static UInt32 Reverse(UInt32 message)
{
UInt32 msgReversed = 0;
for (int i = 0; i < 32; i++)
{
msgReversed = ((message & 0x80000000) >> (31 - i)) | msgReversed;
message = message << 1;
}
return msgReversed;
}
public static byte Reverse(byte message)
{
byte msgReversed = 0;
for (int i = 0; i < 8; i++)
{
msgReversed = (byte)(((byte)((byte)(message) & 0x80) >> (7 - i)) | msgReversed);
message = (byte)(message << 1);
}
return msgReversed;
}
我对上述内容进行了如下修改,以下是修改(注释以内联方式添加到代码中):
UInt32 remainder = Convert.ToUInt32(augmentedMsg[0]) << 24 |
Convert.ToUInt32(augmentedMsg[1]) << 16 |
Convert.ToUInt32(augmentedMsg[2]) << 8 |
Convert.ToUInt32(augmentedMsg[3]);
remainder = ~remainder; // Overwrite the above and initialized the register to 0xFFFFFFFF
for (Int32 i = 4; i < augmentedMsg.Length; i++)
{
byte reversedMessage = Reverse(augmentedMsg[i]); // Reversed the augmented message byte
for (int bit = 0; bit < 8; bit++)
{
UInt32 nextBit = Convert.ToUInt32(reversedMessage >> (7 - bit)) & 0x1; // Use the reversed message byte
if ((remainder & 0x80000000) > 0)
{
Console.WriteLine("---------------DO XOR --------------------");
Console.WriteLine(Convert.ToString(((remainder << 1) | nextBit), 2).PadLeft(32, '0'));
Console.WriteLine(Convert.ToString(poly32, 2).PadLeft(32, '0'));
Console.WriteLine("------------------------------------------");
remainder = Convert.ToUInt32((UInt32)((UInt32)(remainder << 1) | nextBit) ^ poly32);
Console.WriteLine(Convert.ToString(remainder, 2).PadLeft(32, '0'));
Console.WriteLine("------------------------------------------");
}
else
{
remainder = (UInt32)((UInt32)(remainder << 1) | nextBit);
Console.WriteLine("--------------NO---------------------");
Console.WriteLine(Convert.ToString(remainder, 2).PadLeft(32, '0'));
Console.WriteLine("------------------------------------------");
}
}
}
Console.WriteLine(Convert.ToString(remainder, 2).PadLeft(32, '0') + "(" + remainder.ToString("X") + ")");
remainder = (~remainder);
Console.WriteLine("XOR ^ 0xFFFFFFFF : " + Convert.ToString(remainder, 2).PadLeft(32, '0') + "(" + remainder.ToString("X") + ")");
remainder = Reverse(remainder);
Console.WriteLine("Reversed the Abv : " + Convert.ToString(remainder, 2).PadLeft(32, '0') + "(" + remainder.ToString("X") + ")");
return remainder;
这不是预期的输出。我使用下表查找代码实现了相同的输出,结果与上面的结果完全相同(0xC7F9861B),这是错误的
public static UInt32 GenerateCRC_32_from_Table(byte[] message)
{
byte[] augmentedMsg = new byte[message.Length + 4];
message.CopyTo(augmentedMsg, 0);
UInt32 remainder = 0xFFFFFFFF;
foreach (byte msgByte in augmentedMsg)
{
byte reversedMsgByte = Reverse(msgByte);
remainder = ((remainder << 8) | Convert.ToUInt32(reversedMsgByte)) ^ crc32_table[((remainder >> 24)) & 0xFF];
}
remainder = Reverse(~remainder);
return remainder;
}
publicstaticuint32从表生成ecrc\u(字节[]消息)
{
字节[]augmentedMsg=新字节[message.Length+4];
message.CopyTo(augmentedMsg,0);
UInt32余数=0xFFFFFF;
foreach(augmentedMsg中的字节msgByte)
{
byte reversedMsgByte=反向(msgByte);
余数=((余数>24))&0xFF];
}
余数=反向(~余数);
返回剩余部分;
}
然而,如果我使用下面的代码(它避免了消息扩充),就会产生正确的结果
public static UInt32 GenerateCRC_32_from_Table(byte[] message)
{
UInt32 remainder = 0xFFFFFFFF;
foreach (byte msgByte in message)
{
byte reversedMsgByte = Reverse(msgByte);
remainder = (remainder << 8) ^ crc32_table[((remainder >> 24) ^ Convert.ToUInt32(reversedMsgByte)) & 0xFF];
}
remainder = Reverse(~remainder);
return remainder;
}
publicstaticuint32从表生成ecrc\u(字节[]消息)
{
UInt32余数=0xFFFFFF;
foreach(消息中的字节msgByte)
{
byte reversedMsgByte=反向(msgByte);
余数=(余数>24)^Convert.ToUInt32(reversedMsgByte))&0xFF];
}
余数=反向(~余数);
返回剩余部分;
}
Reverse()和poly32,如注释中所述:**
const UInt32 poly32 = 0x04C11DB7;
public static UInt32 Reverse(UInt32 message)
{
UInt32 msgReversed = 0;
for (int i = 0; i < 32; i++)
{
msgReversed = ((message & 0x80000000) >> (31 - i)) | msgReversed;
message = message << 1;
}
return msgReversed;
}
public static byte Reverse(byte message)
{
byte msgReversed = 0;
for (int i = 0; i < 8; i++)
{
msgReversed = (byte)(((byte)((byte)(message) & 0x80) >> (7 - i)) | msgReversed);
message = (byte)(message << 1);
}
return msgReversed;
}
const UInt32 poly32=0x04C11DB7;
公共静态UInt32反向(UInt32消息)
{
UInt32 msgReversed=0;
对于(int i=0;i<32;i++)
{
msgReversed=((消息&0x8000000)>>(31-i))| msgReversed;
message=message>(7-i))| msgReversed);
message=(byte)(message反映您所指的标准CRC,即位被反转,并用0xfffffff
初始化,最后的CRC用0xffffffff
进行异或
生成CRC时,位不反转,初始CRC为零,并且末尾没有异或
一般来说,要实现位反转CRC,输入字节保持原样,但反映多项式并向另一个方向移动。输入字节被送入CRC的底部,而不是顶部。这还可以通过增强消息方法将要处理的字节总数减少四个
更新问题的更新:
问题中的代码尝试“扩充”消息,但随后甚至不使用扩充。相反,它使用从偏移量4开始的数据,这相当于使用偏移量0中的原始消息
相反,应该做的是甚至不尝试增加消息,而是将消息排他或消息放入CRC的顶部,而不是尝试将消息馈送到CRC的底部
此外,反转CRC,应用反向消息,然后再次反转CRC,相当于不执行任何操作,而是反转多项式并向另一个方向移动。多项式是常数,因此在编写代码时进行反转,如我的原始答案所述。0x04c11db7
reverseed为0xedb88320
因此代码最终看起来像这样(在C中):
#包括
#包括
/*CRC-32(以太网、ZIP等)多项式的位顺序相反*/
#定义多边形0xedb88320
/*使用初始CRC计算buf[0..len-1]的CRC。这允许
通过将一块输入数据以一定的速率提供给该例程来计算CRC
时间。第一个块的crc值应为零*/
uint32\u t crc32(uint32\u t crc,常量无符号字符*buf,大小长度)
{
int k;
crc=~crc;
而(len--){
crc^=*buf++;
对于(k=0;k<8;k++)
crc=crc&1(crc>>1)^POLY:crc>>1;
}
返回~crc;
}
Reverse
有什么作用?我看不到任何代码。而且你没有定义poly32
。谢谢你的回复。很抱歉,我现在没有代码,因为我在另一个地方,将在几天内粘贴我用于Reverse的代码。Reverse()仅反映二进制数据,您可以在我的输出中看到Reverse的示例用法。XOR^0xFFFFFF:11011000011000011001111111100011(D8619FE3)反转了Abv:11000111111100001100001011(C7F9861B)
。也很抱歉没有定义“poly32”,我将第一个示例中的“poly”重命名为“poly32”,因此“const UInt32 poly32=0x04C11DB7;”是定义。谢谢!@Mark Adler我已用详细信息更新了问题。谢谢!谢谢你的回复!我已将“8”空字节(在第二个示例中)添加到数组中,而不是“4”(如第一个示例中所示),byte[]augmentedMsg=new byte[message.Length+8];
因此,实际上存在并使用消息扩展的最后四个空字节(扩展添加到消息末尾),即使它从4开始。我使用了第一个“4”空字节将余数初始化为0xFFFFFF余数=~rements;//覆盖上述内容并将寄存器初始化为0xFFFFFF
第一个fou
const UInt32 poly32 = 0x04C11DB7;
public static UInt32 Reverse(UInt32 message)
{
UInt32 msgReversed = 0;
for (int i = 0; i < 32; i++)
{
msgReversed = ((message & 0x80000000) >> (31 - i)) | msgReversed;
message = message << 1;
}
return msgReversed;
}
public static byte Reverse(byte message)
{
byte msgReversed = 0;
for (int i = 0; i < 8; i++)
{
msgReversed = (byte)(((byte)((byte)(message) & 0x80) >> (7 - i)) | msgReversed);
message = (byte)(message << 1);
}
return msgReversed;
}
#include <stddef.h>
#include <stdint.h>
/* CRC-32 (Ethernet, ZIP, etc.) polynomial in reversed bit order. */
#define POLY 0xedb88320
/* Compute CRC of buf[0..len-1] with initial CRC crc. This permits the
computation of a CRC by feeding this routine a chunk of the input data at a
time. The value of crc for the first chunk should be zero. */
uint32_t crc32(uint32_t crc, const unsigned char *buf, size_t len)
{
int k;
crc = ~crc;
while (len--) {
crc ^= *buf++;
for (k = 0; k < 8; k++)
crc = crc & 1 ? (crc >> 1) ^ POLY : crc >> 1;
}
return ~crc;
}