生活随笔
收集整理的這篇文章主要介紹了
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_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_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
):length_b
= len(m
)*4b
= mb
= b
+ '8'c
= len(b
)%128c
= 112 - cd
= '0'*cb
= b
+ dlength_m
= '{:016x}'.format(length_b
)b
= b
+ length_m
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
):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)):w
= B
[n
][i
*8:(i
+1)*8]W
[i
] = w
for j
in range(16,68):a
= or_16
(W
[j
-16],W
[j
-9])W_j_3
= Cyc_shift
(W
[j
-3],15)a
= or_16
(a
,W_j_3
)a
= Replace_P1
(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
for 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]all=''for j
in range(64):b
= a
= Cyc_shift
(A
,12)T
= 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
= TT1H
= GG
= Cyc_shift
(F
,19)F
= EE
= Replace_P0
(TT2
) all = A
+B
+C
+D
+E
+F
+G
+HV
[k
+1]=or_16
(V
[k
],all)
(5)雜湊值
ABCDEFGH←V(n)ABCDEFGH ←V^{(n)} ABCDEFGH←V(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
):length_b
= len(m
)*4b
= mb
= b
+ '8'c
= len(b
)%128c
= 112 - cd
= '0'*cb
= b
+ dlength_m
= '{:016x}'.format(length_b
)b
= b
+ length_m
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
):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)):w
= B
[n
][i
*8:(i
+1)*8]W
[i
] = w
for j
in range(16,68):a
= or_16
(W
[j
-16],W
[j
-9])W_j_3
= Cyc_shift
(W
[j
-3],15)a
= or_16
(a
,W_j_3
)a
= Replace_P1
(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
for j
in range(64):W_0
[j
]=or_16
(W
[j
],W
[j
+4])return W
,W_0
def Replace_P1(X
):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_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
def T_j(j
):if j
<=15:T_j
='79cc4519'else:T_j
='7a879d8a'return T_j
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
)a
= [0 for _
in range(32)]carry
= 0for i
in range(32):m
= int(x
[31-i
])+int(y
[31-i
])+carry
if m
>=2:d
=m
-2a
[31-i
]=str(d
)carry
=1else:carry
=0d
=ma
[31 - i
] = str(d
)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]all=''for j
in range(64):b
= a
= Cyc_shift
(A
,12)T
= 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
= TT1H
= GG
= Cyc_shift
(F
,19)F
= EE
= Replace_P0
(TT2
) all = A
+B
+C
+D
+E
+F
+G
+HV
[k
+1]=or_16
(V
[k
],all)
def hash(m
=m
):for i
in range(m_len
):v_n
=CF
(m
,i
,i
)print(V
[-1])return V
[-1]
hash()
注意:循環移位以字(32bit)處理,所以要模32后再移位,否則壓縮函數在Tj<<<j時后續會出錯。
總結
以上是生活随笔為你收集整理的python实现sm3算法的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。