数字问题
两个外观相近的问题具有不同的已知复杂度:因数分解 要求把 N N N 写成素因子乘积,尚无已知经典多项式时间算法;素性判定 只判断 N N N 是否为素数,已有多项式时间算法。AKS 算法在 2002 年首次给出了无条件、确定性的多项式时间素性判定方法。大整数分解的困难性与 RSA 等公钥密码系统的安全分析密切相关,后文还会给出更具体的 RSA 单向性假设。
数字的表示
计算机用二进制表示数。进制越大表示越短,但换底只差常数因子。
例如十进制的 1024 1024 1024 只写 4 位,二进制写作 10000000000 2 10000000000_2 1000000000 0 2 ,需要 11 位。两种记法的长度不同,但都与 log 1024 \log 1024 log 1024 成正比。
位数 :在 b b b 进制下表示 N ≥ 1 N\ge1 N ≥ 1 需 ⌊ log b N ⌋ + 1 = ⌈ log b ( N + 1 ) ⌉ \lfloor\log_bN\rfloor+1=\lceil \log_b(N+1)\rceil ⌊ log b N ⌋ + 1 = ⌈ log b ( N + 1 )⌉ 位;0 0 0 通常用一位表示。
换底公式 :log b N = log a N log a b \log_b N = \dfrac{\log_a N}{\log_a b} log b N = log a b log a N 。O O O 记号下底数无关,故数 N N N 的规模统一记 O ( log N ) O(\log N) O ( log N ) 。
数论算法的输入规模是位数 O ( log N ) O(\log N) O ( log N ) ,而非数值 N N N 本身。一个几百位的数,规模是几百,数值却是天文数字。
log N \log N log N 还可从多种角度理解:它是得到 N N N 所需的指数、把 N N N 连续减半到 1 的次数、N N N 的二进制位数,以及含 N N N 个结点的完全二叉树深度,以上说法只相差取整或常数因子。调和和 1 + 1 / 2 + ⋯ + 1 / N 1+1/2+\cdots+1/N 1 + 1/2 + ⋯ + 1/ N 也为 Θ ( log N ) \Theta(\log N) Θ ( log N ) 。
练习 1.31:计算 N ! = 1 ⋅ 2 ⋯ N N!=1\cdot2\cdots N N ! = 1 ⋅ 2 ⋯ N 。
考查输入数值与输入位数的区别、结果长度,以及大整数乘法的位复杂度。
(a) 若 N N N 是一个 n n n 位二进制数,N ! N! N ! 约需多少位?用 Θ \Theta Θ 表示。
取阶乘中最大的 ⌊ N / 2 ⌋ \lfloor N/2\rfloor ⌊ N /2 ⌋ 个因子,得到
( N 2 ) ⌊ N / 2 ⌋ ≤ N ! ≤ N N . \left(\frac N2\right)^{\lfloor N/2\rfloor}\le N!\le N^N.
( 2 N ) ⌊ N /2 ⌋ ≤ N ! ≤ N N .
log 2 ( N ! ) = Θ ( N log N ) . \log_2(N!)=\Theta(N\log N).
log 2 ( N !) = Θ ( N log N ) .
由于 2 n − 1 ≤ N < 2 n 2^{n-1}\le N<2^n 2 n − 1 ≤ N < 2 n ,所需位数为 ⌊ log 2 ( N ! ) ⌋ + 1 = Θ ( n 2 n ) \lfloor\log_2(N!)\rfloor+1=\Theta(n2^n) ⌊ log 2 ( N !)⌋ + 1 = Θ ( n 2 n ) 。输出本身就比输入指数级地长。
(b) 给出计算 N ! N! N ! 的算法并分析运行时间。
累乘过程的伪代码如下:
1 2 3 4 5 6 // 依次乘入所有因子,计算正整数 N 的阶乘。 function FACTORIAL(N): P ← 1 for k ← 2 to N: P ← P × k return P
令 P 1 = 1 P_1=1 P 1 = 1 ,按 P k = k P k − 1 P_k=kP_{k-1} P k = k P k − 1 (2 ≤ k ≤ N 2\le k\le N 2 ≤ k ≤ N )依次相乘,返回 P N P_N P N 。归纳可得 P k = k ! P_k=k! P k = k ! 。第 k k k 次乘法的两个数分别有 Θ ( k log k ) \Theta(k\log k) Θ ( k log k ) 位和 Θ ( log k ) \Theta(\log k) Θ ( log k ) 位;采用普通乘法,
T ( N ) = Θ ( ∑ k = 2 N k ( log k ) 2 ) . T(N)=\Theta\!\left(\sum_{k=2}^{N}k(\log k)^2\right).
T ( N ) = Θ ( k = 2 ∑ N k ( log k ) 2 ) .
T ( N ) = Θ ( N 2 ( log N ) 2 ) = Θ ( 4 n n 2 ) . T(N)=\Theta\!\left(N^2(\log N)^2\right)
=\Theta(4^n n^2).
T ( N ) = Θ ( N 2 ( log N ) 2 ) = Θ ( 4 n n 2 ) .
保存当前乘积需要 Θ ( N log N ) = Θ ( n 2 n ) \Theta(N\log N)=\Theta(n2^n) Θ ( N log N ) = Θ ( n 2 n ) 位空间。
加法
引理 :任意三个单位数的和最多是两位数。
这是加法算法的基石。它在任意进制 b ≥ 2 b \ge 2 b ≥ 2 都成立——三个最大单位数之和为 3 ( b − 1 ) ≤ b 2 − 1 3(b-1) \le b^2 - 1 3 ( b − 1 ) ≤ b 2 − 1 ,仍为两位数。二进制下三个单位比特之和最大为 3(即 11)。据此逐位相加、处理进位即可完成加法。
课件中的逐位例子是 110101 2 + 100011 2 = 1011000 2 110101_2+100011_2=1011000_2 11010 1 2 + 10001 1 2 = 101100 0 2 ,即 53 + 35 = 88 53+35=88 53 + 35 = 88 。每一列只需看两数的当前位与上一列进位,不必先转换成十进制。
复杂度 :两个 n n n 位数相加,和最多 n + 1 n+1 n + 1 位,每位常数时间算出,总时间 O ( n ) O(n) O ( n ) 。该算法最优 :读入两个 n n n 位数并写出答案就需 Ω ( n ) \Omega(n) Ω ( n ) 次操作,故加法为 Θ ( n ) \Theta(n) Θ ( n ) 。
CPU 一条指令能加 64 位内整数,但密码学常需处理几千位的数,此时必须回到逐位操作分析——即位复杂度 (对单个比特的基本操作次数)。
乘法与除法
竖式乘法 (grade-school)对两个 n n n 位数生成 n n n 行中间和,每行至多 2 n 2n 2 n 位,共 n n n 次 O ( n ) O(n) O ( n ) 的加法,总复杂度 O ( n 2 ) O(n^2) O ( n 2 ) 。
Quiz:一个 n n n 位整数乘以 2 的复杂度是多少?
二进制下乘以 2 等于末尾补一个 0 0 0 。若要显式写出 n + 1 n+1 n + 1 位结果,仅输出就需 Θ ( n ) \Theta(n) Θ ( n ) 时间;若只在固定字长寄存器上执行一次左移,指令数可以是常数。课件后续使用逐位操作的位复杂度,因此按 O ( n ) O(n) O ( n ) 计入乘法递归的单层工作。
Al Khwarizmi 乘法 。以 11 × 13 11 \times 13 11 × 13 为例:
第一个数(减半)
第二个数(加倍)
11
13
5
26
2
52
1
104
规则:第一个数不断减半(向下取整),第二个数不断加倍,直到第一个数降到 1;划掉第一个数为偶数的行;剩余第二个数求和。13 + 26 + 104 = 143 = 11 × 13 13 + 26 + 104 = 143 = 11 \times 13 13 + 26 + 104 = 143 = 11 × 13 。本质是左边求第二个数的二进制表示,右边是相应移位——减半对应右移,加倍对应左移,划偶数行即筛出二进制位为 1 的项。
递归乘法 MULTIPLY :
x ⋅ y = { 2 ( x ⋅ ⌊ y / 2 ⌋ ) y 是偶数 x + 2 ( x ⋅ ⌊ y / 2 ⌋ ) y 是奇数 x \cdot y =
\begin{cases}
2\left(x \cdot \lfloor y/2 \rfloor\right) & y \text{ 是偶数} \\
x + 2\left(x \cdot \lfloor y/2 \rfloor\right) & y \text{ 是奇数}
\end{cases}
x ⋅ y = { 2 ( x ⋅ ⌊ y /2 ⌋ ) x + 2 ( x ⋅ ⌊ y /2 ⌋ ) y 是偶数 y 是奇数
算法:MULTIPLY ( x , y ) 输入: 两个 n 位整数 x 和 y , y ≥ 0 if y = 0 then return 0 z = MULTIPLY ( x , ⌊ y / 2 ⌋ ) if y 是偶数 then return 2 z else return x + 2 z \begin{aligned}
&\begin{array}{l}
\hline
\textbf{算法:MULTIPLY}(x, y) \\[4pt]
\hline
\textbf{输入:}\ \text{两个 } n \text{ 位整数 } x \text{ 和 } y,\ y \ge 0 \\
\textbf{if}\ y = 0\ \textbf{then}\ \text{return}\ 0 \\
z = \text{MULTIPLY}(x, \lfloor y/2 \rfloor) \\
\textbf{if}\ y \text{ 是偶数}\ \textbf{then}\ \text{return}\ 2z \\
\textbf{else}\ \text{return}\ x + 2z \\
\hline
\end{array}&&
\end{aligned}
算法: MULTIPLY ( x , y ) 输入: 两个 n 位整数 x 和 y , y ≥ 0 if y = 0 then return 0 z = MULTIPLY ( x , ⌊ y /2 ⌋) if y 是偶数 then return 2 z else return x + 2 z
把乘数 y y y 的二进制逐位剥出——x ⋅ y = 2 ( x ⋅ ⌊ y / 2 ⌋ ) x \cdot y = 2(x \cdot \lfloor y/2 \rfloor) x ⋅ y = 2 ( x ⋅ ⌊ y /2 ⌋) (偶数)或 x + 2 ( x ⋅ ⌊ y / 2 ⌋ ) x + 2(x \cdot \lfloor y/2 \rfloor) x + 2 ( x ⋅ ⌊ y /2 ⌋) (奇数),递归到底后逐步回代。每次调用 y y y 减半,共 n n n 次递归;每次做常数次操作(右移、判奇偶、左移、可能一次 O ( n ) O(n) O ( n ) 加法),故总时间 O ( n 2 ) O(n^2) O ( n 2 ) 。分治乘法(Karatsuba)可进一步降到 O ( n 1.585 ) O(n^{1.585}) O ( n 1.585 ) 。
除法 同样用递归实现:
算法:DIVIDE ( x , y ) 输入: 两个 n 位整数 x 和 y , y ≥ 1 if x = 0 then return ( 0 , 0 ) ( q , r ) = DIVIDE ( ⌊ x / 2 ⌋ , y ) q = 2 q , r = 2 r if x 是奇数 then r = r + 1 if r ≥ y then r = r − y , q = q + 1 return ( q , r ) \begin{aligned}
&\begin{array}{l}
\hline
\textbf{算法:DIVIDE}(x, y) \\[4pt]
\hline
\textbf{输入:}\ \text{两个 } n \text{ 位整数 } x \text{ 和 } y,\ y \ge 1 \\
\textbf{if}\ x = 0\ \textbf{then}\ \text{return}(0, 0) \\
(q, r) = \text{DIVIDE}(\lfloor x/2 \rfloor, y) \\
q = 2q,\ r = 2r \\
\textbf{if}\ x \text{ 是奇数}\ \textbf{then}\ r = r + 1 \\
\textbf{if}\ r \ge y\ \textbf{then}\ r = r - y,\ q = q + 1 \\
\text{return}(q, r) \\
\hline
\end{array}&&
\end{aligned}
算法: DIVIDE ( x , y ) 输入: 两个 n 位整数 x 和 y , y ≥ 1 if x = 0 then return ( 0 , 0 ) ( q , r ) = DIVIDE (⌊ x /2 ⌋ , y ) q = 2 q , r = 2 r if x 是奇数 then r = r + 1 if r ≥ y then r = r − y , q = q + 1 return ( q , r )
逐位恢复商与余数。先递归求 ⌊ x / 2 ⌋ \lfloor x/2 \rfloor ⌊ x /2 ⌋ 的商余,再翻倍并“塞回”被移走的最低位(奇数则 r r r 加 1),最后若余数超界则减 y y y 、商加 1。
正确性可由递归不变量说明。设递归结果满足
⌊ x 2 ⌋ = q y + r , 0 ≤ r < y . \left\lfloor\frac x2\right\rfloor=qy+r,
\qquad 0\le r<y.
⌊ 2 x ⌋ = q y + r , 0 ≤ r < y .
翻倍并补回 x x x 的最低位 b = x m o d 2 b=x\bmod2 b = x mod 2 后,得到 x = ( 2 q ) y + ( 2 r + b ) x=(2q)y+(2r+b) x = ( 2 q ) y + ( 2 r + b ) ,且 0 ≤ 2 r + b < 2 y 0\le2r+b<2y 0 ≤ 2 r + b < 2 y 。因此至多减一次 y y y 就能使余数重新落入 [ 0 , y − 1 ] [0,y-1] [ 0 , y − 1 ] ,同时相应地把商加 1。递归深度为 O ( n ) O(n) O ( n ) ,每层比较、加减和移位最多处理 O ( n ) O(n) O ( n ) 位,故普通位运算模型下总时间为 O ( n 2 ) O(n^2) O ( n 2 ) ,递归栈为 O ( n ) O(n) O ( n ) 。
例如 DIVIDE( 13 , 3 ) (13,3) ( 13 , 3 ) 会先处理 13 → 6 → 3 → 1 → 0 13\to6\to3\to1\to0 13 → 6 → 3 → 1 → 0 ,再逐层补回二进制最低位,最终得到商 4 4 4 、余数 1 1 1 ,满足 13 = 4 ⋅ 3 + 1 13=4\cdot3+1 13 = 4 ⋅ 3 + 1 。
模运算
模运算 处理有限范围整数。x m o d N x \bmod N x mod N 是 x x x 除以 N N N 的余数:若 x = q N + r x = qN + r x = qN + r 且 0 ≤ r < N 0 \le r < N 0 ≤ r < N ,则 x m o d N = r x \bmod N = r x mod N = r 。x ≡ y ( m o d N ) x \equiv y \pmod N x ≡ y ( mod N ) (同余)指两者相差 N N N 的整数倍,即 N ∣ ( x − y ) N \mid (x - y) N ∣ ( x − y ) 。模运算有两种理解:限制范围(越界回绕,如钟表),或把整数划分为 N N N 个等价类 { i + k N ∣ k ∈ Z } \{i + kN \mid k \in \mathbb{Z}\} { i + k N ∣ k ∈ Z } 。
模运算的典型例子是补码 :n n n 位补码表示 [ − 2 n − 1 , 2 n − 1 − 1 ] [-2^{n-1}, 2^{n-1}-1] [ − 2 n − 1 , 2 n − 1 − 1 ] ,非负数用普通二进制(首位 0);负数 − x -x − x 先写出正数 x x x 的 n n n 位二进制,再逐位取反并加 1(首位 1)。例如 8 位的 5 5 5 是 00000101 00000101 00000101 ,取反加 1 得 11111011 11111011 11111011 ,它作为无符号数是 251 251 251 ,而 251 ≡ − 5 ( m o d 256 ) 251\equiv-5\pmod{256} 251 ≡ − 5 ( mod 256 ) 。由此可见,补码加法与模 2 8 2^8 2 8 加法使用相同的比特运算。
替换规则 :若 x ≡ x ′ ( m o d N ) x \equiv x' \pmod N x ≡ x ′ ( mod N ) 且 y ≡ y ′ ( m o d N ) y \equiv y' \pmod N y ≡ y ′ ( mod N ) ,则
x + y ≡ x ′ + y ′ ( m o d N ) , x y ≡ x ′ y ′ ( m o d N ) . \begin{aligned}
x+y&\equiv x'+y'\pmod N,\\
xy&\equiv x'y'\pmod N.
\end{aligned}
x + y x y ≡ x ′ + y ′ ( mod N ) , ≡ x ′ y ′ ( mod N ) .
另有结合律、交换律、分配律。核心结论:任意中间步骤都可归约到模 N N N 的余数 ,使每次归约后的数都落在 [ 0 , N − 1 ] [0,N-1] [ 0 , N − 1 ] 。
例如利用 2 5 = 32 ≡ 1 ( m o d 31 ) 2^5=32\equiv1\pmod{31} 2 5 = 32 ≡ 1 ( mod 31 ) ,可直接化简
2 345 = ( 2 5 ) 69 ≡ 32 69 ≡ 1 69 ≡ 1 ( m o d 31 ) . 2^{345}=(2^5)^{69}\equiv32^{69}\equiv1^{69}\equiv1\pmod{31}.
2 345 = ( 2 5 ) 69 ≡ 3 2 69 ≡ 1 69 ≡ 1 ( mod 31 ) .
三种模运算的复杂度:模加法 x , y ∈ [ 0 , N − 1 ] x, y \in [0, N-1] x , y ∈ [ 0 , N − 1 ] ,和超界减 N N N 即可,O ( n ) O(n) O ( n ) ;模乘法 乘积最大 ( N − 1 ) 2 (N-1)^2 ( N − 1 ) 2 (约 2 n 2n 2 n 位),乘后取余即一次除法,O ( n 2 ) O(n^2) O ( n 2 ) ;模除法 仅当除数与 N N N 互质时合法,可在 O ( n 3 ) O(n^3) O ( n 3 ) 完成(见后)。
模幂
密码系统中需计算 x y ( m o d N ) x^y \pmod N x y ( mod N ) ,其中 x , y , N x, y, N x , y , N 均几百位。结果只几百位,但 x y x^y x y 可能上千万位(x , y x, y x , y 仅 20 位时)。朴素法反复乘 x x x 并取余需 y y y 次乘法,y y y 有 500 位时不可行。
快速幂(反复平方) :从 x x x 出发反复平方:
x m o d N → x 2 m o d N → x 4 m o d N → x 8 m o d N → ⋯ → x 2 ⌊ log y ⌋ m o d N x \bmod N \to x^2 \bmod N \to x^4 \bmod N \to x^8 \bmod N \to \cdots \to x^{2^{\lfloor \log y \rfloor}} \bmod N
x mod N → x 2 mod N → x 4 mod N → x 8 mod N → ⋯ → x 2 ⌊ l o g y ⌋ mod N
每步 O ( log 2 N ) O(\log^2 N) O ( log 2 N ) ,共 log y \log y log y 次乘法。求 x y x^y x y 只需把 y y y 二进制中为 1 的幂相乘:x 25 = x 11001 2 = x 16 ⋅ x 8 ⋅ x 1 x^{25} = x^{11001_2} = x^{16} \cdot x^8 \cdot x^1 x 25 = x 1100 1 2 = x 16 ⋅ x 8 ⋅ x 1 。递归形式:
x y m o d N = { ( x ⌊ y / 2 ⌋ ) 2 m o d N y 是偶数 x ( x ⌊ y / 2 ⌋ ) 2 m o d N y 是奇数 x^y \bmod N =
\begin{cases}
\left(x^{\lfloor y/2 \rfloor}\right)^2 \bmod N & y \text{ 是偶数} \\
x \left(x^{\lfloor y/2 \rfloor}\right)^2 \bmod N & y \text{ 是奇数}
\end{cases}
x y mod N = { ( x ⌊ y /2 ⌋ ) 2 mod N x ( x ⌊ y /2 ⌋ ) 2 mod N y 是偶数 y 是奇数
算法:MODEXP ( x , y , N ) 输入: 两个 n 位整数 x , N , N ≥ 2 ; 非负整数指数 y if y = 0 then return 1 z = MODEXP ( x , ⌊ y / 2 ⌋ , N ) if y 是偶数 then return z 2 m o d N else return x ⋅ z 2 m o d N \begin{aligned}
&\begin{array}{l}
\hline
\textbf{算法:MODEXP}(x, y, N) \\[4pt]
\hline
\textbf{输入:}\ \text{两个 } n \text{ 位整数 } x,N,\ N\ge2;\ \text{非负整数指数 } y \\
\textbf{if}\ y = 0\ \textbf{then}\ \text{return}\ 1 \\
z = \text{MODEXP}(x, \lfloor y/2 \rfloor, N) \\
\textbf{if}\ y \text{ 是偶数}\ \textbf{then}\ \text{return}\ z^2 \bmod N \\
\textbf{else}\ \text{return}\ x \cdot z^2 \bmod N \\
\hline
\end{array}&&
\end{aligned}
算法: MODEXP ( x , y , N ) 输入: 两个 n 位整数 x , N , N ≥ 2 ; 非负整数指数 y if y = 0 then return 1 z = MODEXP ( x , ⌊ y /2 ⌋ , N ) if y 是偶数 then return z 2 mod N else return x ⋅ z 2 mod N
与递归乘法同构,都是“减半后平方/倍乘”——把指数 y y y 的二进制逐位剥出,y y y 偶则 x y = ( x y / 2 ) 2 x^y = (x^{y/2})^2 x y = ( x y /2 ) 2 ,奇则 x y = x ( x y / 2 ) 2 x^y = x(x^{y/2})^2 x y = x ( x y /2 ) 2 。若 y y y 有 m m m 位,就递归 O ( m ) O(m) O ( m ) 层,每层进行常数次 n n n 位模乘,总时间为 O ( m n 2 ) O(mn^2) O ( m n 2 ) ;当指数也至多 n n n 位时,得到课件给出的 O ( n 3 ) O(n^3) O ( n 3 ) 。未经取模的 x y x^y x y 可能有 Θ ( y log x ) \Theta(y\log x) Θ ( y log x ) 位,快速幂只需处理指数的 Θ ( log y ) \Theta(\log y) Θ ( log y ) 个二进制位。
练习 1.14:怎样高效计算第 n n n 个斐波那契数 F n F_n F n 模整数 p p p 的余数?提示使用矩阵方法。
本题考查第一讲的斐波那契递推、模运算替换规则,以及本节的二进制快速幂。令
A = ( 0 1 1 1 ) . A=\begin{pmatrix}0&1\\1&1\end{pmatrix}.
A = ( 0 1 1 1 ) .
A n ( 0 1 ) = ( F n F n + 1 ) . A^n\begin{pmatrix}0\\1\end{pmatrix}
=\begin{pmatrix}F_n\\F_{n+1}\end{pmatrix}.
A n ( 0 1 ) = ( F n F n + 1 ) .
n = 0 n=0 n = 0 时等式成立;若在 n n n 时成立,左乘 A A A 就得到下一项,因此归纳可证。于是只需计算 A n m o d p A^n\bmod p A n mod p ,再取其与 ( 0 , 1 ) T (0,1)^T ( 0 , 1 ) T 乘积的第一项。若 p = 1 p=1 p = 1 ,答案直接为 0 0 0 。
当 p ≥ 2 p\ge2 p ≥ 2 时,初始化 R = I R=I R = I 、B = A m o d p B=A\bmod p B = A mod p 、e = n e=n e = n 。每轮若 e e e 为奇数,先令 R ← R B m o d p R\leftarrow RB\bmod p R ← RB mod p ;随后令 B ← B 2 m o d p B\leftarrow B^2\bmod p B ← B 2 mod p 、e ← ⌊ e / 2 ⌋ e\leftarrow\lfloor e/2\rfloor e ← ⌊ e /2 ⌋ 。不变量是 R B e ≡ A n ( m o d p ) RB^e\equiv A^n\pmod p R B e ≡ A n ( mod p ) ,因此循环结束时 R ≡ A n ( m o d p ) R\equiv A^n\pmod p R ≡ A n ( mod p ) 。
伪代码如下,矩阵下标从 1 1 1 开始;乘法为矩阵乘法,取模作用于每个元素。由于 R ( 0 , 1 ) T R(0,1)^T R ( 0 , 1 ) T 的第一项为 R [ 1 , 2 ] R[1,2] R [ 1 , 2 ] ,可直接返回该元素。
1 2 3 4 5 6 7 8 9 10 11 12 13 // 用矩阵快速幂计算 F_n mod p;输入 n ≥ 0,p ≥ 1。 function FIBONACCI-MOD(n, p): if p = 1: return 0 R ← [[1, 0], [0, 1]] B ← [[0, 1], [1, 1]] e ← n while e > 0: if e mod 2 = 1: R ← (R × B) mod p B ← (B × B) mod p e ← floor(e / 2) return R[1, 2]
每轮处理指数的一位,执行 O ( log ( n + 2 ) ) O(\log(n+2)) O ( log ( n + 2 )) 轮。矩阵规模固定,元素均可约到 [ 0 , p − 1 ] [0,p-1] [ 0 , p − 1 ] ,用普通乘法时位复杂度为 O ( log ( n + 2 ) ( log p ) 2 ) O\!\left(\log(n+2)(\log p)^2\right) O ( log ( n + 2 ) ( log p ) 2 ) 。
欧几里得算法
问题 :求 gcd ( x , y ) \gcd(x, y) g cd( x , y ) 。
欧几里得规则 :若 x , y x, y x , y 是正整数且 x ≥ y x \ge y x ≥ y ,则
gcd ( x , y ) = gcd ( x m o d y , y ) \gcd(x, y) = \gcd(x \bmod y, y)
g cd( x , y ) = g cd( x mod y , y )
证明 :只需证 gcd ( x , y ) = gcd ( x − y , y ) \gcd(x, y) = \gcd(x - y, y) g cd( x , y ) = g cd( x − y , y ) (x m o d y x \bmod y x mod y 是 x x x 反复减 y y y 的结果)。任何同时整除 x x x 和 y y y 的数也整除 x − y x - y x − y ,反之亦然,故两边公约数集合相同,最大公约数相等。
算法:EUCLID ( x , y ) 输入: 两个整数 x 和 y , x ≥ y ≥ 0 if y = 0 then return x return EUCLID ( y , x m o d y ) \begin{aligned}
&\begin{array}{l}
\hline
\textbf{算法:EUCLID}(x, y) \\[4pt]
\hline
\textbf{输入:}\ \text{两个整数 } x \text{ 和 } y \text{,} x \ge y \ge 0 \\
\textbf{if}\ y = 0\ \textbf{then}\ \text{return}\ x \\
\text{return}\ \text{EUCLID}(y, x \bmod y) \\
\hline
\end{array}&&
\end{aligned}
算法: EUCLID ( x , y ) 输入: 两个整数 x 和 y , x ≥ y ≥ 0 if y = 0 then return x return EUCLID ( y , x mod y )
不断用"取余"替换较大的数,直到 y = 0 y = 0 y = 0 时返回 x x x ,每一步都缩小规模并收敛到 gcd。复杂度依赖关键引理:
引理 :若 a ≥ b > 0 a \ge b > 0 a ≥ b > 0 ,则 a m o d b < a / 2 a \bmod b < a/2 a mod b < a /2 。
证明 :若 b ≤ a / 2 b \le a/2 b ≤ a /2 ,则 a m o d b < b ≤ a / 2 a \bmod b < b \le a/2 a mod b < b ≤ a /2 ;若 b > a / 2 b > a/2 b > a /2 ,则 a m o d b = a − b < a / 2 a \bmod b = a - b < a/2 a mod b = a − b < a /2 。两种情况均成立。
由此每连续两轮参数至少减半一次 ,即长度至少缩一位。初始 n n n 位整数,2 n 2n 2 n 次递归内到达基例;每次调用做一次 O ( n 2 ) O(n^2) O ( n 2 ) 除法,故总时间 O ( n 3 ) O(n^3) O ( n 3 ) 。
扩展欧几里得算法 :如何验证 d d d 是 gcd ( x , y ) \gcd(x, y) g cd( x , y ) ?仅验证 d d d 整除 x , y x, y x , y 不够(d d d 可能只是某个公约数)。
引理 :若 d d d 同时整除 x x x 和 y y y ,且 d = a x + b y d = ax + by d = a x + b y 对某整数 a , b a, b a , b 成立,则 d = gcd ( x , y ) d = \gcd(x, y) d = g cd( x , y ) 。
证明 :d d d 是公约数,故 d ≤ gcd ( x , y ) d \le \gcd(x, y) d ≤ g cd( x , y ) ;反过来 gcd ( x , y ) \gcd(x, y) g cd( x , y ) 整除 x , y x, y x , y ,也整除 a x + b y = d ax + by = d a x + b y = d ,故 gcd ( x , y ) ≤ d \gcd(x, y) \le d g cd( x , y ) ≤ d 。两边夹逼得 d = gcd ( x , y ) d = \gcd(x, y) d = g cd( x , y ) 。
故若能找到 a , b a, b a , b 使 d = a x + b y d = ax + by d = a x + b y ,即得到 gcd:
算法:EXTENDED-EUCLID ( x , y ) 输入: 两个整数 x 和 y , x ≥ y ≥ 0 if y = 0 then return ( 1 , 0 , x ) ( x ′ , y ′ , d ) = EXTENDED-EUCLID ( y , x m o d y ) return ( y ′ , x ′ − ⌊ x / y ⌋ y ′ , d ) \begin{aligned}
&\begin{array}{l}
\hline
\textbf{算法:EXTENDED-EUCLID}(x, y) \\[4pt]
\hline
\textbf{输入:}\ \text{两个整数 } x \text{ 和 } y \text{,} x \ge y \ge 0 \\
\textbf{if}\ y = 0\ \textbf{then}\ \text{return}(1, 0, x) \\
(x', y', d) = \text{EXTENDED-EUCLID}(y, x \bmod y) \\
\text{return}(y', x' - \lfloor x/y \rfloor y', d) \\
\hline
\end{array}&&
\end{aligned}
算法: EXTENDED-EUCLID ( x , y ) 输入: 两个整数 x 和 y , x ≥ y ≥ 0 if y = 0 then return ( 1 , 0 , x ) ( x ′ , y ′ , d ) = EXTENDED-EUCLID ( y , x mod y ) return ( y ′ , x ′ − ⌊ x / y ⌋ y ′ , d )
返回三元组 ( a , b , d ) (a, b, d) ( a , b , d ) 使 a x + b y = d = gcd ( x , y ) ax + by = d = \gcd(x, y) a x + b y = d = g cd( x , y ) 。核心是递归回代——已知 x ′ y + y ′ ( x m o d y ) = d x'y + y'(x \bmod y) = d x ′ y + y ′ ( x mod y ) = d ,代入 x m o d y = x − ⌊ x / y ⌋ y x \bmod y = x - \lfloor x/y \rfloor y x mod y = x − ⌊ x / y ⌋ y ,再整理出关于 x , y x, y x , y 的线性组合。
其正确性可用归纳法证明。基例 y = 0 y=0 y = 0 返回 ( 1 , 0 , x ) (1,0,x) ( 1 , 0 , x ) ,满足 1 ⋅ x + 0 ⋅ y = x = gcd ( x , 0 ) 1\cdot x+0\cdot y=x=\gcd(x,0) 1 ⋅ x + 0 ⋅ y = x = g cd( x , 0 ) 。递归层设
x ′ y + y ′ ( x m o d y ) = d . x'y+y'(x\bmod y)=d.
x ′ y + y ′ ( x mod y ) = d .
代入 x m o d y = x − ⌊ x / y ⌋ y x\bmod y=x-\lfloor x/y\rfloor y x mod y = x − ⌊ x / y ⌋ y ,得到
y ′ x + ( x ′ − ⌊ x y ⌋ y ′ ) y = d , y'x+\left(x'-\left\lfloor\frac xy\right\rfloor y'\right)y=d,
y ′ x + ( x ′ − ⌊ y x ⌋ y ′ ) y = d ,
恰好对应返回的两个系数;欧几里得规则又保证 d = gcd ( x , y ) d=\gcd(x,y) d = g cd( x , y ) 。递归深度与普通欧几里得算法相同,因此在讲义采用的普通除法模型下时间为 O ( n 3 ) O(n^3) O ( n 3 ) 。
模逆与模除法
模逆 :若 a x ≡ 1 ( m o d N ) ax \equiv 1 \pmod N a x ≡ 1 ( mod N ) ,则 x x x 是 a a a 模 N N N 的乘法逆元 a − 1 a^{-1} a − 1 ,模 N N N 至多一个。逆元不一定存在,如 2 2 2 模 6 6 6 不可逆。
引理 :若 gcd ( a , N ) > 1 \gcd(a, N) > 1 g cd( a , N ) > 1 ,则 a x ≢ 1 ( m o d N ) ax \not\equiv 1 \pmod N a x ≡ 1 ( mod N ) 对任意 x x x 。
证明 :由带余除法,a x ax a x 除以 N N N 得商 q q q 与余数 r = a x m o d N r = ax \bmod N r = a x mod N ,即 a x = q N + r ax = qN + r a x = qN + r ,故
a x m o d N = a x − q N ax \bmod N = ax - qN
a x mod N = a x − qN
gcd ( a , N ) \gcd(a, N) g cd( a , N ) 同时整除 a x ax a x 与 q N qN qN (它整除 a a a 与 N N N ,故整除它们的任意倍数),因而也整除两者的差 a x − q N = a x m o d N ax - qN = ax \bmod N a x − qN = a x mod N 。也就是说,余数 a x m o d N ax \bmod N a x mod N 一定是 gcd ( a , N ) \gcd(a, N) g cd( a , N ) 的整数倍。若 gcd ( a , N ) > 1 \gcd(a, N) > 1 g cd( a , N ) > 1 ,这个余数可能是 0 0 0 或不小于 2 2 2 的倍数,但不可能等于 1 1 1 ,故 a x ≢ 1 ( m o d N ) ax \not\equiv 1 \pmod N a x ≡ 1 ( mod N ) 。
反之若 gcd ( a , N ) = 1 \gcd(a, N) = 1 g cd( a , N ) = 1 ,扩展欧几里得给出 a x + N y = 1 ax + Ny = 1 a x + N y = 1 ,即 a x ≡ 1 ( m o d N ) ax \equiv 1 \pmod N a x ≡ 1 ( mod N ) ——此 x x x 即逆元。
定理(模除法) :a a a 有模 N N N 的乘法逆元,当且仅当 a a a 与 N N N 互质;逆元存在时可用扩展欧几里得算法在 O ( n 3 ) O(n^3) O ( n 3 ) 内求出。
故模 N N N 下只能除以与 N N N 互质的数,而"除法"实为乘以逆元 。
练习 1.20:分别求下列乘法逆元;若不存在,说明原因。
本题考查扩展欧几里得算法、贝祖等式,以及“存在逆元当且仅当与模数互质”。
(a) 求 20 20 20 模 79 79 79 的逆元。
79 = 3 ⋅ 20 + 19 , 20 = 19 + 1 79=3\cdot20+19,\ 20=19+1 79 = 3 ⋅ 20 + 19 , 20 = 19 + 1 ,回代得 1 = 4 ⋅ 20 − 79 1=4\cdot20-79 1 = 4 ⋅ 20 − 79 ,所以 20 − 1 ≡ 4 ( m o d 79 ) 20^{-1}\equiv4\pmod{79} 2 0 − 1 ≡ 4 ( mod 79 ) 。
(b) 求 3 3 3 模 62 62 62 的逆元。
62 = 20 ⋅ 3 + 2 , 3 = 2 + 1 62=20\cdot3+2,\ 3=2+1 62 = 20 ⋅ 3 + 2 , 3 = 2 + 1 ,回代得 1 = 21 ⋅ 3 − 62 1=21\cdot3-62 1 = 21 ⋅ 3 − 62 ,所以 3 − 1 ≡ 21 ( m o d 62 ) 3^{-1}\equiv21\pmod{62} 3 − 1 ≡ 21 ( mod 62 ) 。
© 求 21 21 21 模 91 91 91 的逆元。
91 = 4 ⋅ 21 + 7 , 21 = 3 ⋅ 7 91=4\cdot21+7,\ 21=3\cdot7 91 = 4 ⋅ 21 + 7 , 21 = 3 ⋅ 7 ,故 gcd ( 21 , 91 ) = 7 \gcd(21,91)=7 g cd( 21 , 91 ) = 7 ,逆元不存在。
(d) 求 5 5 5 模 23 23 23 的逆元。
23 = 4 ⋅ 5 + 3 , 5 = 3 + 2 , 3 = 2 + 1 23=4\cdot5+3,\ 5=3+2,\ 3=2+1 23 = 4 ⋅ 5 + 3 , 5 = 3 + 2 , 3 = 2 + 1 ,回代得 1 = 14 ⋅ 5 − 3 ⋅ 23 1=14\cdot5-3\cdot23 1 = 14 ⋅ 5 − 3 ⋅ 23 ,所以 5 − 1 ≡ 14 ( m o d 23 ) 5^{-1}\equiv14\pmod{23} 5 − 1 ≡ 14 ( mod 23 ) 。
本讲各基本运算的复杂度汇总(输入规模为位数 n = O ( log N ) n = O(\log N) n = O ( log N ) ):
运算
复杂度
说明
加法
O ( n ) O(n) O ( n )
最优,下界 Ω ( n ) \Omega(n) Ω ( n )
乘法
O ( n 2 ) O(n^2) O ( n 2 )
竖式 / 递归;可优化到 O ( n 1.585 ) O(n^{1.585}) O ( n 1.585 )
除法
O ( n 2 ) O(n^2) O ( n 2 )
递归逐位恢复商和余数
模加法
O ( n ) O(n) O ( n )
一次加法,至多再减一次 N N N
模乘法
O ( n 2 ) O(n^2) O ( n 2 )
普通乘法后取余
模幂
O ( n 3 ) O(n^3) O ( n 3 )
指数也至多 n n n 位时,反复平方 + 二进制分解
最大公约数
O ( n 3 ) O(n^3) O ( n 3 )
欧几里得算法
模逆 / 模除法
O ( n 3 ) O(n^3) O ( n 3 )
扩展欧几里得算法;仅对互质除数合法
费马小定理
费马小定理是素数判定与 RSA 密码系统的理论基础。
定理(费马小定理) :若 p p p 是素数,则对任意 1 ≤ a < p 1 \le a < p 1 ≤ a < p ,有 a p − 1 ≡ 1 ( m o d p ) a^{p-1} \equiv 1 \pmod p a p − 1 ≡ 1 ( mod p ) 。
证明 :设 S = { 1 , 2 , … , p − 1 } S = \{1, 2, \dots, p-1\} S = { 1 , 2 , … , p − 1 } 。将 S S S 中每个数乘以 a a a 再取模 p p p ,得到的集合 { a ⋅ 1 m o d p , a ⋅ 2 m o d p , … , a ⋅ ( p − 1 ) m o d p } \{a \cdot 1 \bmod p, a \cdot 2 \bmod p, \dots, a \cdot (p-1) \bmod p\} { a ⋅ 1 mod p , a ⋅ 2 mod p , … , a ⋅ ( p − 1 ) mod p } 恰好是 S S S 的一个排列——因为 a ⋅ i m o d p a \cdot i \bmod p a ⋅ i mod p (i ∈ S i \in S i ∈ S )两两不同(若 a ⋅ i ≡ a ⋅ j ( m o d p ) a \cdot i \equiv a \cdot j \pmod p a ⋅ i ≡ a ⋅ j ( mod p ) 且 i ≠ j i \ne j i = j ,则 p ∣ a ( i − j ) p \mid a(i-j) p ∣ a ( i − j ) ,与 p p p 是素数且 p ∤ a p \nmid a p ∤ a 、∣ i − j ∣ < p |i-j| < p ∣ i − j ∣ < p 矛盾),且都不为 0。于是两边元素乘积相等:
( p − 1 ) ! ≡ a p − 1 ⋅ ( p − 1 ) ! ( m o d p ) (p-1)! \equiv a^{p-1} \cdot (p-1)! \pmod p
( p − 1 )! ≡ a p − 1 ⋅ ( p − 1 )! ( mod p )
两边消去 ( p − 1 ) ! (p-1)! ( p − 1 )! (与 p p p 互质),得 a p − 1 ≡ 1 ( m o d p ) a^{p-1} \equiv 1 \pmod p a p − 1 ≡ 1 ( mod p ) 。
素数测试
费马小定理给出素数的一个必要条件,据此可设计素数测试:
算法:PRIMALITY ( N ) 输入: 整数 N ≥ 2 随机选取正整数 a < N if a N − 1 ≡ 1 ( m o d N ) then return yes else return no \begin{aligned}
&\begin{array}{l}
\hline
\textbf{算法:PRIMALITY}(N) \\[4pt]
\hline
\textbf{输入:}\ \text{整数 } N\ge2 \\
\text{随机选取正整数 } a < N \\
\textbf{if}\ a^{N-1} \equiv 1 \pmod N\ \textbf{then}\ \text{return}\ \text{yes} \\
\textbf{else}\ \text{return}\ \text{no} \\
\hline
\end{array}&&
\end{aligned}
算法: PRIMALITY ( N ) 输入: 整数 N ≥ 2 随机选取正整数 a < N if a N − 1 ≡ 1 ( mod N ) then return yes else return no
问题在于费马定理不是充要条件:存在合数 N N N 满足 a N − 1 ≡ 1 ( m o d N ) a^{N-1} \equiv 1 \pmod N a N − 1 ≡ 1 ( mod N ) 。例如 341 = 11 × 31 341 = 11 \times 31 341 = 11 × 31 ,却有 2 340 ≡ 1 ( m o d 341 ) 2^{340} \equiv 1 \pmod{341} 2 340 ≡ 1 ( mod 341 ) 。更糟的是卡迈克尔数 :
定理(卡迈克尔数) :存在合数 N N N ,使得对所有与 N N N 互质的 a < N a < N a < N 都有 a N − 1 ≡ 1 ( m o d N ) a^{N-1} \equiv 1 \pmod N a N − 1 ≡ 1 ( mod N ) 。
例:561 = 3 × 11 × 17 561 = 3 \times 11 \times 17 561 = 3 × 11 × 17 就是卡迈克尔数,此时所有与 561 561 561 互质的底数都会通过费马测试。
对非卡迈克尔数,费马测试的可靠性有保证:
引理 :若对某个与 N N N 互质的 a a a 有 a N − 1 ≢ 1 ( m o d N ) a^{N-1} \not\equiv 1 \pmod N a N − 1 ≡ 1 ( mod N ) ,则至少一半的 a < N a < N a < N 会不通过该测试。
证明 :固定一个不通过的 a a a 。考察函数 b ↦ a ⋅ b m o d N b \mapsto a \cdot b \bmod N b ↦ a ⋅ b mod N ——它是一一对应的(a a a 与 N N N 互质,存在逆元),因此每个通过的 b b b 都对应一个不通过的 a ⋅ b a \cdot b a ⋅ b (因为 ( a ⋅ b ) N − 1 = a N − 1 b N − 1 ≢ b N − 1 ≡ 1 (a \cdot b)^{N-1} = a^{N-1} b^{N-1} \not\equiv b^{N-1} \equiv 1 ( a ⋅ b ) N − 1 = a N − 1 b N − 1 ≡ b N − 1 ≡ 1 ),故不通过的个数至少与通过的一样多。
暂时排除卡迈克尔数后,可以断言:N N N 为素数时所有 a a a 都通过;N N N 为合数时至多一半的 a a a 通过。即
Pr ( yes ∣ N 为素数 ) = 1 , Pr ( yes ∣ N 为非卡迈克尔合数 ) ≤ 1 2 . \Pr(\text{yes}\mid N\text{ 为素数})=1,
\qquad
\Pr(\text{yes}\mid N\text{ 为非卡迈克尔合数})\le\frac12.
Pr ( yes ∣ N 为素数 ) = 1 , Pr ( yes ∣ N 为非卡迈克尔合数 ) ≤ 2 1 .
独立随机选择 a 1 , … , a k < N a_1,\ldots,a_k<N a 1 , … , a k < N ,仅当所有底数都通过时才返回 yes,便得到 PRIMALITY2 。对非卡迈克尔合数,其单侧错误概率至多为 2 − k 2^{-k} 2 − k 。例如取 k = 10 k=10 k = 10 时,这个上界是 1 / 1024 1/1024 1/1024 。这个界不能直接用于卡迈克尔数;费马测试只能给出“发现证据即可确认是合数”的筛查方法,处理任意输入还需使用能够避开此缺陷的素性测试。讲义开头提到的 AKS 是确定性方案。
练习 1.35:威尔逊定理断言,对 N ≥ 2 N\ge2 N ≥ 2 ,N N N 为素数当且仅当 ( N − 1 ) ! ≡ − 1 ( m o d N ) (N-1)!\equiv-1\pmod N ( N − 1 )! ≡ − 1 ( mod N ) 。
本题考查模逆、素数模下的消去律、最大公约数,以及数值 N N N 与输入位数 log N \log N log N 的区别。
(a) 若 p p p 为素数,哪些 1 ≤ x < p 1\le x<p 1 ≤ x < p 是自己的模 p p p 逆元?
x − 1 ≡ x ( m o d p ) x^{-1}\equiv x\pmod p x − 1 ≡ x ( mod p ) 等价于 ( x − 1 ) ( x + 1 ) ≡ 0 ( m o d p ) (x-1)(x+1)\equiv0\pmod p ( x − 1 ) ( x + 1 ) ≡ 0 ( mod p ) 。因为 p p p 是素数,x ≡ 1 x\equiv1 x ≡ 1 或 x ≡ − 1 ( m o d p ) x\equiv-1\pmod p x ≡ − 1 ( mod p ) 。所以答案是 1 1 1 和 p − 1 p-1 p − 1 ;p = 2 p=2 p = 2 时两者相同。
(b) 将逆元两两配对,证明 ( p − 1 ) ! ≡ − 1 ( m o d p ) (p-1)!\equiv-1\pmod p ( p − 1 )! ≡ − 1 ( mod p ) 。
当 p > 2 p>2 p > 2 ,除 1 1 1 、p − 1 p-1 p − 1 外,其余元素与各自不同的逆元两两配对,每对乘积模 p p p 为 1 1 1 。因此 ( p − 1 ) ! ≡ 1 ⋅ ( p − 1 ) ≡ − 1 ( m o d p ) (p-1)!\equiv1\cdot(p-1)\equiv-1\pmod p ( p − 1 )! ≡ 1 ⋅ ( p − 1 ) ≡ − 1 ( mod p ) 。当 p = 2 p=2 p = 2 ,1 ! ≡ − 1 ( m o d 2 ) 1!\equiv-1\pmod2 1 ! ≡ − 1 ( mod 2 ) 也成立。
© 证明合数 N N N 不满足 ( N − 1 ) ! ≡ − 1 ( m o d N ) (N-1)!\equiv-1\pmod N ( N − 1 )! ≡ − 1 ( mod N ) 。
若 N N N 为合数,取真因子 1 < a < N 1<a<N 1 < a < N 。由于 a ∣ N a\mid N a ∣ N 且 a ∣ ( N − 1 ) ! a\mid(N-1)! a ∣ ( N − 1 )! ,有 gcd ( N , ( N − 1 ) ! ) ≥ a > 1 \gcd(N,(N-1)!)\ge a>1 g cd( N , ( N − 1 )!) ≥ a > 1 ;但若 ( N − 1 ) ! ≡ − 1 ( m o d N ) (N-1)!\equiv-1\pmod N ( N − 1 )! ≡ − 1 ( mod N ) ,这个最大公约数必须是 1 1 1 ,矛盾。这里须排除 N = 1 N=1 N = 1 :模 1 1 1 时同余式成立,但 1 1 1 不是素数。
(d) 既然这是素数的充要条件,为什么不能直接据此得到高效的素数测试?
直接计算 ( N − 1 ) ! m o d N (N-1)!\bmod N ( N − 1 )! mod N 需要 N − 1 N-1 N − 1 次模乘。若 N N N 有 n n n 位,则 N = Θ ( 2 n ) N=\Theta(2^n) N = Θ ( 2 n ) ,普通位运算实现约需 O ( 2 n n 2 ) O(2^n n^2) O ( 2 n n 2 ) 时间,随输入位数指数增长。
随机素数生成
定理(素数定理) :设 π ( x ) \pi(x) π ( x ) 为不超过 x x x 的素数个数,则 π ( x ) ∼ x ln x \pi(x) \sim \frac{x}{\ln x} π ( x ) ∼ l n x x ,即 lim x → ∞ π ( x ) x / ln x = 1 \lim_{x\to\infty} \frac{\pi(x)}{x/\ln x} = 1 lim x → ∞ x / l n x π ( x ) = 1 。
素数分布足够密集,因此可反复随机取 n n n 位数 N N N 并做素数测试,通过则输出,否则重试。对充分大的 n n n ,每轮抽到真正素数的概率为 Θ ( 1 / n ) \Theta(1/n) Θ ( 1/ n ) ;若所用测试总能接受素数,平均 O ( n ) O(n) O ( n ) 轮便会遇到素数。若只用上文的费马测试,“通过”仍可能是合数,特别是卡迈克尔数,因此这个过程还不能保证输出一定为素数。
上述素数测试属于随机算法 ,分两类:
Monte Carlo 算法 :运行时间有界,正确性随机。例:素数测试。
Las Vegas 算法 :一定正确,运行时间随机(以较大概率较快)。例:快速排序、哈希。
密码学
密码学的典型场景:Alice 想向 Bob 私密发送消息 x x x (二进制)。Alice 用加密函数 e e e 编码为 e ( x ) e(x) e ( x ) 发送,Bob 用解密函数 d d d 解码得 d ( e ( x ) ) = x d(e(x)) = x d ( e ( x )) = x 。窃听者 Eve 截获 e ( x ) e(x) e ( x ) ,入侵者 Ida 甚至可冒充 Alice 或 Bob。
私钥与公钥 :传统密码学基于私钥协议 ——Alice 和 Bob 事先见面约定密码本。而公钥协议 允许 Alice 给素未谋面的 Bob 发消息:Bob 造一把"数字锁"公开,只有他有钥匙。
一次性密码本(One-Time Pad) :Alice 和 Bob 秘密共享与消息等长的随机二进制串 r r r ,加密为按位异或 e r ( x ) = x ⊕ r e_r(x) = x \oplus r e r ( x ) = x ⊕ r 。e r e_r e r 是双射且是自身的逆:e r ( e r ( x ) ) = ( x ⊕ r ) ⊕ r = x e_r(e_r(x)) = (x \oplus r) \oplus r = x e r ( e r ( x )) = ( x ⊕ r ) ⊕ r = x 。当 r r r 均匀随机、保持秘密且只使用一次时,Eve 截获 y = x ⊕ r y = x \oplus r y = x ⊕ r 得不到 x x x 的任何信息。但 r r r 不可重复使用 :若用同一 r r r 加密两条消息 x , z x, z x , z ,则知道 x ⊕ r x \oplus r x ⊕ r 和 z ⊕ r z \oplus r z ⊕ r 即可推出 x ⊕ z x \oplus z x ⊕ z ,暴露两者相同的前缀、后缀或可猜测结构。随机串需覆盖所有消息的总长度,生成和分发成本很高。
AES 是可重复使用密钥的现代分组密码标准,分组长度固定为 128 位。其安全性仍依赖正确的工作模式、随机数和密钥管理,不能把“底层密码算法难以破解”等同于整个通信过程安全。
RSA 密码系统 的核心性质:选两个不同的素数 p , q p, q p , q ,令 N = p q N = pq N = pq 。
RSA 基本性质 :对任意与 ( p − 1 ) ( q − 1 ) (p-1)(q-1) ( p − 1 ) ( q − 1 ) 互质的 e e e ,映射 x ↦ x e m o d N x \mapsto x^e \bmod N x ↦ x e mod N 是 { 0 , 1 , … , N − 1 } \{0, 1, \dots, N-1\} { 0 , 1 , … , N − 1 } 上的双射;其逆由 d d d 给出,其中 d d d 是 e e e 模 ( p − 1 ) ( q − 1 ) (p-1)(q-1) ( p − 1 ) ( q − 1 ) 的逆元,即 ( x e ) d ≡ x ( m o d N ) (x^e)^d \equiv x \pmod N ( x e ) d ≡ x ( mod N ) 。
证明 :e e e 与 ( p − 1 ) ( q − 1 ) (p-1)(q-1) ( p − 1 ) ( q − 1 ) 互质,故模 ( p − 1 ) ( q − 1 ) (p-1)(q-1) ( p − 1 ) ( q − 1 ) 可逆。e d ≡ 1 ( m o d ( p − 1 ) ( q − 1 ) ) ed \equiv 1 \pmod{(p-1)(q-1)} e d ≡ 1 ( mod ( p − 1 ) ( q − 1 )) ,即 e d = 1 + k ( p − 1 ) ( q − 1 ) ed = 1 + k(p-1)(q-1) e d = 1 + k ( p − 1 ) ( q − 1 ) 。模 p p p 考察 x e d x^{ed} x e d :若 p ∣ x p\mid x p ∣ x ,则 x e d ≡ x ≡ 0 ( m o d p ) x^{ed}\equiv x\equiv0\pmod p x e d ≡ x ≡ 0 ( mod p ) ;若 p ∤ x p\nmid x p ∤ x ,由费马小定理 x p − 1 ≡ 1 ( m o d p ) x^{p-1}\equiv1\pmod p x p − 1 ≡ 1 ( mod p ) ,所以
x e d = x ( x p − 1 ) k ( q − 1 ) ≡ x ( m o d p ) . x^{ed}=x\left(x^{p-1}\right)^{k(q-1)}\equiv x\pmod p.
x e d = x ( x p − 1 ) k ( q − 1 ) ≡ x ( mod p ) .
模 q q q 同理。由于不同素数 p , q p,q p , q 互质,p p p 与 q q q 都整除 x e d − x x^{ed}-x x e d − x ,故 p q = N pq=N pq = N 整除它,即 ( x e ) d ≡ x ( m o d N ) (x^e)^d\equiv x\pmod N ( x e ) d ≡ x ( mod N ) 。这也证明了加密映射存在逆映射,因而是双射。
RSA 协议 :Bob 选两个 n n n 位随机素数 p , q p, q p , q ,公钥为 ( N , e ) (N, e) ( N , e ) (N = p q N = pq N = pq ,e e e 是与 ( p − 1 ) ( q − 1 ) (p-1)(q-1) ( p − 1 ) ( q − 1 ) 互质的 2 n 2n 2 n 位数),私钥为 d = e − 1 m o d ( p − 1 ) ( q − 1 ) d = e^{-1} \bmod (p-1)(q-1) d = e − 1 mod ( p − 1 ) ( q − 1 ) 。Alice 查公钥 ( N , e ) (N, e) ( N , e ) ,发送 y = x e m o d N y = x^e \bmod N y = x e mod N ;Bob 计算 y d m o d N y^d \bmod N y d mod N 解密。
用小数验证流程:取 p = 5 , q = 11 p=5,q=11 p = 5 , q = 11 ,则 N = 55 N=55 N = 55 、( p − 1 ) ( q − 1 ) = 40 (p-1)(q-1)=40 ( p − 1 ) ( q − 1 ) = 40 。选 e = 3 e=3 e = 3 ,其模 40 的逆元为 d = 27 d=27 d = 27 ,因为 3 ⋅ 27 = 81 ≡ 1 ( m o d 40 ) 3\cdot27=81\equiv1\pmod{40} 3 ⋅ 27 = 81 ≡ 1 ( mod 40 ) 。若消息 x = 7 x=7 x = 7 ,密文为 y = 7 3 m o d 55 = 13 y=7^3\bmod55=13 y = 7 3 mod 55 = 13 ;Bob 计算 13 27 m o d 55 = 7 13^{27}\bmod55=7 1 3 27 mod 55 = 7 ,恢复原消息。这个例子只展示代数正确性,小素数不能用于实际保密通信。
安全性假设 :给定 N , e N, e N , e 和 y = x e m o d N y = x^e \bmod N y = x e mod N ,确定 x x x 在计算上不可行。Eve 穷举 x x x 需指数时间;分解 N N N 得到 p , q p, q p , q 再求 d d d 也因分解困难而不可行。
数字签名 用于证明消息真实性,含两个算法:签名算法(给定消息和私钥产生签名)与验证算法(给定消息、公钥和签名,接受或拒绝)。
协议安全
密码算法本身难以破解,并不保证组合它们的通信协议安全。Needham-Schroeder 公钥协议(NSPK)展示了身份信息与随机数绑定不充分时的中间人攻击。记 { M } + K X \{M\}_{+K_X} { M } + K X 为使用 X X X 的公钥加密消息 M M M ,N A , N B N_A,N_B N A , N B 为双方各自产生的一次性随机数。原协议为
A → B : { A , N A } + K B , B → A : { N A , N B } + K A , A → B : { N B } + K B . \begin{aligned}
A\to B &: \{A,N_A\}_{+K_B},\\
B\to A &: \{N_A,N_B\}_{+K_A},\\
A\to B &: \{N_B\}_{+K_B}.
\end{aligned}
A → B B → A A → B : { A , N A } + K B , : { N A , N B } + K A , : { N B } + K B .
第一步使 B B B 得到 A A A 的身份和挑战值 N A N_A N A ;第二步回传 N A N_A N A 证明响应与本次会话相关,同时用 N B N_B N B 挑战 A A A ;第三步回传 N B N_B N B 。然而,第二条消息没有写明响应者身份。攻击者 I I I 可利用 Alice 主动与自己建立的会话,把消息转发给 Bob:
A → I : { A , N A } + K I , I ( A ) → B : { A , N A } + K B , B → I ( A ) : { N A , N B } + K A , I → A : { N A , N B } + K A , A → I : { N B } + K I , I ( A ) → B : { N B } + K B . \begin{aligned}
A\to I &: \{A,N_A\}_{+K_I},\\
I(A)\to B &: \{A,N_A\}_{+K_B},\\
B\to I(A) &: \{N_A,N_B\}_{+K_A},\\
I\to A &: \{N_A,N_B\}_{+K_A},\\
A\to I &: \{N_B\}_{+K_I},\\
I(A)\to B &: \{N_B\}_{+K_B}.
\end{aligned}
A → I I ( A ) → B B → I ( A ) I → A A → I I ( A ) → B : { A , N A } + K I , : { A , N A } + K B , : { N A , N B } + K A , : { N A , N B } + K A , : { N B } + K I , : { N B } + K B .
I ( A ) I(A) I ( A ) 表示 I I I 冒充 A A A 。攻击者不能解开 Bob 发出的第二条消息,却可原样转交给 Alice。Alice 误以为该消息属于自己与 I I I 的会话,解密后把 N B N_B N B 用 I I I 的公钥发回;I I I 因而获得 N B N_B N B ,再向 Bob 完成认证。最终 Bob 错误地相信正在与 Alice 通信。
修复方法是在第二条消息中加入 Bob 的身份,使响应与具体通信方绑定:
A → B : { A , N A } + K B , B → A : { B , N A , N B } + K A , A → B : { N B } + K B . \begin{aligned}
A\to B &: \{A,N_A\}_{+K_B},\\
B\to A &: \{B,N_A,N_B\}_{+K_A},\\
A\to B &: \{N_B\}_{+K_B}.
\end{aligned}
A → B B → A A → B : { A , N A } + K B , : { B , N A , N B } + K A , : { N B } + K B .
若攻击者再次转发消息,Alice 会在解密结果中看到身份 B B B ,而不是当前会话预期的 I I I ,于是终止协议。这说明协议验证不仅要检查加密是否正确,还要检查消息的身份、方向和会话上下文是否被完整绑定。