技術力量 | AES 和 SM4 S盒複合域實現方法

2021-02-13 深圳密碼
AES 和 SM4 S 盒複合域實現方法導語

本文介紹AES和SM4 S盒的複合域實現方法,該方法由D.Canright在《A Very Compact Rijndael S-box》一文中提出,是分組密碼bitslice實現、受限資源算法硬體實現和一些掩碼方案的基礎。

是的,你沒看錯。本文要講一下如何實現 AES 和 SM4 的 S 盒實現。你可能好奇,S 盒實現有什麼好講的,c 語言一個unsigned int Sbox[256] = {...},verilog  一個always case xxx:解決問題。沒錯,查表實現是S盒最基本的實現方法。高端一點的查表,可以將 S 盒的實現結合線性變換(AES 的 MixColumn,SM4 的 L)形成8→32的大表 T-Table 進行加速,例如openssl的查表實現。

其實,我們本文將探討一種不通過查表,只是通過邏輯運算的 S 盒實現方法。

AES 和 SM4 的 S 盒都是由 GF(28) 有限域上的運算進行生成的。我們可以直接基於其實現方法,對 S 盒進行計算實現。在 AES 和 SM4 的 S 盒生成公式中,均設計在 GF(28) 的求逆運算,該運算比較耗時。有限域中求逆運算可以轉化冪運算,例如 AES 的 S 盒可以表達為:
S(x)=63+05x254+09x253+F9x251+25x247+01x223+B5x191+8Fx127.
該運算定義在GF(28)上,直接實現同樣較為複雜。

還有一種方法,是使用布爾函數對 S 盒進行表達,利用布爾函數進行實現。該方法其實可以看作GF(2)上的表達。On Deviations of the AES S-box when Represented as Vector Valued Boolean Function對 AES 的 S 盒進行了分析,得到其布爾函數表達式,例如,其中第0比特可表示為:

布爾函數非常複雜,直接利用布爾函數表達式也不是一個好的思路。

D.Canright在A Very Compact Rijndael S-box一文中,提出一種實現思路:基於複合域進行實現。文章提出該方法實現在資源有限情況下的該類 S 盒的實現方式,後該方法被用於構造掩碼實現(抵抗DPA攻擊)和bitslice實現上。本文將對這個方法進行介紹。

AES 和 SM4 的 S 盒生成都是基於GF(28)進行構造的,利用逆運算和仿射變換(affine)。仿射變換本身就能表示成邏輯運算,我們重點關注求逆運算。AES 和 SM4 的表達都是基於多項式基,以 AES 的有限域為例,假設A為多項式x8+x4+x3+x+1的根,即A8+A4+A3+A+1=0。那麼任何一個元素x可以表示為x=x7A7+x6A6+x5A5+x4A4+x3A3+x2A2+x1A+x0。這種做法是將GF(28)直接看作GF(2)的8次擴域。我們也可以不這麼看,將GF(28)看成GF(24)的2次擴域,GF(24)可以進一步看作GF(22)的2次擴域,再進一步GF(22)可以看作GF(2)的2次擴域。而GF(28)的求逆運算,可以通過數學表達式,轉換為GF(24)的求逆和一些乘、加操作。這些操作可以進一步向下轉化。下面我們詳細說明一下。

K=GF(qn)為GF(q)的n次擴域,β 為多項式的根,那麼多項式基為{1,β,β2,…,βn−1},任何一個元素x,可以表示為x=xn−1βn−1+…+x1β+x0,這也是AES 和 SM4 所採用的基表示方式。此外,除了多項式基以外,域的表達方式還可以使用正規基進行表達,正規基為{β,βq,βq2,…,βqn−1},正規基使用了多項式的全部根。

GF(28),可以看作GF(24)的2次擴域,也就是在GF(24)上尋找一個不可約二次多項式,r(y)=y2+τy+υ,其中,τ 和 υ 為 GF(24) 的元素。設 Y 為 r(y) 的根,則 GF(28) 元素的多項式基為 Y,1,正規基為Y,Y16。Canright在文章中討論了多項式基和正規基兩種方式,我們這裡只看正規基。對於GF(28)的元素 g=γ1Y16+γ0Y,求逆 d=δ1Y16+δ0Y,γi 和 δi 都是GF(24)的元素, gd=1,待定係數求解,可得出

{
  δ1=[γ1γ0τ2+(γ21+γ20)υ]−1γ0δ0=[γ1γ0τ2+(γ21+γ20)υ]−1γ1

文內有詳細推導方法,不再贅述。觀察係數,其達到的效果就是,GF(28)的求逆運算,轉化成為GF(24)的乘法、平方和求逆,特別的,可以選擇不可約多項式為r(y)=y2+y+υ,也就是 τ 取1來降低求解複雜度,這樣,對g=γ1Y16+γ0Y的求逆可簡化為如下圖:

同樣,GF(24)可以看作GF(22)的二次擴域,也就是在GF(22)尋找一個不可約二次多項式,s(z)=z2+Tz+N,設Z 為該多項式的根,取正規基{Z4,Z}。和GF(28)計算方法相同,可計算GF(24)元素υ=Γ1Z4+Γ0Z 的逆為δ=ΔZ4+ΔZ,其中,

也可以取T=1降低複雜度,那麼在GF(24)求逆運算如下圖所示:

在GF(28)求逆時,也涉及到了GF(24)的乘法。GF(24)的乘法υδ=(Γ1Z4+Γ0Z)(Δ1Z4+Δ0Z)可按照如下公式計算:

如下圖:

進一步,GF(22)可以看作GF(2)的二次擴域,在GF(2)上的不可約多項式只有t(ω)=ω2+ω+1,取正規基W2,W,則Γ=g1W2+g0W,逆為Δ=d1W2+d0W,其中,

GF(22)的乘法,ΓΔ=(g1W2+g0W)(d1W2+d0W),計算如下:

如下圖:

將GF(28)進行轉化,我們還有一些操作未介紹,包括 υγ2、NΓ2 和 NΓ。這些值可通過選擇不同的 υ 和 N 進行簡化。文章詳細討論了選取的方法。我們直接給結論:

對於GF(22),不可約多項式為t(ω)=ω2+ω+1,正規基{W2,W}

對於GF(24)/GF(22),不可約多項式為s(z)=z2+z+N,N=W2,正規基Z4,Z,N(g1W2+g2W)2=W2(g1W2+g2W)=g1W2+(g1+g0)W

對於GF(28)/GF(24),不可約多項式為r(y)=y2+y+υ,υ=N2Z,如此,υ(AZ4+BZ)2=(A+B)2Z4+N2B2

複合域下,實際上是以


表示GF(28)的一個元素。
而 S 盒的輸入是以多項式基表示進行輸入的。要利用複合域進行運算,需要將輸入表示進行轉換。以線性空間的角度看,這複合域表示相當於是給GF(28)找了一組新基。兩組基有如下關係:

找到w2z4y16等在多項式基下的表示,形成矩陣X:

計算X−1,乘以多項式基下的表示即可得到複合域基下的表示。S盒計算完成後,再進行反變換即可。

AES的S盒是定義在GF(28)(不可約多項式x8+x4+x3+x+1),其表達式為S(x)=Ax−1+c,具體如下:

求 X 和 X−1,我們需要計算 w,z 和 y,計算 w2z4y16等一系列係數值。Canright在文章中給出了 GF(28) 生成元 B 的 對數表,方便計算。這裡我們直接通過搜索進行計算。

from pyfinite import ffield

gen = 0b100011011
F = ffield.FField(8, gen, useLUT=0) # 這裡一定要寫useLUT=0,不然會出問題。。。

def field_pow2(x, F): #計算在F域上的平方
return F.Multiply(x, x)

def field_pow3(x, F): #計算在F域上的三次方
return F.Multiply(x, field_pow2(x, F))

def field_pow4(x, F): #計算在F域上的四次方
return field_pow2(field_pow2(x, F), F)

首先,搜索GF(22)的正規基{W2,W},我們求出其在GF(28)下多項式基的表示。

for i in range(256):
if field_pow2(i, F)^i^1 == 0: # 搜索 w^2+w+1 = 0的根
print(hex(i))

我們可得到,W=0xbd,W2=0xbc(一定要注意,這是GF(28)的多項式基表示)

2. 然後,搜索GF(24)/GF(22)的正規基Z4,Z,我們求出其在GF(28)下多項式基的表示。s(z)=z2+z+N,N=W2=0xbc

for i in range(256):
if field_pow2(i, F)^i^0xbc == 0: # 搜索 z^2+z+0xbc = 0的根
print(hex(i))

於是我們又得到,Z=0x5c,Z4=0x5d

3. 最後,搜索GF(28)/GF(24)的正規基{Y16,Y},我們求出其在GF(28)下多項式基的表示。r(y)=y2+y+υ,υ=N2Z

u = F.Multiply(field_pow2(0xbc, F), 0x5c)
for i in range(256):
if field_pow2(i, F)^i^0xec == 0: # 搜索 z^2+z+0xbc = 0的根
print(hex(i))

於是我們又得到,Y=0xff,Y16=0xfe

w = 0xbd
w_2 = 0xbc
z = 0x5c
z_4 = 0x5d
y = 0xff
y_16 = 0xfe
w_2_z_4_y_16 = F.Multiply(F.Multiply(w_2, z_4), y_16)
w_z_4_y_16 = F.Multiply(F.Multiply(w, z_4), y_16)
w_2_z_y_16 = F.Multiply(F.Multiply(w_2, z), y_16)
w_z_y_16 = F.Multiply(F.Multiply(w, z), y_16)
w_2_z_4_y = F.Multiply(F.Multiply(w_2, z_4), y)
w_z_4_y = F.Multiply(F.Multiply(w, z_4), y)
w_2_z_y = F.Multiply(F.Multiply(w_2, z), y)
w_z_y = F.Multiply(F.Multiply(w, z), y)
print('w_2_z_4_y_16\t', hex(w_2_z_4_y_16))
print('w_z_4_y_16\t', hex(w_z_4_y_16))
print('w_2_z_y_16\t', hex(w_2_z_y_16))
print('w_z_y_16\t', hex(w_z_y_16))
print('w_2_z_4_y\t', hex(w_2_z_4_y))
print('w_z_4_y\t\t', hex(w_z_4_y))
print('w_2_z_y\t\t', hex(w_2_z_y))
print('w_z_y\t\t', hex(w_z_y))

得到多項式基在複合域基下表示如下:

求X−1,可得到複合域基下多項式基的表示:

from pyfinite import genericmatrix

XOR = lambda x,y: x^y
AND = lambda x,y: x&y
DIV = lambda x,y: x
m = genericmatrix.GenericMatrix(size=(8, 8),zeroElement=0,identityElement=1,add=XOR,mul=AND,sub=XOR,div=DIV)

m.SetRow(0, [0, 0, 0, 1, 0, 0, 1, 0])
m.SetRow(1, [1, 1, 1, 0, 1, 0, 1, 1])
m.SetRow(2, [1, 1, 1, 0, 1, 1, 0, 1])
m.SetRow(3, [0, 1, 0, 0, 0, 0, 1, 0])
m.SetRow(4, [0, 1, 1, 1, 1, 1, 1, 0])
m.SetRow(5, [1, 0, 1, 1, 0, 0, 1, 0])
m.SetRow(6, [0, 0, 1, 0, 0, 0, 1, 0])
m.SetRow(7, [0, 0, 0, 0, 0, 1, 0, 0])
print(m)

print(m.Inverse())

基礎函數定義

g2b = [0b10011000, 0b11110011, 0b11110010, 0b01001000, 0b00001001, 0b10000001, 0b10101001, 0b11111111]
b2g = [0b01100100, 0b01111000, 0b01101110, 0b10001100, 0b01101000, 0b00101001, 0b11011110, 0b01100000]

def G4_mul(x, y):
'''
GF(2^2)的乘法運算,正規基{W^2, W}
'''
a = (x & 0x02)>>1
b = x & 0x01
c = (y & 0x02)>>1
d = y & 0x01
e = (a ^ b) & (c ^ d)
return (((a & c) ^ e) << 1)|((b & d) ^ e)

def G4_mul_N(x):
'''
GF(2^2)的乘N操作,N = W^2
'''
a = (x & 0x02)>>1
b = x & 0x01
p = b
q = a ^ b
return (p<<1)|q

def G4_mul_N2(x):
'''
GF(2^2)的乘N^2操作,N = W^2
'''
a = (x & 0x02)>>1
b = x & 0x01
return ((a ^ b)<<1)|a

def G4_inv(x):
'''
GF(2^2)的求逆操作,該操作和GF(2^2)的平方操作等價
'''
a = (x & 0x02)>>1
b = x & 0x01
return (b<<1)|a

def G16_mul(x, y):
'''
GF(2^4)的乘法操作,正規基{Z^4, Z}
'''
a = (x & 0xc)>>2
b = x & 0x03
c = (y & 0xc)>>2
d = y & 0x03
e = G4_mul(a ^ b, c ^ d)
e = G4_mul_N(e)
p = G4_mul(a, c) ^ e
q = G4_mul(b, d) ^ e
return (p<<2) | q

def G16_sq_mul_u(x):
'''
GF(2^4)的平方後乘u操作, u = N^2Z, N = W^2
'''
a = (x & 0xc)>>2
b = x & 0x03
p = G4_inv(a ^ b) # G4平方和求逆等價
q = G4_mul_N2(G4_inv(b))
return (p<<2)|q

def G16_inv(x):
'''
GF(2^4)的求逆操作
'''
a = (x & 0xc)>>2
b = x & 0x03
c = G4_mul_N(G4_inv(a ^ b))
d = G4_mul(a, b)
e = G4_inv(c ^ d)
p = G4_mul(e, b)
q = G4_mul(e, a)
return (p<<2)|q

def G256_inv(x):
'''
GF(2^8)的求逆操作
'''
a = (x & 0xF0)>>4
b = x & 0x0F
c = G16_sq_mul_u(a ^ b)
d = G16_mul(a, b)
e = G16_inv(c ^ d)
p = G16_mul(e, b)
q = G16_mul(e, a)
return (p<<4)|q

def G256_new_basis(x, b):
'''
x在新基b下的表示
'''
y = 0
for i in range(8):
if x & (1<<(7-i)):
y ^= b[i]
return y

計算S盒輸出值

A = [0b10001111, 0b11000111, 0b11100011, 0b11110001, 0b11111000, 0b01111100, 0b00111110, 0b00011111] #仿射變換矩陣乘

def AES_SBOX(x):
t = G256_new_basis(x, g2b)
t = G256_inv(t)
t = G256_new_basis(t, b2g)
t = G256_new_basis(t, A) #仿射變換乘
return t ^ 0x63

sbox = []
for i in range(256):
sbox.append(AES_SBOX(i)) # 生成sbox

for i,s in enumerate(sbox):
print(f'%02x'%s,', ', end='')
if (i+1)%16==0:
print()

SM4 的 S 盒和 AES 不同, 定義在GF(28)採用的不可約多項式為x8+x7+x6+x5+x4+x2+1,生成方式為S(x)=A(Ax+c)−1+c,其中:

不可約多項式不同,X 矩陣也不相同。下面我們為 SM4 求 X 和 X−1,我們需要計算 w,z 和 y,計算 w2z4y16等一系列係數值

from pyfinite import ffield

gen = 0b111110101
F = ffield.FField(8, gen, useLUT=0) # 這裡一定要寫useLUT=0,不然會出問題。。。

首先,搜索GF(22)的正規基{W2,W},我們求出其在GF(28)下多項式基的表示。

for i in range(256):
if field_pow2(i, F)^i^1 == 0: # 搜索 w^2+w+1 = 0的根
print(hex(i))

我們得到,W=0x5d,W2=0x5c(一定要注意,這是GF(28)的多項式基表示)

然後,搜索GF(24)/GF(22)的正規基Z4,Z,我們求出其在GF(28)下多項式基的表示。s(z)=z2+z+N,N=W2=0x5c

for i in range(256):
if field_pow2(i, F)^i^0x5c == 0: # 搜索 z^2+z+0x5c = 0的根
print(hex(i))

於是我們又得到,Z=0x0c,Z4=0x0d

最後,搜索GF(28)/GF(24)的正規基Y16,Y,我們求出其在GF(28)下多項式基的表示。r(y)=y2+y+υ,υ=N2Z

u = F.Multiply(field_pow2(0x5c, F), 0x0c)
for i in range(256):
if field_pow2(i, F)^i^0x76 == 0: # 搜索 z^2+z+0x76 = 0的根
print(hex(i))

於是我們又得到,Y=0xef,Y16=0xee

w = 0x5d
w_2 = 0x5c
z = 0x0c
z_4 = 0x0d
y = 0xef
y_16 = 0xee
w_2_z_4_y_16 = F.Multiply(F.Multiply(w_2, z_4), y_16)
w_z_4_y_16 = F.Multiply(F.Multiply(w, z_4), y_16)
w_2_z_y_16 = F.Multiply(F.Multiply(w_2, z), y_16)
w_z_y_16 = F.Multiply(F.Multiply(w, z), y_16)
w_2_z_4_y = F.Multiply(F.Multiply(w_2, z_4), y)
w_z_4_y = F.Multiply(F.Multiply(w, z_4), y)
w_2_z_y = F.Multiply(F.Multiply(w_2, z), y)
w_z_y = F.Multiply(F.Multiply(w, z), y)

print('w_2_z_4_y_16\t', hex(w_2_z_4_y_16))
print('w_z_4_y_16\t', hex(w_z_4_y_16))
print('w_2_z_y_16\t', hex(w_2_z_y_16))
print('w_z_y_16\t', hex(w_z_y_16))
print('w_2_z_4_y\t', hex(w_2_z_4_y))
print('w_z_4_y\t\t', hex(w_z_4_y))
print('w_2_z_y\t\t', hex(w_2_z_y))
print('w_z_y\t\t', hex(w_z_y))

得到多項式基在複合域基下表示如下:

求X−1,可得到複合域基下多項式基的表示:

from pyfinite import genericmatrix

XOR = lambda x,y: x^y
AND = lambda x,y: x&y
DIV = lambda x,y: x
m = genericmatrix.GenericMatrix(size=(8, 8),zeroElement=0,identityElement=1,add=XOR,mul=AND,sub=XOR,div=DIV)

m.SetRow(0, [1, 1, 0, 1, 1, 1, 0, 1])
m.SetRow(1, [1, 1, 1, 0, 1, 1, 0, 1])
m.SetRow(2, [1, 1, 0, 1, 0, 0, 1, 0])
m.SetRow(3, [1, 0, 1, 0, 1, 0, 0, 1])
m.SetRow(4, [0, 1, 0, 0, 0, 0, 1, 0])
m.SetRow(5, [1, 1, 1, 0, 0, 1, 1, 1])
m.SetRow(6, [0, 0, 0, 1, 1, 1, 1, 0])
m.SetRow(7, [0, 0, 0, 0, 0, 1, 0, 0])
print(m)
print(m.Inverse())

基礎函數定義

SM4 和 AES 採用的複合域結構相同,其基礎函數也相同。僅定義X矩陣即可。

g2b = [0b00100001, 0b11010011, 0b10000001, 0b01001010, 0b10001010, 0b10111001, 0b10110000, 0b11111111]
b2g = [0xf4, 0xec, 0x54, 0xa2, 0xd2, 0xc7, 0x2e, 0xd4]

計算S盒輸出值

A = [0b11100101, 0b11110010, 0b01111001, 0b10111100, 0b01011110, 0b00101111, 0b10010111, 0b11001011]
def SM4_SBOX(x):
t = G256_new_basis(x, A)
t ^= 0xd3
t = G256_new_basis(t, g2b)
t = G256_inv(t)
t = G256_new_basis(t, b2g)
t = G256_new_basis(t, A) #仿射變換乘
return t ^ 0xd3

sbox = []
for i in range(256):
sbox.append(SM4_SBOX(i)) # 生成sbox

for i,s in enumerate(sbox):
print(f'%02x'%s,', ', end='')
if (i+1)%16==0:
print()

通過 AES 和 SM4 的 S 盒複合域實現,我們不難發現,在複合域上,AES 和 SM4 的求逆運算過程相同,而除此之外,其他操作都是線性的仿射變換。那麼我們能不能通過 AES 的 S 盒計算 SM4 的 S 盒輸出呢?也就是,

Ssm4(x)=L(Saes(Mx+C1))+C2,下面我們嘗試進行推導。

假設複合域求逆運算為f,則


由此得出:
Ssm4(x)=Asm4Xsm4f(X−1sm4(Asm4x+0xd3))+0xd3⇒Ssm4(x)=Asm4Xsm4X−1aesA−1aes(Saes(Xaes(X−1sm4(Asm4x+0xd3)))+0x63)+0xd3
由此可得出,

M=XaesX−1sm4Asm4C1=XaesX−1sm40xd3L=Asm4Xsm4X−1aesA−1aesC2=Asm4Xsm4X−1aesA−1aes0x63+0xd3

XOR = lambda x,y: x^y
AND = lambda x,y: x&y
DIV = lambda x,y: x
X_aes = genericmatrix.GenericMatrix(size=(8, 8),zeroElement=0,identityElement=1,add=XOR,mul=AND,sub=XOR,div=DIV)
X_sm4 = genericmatrix.GenericMatrix(size=(8, 8),zeroElement=0,identityElement=1,add=XOR,mul=AND,sub=XOR,div=DIV)
A_aes = genericmatrix.GenericMatrix(size=(8, 8),zeroElement=0,identityElement=1,add=XOR,mul=AND,sub=XOR,div=DIV)
A_sm4 = genericmatrix.GenericMatrix(size=(8, 8),zeroElement=0,identityElement=1,add=XOR,mul=AND,sub=XOR,div=DIV)
c_aes = genericmatrix.GenericMatrix(size=(8, 1),zeroElement=0,identityElement=1,add=XOR,mul=AND,sub=XOR,div=DIV)
c_sm4 = genericmatrix.GenericMatrix(size=(8, 1),zeroElement=0,identityElement=1,add=XOR,mul=AND,sub=XOR,div=DIV)

X_aes.SetRow(0, [0, 0, 0, 1, 0, 0, 1, 0])
X_aes.SetRow(1, [1, 1, 1, 0, 1, 0, 1, 1])
X_aes.SetRow(2, [1, 1, 1, 0, 1, 1, 0, 1])
X_aes.SetRow(3, [0, 1, 0, 0, 0, 0, 1, 0])
X_aes.SetRow(4, [0, 1, 1, 1, 1, 1, 1, 0])
X_aes.SetRow(5, [1, 0, 1, 1, 0, 0, 1, 0])
X_aes.SetRow(6, [0, 0, 1, 0, 0, 0, 1, 0])
X_aes.SetRow(7, [0, 0, 0, 0, 0, 1, 0, 0])
print(X_aes)

X_aes_inv = X_aes.Inverse()
X_aes_inv

X_sm4.SetRow(0, [1, 1, 0, 1, 1, 1, 0, 1])
X_sm4.SetRow(1, [1, 1, 1, 0, 1, 1, 0, 1])
X_sm4.SetRow(2, [1, 1, 0, 1, 0, 0, 1, 0])
X_sm4.SetRow(3, [1, 0, 1, 0, 1, 0, 0, 1])
X_sm4.SetRow(4, [0, 1, 0, 0, 0, 0, 1, 0])
X_sm4.SetRow(5, [1, 1, 1, 0, 0, 1, 1, 1])
X_sm4.SetRow(6, [0, 0, 0, 1, 1, 1, 1, 0])
X_sm4.SetRow(7, [0, 0, 0, 0, 0, 1, 0, 0])
print(X_sm4)

X_sm4_inv = X_sm4.Inverse()
X_sm4_inv

A_aes.SetRow(0, [1, 1, 1, 1, 1, 0, 0, 0])
A_aes.SetRow(1, [0, 1, 1, 1, 1, 1, 0, 0])
A_aes.SetRow(2, [0, 0, 1, 1, 1, 1, 1, 0])
A_aes.SetRow(3, [0, 0, 0, 1, 1, 1, 1, 1])
A_aes.SetRow(4, [1, 0, 0, 0, 1, 1, 1, 1])
A_aes.SetRow(5, [1, 1, 0, 0, 0, 1, 1, 1])
A_aes.SetRow(6, [1, 1, 1, 0, 0, 0, 1, 1])
A_aes.SetRow(7, [1, 1, 1, 1, 0, 0, 0, 1])
print(A_aes)

A_aes_inv = A_aes.Inverse()

A_sm4.SetRow(0, [1, 1, 0, 1, 0, 0, 1, 1])
A_sm4.SetRow(1, [1, 1, 1, 0, 1, 0, 0, 1])
A_sm4.SetRow(2, [1, 1, 1, 1, 0, 1, 0, 0])
A_sm4.SetRow(3, [0, 1, 1, 1, 1, 0, 1, 0])
A_sm4.SetRow(4, [0, 0, 1, 1, 1, 1, 0, 1])
A_sm4.SetRow(5, [1, 0, 0, 1, 1, 1, 1, 0])
A_sm4.SetRow(6, [0, 1, 0, 0, 1, 1, 1, 1])
A_sm4.SetRow(7, [1, 0, 1, 0, 0, 1, 1, 1])
print(A_sm4)

A_sm4_inv = A_sm4.Inverse()

M = X_aes*X_sm4_inv*A_sm4
print(M)

A = [0, 1, 1, 0, 0, 0, 1, 1]
for i in range(8):
c_aes.SetRow(i, [A[i]])
print(c_aes)

A = [1, 1, 0, 1, 0, 0, 1, 1]
for i in range(8):
c_sm4.SetRow(i, [A[i]])
print(c_sm4)

C1 = X_aes*(X_sm4_inv*c_sm4)
print(C1)

L = A_sm4*X_sm4*X_aes_inv*A_aes_inv
print(L)

因此,

可以進行程序驗證如下:

L = [0b10100101, 0b11001101, 0b11100000, 0b10100100, 0b10010100, 0b01100100, 0b10010000, 0b00001111]
M = [0b10101011, 0b01101100, 0b00110111, 0b10011000, 0b00111010, 0b11011111, 0b11001001, 0b01110101]
c1 = 0x69
c2 = 0x61

SBOX_AES = [0x63 , 0x7c , 0x77 , 0x7b , 0xf2 , 0x6b , 0x6f , 0xc5 , 0x30 , 0x01 , 0x67 , 0x2b , 0xfe , 0xd7 , 0xab , 0x76 ,
0xca , 0x82 , 0xc9 , 0x7d , 0xfa , 0x59 , 0x47 , 0xf0 , 0xad , 0xd4 , 0xa2 , 0xaf , 0x9c , 0xa4 , 0x72 , 0xc0 ,
0xb7 , 0xfd , 0x93 , 0x26 , 0x36 , 0x3f , 0xf7 , 0xcc , 0x34 , 0xa5 , 0xe5 , 0xf1 , 0x71 , 0xd8 , 0x31 , 0x15 ,
0x04 , 0xc7 , 0x23 , 0xc3 , 0x18 , 0x96 , 0x05 , 0x9a , 0x07 , 0x12 , 0x80 , 0xe2 , 0xeb , 0x27 , 0xb2 , 0x75 ,
0x09 , 0x83 , 0x2c , 0x1a , 0x1b , 0x6e , 0x5a , 0xa0 , 0x52 , 0x3b , 0xd6 , 0xb3 , 0x29 , 0xe3 , 0x2f , 0x84 ,
0x53 , 0xd1 , 0x00 , 0xed , 0x20 , 0xfc , 0xb1 , 0x5b , 0x6a , 0xcb , 0xbe , 0x39 , 0x4a , 0x4c , 0x58 , 0xcf ,
0xd0 , 0xef , 0xaa , 0xfb , 0x43 , 0x4d , 0x33 , 0x85 , 0x45 , 0xf9 , 0x02 , 0x7f , 0x50 , 0x3c , 0x9f , 0xa8 ,
0x51 , 0xa3 , 0x40 , 0x8f , 0x92 , 0x9d , 0x38 , 0xf5 , 0xbc , 0xb6 , 0xda , 0x21 , 0x10 , 0xff , 0xf3 , 0xd2 ,
0xcd , 0x0c , 0x13 , 0xec , 0x5f , 0x97 , 0x44 , 0x17 , 0xc4 , 0xa7 , 0x7e , 0x3d , 0x64 , 0x5d , 0x19 , 0x73 ,
0x60 , 0x81 , 0x4f , 0xdc , 0x22 , 0x2a , 0x90 , 0x88 , 0x46 , 0xee , 0xb8 , 0x14 , 0xde , 0x5e , 0x0b , 0xdb ,
0xe0 , 0x32 , 0x3a , 0x0a , 0x49 , 0x06 , 0x24 , 0x5c , 0xc2 , 0xd3 , 0xac , 0x62 , 0x91 , 0x95 , 0xe4 , 0x79 ,
0xe7 , 0xc8 , 0x37 , 0x6d , 0x8d , 0xd5 , 0x4e , 0xa9 , 0x6c , 0x56 , 0xf4 , 0xea , 0x65 , 0x7a , 0xae , 0x08 ,
0xba , 0x78 , 0x25 , 0x2e , 0x1c , 0xa6 , 0xb4 , 0xc6 , 0xe8 , 0xdd , 0x74 , 0x1f , 0x4b , 0xbd , 0x8b , 0x8a ,
0x70 , 0x3e , 0xb5 , 0x66 , 0x48 , 0x03 , 0xf6 , 0x0e , 0x61 , 0x35 , 0x57 , 0xb9 , 0x86 , 0xc1 , 0x1d , 0x9e ,
0xe1 , 0xf8 , 0x98 , 0x11 , 0x69 , 0xd9 , 0x8e , 0x94 , 0x9b , 0x1e , 0x87 , 0xe9 , 0xce , 0x55 , 0x28 , 0xdf ,
0x8c , 0xa1 , 0x89 , 0x0d , 0xbf , 0xe6 , 0x42 , 0x68 , 0x41 , 0x99 , 0x2d , 0x0f , 0xb0 , 0x54 , 0xbb , 0x16]

def SM4_SBOX_CALC_WITH_AES(x):
t = G256_new_basis(x, M)
t ^= c1
t = SBOX_AES[t]
t = G256_new_basis(t, L)
t ^= c2
return t

sbox = []
for i in range(256):
sbox.append(SM4_SBOX_CALC_WITH_AES(i)) # 生成sbox

for i,s in enumerate(sbox):
print(f'%02x'%s,', ', end='')
if (i+1)%16==0:
print()

對 AES 和 SM4 來說,我們都可以把仿射變換和基變換操作的矩陣乘結合起來,簡化對應的計算過程,從而減少運算。利用這一思想,我們可以對 AES 和 SM4 的 bit直接進行邏輯運算,避免查表操作。在硬體實現時,可利用該方法構造資源非常受限情況下的S盒實現。在軟體上,該方法在抵抗cache攻擊方面有效果,同時,我們可以使用bitslice並行技術進行加速。

此外,SM4 的 S 盒可由 AES 表示得出,這一點在 CPU 有 AES 的指令集時,可將 SM4 的 S 盒運算轉化為 AES 的 S 盒運算進行加速。

(點擊閱讀原文顯示文中公式)

 ** 休息時刻,輕鬆一下 ** 

紐創信安提供基於Python、Java、C開發的多種算法軟體庫,並提供通過GM/T 0028-2014《密碼模塊安全技術要求》認證的國產密碼算法軟體引擎SM2/SM3/SM4,為客戶量身訂製基於上述軟體引擎的系統級安全解決方案,並構建基於PUF硬體信任根的增強安全解決方案,有效的保護客戶的信息系統安全。聯繫我們 sales@osr-tech.com。

相關焦點

  • AES 和 SM4 S盒複合域實現方法
    AES 和 SM4 S 盒複合域實現方法導語本文介紹AES和SM4 S盒的複合域實現方法,該方法由D.Canright在《A Very Compact Rijndael S-box》一文中提出,是分組密碼bitslice實現、受限資源算法硬體實現和一些掩碼方案的基礎。是的,你沒看錯。
  • AES加密算法的詳細介紹【面試+工作】
    AES的整體結構如下圖所示,其中的W[0,3]是指W[0]、W[1]、W[2]和W[3]串聯組成的128位密鑰。加密的第1輪到第9輪的輪函數一樣,包括4個操作:字節代換、行位移、列混合和輪密鑰加。最後一輪迭代不執行列混合。另外,在第一輪迭代之前,先將明文和原始密鑰進行一次異或加密操作。
  • 基於webGL技術的3D庫ThingJS支持天空盒技術實現
    描述三維天空的技術有平面型天空(Sky Plane)、天空穹廬(Sky Dome)、天空盒(Sky Box)三種類型。基於webGL技術的3D庫ThingJS支持天空盒技術實現。引用地圖組件腳本之後地球相機參數就改變,需要校正天空盒。為什麼偏偏是天空盒呢?這就得問一下,天空盒的原理是什麼?
  • 網絡安全加密——DES、AES、RSA、Base64、MD5加密原理介紹,代碼實現
    乾貨分享之《網絡安全加密》,又和大家見面了。
  • 基於Verilog硬體描述語言的AES密碼算法實現
    目前,分組密碼算法AES以其高效率、低開銷、實現簡單等特點被廣泛應用於密碼模塊的研製。隨著計算機信息技術和超大規模集成電路技術的成熟與發展,通過硬體來實現密鑰模塊的內部運作,可保證在外界無密鑰的明文流動,能夠實現真正意義上的保密。此外,硬體實現還具有高速、高可靠性等特點。目前許多AES算法的硬體實現採用基於RAM查找表方式來實現算法中最關鍵的SubBytes部分。
  • 使用ggtree實現進化樹的可視化和注釋
    最簡單的方法是計算一下序列中不匹配的數目,稱之為hamming distance(通常用序列長度做歸一化),使用距離當然也可以應用層次聚類的方法。進化樹的構建最簡單的方法是非加權配對平均法(Unweighted Pair Group Method with Arithmetic Mean, UPGMA),這其實是使用average linkage的層次聚類。這種方法在進化樹推斷上現在基本沒人用。
  • 淺析AES加密算法的硬體設計方法
    The Art of Hardware Architecture: Design Methods and Techniques for Digital Circuits[M]. 李海東,來萍,師謙等譯. 北京:機械工業出版社,2014.2[3] Michael D Ciletti. Verilog HDL高級數字設計[M]. 張雅綺,譯.
  • Springcloud序之Springboot2x模塊化+rest assured+AES加解密實現
    本文主要使用Springboot進行多模塊項目的實現方式,並結合接口測試常用框架rest assured以及AES加解密來綜合講解多模塊項目的一些常用功能的實現。並作為後續Springcloud的序篇,後面我會以模塊化項目的方式來逐步實現Springcloud各個組件的講解與代碼演示,以期和大家一起對Springcloud常用功能有更深入的理解。
  • 百樂74sm與百樂92fm、寫樂長刀研nmf的對比評測
    其實這次是74sm分別和92fm、長刀nmf 的比較,92fm和長刀nmf之間就沒有對比性了。74sm和92fm比較,重點在於74多了這個s(soft),軟,那為什麼不是sfm和fm比較更容易知道嗎、因為fm尖我買在先,沒必要再買同樣筆畫粗細的,目的就是感受普通尖和加軟尖有什麼區別;74sm和長刀研nmf比較,緣於在網上看見評論說74sm比長刀研nmf還軟彈,於是非常好奇,綜合以上兩種原因就買了74sm。因為寫感是玄學,因人而異,所以以下評測只代表我個人感覺,僅供參考!
  • AES加密算法(一)
    且s-box是可逆的。verilog中使用查找表實現。把該字節的高4位作為行值,低4位作為列值,取出S盒或者逆S盒中對應的行的元素作為輸出。例如,加密時,輸出的字節S1為0x12,則查S盒的第0x01行和0x02列,得到值0xc9,然後替換S1原有的0x12為0xc9。
  • 用StackOverflow訪問數據實現主成分分析(PCA)
    演講的重點主要是我對於PCA的理解,而這篇文章中,我將主要介紹我是如何實現PCA的,以及我是如何製作演講中使用到的圖表的。0.00474## 8 1 mysql 0.000948## 9 1 svg 0.000948## 10 1 model-view-controller 0.000948## # ... with 28,791,653 more rows可以看出,數據很乾淨,每行只有用戶編號和技術標籤
  • 對稱加密及AES加密算法
    ) 4、AES加密的代碼 5、實際開發中使用AES加密需要注意的地方一、對稱加密1、什麼是對稱加密?(記住這個特點,實際使用是會用到的)4、對稱加密的兩大不足密鑰傳輸問題:如上所說,由於對稱加密的加密和解密使用的是同一個密鑰,所以對稱加密的安全性就不僅僅取決於加密算法本身的強度,更取決於密鑰是否被安全的保管,因此加密者如何把密鑰安全的傳遞到解密者手裡,就成了對稱加密面臨的關鍵問題。
  • 技術貼 | R語言:繪製基因組基因箭頭圖
    按geneE對齊 方法:make_alignment_dummies()dummies <- make_alignment_dummies(  example_genes,  aes(xmin = start, xmax = end, y = molecule,
  • some[sm]:特殊用法
    1.some(重讀[sm]可以用來跟 others,a或 enough作對比。2.some(重讀[sm])可與單數可數名詞連用,其含義為「未知的」,它常暗示缺乏興趣或蔑視。There must be some job Icould do.一定有什麼我能做的工作。
  • CRYPTO : AES加密
    在對稱密碼學中,加密和解密用的是同一個鑰匙,因此鑰匙需要保密。S盒在密碼學中,一個 S 盒 (Substitution-box,替換盒) 是對稱密鑰加密算法執行替換計算的基本結構。在塊密碼中,它們通常用於模糊密鑰與密文之間的關係。
  • 從決策樹到隨機森林:樹型算法的原理與實現
    它常使用 scikit 生成並實現決策樹: sklearn.tree.DecisionTreeClassifier 和 sklearn.tree.DecisionTreeRegressor 分別構建分類和回歸樹。CART 模型CART 模型包括選擇輸入變量和那些變量上的分割點,直到創建出適當的樹。
  • 用圖層疊加方法繪製環形進化樹
    前幾年的一款基於python開發的GraPhlan(Asnicar et al.2015),可以實現在環形進化樹外圈添加相關數據信息。但其支持的幾何圖層有限,而且一開始的配置文件對於大多數研究者都很難構建,其支持的樹文件格式也較少,支持的可視化進化樹的布局也只有circular。
  • 侯毅:盒馬機器人餐廳「Robot.HE」開業4個月實現盈虧平衡
    新零售大環境下,服裝、酒水和汽車零售都在升級。現在輪到了餐飲。   一個趨勢是,盒馬、京東等零售商們正在布局機器人餐廳,試圖讓吃飯這件事情的效率最大化。目前,盒馬機器人餐廳「Robot.HE」開業四個月已經實現盈虧平衡。此外,京東也於近日宣布將在今年8月落地第一家機器人餐廳。   以盒馬機器人餐廳為例。在前端,該餐廳已經實現遠程點餐。
  • OPLS-DA在R語言中的實現
    而 OPLS-DA(正交偏最小二乘判別分析)結合了正交信號和 PLS-DA 來篩選差異變量。下面的分析主要包含 PCA、PLS-DA 和 OPLS-DA。 [5] 3,4-Dihydroxybenzeneacetic acid                                                      [6] 3,5-dihydroxybenzoic acid/3,4-dihydroxybenzoic acid                                  [7] 4-Acetamidobutanoic