CRC32的原理介绍以及查表法实现和多项式相除实现

news2024/12/26 11:31:00

1、CRC32的生成多项式

G\left ( x \right )=x^{32}+x^{26}+x^{23}+x^{22}+x^{16}+x^{12}+x^{11}+x^{10}+x^{8}+x^{7}+x^{5}+x^{4}+x^{2}+x^{1}+1

 多项式系数提取出来,改写位16进制数为:0x104C11DB7,如果转换为33个二进制数[1, 0, 0, 0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 1,
       1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 1] ,那么从左到右对应于生成多项式的每个项目的系数(0或1)。

2  CRC32校验码的生成:

    如果待校验的数据写成多项式的形式,也就是把数据先转换为二进制的数,然后每个二进制数对应一个多项式的一个系数;比如待校验的数据是0x85,那么对应二进制[1000 0101],对应多项式:X^{7}+X^{2}+1,把这个多项式再乘以X^{32},然后再除以G(x),最终的余数就是CRC校验码,也就是(X^{7}+X^{2}+1)*X^{32}/G(x)的余数。

3 CRC32校验码完整流程介绍:

  1. Invert bits on each byte,如果输入是多个字节的数据,每个字节的对应二进制数字要逆序排列,字节之间还是保持输入顺序;
  2. 经过上面处理的数据,需要在末尾增加0x00000000四个字节;相当于给输入数据的多项式乘以X^{32}
  3. xor first four bytes with 0xFF (this is to avoid errors on the leading 0s),经过上面步骤处理后输入数据的前四个字节要和0xFFFFFFFF异或。如果输入数据不足4个字节,也没关系,因为步骤2末尾增加0x00000000四个字节,总长度是够4个字节的。
  4. Compute the reminder ,上面步骤生成的数据对应的多项式除以生成多项式G(x)后的余数
  5. Reverse the bits again,余数是4个字节,这4个字节对应的二进制数字要按一个整体逆序排列。
  6. xor the result again. 逆序后的4个字节再和0xFFFFFFFF异或,得到最终的CRC校验值。

上面步骤中,输入数据的逆序,余数的逆序,输入数据和0xFFFFFFFF的异或,以及余数和0xFFFFFFFF的异或,都是可选步骤,根据不同的应用,可能会有不同的选择。

CRC(循环冗余校验)在线计算_ip33.com

4 举例:

calculate the CRC-32 hash for the 'ANSI' string 'abc':

inputs:
dividend: binary for 'abc': 0b011000010110001001100011 = 0x616263
polynomial: 0b100000100110000010001110110110111 = 0x104C11DB7

start with the 3 bytes 'abc':
61 62 63 (as hex)
01100001 01100010 01100011 (as bin)

reverse the bits in each byte:
10000110 01000110 11000110

append 32 0 bits:
10000110010001101100011000000000000000000000000000000000

XOR (exclusive or) the first 4 bytes with 0xFFFFFFFF:
(i.e. flip the first 32 bits:)
01111001101110010011100111111111000000000000000000000000

next we will perform 'CRC division':

a simple description of 'CRC division':
we put a 33-bit box around the start of a binary number,
start of process:
if the first bit is 1, we XOR the number with the polynomial,
if the first bit is 0, we do nothing,
we then move the 33-bit box right by 1 bit,
if we have reached the end of the number,
then the 33-bit box contains the 'remainder',
otherwise we go back to 'start of process'

note: every time we perform a XOR, the number begins with a 1 bit,
and the polynomial always begins with a 1 bit,
1 XORed with 1 gives 0, so the resulting number will always begin with a 0 bit

'CRC division':
'divide' by the polynomial 0x104C11DB7:
01111001101110010011100111111111000000000000000000000000
 100000100110000010001110110110111
 ---------------------------------
  111000100010010111111010010010110
  100000100110000010001110110110111
  ---------------------------------
   110000001000101011101001001000010
   100000100110000010001110110110111
   ---------------------------------
    100001011101010011001111111101010
    100000100110000010001110110110111
    ---------------------------------
         111101101000100000100101110100000
         100000100110000010001110110110111
         ---------------------------------
          111010011101000101010110000101110
          100000100110000010001110110110111
          ---------------------------------
           110101110110001110110001100110010
           100000100110000010001110110110111
           ---------------------------------
            101010100000011001111110100001010
            100000100110000010001110110110111
            ---------------------------------
              101000011001101111000001011110100
              100000100110000010001110110110111
              ---------------------------------
                100011111110110100111110100001100
                100000100110000010001110110110111
                ---------------------------------
                    110110001101101100000101110110000
                    100000100110000010001110110110111
                    ---------------------------------
                     101101010111011100010110000001110
                     100000100110000010001110110110111
                     ---------------------------------
                       110111000101111001100011011100100
                       100000100110000010001110110110111
                       ---------------------------------
                        10111100011111011101101101010011

we obtain the 32-bit remainder:
0b10111100011111011101101101010011 = 0xBC7DDB53

note: the remainder is a 32-bit number, it may start with a 1 bit or a 0 bit

XOR the remainder with 0xFFFFFFFF:
(i.e. flip the 32 bits:)
0b01000011100000100010010010101100 = 0x438224AC

reverse bits:
bit-reverse the 4 bytes (32 bits), treating them as one entity:
(e.g. 'abcdefgh ijklmnop qrstuvwx yzABCDEF'
to 'FEDCBAzy xwvutsrq ponmlkji hgfedcba':)
0b00110101001001000100000111000010 = 0x352441C2

thus the CRC-32 hash for the 'ANSI' string 'abc' is: 0x352441C2

5 查表法计算原理:

  1.  输入数据是多个字节,可以按照逐个字节的方式去计算CRC检验值
  2. 首先要对0-255这256个数字,计算每个数字对应的CRC检验值,形成一个表格,可以用0-255来索引校验值
  3. 对于第一个输入字节,首先进行逆序,然后逆序后取值作为索引去查表,获得校验值,得到校验值是4个字节,那么按照多项式的除法步骤,校验值4个字节的开头一个字节需要和第二个输入字节(逆序处理后的)进行二进制加法,也就是异或,然后用这个异或后的值作为索引去查表,得到新的校验值,然后再和下一个字节进行相同的处理,以此类推,直至所有输入数据处理完。
  4. 最后得到的4个字节校验值,进行整体逆序,然后和0xFFFFFFFF异或,得到最终的CRC32校验值。

6  多项式相除方法和查表方法的python代码:

mport numpy as np


hex_num = "104C11DB7" # 要转换的十六进制数字
binary_num = bin(int(hex_num, 16))[2:] # 将十六进制转换为十进制再转换为二进制
print("二进制结果:", binary_num)
crc32_gen = np.array(list(binary_num), dtype=int)
print(crc32_gen)



# 使用np.pad()函数进行补零操作

myCRC32Table = np.zeros(0,dtype=int)

for j in range(256):
    Bytes = bin(j)[2:]
    Bytes_bin_array = np.array(list(Bytes), dtype=int)
    Padded_Bytes_bin_array = np.pad(Bytes_bin_array,(0, 32), mode='constant')
    #print("\n补零后的数组:\n", Padded_Bytes_bin_array)
    
    for i in range(len(Padded_Bytes_bin_array)-33+1) :
        tmp_value = Padded_Bytes_bin_array[i:i+33]
        #print(tmp_value)
        if tmp_value[0] ==0:
            continue
        else:
            Padded_Bytes_bin_array[i:i+33] =  tmp_value ^   crc32_gen
            #print(Padded_Bytes_bin_array[i:i+33]) 
    remaider_of_Padded_Bytes_bin_array = Padded_Bytes_bin_array[-32:]        
    CRC32_bytes = int(''.join(map(str, remaider_of_Padded_Bytes_bin_array)),2)       
    myCRC32Table = np.append(myCRC32Table,CRC32_bytes)
   



#hex_num = "EDB883208" # 要转换的十六进制数字

#################   下面是查表法方法计算CRC32 ===================================
Message1 ='0102'
Message1_bin = bin(int(Message1, 16))[2:].zfill(len(Message1)*4) # 将十六进制转换为十进制再转换为二进制
Message1_bin_array = np.array(list(Message1_bin), dtype=int)

##reverse the bits in each byte:

Message1_bin_array_reverse = np.zeros(0,dtype=int)
for i in range(int(np.size(Message1_bin_array)/8)) :
    tmp_flip = np.flipud(Message1_bin_array[i*8:i*8+8])
    tmp_flip_number = int(''.join(map(str, tmp_flip)),2)
    Message1_bin_array_reverse = np.append(Message1_bin_array_reverse,tmp_flip_number)

# 按照字节查询CRC32 table,前一个字节的CRC查表值的前8位需要和下个字节进行异或操作,算出来的新值作为新的查表索引值;每次查出的CRC值还需要和上一次查出的CRC值的高24位异或操作
crc32_result = 0
for i in range(int(np.size(Message1_bin_array_reverse))) :    
    if i < 4:
        Message1_bin_array_reverse[i] =Message1_bin_array_reverse[i] ^ 0xFF
    crc32_result =myCRC32Table[(crc32_result >> 24) ^ Message1_bin_array_reverse[i]] ^ (crc32_result & 0x00FFFFFF)<<8   

#### 如果输入数据小于4个字节,需要对FFFFFFFF剩余的FF特别处理下,比如原始输入数据1个字节,那么有3个0xFF没有在上面的代码中用到,所以要在下面的代码中异或上这三个FF
if int(np.size(Message1_bin_array_reverse)) < 4:
    if 4-int(np.size(Message1_bin_array_reverse))      ==1 :
        crc32_result = crc32_result ^ 0xFF000000
    if 4- int(np.size(Message1_bin_array_reverse))     ==2 :
        crc32_result = crc32_result ^ 0xFFFF0000                
    if 4- int(np.size(Message1_bin_array_reverse))     ==3 :
        crc32_result = crc32_result ^ 0xFFFFFF00
            


# Reverse the result:
crc32_result_bin = bin(crc32_result)[2:].zfill(32)
crc32_result_array = np.array(list(crc32_result_bin), dtype=int)
crc32_result_reverse = np.flipud(crc32_result_array)
crc32_result_reverse = ''.join(map(str, crc32_result_reverse))
print('crc32_result_reverse =  ',hex(int(crc32_result_reverse,2)))

crc32_result_reverse_complement  = int(crc32_result_reverse,2)^0xFFFFFFFF
print('crc32_result_reverse_complement',hex(crc32_result_reverse_complement))







#################   下面是多项式相除方法计算CRC32 ===================================

#Message ='8040C020'
Message ='0102'

Message_bin = bin(int(Message, 16))[2:].zfill(len(Message)*4) # 将十六进制转换为十进制再转换为二进制
#Message_bin = '01111001101110010011100111111111000000000000000000000000'
Message_bin_array = np.array(list(Message_bin), dtype=int)

############ Reverse input per byte
Message_bin_array_reverse = np.zeros(0,dtype=int)
for i in range(int(np.size(Message_bin_array)/8)) :
    tmp_flip = np.flipud(Message_bin_array[i*8:i*8+8])
    Message_bin_array_reverse = np.append(Message_bin_array_reverse,tmp_flip)


outputXor = 'ffffffff'
outputXor_bin = bin(int(outputXor, 16))[2:]
outputXor_array = np.array(list(outputXor_bin), dtype=int)

kk = len(Message)*4

 
# 使用np.pad()函数进行补零操作
padded_message = np.pad(Message_bin_array_reverse,(0, 32), mode='constant')
print("\n补零后的数组:\n", padded_message)

#padded_message = Message_bin_array

padded_outputXor = np.pad(outputXor_array,(0, kk), mode='constant')


#padded_message = padded_message^padded_outputXor

for i in range(len(padded_message)-33+1) :
    tmp_value = padded_message[i:i+33]
    print(tmp_value)
    if tmp_value[0] ==0:
        continue
    else:
        padded_message[i:i+33] =  tmp_value ^ crc32_gen
        print(padded_message[i:i+33]) 

remaider_of_padded_message = padded_message[-32:]

CRC32 = ''.join(map(str, remaider_of_padded_message))
print('remaider_of_padded_message = ',hex(int(CRC32,2)))
 
remaider_of_padded_message_reverse = np.flipud(remaider_of_padded_message)
CRC32 = ''.join(map(str, remaider_of_padded_message_reverse))
print('remaider_of_padded_message_reverse = ',hex(int(CRC32,2)))


for i in range(len(padded_outputXor)-33+1) :
    tmp_value = padded_outputXor[i:i+33]
    print(tmp_value)
    if tmp_value[0] ==0:
        continue
    else:
        padded_outputXor[i:i+33] =  tmp_value ^   crc32_gen
        print(padded_outputXor[i:i+33]) 
remaider_of_padded_outputXor = padded_outputXor[-32:]
remaider_of_padded_outputXor_reverse = np.flipud(remaider_of_padded_outputXor)
CRC32 = ''.join(map(str, remaider_of_padded_outputXor_reverse))
print('remaider_of_padded_outputXor_reverse = ',hex(int(CRC32,2)))



CRC32 = remaider_of_padded_message ^ remaider_of_padded_outputXor
CRC32_reverse = np.flipud(CRC32)

print(CRC32)

CRC32 = ''.join(map(str, CRC32))
print(hex(int(CRC32,2)))


print(CRC32_reverse)

CRC32_reverse = ''.join(map(str, CRC32_reverse))
print(hex(int(CRC32_reverse,2)))


CRC32_reverse_complement  = int(CRC32_reverse,2)^0xFFFFFFFF
print('CRC32_reverse_complement=',hex(CRC32_reverse_complement))

 注意:WLAN的MAC帧的FCS是完整的CRC32校验

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1362597.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

工地云平台源码,智慧工地源码,Spring Cloud智慧工地管理系统源码

智慧工地是一种基于信息技术和大数据应用的智能化管理平台&#xff0c;旨在提升建筑施工现场的安全、效率和质量。通过物联网、云计算、人工智能等技术手段&#xff0c;智慧工地可以对施工现场的各个要素进行全面感知、实时交互和智能分析&#xff0c;以实现更高效、更安全、更…

【LMM 015】LAMM:多模态指令微调数据集,框架和基准

论文标题&#xff1a;LAMM: Language-Assisted Multi-Modal Instruction-Tuning Dataset, Framework, and Benchmark 论文作者&#xff1a;Zhenfei Yin, Jiong Wang, Jianjian Cao, Zhelun Shi, Dingning Liu, Mukai Li, Lu Sheng, Lei Bai, Xiaoshui Huang, Zhiyong Wang, Jin…

视觉检测不合格品剔除FC(Smart PLC简单状态机编程应用)

视觉系统检测到不合格产品后&#xff0c;往往都需要控制我们的剔除电磁阀吹气剔除不合格产品&#xff0c;三菱PLC里的推荐编程方法&#xff0c;可以参考下面的链接文章&#xff1a; https://rxxw-control.blog.csdn.net/article/details/125027866https://rxxw-control.blog.c…

【算法每日一练]-图论(保姆级教程篇14 )#会议(模板题) #医院设置 #虫洞 #无序字母对 #旅行计划 #最优贸易

目录 今日知识点&#xff1a; 求数的重心先dfs出d[1]和cnt[i]&#xff0c;然后从1进行dp求解所有d[i] 两两点配对的建图方式&#xff0c;检查是否有环 无向图欧拉路径路径输出 topodp求以i为终点的游览城市数 建立分层图转化盈利问题成求最长路 会议&#xff08;模板题&a…

I.MX6ULL开发笔记(二)——硬件外设操作

0x01 点亮第一个RGB灯 在文章http://t.csdnimg.cn/EGWt9中有介绍Linux下文件目录&#xff0c;那么在Linux系统下&#xff0c;RGB灯也是一个设备&#xff0c;所以我们需要到/sys目录下去操作这个设备。 之后&#xff0c;我们进入到class目录&#xff0c;这里挂载着开发板上的外…

【数据仓库与联机分析处理】多维数据模型

目录 一、数据立方体 二、数据模型 &#xff08;一&#xff09;星形模型 &#xff08;二&#xff09;雪花模式 &#xff08;三&#xff09;事实星座模式 三、多维数据模型中的OLAP操作 &#xff08;一&#xff09;下钻 &#xff08;二&#xff09;上卷 &#xff08;三…

【GitHub】-design-pattern-extend(设计模式扩展)

写在前面 偶然间看到一篇文章 《Java 中保持扩展性的几种套路和实现》&#xff0c;写的不错&#xff0c;但是类图画的差了点儿意思。于是&#xff0c;自己动手画了画&#xff0c;对其中的内容作了一些调整&#xff0c;对包做了进一步划分&#xff0c;便于理解消化。以下是对Git…

第11章 GUI Page462~476 步骤二十三,二十四,二十五 Undo/Redo ③实现“Undo/Redo”菜单项

工程六 添加“编辑”菜单和子菜单 菜单ID分别为 idMenuEditUndo 和 idMenuEditRedo 热键&#xff08;快捷键&#xff09;分别为CtrlZ 和 CtrlShiftZ 变量名分别为 MenuItemEditUndo 和 MenuItemEditRedo 分别添加事件 ActionLink类增加成员函数 运行效果&#xff1a;“添加…

【C语言】Linux实现高并发处理的过程

一、实现高并发的几种策略 C语言本身并没有内建的多线程支持&#xff08;新版C语言支持&#xff0c;但用得不多&#xff09;&#xff0c;但是在多数操作系统中&#xff0c;可以使用库来实现多线程编程。例如&#xff0c;在POSIX兼容系统上&#xff0c;可以使用 pthreads 库来创…

【Web开发】会话管理与无 Cookie 环境下的实现策略

&#x1f34e;个人博客&#xff1a;个人主页 &#x1f3c6;个人专栏&#xff1a; Web开发 ⛳️ 功不唐捐&#xff0c;玉汝于成 目录 前言 正文 问题&#xff1a; 思路&#xff1a; 方法&#xff1a; 结语 我的其他博客 前言 在当今Web应用程序中&#xff0c;会话…

实时语义分割模型PP-LiteSeg论文解读

paper&#xff1a;PP-LiteSeg: A Superior Real-Time Semantic Segmentation Model official implementation&#xff1a;https://github.com/PaddlePaddle/PaddleSeg/blob/release/2.8/paddleseg/models/pp_liteseg.py 本文的创新点 提出了一种灵活的轻量级解码器&#xf…

力扣:438. 找到字符串中所有字母异位词 题解

Problem: 438. 找到字符串中所有字母异位词 438. 找到字符串中所有字母异位词 预备知识解题思路复杂度Code其它细节推荐博客或题目博客题目滑动窗口哈希表 预备知识 此题用到了双指针算法中的滑动窗口思想&#xff0c;以及哈希表的运用。c中是unordered_map。如果对此不了解的u…

基于Spring-boot-websocket的聊天应用开发总结

目录 1.概述 1.1 Websocket 1.2 STOMP 1.3 源码 2.Springboot集成WS 2.1 添加依赖 2.2 ws配置 2.2.1 WebSocketMessageBrokerConfigurer 2.2.2 ChatController 2.2.3 ChatInRoomController 2.2.4 ChatToUserController 2.3 前端聊天配置 2.3.1 index.html和main.j…

路由器01_工作原理

一、回顾交换机工作原理 交换机里面维护了一张MAC地址表&#xff0c;主要记录的是MAC地址和接口的对应关系。 交换机在初始状态下&#xff0c;MAC地址表是空的&#xff0c;当收到一个来自某接口的数据时&#xff0c;首先查看数据帧中的MAC地址表&#xff0c;对照自己的MAC地址…

MySQL进阶篇(二) 索引

一、索引概述 1. 介绍 索引&#xff08;index&#xff09;是帮助 MySQL 高效获取数据 的 数据结构&#xff08;有序&#xff09;。在数据之外&#xff0c;数据库系统还维护着满足特定查找算法的数据结构&#xff0c;这些数据结构以某种方式引用&#xff08;指向&#xff09;数…

React 实现拖放功能

介绍 本篇文章将会使用react实现简单拖放功能。 样例 布局拖放 LayoutResize.js import React, {useState} from "react"; import { Button } from "antd"; import "./LayoutResize.css";export const LayoutResize () > {const [state,…

imgaug库指南(六):从入门到精通的【图像增强】之旅

引言 在深度学习和计算机视觉的世界里&#xff0c;数据是模型训练的基石&#xff0c;其质量与数量直接影响着模型的性能。然而&#xff0c;获取大量高质量的标注数据往往需要耗费大量的时间和资源。正因如此&#xff0c;数据增强技术应运而生&#xff0c;成为了解决这一问题的…

海康威视安全接入网关 任意文件读取漏洞复现

0x01 产品简介 海康威视安全接入网关是一种网络安全产品,旨在提供安全、可靠的远程访问和连接解决方案. 0x02 漏洞概述 海康威视安全接入网关使用Jquery-1.7.2 , 该版本存在任意文件读取漏洞,可获取服务器内部敏感信息泄露(安博通应用网关也存在此漏洞) 0x03 复现环境 …

未完成销量任务的智己汽车突发大规模车机故障,竞争压力不小

2024年刚开年&#xff0c;智己汽车便上演了一出“开门黑”。 近日&#xff0c;不少车主在社交平台发帖&#xff0c;反映智己LS6出现大规模车机故障&#xff0c;包括但不限于主驾驶屏幕不显示车速、档位、行驶里程&#xff0c;左右转盲区显示失效&#xff0c;无转向灯、雷达提醒…

04 帧 Frame

文章目录 04 帧 Frame4.1 相机相关信息4.2 特征点提取4.2.1 特征点提取 ExtractORB()4.3 ORB-SLAM2对双目/RGBD特征点的预处理4.3.1 双目视差公式4.3.2 双目图像特征点匹配 ComputeStereoMatches()4.3.3 根据深度信息构造虚拟右目图像&#xff1a;ComputeStereoFromRGBD() 4.4 …