C# 基本的CRC32维基百科实现不同于在线看到的标准CRC32

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

我有一个基本的CRC32实现,遵循维基百科的。我认为我做得对,修改后的余数多项式使用n位寄存器,而不是如示例所示使用n+1位寄存器

我得到的结果与在线CRC32实施结果不同。在我的实现中,我必须改变什么

请忽略用于逻辑的Console.Writeline语句

    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;
    }
我对上述内容进行了如下修改,以下是修改(注释以内联方式添加到代码中):

  • 已初始化为0xFFFFFF
  • 反转输入消息字节
  • XOR为最终值,与XORD值相反

    公共静态UInt32发生器CRC_32(字节[]消息) { 字节[]augmentedMsg=新字节[message.Length+8]; message.CopyTo(augmentedMsg,4);//修改为创建初始化空间

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