1.1 有限域上的四则运算
在密码学当中,有限域通常特指 G F ( 2 m ) GF(2^m) GF(2m) 域,因为这类域有较为良好的性质,便于复杂密码学算法的硬件实现。
1.1.1 有限域上的加减法
G F ( 2 m ) GF(2^m) GF(2m)域实质上由二元域扩张形成,因此域中元素的加减法符合实数域中的模2加减法,即 a + b ( m o d 2 ) a + b \pmod {2} a+b(mod2)。在模2加减法中, − 1 ≡ 1 ( m o d 2 ) -1 \equiv {1 \pmod {2}} −1≡1(mod2),因此减法于加法的结果相同。同时,可以观察到 0 + 0 ≡ 0 ( m o d 2 ) 0 + 0 \equiv {0 \pmod {2}} 0+0≡0(mod2), 1 + 0 ≡ 1 ( m o d 2 ) 1 + 0 \equiv {1 \pmod {2}} 1+0≡1(mod2), 1 + 1 ≡ 0 ( m o d 2 ) 1 + 1 \equiv {0 \pmod {2}} 1+1≡0(mod2),这与异或运算的结果相同。所以 G F ( 2 m ) GF(2^m) GF(2m) 域上的加减法等同于两数异或运算,即 a + b ( m o d 2 ) = a ⊕ b a + b \pmod {2} = a \oplus b a+b(mod2)=a⊕b。
1.1.2 有限域上的乘法
以AES算法常用的 G F ( 2 8 ) GF(2^8) GF(28) 域为例,域中任意元素均可由下表所示的一组数异或组合而成,该组数可以看作这个域的一个基。
0x01(0b00000001) 0x10(0b00010000)
0x02(0b00000010) 0x20(0b00010000)
0x04(0b00000100) 0x40(0b01000000)
0x08(0b00001000) 0x80(0b10000000)
取
G
F
(
2
8
)
GF(2^8)
GF(28) 域中的元素0x78和0x39,设
x
=
0
x
78
x = 0x78
x=0x78,
y
=
0
x
39
y = 0x39
y=0x39,不可约多项式
p
(
x
)
=
0
x
11
b
=
x
8
+
x
4
+
x
3
+
x
+
1
p(x) = 0x11b = x^8 + x^4 + x^3 + x + 1
p(x)=0x11b=x8+x4+x3+x+1 那么有
y
=
0
b
00111001
=
0
x
20
⊕
0
x
10
⊕
0
x
08
⊕
0
x
01
y = 0b00111001 = 0x20 \oplus 0x10 \oplus 0x08 \oplus 0x01
y=0b00111001=0x20⊕0x10⊕0x08⊕0x01,由有限域内的分配律可得:
x
×
y
=
x
×
(
0
x
20
⊕
0
x
10
⊕
0
x
08
⊕
0
x
01
)
(
m
o
d
0
x
11
b
)
=
(
x
×
0
x
20
(
m
o
d
0
x
11
b
)
)
⊕
(
x
×
0
x
10
(
m
o
d
0
x
11
b
)
)
⊕
(
x
×
0
x
08
(
m
o
d
0
x
11
b
)
)
⊕
(
x
×
0
x
01
(
m
o
d
0
x
11
b
)
)
\begin{aligned} x \times y =&\ x \times (0x20 \oplus 0x10 \oplus 0x08 \oplus 0x01) \pmod {0x11b} \\ =& \ (x \times 0x20 \pmod {0x11b}) \oplus \\& \ (x \times 0x10 \pmod {0x11b}) \oplus \\& \ (x \times 0x08 \pmod {0x11b}) \oplus \\& \ (x \times 0x01 \pmod {0x11b}) \end{aligned}
x×y== x×(0x20⊕0x10⊕0x08⊕0x01)(mod0x11b) (x×0x20(mod0x11b))⊕ (x×0x10(mod0x11b))⊕ (x×0x08(mod0x11b))⊕ (x×0x01(mod0x11b))
由此可知,若得到下表所示的一组关于
x
x
x 的数,则可以计算出
x
×
y
x \times y
x×y 的值。
x·0x01 (mod p(x)) x·0x10 (mod p(x))
x·0x02 (mod p(x)) x·0x20 (mod p(x))
x·0x04 (mod p(x)) x·0x40 (mod p(x))
x·0x08 (mod p(x)) x·0x80 (mod p(x))
上述过程的主要代码如下所示:
# 以GF(2^8)域为例
def get_multi(x, p):
x <<= 1
if x & 0x100 == 0x100:
x ^= p
return x & 0xff
def Multi(x, y, p):
result = 0
while y > 0:
if y & 1 == 1:
result ^= x
# x乘以2,同时进行越界取模不可约多项式处理
x = get_multi(x, p)
y >>= 1
return result
1.1.3 有限域上的除法
有限域上的除法运算实际上可看作对除法竖式的模拟。取 G F ( 2 8 ) GF(2^8) GF(28) 域中的元素0x78和0x09,设被除数 x = 0 x 78 x = 0x78 x=0x78,除数 y = 0 x 09 y = 0x09 y=0x09,则有如下图模拟过程:
设被除数 x x x 的二进制长度为 l e n 1 len_1 len1,除数 y y y 的二进制长度为 l e n 2 len_2 len2,则每次将 x x x 刷新为 x = x − ( y ≪ ( l e n 1 − l e n 2 ) ) ( m o d 2 ) = x ⊕ ( y ≪ ( l e n 1 − l e n 2 ) ) x = x - (y \ll (len_1 - len_2)) \pmod {2} = x \oplus { (y \ll (len_1 - len_2))} x=x−(y≪(len1−len2))(mod2)=x⊕(y≪(len1−len2)),直到 l e n 1 ≤ l e n 2 len_1 \leq {len_2} len1≤len2 为止。
上述过程的主要代码如下所示:
def Div(x, y):
len1, len2 = len(bin(x)), len(bin(y))
len_t = len1 - len2 + 1
if len_t < 1:
return 0, x
elif len_t == 1:
return 1, x ^ y
else:
ans = 0
while len1 >= len2:
x ^= y << (len1 - len2)
ans ^= 1 << (len1 - len2)
len1 = len(bin(x))
return ans, x #ans为商,x为余数
注:上述代码中的方法名与后文一致
1.2 Eucilid 算法
Eucilid算法又称辗转相除法,基于(1)式(Bezout等式),可以求出整数
a
a
a,
b
b
b的最大公因数、
a
a
a模
b
b
b的逆元
s
s
s和
b
b
b模
a
a
a的逆元
t
t
t。
s
a
+
t
b
=
g
c
d
(1)
sa + tb = gcd \tag{1}
sa+tb=gcd(1)
在下面的一系列运算中可以看到Eucilid算法的流程,设
a
≥
b
a\geq b
a≥b。第i轮带余除法的除数作为第i+1轮带余除法的被除数,第i轮带余除法的余数作为第i+1轮带余除法的除数,这就是辗转
的核心。
a
=
q
1
b
+
r
1
0
<
r
1
<
b
b
=
q
2
r
1
+
r
2
0
<
r
2
<
r
1
⋯
⋯
r
n
−
2
=
q
n
r
n
−
1
+
r
n
0
<
r
n
<
r
n
−
1
r
n
−
1
=
q
n
r
n
+
0
g
c
d
(
a
,
b
)
=
r
n
\begin{aligned} a &= q_1b + r_1 & 0 < &r_1 < b\\ b &= q_2r_1 + r_2 & 0 < &r_2 < r_1\\ &\cdots & & \cdots\\ r_{n-2} &= q_nr_{n-1} + r_{n} & 0 < &r_{n} < r_{n-1}\\ r_{n-1} &= q_nr_{n} + 0\\ gcd(a, b)&=r_{n} \end{aligned}
abrn−2rn−1gcd(a,b)=q1b+r1=q2r1+r2⋯=qnrn−1+rn=qnrn+0=rn0<0<0<r1<br2<r1⋯rn<rn−1
其主要代码如下所示:
#实数域
def euc_div(a, b):
if b == 0:
return 1, 0, a
x, y, gcd = euc_div(b, a % b)
x, y = y, (x - (a // b) * y)
return x, y, gcd
#GF(2^m域)
def euc_div(a, b, p):
if b == 0:
return 1, 0, a
div, rem = Div(a, b)
x, y, gcd = euc_div(b, rem, p)
x, y = y, x ^ Multi(div, y, p)
return x, y, gcd
1.3 快速幂取模算法
当幂和模数增大时,幂取模的运算复杂度呈指数倍增长,在幂和模数达到一定数量级(例如RSA算法中常用的1024bit)时,普通幂运算的运算效率远远低于所需效率,此时则需要更高效的幂取模运算。
快速幂取模运算核心思想在于把指数转化为二进制序列,将大量复杂的取模运算转化为少量的取模运算和大量简便的乘幂运算,提升运算效率也适合硬件实现。举个例子:
b
a
s
e
=
1234
,
p
o
w
e
r
=
17
=
(
10001
)
2
,
m
o
d
=
2048
123
4
17
=
123
4
1
×
2
0
×
123
4
0
×
2
1
×
123
4
0
×
2
2
×
123
4
0
×
2
3
×
123
4
1
×
2
4
=
123
4
2
0
×
1
×
1
×
1
×
123
4
2
4
=
(
123
4
0
)
2
×
1
×
1
×
1
×
(
123
4
4
)
2
123
4
17
(
m
o
d
2048
)
=
(
123
4
0
)
2
(
m
o
d
2048
)
×
(
123
4
4
)
2
(
m
o
d
2048
)
\begin{aligned} base &= 1234,\ power = 17 = (1 0001)_2,\ mod = 2048\\ \\ 1234^{17} &= 1234^{1 \times 2^0} \times 1234^{0 \times 2^1} \times 1234^{0 \times 2^2} \times 1234^{0 \times 2^3} \times 1234^{1 \times 2^4}\\ &= 1234^{2^0} \times 1 \times1 \times 1 \times 1234^{2^4}\\ &= (1234^{0})^2 \times 1 \times1 \times 1 \times (1234^{4})^2\\ \\ 1234^{17} &\pmod {2048} = (1234^{0})^2 \pmod {2048} \times (1234^{4})^2 \pmod {2048}\\ \end{aligned}
base123417123417=1234, power=17=(10001)2, mod=2048=12341×20×12340×21×12340×22×12340×23×12341×24=123420×1×1×1×123424=(12340)2×1×1×1×(12344)2(mod2048)=(12340)2(mod2048)×(12344)2(mod2048)
其主要代码如下所示:
#实数域
def quick_mod(base, power, mod):
ans = 1
while power > 0:
if power & 1 == 1:
ans = (ans * base) % mod
power >>= 1
base = (base * base) % mod
return ans
#GF(2^m域)
def quick_mod(base, power, mod):
ans = 1
while power > 0:
if power & 1 == 1:
ans = Multi(ans, base, mod)
power >>= 1
base = Multi(base, base, mod)
return ans
1.4 中国剩余定理
中国剩余定理(Chinese Remainder Theorem, CRT)可以将一个大整数M转化为若干个剩余类同构,如(2)式所示。
M
=
∏
i
=
1
k
m
i
(
m
i
互素
)
(2)
M = \prod_{i = 1} ^ {k} m_i \ \ (m_i互素) \tag{2}
M=i=1∏kmi (mi互素)(2)
中国剩余定理最广泛的应用是解同余方程组,例如《孙子算经》中一个经典问题:“今有物不知其数,三三数之剩二,五五数之剩三,七七数之剩二,问物几何?”这个问题可以表示成(3)式的方程组:
{
x
≡
2
(
m
o
d
3
)
x
≡
3
(
m
o
d
5
)
x
≡
2
(
m
o
d
7
)
(3)
\begin{cases} x \equiv {2 \pmod {3}} \\ x \equiv {3 \pmod {5}} \\ x \equiv {2 \pmod {7}} \end{cases} \tag{3}
⎩
⎨
⎧x≡2(mod3)x≡3(mod5)x≡2(mod7)(3)
式中
m
1
=
3
m_1 = 3
m1=3、
m
2
=
5
m_2 = 5
m2=5、
m
3
=
7
m_3 = 7
m3=7,
M
=
3
×
5
×
7
=
105
M = 3 \times 5 \times 7 = 105
M=3×5×7=105。则有(4)式:
{
M
1
=
M
m
1
=
35
M
1
−
1
=
M
1
(
m
o
d
m
1
)
=
2
M
2
=
M
m
2
=
21
M
2
−
1
=
M
2
(
m
o
d
m
2
)
=
1
M
3
=
M
m
3
=
15
M
3
−
1
=
M
3
(
m
o
d
m
3
)
=
1
(4)
\begin{cases} M_1 = \frac{M}{m_1} = 35 \ \ M_1^{-1} = M_1 \pmod {m_1} = 2\\ M_2 = \frac{M}{m_2} = 21 \ \ M_2^{-1} = M_2 \pmod {m_2} = 1\\ M_3 = \frac{M}{m_3} = 15 \ \ M_3^{-1} = M_3 \pmod {m_3} = 1 \end{cases} \tag{4}
⎩
⎨
⎧M1=m1M=35 M1−1=M1(modm1)=2M2=m2M=21 M2−1=M2(modm2)=1M3=m3M=15 M3−1=M3(modm3)=1(4)
由此可得方程式的解:
x
≡
a
1
M
1
M
1
−
1
+
a
2
M
2
M
2
−
1
+
a
3
M
3
M
3
−
1
(
m
o
d
M
)
≡
2
×
35
×
2
+
3
×
21
×
1
+
2
×
15
×
1
(
m
o
d
105
)
≡
233
(
m
o
d
105
)
=
23
\begin{aligned} x & \equiv a_1 M_1 M_1^{-1} + a_2 M_2 M_2^{-1} + a_3 M_3 M_3^{-1} \pmod {M} \\ & \equiv 2 \times 35 \times 2 + 3 \times 21 \times 1 + 2 \times 15 \times 1 \pmod {105} \\ & \equiv 233 \pmod {105} \\ &= 23 \end{aligned}
x≡a1M1M1−1+a2M2M2−1+a3M3M3−1(modM)≡2×35×2+3×21×1+2×15×1(mod105)≡233(mod105)=23
上述过程的主要代码如下所示:
def CRT(m, c):
M_sum, x = 1, 0
M_i, t_i = [], []
for num in m:
M_sum *= int(num)
for num in m:
M_i.append(M_sum//int(num))
t_i.append(euc_div(M_sum//int(num), int(num))[0])
for i in range(len(m)):
x += int(c[i]) * t_i[i] * M_i[i]
if x % M_sum > 0:
return x % M_sum
else:
return M_sum