checksum算法详细的计算方法、实现思路与python校验验证

1.checksum是什么?

Checksum:【电脑】总和检验码,校验和。在数据处理和数据通信领域中,用于校验目的的一组数据项的和。这些数据项可以是数字或在计算检验总和过程中看作数字的其它字符串。
它通常是以十六进制为数制表示的形式
通常用来在通信中,尤其是远距离通信中保证数据的完整性和准确性


2.计算方法

1、 先将需要计算checksum数据中的checksum设为0;
2、 计算checksum的数据按2byte划分开来,每2byte组成一个16bit的值,如果最后有单个byte的数据,补一个byte的0组成2byte;
3、 将所有的16bit值累加到一个32bit的值中;
4、 将32bit值的高16bit与低16bit相加到一个新的32bit值中,若新的32bit值大于0Xffff,
再将新值的高16bit与低16bit相加;
5、 将上一步计算所得的16bit值按位取反(取反是取补码),即得到checksum值,存入数据的checksum字段即可。


3.算法实现的具体思路

参考的别的大佬的文章,数据拿过来

 45 00 00 30 80 4c 40 00 80 06 b5 2e d3 43 11 7b cb 51 15 3d

1、第一步,checksum数据中的checksum=b52e设为0

遍历需要校验的数据,将checksum替换为0

45 00 00 30 80 4c 40 00 80 06 00 00 d3 43 11 7b cb 51 15 3d

2、第二步,求和

遍历求和,直接累加,最后输出的是一个int类型的十进制数

3、第三步,转十六进制,将进位添加到低位

python提供了直接将十进制数转为十六进制的内置函数:hex()    返回的是str型   例如:hex(12345)

4500+0030+804c+4000+8006+0000+d343+117b+cb51+153d=0x34ace

将进位(3)加到低16位(4ace)上:0003+4ace=4ad1

4、第四步,取反码
 将4ad1取反得:checksum=b52e


4、使用python实现checksum算法

代码没有整理简化,

'''
自定义checksum算法实现

checksum:校验和
data:需要校验的数据
'''
import math
import numpy as np

class myCheckSum():
    def __init__( self,checkSum,data=[] ):
        self.checkSum=checkSum
        self.data=data
        self.hexadecimal={ 'a':10, 'b':11, 'c':12, 'd':13, 'e':14,  'f':15,
                          10:'a', 11:'b', 12:'c', 13:'d', 14:'e', 15:'f'}      #  十六进制大于9的数
        self.sumdata=0x0 
        
        #第一步,求和(遍历时遇到checksum,替换为0x0)
        datas=self.sumCheckSum()
        
        #第二步,将进位加到低位
        cal=self.carryAddLow( len(self.sumdata),datas ) # len(self.sumdata)=5     cal=0x4ad1
        
        #第三步,取补码
        result=self.complementData(cal)
        print('result:',result)
        print('checksum:',checkSum)   #   checkSum: 46382
        if result==checkSum:
            print('True:正确')
        else:
            print('False:错误')
        
        
    # 求和    
    def sumCheckSum(self):
        dataLen=len(self.data)  
               
        for i in range(dataLen): 
            if self.data[i]==self.checkSum:  # 找到checksum
                self.sumdata+=0x0   #  checksum替换为0x0来累加
            else:
                self.sumdata+=self.data[i]
        #print( type( sel.SumData ) )      #  215758    int型  
        self.sumdata=hex(self.sumdata)[2:]     #  '0x34ace'    str类型   十六进制    
        
        datas=[]
        for i in self.sumdata:
            if i in ['a','b','c','d','e']:
                datas.append( self.hexadecimal[i] )
            else:
                datas.append( int(i) )        
        #print( 'datas:',datas)    #  ['3','4','10','12','14']
        return datas
     
        
    # 取反 ,这里取反取的是补码   在python中 ~ 不能取到补码
    def complementData(self,cal):                   
        tenResult=int(cal,16)
        twoResult=bin(tenResult)
        
        calLen=len( cal[2:])  #  4
        twoResultLen=len( twoResult[2:])    #   15        
        if calLen*4>twoResultLen:
            subLen=calLen*4-twoResultLen      #   1
            twoResult='0'*subLen+twoResult[2:]
        #print( 'twoResult:',twoResult ,'*type:',type(twoResult))    # twoResult: 0100101011010001 *type: 
        
        reverseResult='0b'
        for i in twoResult:
            if i=='1':
                reverseResult+='0'
            else:
                reverseResult+='1'
        #print('reverseResult:',reverseResult)  #  reverseResult: 0b1011010100101110
        #print(hex( eval(reverseResult) ) )      #   0xb52e 
        return eval(reverseResult)    #   46382  十进制
                        
                
        
    #  进位加到低位     返回一个十六进制数        
    #  将32bit值的高16bit与低16bit相加到一个新的32bit值中,若新的32bit值大于0Xffff, 再将新值的高16bit与低16bit相加;       
    def carryAddLow(self,sumDataLen,datas):    #   sumDataLen=5  判断是否大于0Xffff,一种直接数值判断,另一种长度大于0Xffff的四位
        bus,rem=divmod(sumDataLen,4)  # 取bus商  rem余数

        dualLists=[]                   
        if rem != 0:  
            for i in range(bus+1):   # 如果有余数  bus需要+1
                dualLists.append([])   # dualLists=[ [], [], []]
                if i==0:         # 第一个list为 [0,0,0,3]    
                    for j in range(4-rem):  
                        dualLists[i].append(0)
                    for j in range(rem):
                        dualLists[i].append( datas[0] ) 
                        del datas[0]
                else:        
                    for j in range(4):   
                        dualLists[i].append( datas[0] )
                        del datas[0]
        else:
            for i in range(bus):   
                dualLists.append([])     
                for j in range(4):   
                    dualLists[i].append( datas[0] )
                    del datas[0]
        #print( 'dualLists:',dualLists)    #  dualLists: [[0, 0, 0, 3], [4, 10, 12, 14]]
        
        res=[0,0,0,0]
        for i in range( len(dualLists)):
            res=np.array(res)+np.array( dualLists[i] )    #  使用numpy中array把两个list相加    
        #print('res:',res)    #  res: [ 4 10 12 17]    到这里进位加到低位结束
        
        result=[]  
        for i in range( len(res)-1,-1,-1 ):    #  逆序遍历res
            if res[i]>15:    #  大于15的进位  小于等于的直接存了
                result.append( res[i]%16 )
                res[i-1]+=res[i]//15      ###################################################
            else:
                result.append( res[i] )
        #print('result:',result)

        data='0x'
        for i in range( len(result)-1,-1,-1 ):
            if result[i] in [10,11,12,13,14,15]:
                data+=self.hexadecimal[ result[i] ]
            else:
                data+=str( result[i] )
        #print('data:',data)   #   4ad1  
        return data


checksum算法详细的计算方法、实现思路与python校验验证_第1张图片

验证一下

(1)反码求和

4500+0030+804c+4000+8006+b52e+d343+117b+cb51+153d=3fffc
0003+fffc=ffff

(2)取反码:~ffff=0 正确

你可能感兴趣的:(python,Hadoop)