日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > python >内容正文

python

python实现sm3算法

發布時間:2023/12/31 python 37 豆豆
生活随笔 收集整理的這篇文章主要介紹了 python实现sm3算法 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

背景

sm3密碼雜湊算法是中國國家密碼管理局頒布的一種密碼Hash函數,它與sm4分組密碼、sm2橢圓曲線公鑰密鑰一起都是中國商用密碼的重要組成部分。

SM3密碼Hash算法的輸入數據長度為 l 比特,1≤ l ≤ 264-1,輸出Hash值的長度為256比特。

1.常量與函數

SM3密碼Hash函數使用以下常數與函數。

(1)常量

初始值IV=7380166f 4914b2b9 172442d7 da8a0600 a96f30bc 163138aa e38dee4d b0fb0e4e

(2)函數

布爾函數:


式中X、Y、Z為32位字。

#布爾函數 def FF_j(X,Y,Z,j):if j<=15:a = or_16(X,Y)a = or_16(a,Z)else:a = and_Cal(X,Y)b = and_Cal(X,Z)c = and_Cal(Y,Z)a = or_Cal(a,b)a = or_Cal(a,c)return a#布爾函數 def GG_j(X, Y, Z, j):if j <= 15:a = or_16(X, Y)a = or_16(a, Z)else:a = and_Cal(X,Y)b = qufan(X)b = and_Cal(b,Z)a = or_Cal(a,b)return a

置換函數
P0(X) = X ? (X<<<9)?(X<<<17)
P1(X) = X ? (X<<<15)?(X<<<23)
式中X為32位字,符號a<<<n表示把a循環左移n位。

#置換函數 def Replace_P1(X):#X為32位字X_15 = Cyc_shift(X,15) #循環移位X_23 = Cyc_shift(X,23)a = or_16(X,X_15)a = or_16(a,X_23)return a#置換函數 def Replace_P0(X):#X為32位字X_9 = Cyc_shift(X,9)X_17 = Cyc_shift(X,17)a = or_16(X,X_9)a = or_16(a,X_17)return a

2.算法描述

SM3密碼Hash算法對數據進行填充和迭代壓縮后生成Hash值。

(1)填充

對數據進行填充的目的是使填充后的數據長度為512的整數倍。后面進行的迭代壓縮式對512位的數據塊進行的,如果數據的長度不是512的整數倍,最后一塊數據塊將是短塊,這將無法處理。
假設消息m的長度為l 比特。首先將比特“1”添加到消息m的末尾,再添加k個“0”。其中,k 是滿足 l+1+k=448 mod 512 的最小非負整數。然后再添加一個64位比特串,該比特串是長度l 的二進制表示。填充后的消息m的比特串長度一定是512的倍數。
例如,對消息 01100001 01100010 01100011,其長度為l=24,經填充后得到比特串:

#填充函數 def filling(m):#消息m是一個16進制字符串#直接加16進制比較好#61626364616263646162636461626364616263646162636461626364616263646162636461626364616263646162636461626364616263646162636461626364#a = int(m,16)#b = bin(a)[2:]#消息轉換為二進制length_b = len(m)*4#記錄消息的長度#s1='{:04b}'.format(s1)b = mb = b + '8'#補 1c = len(b)%128c = 112 - c#補 0 的個數d = '0'*cb = b + d#補 0length_m = '{:016x}'.format(length_b)#也是16進制b = b + length_m#填充完畢#b = int(b)#b = hex(b)[2:]return b

(2)迭代壓縮

將填充后的信息m’ 按512比特進行分組:m’ = B(0) B(1) … B(n-1) ,其中 n = (l+k+65)/512
對m’ 按下列方式迭代壓縮:

FOR i=0 TO n-1
V(i+1) = CF(V(i),B(i) )
ENDFOR

其中:CF是壓縮函數;V(0) 為256比特初始值IV;B(i) 為填充后的消息分組;迭代壓縮的結果為V(n) 即為消息m的Hash值。

(3)消息擴展

在對消息分組B(i) 進行迭代壓縮之前,首先對其進行消息擴展。進行消息擴展有兩個目的。目的之一是將16個字的消息分組B(i) 擴展成下式(1)的132個字,供壓縮函數CF使用。目的之二是通過消息擴展把原消息位打亂,隱蔽了原信息之間的關聯,增強了Hash函數的安全性。
W0,W1,...W67,W0′,W1′,...W63′??????(1)W_0,W_1,... W_{67},W'_0,W'_1,... W'_{63} ------(1) W0?W1?...W67?W0?W1?...W63???????(1)
消息擴展的步驟如下:

消息分組B(i) 經消息擴展后就可以進行迭代壓縮了。

#擴展函數 def expand(m,n):#n代表是第幾組消息,消息之間沒有關系,不用迭代B = fenzu(m)#列表W = ['0' for i in range(68)]W_0 = ['0' for i in range(64)]for i in range(int(len(B[n])/8)):#128/8=16個字w = B[n][i*8:(i+1)*8]W[i] = wfor j in range(16,68):a = or_16(W[j-16],W[j-9])W_j_3 = Cyc_shift(W[j-3],15)#print(W_j_3)a = or_16(a,W_j_3)a = Replace_P1(a)#print(a)W_j_13=Cyc_shift(W[j-13],7)a = or_16(a,W_j_13)a = or_16(a,W[j-6])W[j]=a#return Wfor j in range(64):W_0[j]=or_16(W[j],W[j+4])return W,W_0

(4)壓縮函數

令A,B,C,D,E,F,G,H為字寄存器,SS1,SS2,TT1,TT2為中間變量,壓縮函數V(i+1) =CF(V(i) ,B(i) ),0 ≤ i ≤ n-1 計算過程描述如下,

其中壓縮函數中的+運算為mod 232 算術加運算,字的存儲為大端格式。
由SM3的壓縮函數的算法可以看出,壓縮函數進行了64次循環迭代。SM3的壓縮函數CF把每一個512位的消息分組 B(i) 壓縮成256位。經過個數據分組之間的迭代處理后把 l 位的信息壓縮成256位的hash值。其中布爾函數FFj(X,Y,Z)和GGj(X,Y,Z)是非線性函數,經過循環迭代后提供混淆作用。置換函數P0(X)和P1(X)是線性函數,經過循環迭代后提供擴散作用,確保算法的安全性。

#壓縮函數 def CF(m,n,k):w = expand(m, n)W = w[0]W_0 = w[1]A=V[k][0:8]B=V[k][8:16]C=V[k][16:24]D=V[k][24:32]E=V[k][32:40]F=V[k][40:48]G=V[k][48:56]H=V[k][56:64]#print(W_0)all=''for j in range(64):#print(E)b= a = Cyc_shift(A,12)#t = bT = T_j(j)#T = Cyc_shift(T,j)#忘記移位了,移位問題a = add(a,E)a = add(a,T)SS1 = Cyc_shift(a,7)SS2 = or_16(SS1,b)b = FF_j(A,B,C,j)b = add(b,D)b = add(b,SS2)TT1 = add(b,W_0[j]) #b = GG_j(E,F,G,j)b = add(b, H)b = add(b, SS1)TT2 = add(b, W[j]) #D = CC = Cyc_shift(B,9)B = AA = TT1#H = GG = Cyc_shift(F,19)F = EE = Replace_P0(TT2) #all = A+B+C+D+E+F+G+H#print(all)#V[k+1]=or_16(all,V[k])#return V[k+1]#print(t)#return allV[k+1]=or_16(V[k],all)

(5)雜湊值

ABCDEFGH←V(n)ABCDEFGH ←V^{(n)} ABCDEFGHV(n)
輸出256比特的雜湊值 y = ABCDEFGH。處理過程如下:

實現示例:
512比特消息:
61626364 61626364 61626364 61626364 61626364 61626364 61626364 61626364
61626364 61626364 61626364 61626364 61626364 61626364 61626364 61626364
填充后消息:
61626364 61626364 61626364 61626364 61626364 61626364 61626364 61626364
61626364 61626364 61626364 61626364 61626364 61626364 61626364 61626364
80000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
80000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
雜湊值:
debe9ff9 2275b8a1 38604889 c18e5a4d 6fdb70e5 387e5765 293dcba3 9c0c5732

全部代碼:sm3.py

m='61626364616263646162636461626364616263646162636461626364616263646162636461626364616263646162636461626364616263646162636461626364' IV='7380166f4914b2b9172442d7da8a0600a96f30bc163138aae38dee4db0fb0e4e' #填充函數 def filling(m):#消息m是一個16進制字符串#直接加16進制比較好#61626364616263646162636461626364616263646162636461626364616263646162636461626364616263646162636461626364616263646162636461626364#a = int(m,16)#b = bin(a)[2:]#消息轉換為二進制length_b = len(m)*4#記錄消息的長度#s1='{:04b}'.format(s1)b = mb = b + '8'#補 1c = len(b)%128c = 112 - c#補 0 的個數d = '0'*cb = b + d#補 0length_m = '{:016x}'.format(length_b)#也是16進制b = b + length_m#填充完畢#b = int(b)#b = hex(b)[2:]return b#分組函數 def fenzu(m):m = filling(m)len_m = len(m)/128m_list = []for i in range(int(len_m)):a = m[0+128*i:+128*(i+1)]m_list.append(a)return m_list#擴展函數 def expand(m,n):#n代表是第幾組消息,消息之間沒有關系,不用迭代B = fenzu(m)#列表W = ['0' for i in range(68)]W_0 = ['0' for i in range(64)]for i in range(int(len(B[n])/8)):#128/8=16個字w = B[n][i*8:(i+1)*8]W[i] = wfor j in range(16,68):a = or_16(W[j-16],W[j-9])W_j_3 = Cyc_shift(W[j-3],15)#print(W_j_3)a = or_16(a,W_j_3)a = Replace_P1(a)#print(a)W_j_13=Cyc_shift(W[j-13],7)a = or_16(a,W_j_13)a = or_16(a,W[j-6])W[j]=a#return Wfor j in range(64):W_0[j]=or_16(W[j],W[j+4])return W,W_0#置換函數 def Replace_P1(X):#X為32位字X_15 = Cyc_shift(X,15) #循環移位X_23 = Cyc_shift(X,23)a = or_16(X,X_15)a = or_16(a,X_23)return a#置換函數 def Replace_P0(X):#X為32位字X_9 = Cyc_shift(X,9)X_17 = Cyc_shift(X,17)a = or_16(X,X_9)a = or_16(a,X_17)return a#異或函數 def or_16(A,B):A = int(A,16)B = int(B,16)C = A ^ BC = '{:08x}'.format(C)return C#循環移位函數 def Cyc_shift(W,n):a = int(W,16)a = '{:032b}'.format(a)while n>=32:n=n-32a = a[n:] + a[:n]a = int(a,2)a = '{:08x}'.format(a)return a#常量Tj def T_j(j):if j<=15:T_j='79cc4519'else:T_j='7a879d8a'return T_j#mod 2^32 算術加運算 def add(x,y):x = int(x,16)x = '{:032b}'.format(x)x = list(x)y = int(y, 16)y = '{:032b}'.format(y)y = list(y)#print(x)#print(y)a = [0 for _ in range(32)]carry = 0for i in range(32):m = int(x[31-i])+int(y[31-i])+carryif m>=2:d=m-2a[31-i]=str(d)carry=1else:carry=0d=ma[31 - i] = str(d)#print(a)b=''.join(a)b=int(b,2)b='{:08x}'.format(b)return b#布爾函數 def FF_j(X,Y,Z,j):if j<=15:a = or_16(X,Y)a = or_16(a,Z)else:a = and_Cal(X,Y)b = and_Cal(X,Z)c = and_Cal(Y,Z)a = or_Cal(a,b)a = or_Cal(a,c)return a#布爾函數 def GG_j(X, Y, Z, j):if j <= 15:a = or_16(X, Y)a = or_16(a, Z)else:a = and_Cal(X,Y)b = qufan(X)b = and_Cal(b,Z)a = or_Cal(a,b)return a#與運算函數 def and_Cal(a,b):a = int(a,16)b = int(b,16)a_b = a & ba_b = '{:08x}'.format(a_b)return a_b#或運算函數 def or_Cal(a,b):a = int(a, 16)b = int(b, 16)a_b = a | ba_b = '{:08x}'.format(a_b)return a_b#按位取反函數 def qufan(A):A = int(A,16)A = '{:032b}'.format(A)A = list(A)for i in range(32):if A[i]=='0':A[i]='1'else:A[i]='0'A = ''.join(A)A = int(A,2)A = '{:08x}'.format(A)return A#壓縮函數 m_list = fenzu(m) m_len = len(m_list) V = ['0' for i in range(m_len+1)] V[0]=IV#壓縮函數 def CF(m,n,k):w = expand(m, n)W = w[0]W_0 = w[1]A=V[k][0:8]B=V[k][8:16]C=V[k][16:24]D=V[k][24:32]E=V[k][32:40]F=V[k][40:48]G=V[k][48:56]H=V[k][56:64]#print(W_0)all=''for j in range(64):#print(E)b= a = Cyc_shift(A,12)#t = bT = T_j(j)#T = Cyc_shift(T,j)#忘記移位了,移位問題a = add(a,E)a = add(a,T)SS1 = Cyc_shift(a,7)SS2 = or_16(SS1,b)b = FF_j(A,B,C,j)b = add(b,D)b = add(b,SS2)TT1 = add(b,W_0[j]) #b = GG_j(E,F,G,j)b = add(b, H)b = add(b, SS1)TT2 = add(b, W[j]) #D = CC = Cyc_shift(B,9)B = AA = TT1#H = GG = Cyc_shift(F,19)F = EE = Replace_P0(TT2) #all = A+B+C+D+E+F+G+H#print(all)#V[k+1]=or_16(all,V[k])#return V[k+1]#print(t)#return allV[k+1]=or_16(V[k],all)#print(CF(m,0,0)) #print(V) def hash(m=m):for i in range(m_len):v_n=CF(m,i,i)print(V[-1])return V[-1]#b='' #b=a[0:8]+'\0'+a[8:16]+'\0'+a[16:24]+'\0'+a[24:32]+'\0'+a[32:40]+'\0'+a[40:48]+'\0'+a[48:56]+'\0'+a[56:64] #print(b) hash() #print('輸入的消息m是:\n',m) #print('消息m的hash值為:\n',b)

注意:循環移位以字(32bit)處理,所以要模32后再移位,否則壓縮函數在Tj<<<j時后續會出錯。

總結

以上是生活随笔為你收集整理的python实现sm3算法的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。