🔥点击进入【硬件安全】社区,查看更多精彩内容🔥
📢 声明:
🥭 作者主页:【摆渡沧桑的CSDN主页】。
⚠️ 未经作者允许,禁止转载。
⚠️ 本文为非盈利性质,目的为个人学习记录及知识分享。因能力受限,存在知识点分析不正确的可能。若您参考本文造成了不良后果,本人不承担相关责任。
⚠️ 若本文所采用图片或相关引用侵犯了您的合法权益,请联系我进行删除。
😄 欢迎大家指出文章错误,欢迎同行与我交流 ~
@[toc]
一、AES S盒实现方法
关于复合域算法实现原理可以参考下面这篇博文:
AES、SM4的 S 盒有限域与复合域算法实现原理
1.1 实现方法
AES的S盒是定义在$GF(2^8)$(不可约多项式$x^8+x^4+x^3+x+1$),其表达式为
具体如下:
1.2 求矩阵X和逆
求 $X$ 和 $X^{-1}$,我们需要计算 $w$,$z$ 和 $y$,计算 $w^2z^4y^{16}$等一系列系数值。
Canright在文章中给出了 $GF(2^8)$ 生成元 $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(2^2)$的正规基${W^2, W}$,我们求出其在$GF(2^8)$下多项式基的表示。
for i in range(256):
if field_pow2(i, F)^i^1 == 0: # 搜索 w^2+w+1 = 0的根
print(hex(i))
我们可得到,$W = 0xbd$,$W^2 = 0xbc$(一定要注意,这是$GF(2^8)$的多项式基表示)
- 然后,搜索$GF(2^4)/GF(2^2)$的正规基${Z^4, Z}$,我们求出其在$GF(2^8)$下多项式基的表示。
for i in range(256): if field_pow2(i, F)^i^0xbc == 0: # 搜索 z^2+z+0xbc = 0的根 print(hex(i))
于是我们又得到,$Z = 0x5c$,$Z^4 = 0x5d$
- 最后,搜索$GF(2^8)/GF(2^4)$的正规基${Y^{16}, Y}$,我们求出其在$GF(2^8)$下多项式基的表示。
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$,$Y^{16} = 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())
1.3、具体函数实现
1.3.1 基础函数定义
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
1.3.2 计算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盒实现方法
2.1 实现方法
SM4 的 S 盒和 AES 不同, 定义在$GF(2^8)$采用的不可约多项式为
生成方式为
其中:
2.2 求矩阵X和逆
不可约多项式不同,$X$ 矩阵也不相同。下面我们为 SM4 求 $X$ 和 $X^{-1}$,我们需要计算 $w$,$z$ 和 $y$,计算 $w^2z^4y^{16}$等一系列系数值
from pyfinite import ffield
gen = 0b111110101
F = ffield.FField(8, gen, useLUT=0) # 这里一定要写useLUT=0,不然会出问题。。。
首先,搜索$GF(2^2)$的正规基${W^2, W}$,我们求出其在$GF(2^8)$下多项式基的表示。
for i in range(256):
if field_pow2(i, F)^i^1 == 0: # 搜索 w^2+w+1 = 0的根
print(hex(i))
我们得到,$W = 0x5d$,$W^2 = 0x5c$(一定要注意,这是$GF(2^8)$的多项式基表示)
然后,搜索$GF(2^4)/GF(2^2)$的正规基${Z^4, Z}$,我们求出其在$GF(2^8)$下多项式基的表示。
for i in range(256):
if field_pow2(i, F)^i^0x5c == 0: # 搜索 z^2+z+0x5c = 0的根
print(hex(i))
于是我们又得到,$Z = 0x0c$,$Z^4 = 0x0d$
最后,搜索$GF(2^8)/GF(2^4)$的正规基${Y^{16}, Y}$,我们求出其在$GF(2^8)$下多项式基的表示。
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$,$Y^{16} = 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())
2.3 具体函数实现
2.3.1 基础函数定义
SM4 和 AES 采用的复合域结构相同,其基础函数也相同。仅定义X矩阵即可。
g2b = [0b00100001, 0b11010011, 0b10000001, 0b01001010, 0b10001010, 0b10111001, 0b10110000, 0b11111111]
b2g = [0xf4, 0xec, 0x54, 0xa2, 0xd2, 0xc7, 0x2e, 0xd4]
2.3.2 计算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 盒输出呢?也就是,,下面我们尝试进行推导。假设复合域求逆运算为$f$,则:
由此得出:
由此可得出:
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 盒运算进行加速。
附录:AES 和 SM4 的 S 盒生成方法简介
AES S盒
原理
AES的S盒是定义在$GF(2^8)$(不可约多项式$x^8+x^4+x^3+x+1$),其表达式为$S(x) = Ax^{-1}+c$,具体如下:该表示是将一个字节(8 bits)看成$GF(2^8)$上的一个元素。将$GF(2^8)$看成向量空间,其上任何一个元素均可由该向量空间的一组基表示。在AES的定义使用多项式基:假设$A$为多项式$x^8+x^4+x^3+x+1$的根,即$A^8+A^4+A^3+A+1=0$。那么任何一个元素$x$可以表示为$x = x_7A^7+x_6A^6+x_5A^5+x_4A^4+x_3A^3+x_2A^2+x_1A+x_0$
生成
下面我们尝试利用pyfinite生成 AES 的 S 盒。
from pyfinite import ffield
gen = 0b100011011
F = ffield.FField(8, gen, useLUT=0) # 这里一定要写useLUT=0,不然会出问题。。。
A = [0b10001111, 0b11000111, 0b11100011, 0b11110001, 0b11111000, 0b01111100, 0b00111110, 0b00011111]
def aes_sbox_gen(x):
'''
输入x,输出S(x)
'''
x_inv = F.Inverse(x)
y = 0
for i, a in enumerate(A):
if(x_inv&(1<<(7-i))):
y ^= a # 若该bit为1,则异或相应列
return y^0x63
sbox = []
for i in range(256):
sbox.append(aes_sbox_gen(i)) # 生成sbox
SM4 S盒
生成
在SM4官方文档中,仅仅给出了S盒的定义。进行学术搜索,发现各个论文上对SM4 S盒的生成方法描述各有不同。比较靠谱的一篇描述为S-box Optimization for SM4 Algorithm,结合GMSSL中关于SM4 bitslice的实现sm4_bs.c,我们可以得出:SM4 S盒同样定义在$GF(2^8)$上。与AES有所不同,该$GF(2^8)$采用的不可约多项式为$x^8+x^7+x^6+x^5+x^4+x^2+1$,生成方式为$S(x) = A(Ax+c)^{-1}+c$,其中:SM4的S盒生成也是采用了多项式基的表示,同AES。
from pyfinite import ffield
gen = 0b111110101
F = ffield.FField(8, gen, useLUT=0) # 这里一定要写useLUT=0,不然会出问题。。。
A = [0b11100101, 0b11110010, 0b01111001, 0b10111100, 0b01011110, 0b00101111, 0b10010111, 0b11001011]
def sm4_sbox_gen(x):
'''
输入x,输出S(x)
'''
y = 0
for i, a in enumerate(A):
if(x&(1<<(7-i))):
y ^= a # 若该bit为1,则异或相应列, y=Ax
y ^= 0xd3
y_inv = F.Inverse(y) # (Ax+c)^(-1)
z = 0
for i, a in enumerate(A):
if(y_inv&(1<<(7-i))):
z ^= a # 若该bit为1,则异或相应列, z=A(Ax+c)^(-1)
return z^0xd3
sbox = []
for i in range(256):
sbox.append(sm4_sbox_gen(i)) # 生成sbox
🔥 精选往期 《硬件安全》系列文章🔥
【算法篇】
密码学之公钥密码体系(1):背包算法
密码学之公钥密码体系(2):RSA算法
密码学之公钥密码体系(3):ElGamal算法
密码学之公钥密码体系(4):Rabin公钥密码方案
密码学之对称加密体系(1):AES、SM4的 S 盒有限域与复合域算法实现原理
密码学之对称加密体系(2):AES、SM4的 S 盒具体算法的实现
【概述篇】
硬件安全技术——概述1-安全威胁和硬件安全技术
硬件安全技术——概述2-5G时代IoT环境下芯片安全风险与挑战
硬件安全技术——芯片安全设计技术1
硬件安全技术——芯片安全设计技术2
硬件安全技术——芯片安全设计技术3
硬件安全技术——芯片安全设计技术4(PUF)