【算法学习笔记】数论算法(3)


7. RSA公钥加密系统

通过一个公钥加密系统 public-key cryptosystem ,我们可以对「在两个通信单位之间传输的消息」进行加密,即使窃听者 eavesdropper 窃听到被加密的消息,也不能对其进行破译。一个公钥加密系统还能让通信的一方,在电子消息的末尾附加一个无法伪造的数字签名 digital signature ——这种签名是纸质文件上的手写签名的电子版本。任何人都可以轻松地核对签名,但却不能伪造它,如果这一消息的任何位有所变化,整个签名就失去了效力。因此,数字签名可以为「签名者的身份和其签署信息的内容」提供证明。

对于电子签署的商业合同、电子支票、电子购货单和其他一些各方希望进行认证的电子信息来说,这是一种理想的工具。

RSA公钥加密系统主要基于以下事实:寻找大素数是很容易的,但要把一个数因子分解为两个大素数的积却相当困难 The RSA public-key cryptosystem relies on the dramatic difference between the ease of finding large prime numbers and the difficulty of factoring the product of two large prime numbers 。(算导31.8节)下面描述了一个能有效地找出大素数的过程,(算导31.9节)讨论大整数的因子分解问题。

7.1 公钥加密系统

在一个公钥加密系统中,每个参与者都拥有一把公钥 public key 和一个私钥 secret key 。每把密钥都是一段信息 Each key is a piece of information 。例如,在RAS加密系统中,每个密钥均由一对整数组成 each key consists of a pair of integers 。在密码学中,常以参与者 Alice 和 Bob 作为例子,用 P A , S A P_A, S_A PA,SA 分别表示 Alice 的公钥和私钥,用 P B P_B PB S B S_B SB 分别表示 Bob 的公钥和私钥。

每个参与者均自己创建公钥和私钥私钥需要保密,但公钥可以对任何人透漏、甚至公之于众。事实上,我们可以假设,每个参与者的公钥都能在一个公开目录中看到,这样通常是很方便的,这使得任何参与者都可以容易地获得任何其他参与者的公钥。

公钥和私钥指定了可用于任何信息的函数 The public and secret keys specify functions that can be applied to any message 。设 D D D 表示允许的信息集合。例如, D D D 可能是所有有限长度的位序列的集合。在最简单的、最原始的公钥加密设想 formulation of publickey cryptography 中,要求公钥与私钥指定「从 D D D 到其自身的一一映射 one-to-one functions from D to itself 」。我们用 P A ( ) P_A() PA() 表示「对应 Alice 的公钥 P A P_A PA 的函数」,用 S A ( ) S_A() SA() 表示「对应她的私钥 S A S_A SA 的函数」,因此 P A ( ) , S A ( ) P_A(), S_A() PA(),SA() 函数都是 D D D 的排列(?)。我们假定已知密钥 P A P_A PA S A S_A SA ,就可以有效地计算出函数 P A ( ) P_A() PA() S A ( ) S_A() SA()

系统中任何参与者的公钥和私钥,都是一个匹配对,它们指定的函数互为反函数,也就是说,对任何消息 M ∈ D M \in D MD ,有: M = S A ( P A ( M ) ) (31.35) M = P A ( S A ( M ) ) (31.36) \begin{aligned} M &= S_A(P_A(M)) \qquad \qquad &\textrm{(31.35)} \\ M &= P_A(S_A(M))\qquad \qquad &\textrm{(31.36)} \end{aligned} MM=SA(PA(M))=PA(SA(M))(31.35)(31.36) 无论用哪种次序,运用两把密钥 P A P_A PA S A S_A SA M M M 相继进行变换后,最后仍然得到消息 M M M

在一个公钥加密系统中,我们需要:除了 Alice 外,没有人能在任意实用的时间内 any practical amount of time 计算出函数 S A ( ) S_A() SA() 。这一假设十分关键,对于保持「送给 Alice 的加密邮件的保密性」和鉴别「Alice 的数字签名的真实性」而言。Alice 必须保密 S A S_A SA ;如果她不能做到这一点,就会失去她的唯一性,而且加密系统也不能提供给她唯一性 unique capabilities 。假设:即使每个人都知道 P A P_A PA 、并能有效地计算出 P A ( ) P_A() PA() 这一 S A ( ) S_A() SA() 的反函数,依然要保证只有 Alice 能计算出 S A ( ) S_A() SA() 。为了创建一个可行的公钥加密系统,我们必须解决以下问题:如何创建一个系统,在该系统中我们可以公开一个变换 P A ( ) P_A() PA() 、而不至于因此公开如何计算其相应的逆变换 S A ( ) S_A() SA() 。这项任务看起来很难,但我们将看到如何去完成它。

在一个公钥加密系统中,加密的工作方式如图31-5所示。假定 Bob 要给 Alice 发送一条加密消息 M M M ,使得该消息对于窃密者像一串无法识别的乱码。发送消息的方案如下:

  1. Bob 取得 Alice 的公钥 P P P(根据一个公开的目录,或者直接向 Alice 索取)。
  2. Bob 计算出相应于 M M M密文 ciphertext C = P A ( M ) C = P_A(M) C=PA(M) ,并把 C C C 发送给 Alice 。
  3. 当 Alice 收到密文后,她运用自己的密钥 S A S_A SA 恢复原始信息: S A ( C ) = S A ( P A ( M ) ) = M S_A(C) = S_A(P_A(M)) = M SA(C)=SA(PA(M))=M
    在这里插入图片描述
    由于 S A ( ) S_A() SA() P A ( ) P_A() PA() 互为反函数,所以 Alice 能从 C C C 中计算出 M M M 。因为只有 Alice 能计算出 S A ( ) S_A() SA() ,所以也只有 Alice 能根据 C C C 计算出 M M M 。因为 BoB 运用 P A ( ) P_A() PA() M M M 进行加密,所以只有 Alice 可以理解接收的信息。

类似地,在公钥加密系统的设想中,我们可以很容易地实现数字签名(有其他方式可以解决构造数字签名的问题,但在这里不讨论)。假设现在 Alice 希望把一个数字签署的响应 M ′ M' M 发送给 Bob。数字签名方案的过程如图31-6所示。

  1. Alice 使用她的私钥 S A S_A SA 和等式 σ = S A ( M ′ ) \sigma = S_A(M') σ=SA(M) 计算出信息 M ′ M' M数字签名 σ \sigma σ

  2. Alice 把信息/签名对 ( M ′ , σ ) (M', \sigma) (M,σ) 发送给 Bob 。

  3. 当 Bob 收到 ( M ′ , σ ) (M', \sigma) (M,σ) 时,他可以利用 Alice 的公钥、通过验证等式 M ′ = P A ( σ ) M' = P_A(\sigma) M=PA(σ) 来证实,该消息确实是来自于 Alice 。这里假设 M ′ M' M 包含 Alice 的名字,这样 Bob 就知道应该使用谁的公钥。如果等式成立,则 Bob 可以得出结论:消息 M ′ M' M 确实是由 Alice 签名的;如果等式不成立,则 Bob 可以得出结论:要么是信息 M ′ M' M 或数字签名 σ \sigma σ 因传输错误而损坏,要么信息/签名对 ( M ′ , σ ) (M', \sigma) (M,σ) 是一个故意的伪造。
    在这里插入图片描述

    因为一个数字签名既证明了签署者的身份,也证明了签署信息的内容,所以它是对「文件末尾的手写签名」的一种模拟。

一个数字签名必须能被「任何能取得签署者的公钥的人」所验证。一条签署过的消息可以被一方确认后,再传送到其他可以验证签名的各方。例如,这条消息可能是 Alice 发给 Bob 的一张电子支票,在 Bob 确认了支票上 Alice 的签名后,就可以把这张支票送交银行,而银行也可以对签名进行验证,然后调拨相应的资金。

一条签署过的信息不必是加密的,该信息可以是公开的、没有受到保护。如果把上述有关加密和签名的两种方案结合起来使用,就可以创建出同时被签署和加密的消息 messages that are both signed and encrypted

  1. 签署者首先把其数字签名(用私钥)附加在消息的后面,然后再用「他预定的接收者的公钥」,对最终的消息/签名对进行加密,从而发送消息;
  2. 接收者用其私钥对收到的消息进行解密,以同时获取原始消息和数字签名;
  3. 然后,接收者可以用「签署者的公钥」对签名进行验证。
  4. 相应的纸质文件系统的实现过程为:对文件签名后,将文件封入一个纸质信封内,该信封只能由预定的接收者打开。

7.2 RSA加密系统

在RSA公钥加密系统中,一个参与者按下列过程创建他的公钥和私钥:

  1. 随机选取两个大素数 p , q p, q p,q ,使得 p ≠ q p \ne q p=q 。例如,素数 p , q p, q p,q 可能各有 1024 1024 1024 位。
  2. 计算 n = p q n = pq n=pq
  3. 选取一个 ϕ ( n ) \phi(n) ϕ(n) 互质的小奇数 e e e ,其中由等式 ( 31.20 ) (31.20) (31.20) ϕ ( n ) = n ∏ p   :   p   i s   p r i m e   a n d   p ∣ n ( 1 − 1 p ) = p q ( 1 − 1 p ) ( 1 − 1 q ) = ( p − 1 ) ( q − 1 ) \phi(n) = n \prod_{\mathrm{ p\ :\ p\ is\ prime\ and\ p \mid n}} (1 - \dfrac{1}{p}) =pq(1- \dfrac{1}{p}) ( 1- \dfrac{1}{q}) = (p - 1)(q - 1) ϕ(n)=np : p is prime and pn(1p1)=pq(1p1)(1q1)=(p1)(q1)
  4. (利用算导31.4节中的方法)计算出 e e e 的模 ϕ ( n ) \phi(n) ϕ(n) 乘法逆元 d d d 的值(推论31.26保证 d d d 存在且唯一——给定 e , ϕ ( n ) e, \phi(n) e,ϕ(n) ,当 g c d ( e , ϕ ( n ) ) = 1 gcd(e, \phi(n)) = 1 gcd(e,ϕ(n))=1 即二者互质时, e d ≡ 1 ( m o d ϕ ( n ) ) e d \equiv 1 \pmod {\phi(n)} ed1(modϕ(n)) 有唯一解, d d d e e e 的乘法逆元)。
  5. 将对 P = ( e , n ) P = (e, n) P=(e,n) 公开,并作为参与者的RSA公钥
  6. 使对 S = ( d , n ) S = (d, n) S=(d,n) 保密,并作为参与者的RSA私钥

对于这个方案,域 D D D 为集合 Z n \Z_n Zn 。为了变换与公钥 P = ( e , n ) P = (e, n) P=(e,n) 相关的消息 M M M ,计算: P ( M ) = M e   m o d   n (31.37) P(M) = M^e \bmod n \tag{31.37} P(M)=Memodn(31.37) 为了变换与私钥 S = ( d , n ) S = (d, n) S=(d,n) 相关的密文 C C C ,计算: S ( C ) = C d   m o d   n (31.38) S(C) = C^d \bmod n \tag{31.38} S(C)=Cdmodn(31.38)

这两个等式对加密与签名是通用的 These equations apply to both encryption and signatures 。只是为了创建一个签名,签署人将其私钥应用于待签署的消息、而不是一个密文中;为了确认签名,将签署人的公钥应用在签名中、而非待加密的消息中。

我们可以运用31.6节中描述的过程 MODULAR-EXPONENTIATION 、来实现上述公钥与私钥的有关操作。为了分析这些操作的运行时间,假定公钥 ( e , n ) (e, n) (e,n) 和私钥 ( d , n ) (d, n) (d,n) 满足 log ⁡ e = O ( 1 ) , log ⁡ d ≤ β , log ⁡ n ≤ β \log e = O(1), \log d \le \beta, \log n \le \beta loge=O(1),logdβ,lognβ e e e 为小奇数, d d d e e e ϕ ( n ) \phi(n) ϕ(n) 的乘法逆元, n = p q n = pq n=pq 为大素数乘积)。然后,应用公钥需要执行 O ( 1 ) O(1) O(1) 次模乘法运算、使用 O ( β 2 ) O(\beta^2) O(β2) 次位操作,应用密钥需要执行 O ( β ) O(\beta) O(β) 次模乘法操作、使用 O ( β 3 ) O(\beta^3) O(β3) 次位操作。

定理31.36RSA的正确性)RSA等式 ( 31.37 ) (31.37) (31.37) ( 31.38 ) (31.38) (31.38) 定义了满足等式 ( 31.35 ) (31.35) (31.35) ( 31.36 ) (31.36) (31.36) 的逆变换。
证明:根据等式 ( 31.37 ) (31.37) (31.37) ( 31.38 ) (31.38) (31.38) ,对任意 M ∈ Z n M \in \Z_n MZn ,有: P ( S ( M ) ) = S ( P ( M ) ) = M e d   m o d   n P(S(M)) = S(P(M)) = M^{ed} \bmod n P(S(M))=S(P(M))=Medmodn 因为 e , d e, d e,d 是模 ϕ ( n ) = ( p − 1 ) ( q − 1 ) \phi(n) = (p-1)(q-1) ϕ(n)=(p1)(q1) 的乘法逆元,所以对某个整数 k k k ,有: e d = 1 + k ( p − 1 ) ( q − 1 ) ed = 1 + k(p - 1)(q - 1) ed=1+k(p1)(q1) 但是,如果 M ≡   0 ( m o d p ) M \cancel {\equiv}\ 0 \pmod p M  0(modp) ,则有:
M e d ≡ M ( M p − 1 ) k ( q − 1 ) ( m o d p ) ≡ M ( ( M   m o d   p ) p − 1 ) k ( q − 1 ) ( m o d p ) ≡ M ( 1 ) k ( q − 1 ) ( m o d p ) ( 根 据 定 理 31.31 费 马 小 定 理 ) ≡ M ( m o d p ) \begin{aligned}M^{ed} &\equiv M(M^{p - 1} ) ^{k (q - 1) } &\pmod p \\ &\equiv M((M \bmod p)^{p-1})^{k(q - 1)} &\pmod p \\ &\equiv M(1)^{k(q-1)} &\pmod p &\quad (根据定理31.31费马小定理) \\ &\equiv M &\pmod p \end{aligned} MedM(Mp1)k(q1)M((Mmodp)p1)k(q1)M(1)k(q1)M(modp)(modp)(modp)(modp)(31.31)

类似地,对所有 M M M 有: M e d ≡ M ( m o d q ) M^{ed} \equiv M \pmod q MedM(modq) 因此,根据中国余数定理的推论31.29,对所有 M M M ,有: M e d ≡ M   m o d   n ■ M^{ed} \equiv M \bmod n\qquad \qquad \blacksquare MedMmodn

RSA加密系统的安全性,主要来源于「对大整数进行因式分解的困难性」。如果对手能对公钥中的模数 n n n 进行分解,就可以根据公钥推导出私钥,这是因为对方和公钥创建者以同样的方式使用因子 p , q p, q p,q 。因此,如果能轻易地分解大整数,也就能够轻易地打破RSA加密系统。这一命题的逆命题是,如果分解大整数是困难的,则打破RSA也是困难的。经过二十年的研究,人们还没有发现比因子分解模 n n n 更容易的方法来打破RSA加密系统。并且正如我们将(在算导31.9节中)所见,对大整数进行因子分解的困难程度令人惊异。通过随机地选取两个 1024 1024 1024 位的素数、并将其相乘,就可以创建出一把无法用现行技术、在可行的时间内“破解”的公钥。在数论算法的设计方法还缺乏根本突破的情况下,细心地遵循所推荐标准来实现,RSA加密系统可以为实际应用提供高度的安全性

然而,为了通过RSA加密系统实现安全性,应该在很长(数百位乃至千位)的整数上操作、以防御因子分解技术可能的进步。2009年,RSA模数通常是在 768 ∼ 2048 768 \sim 2048 7682048 位的范围内,要建立这样大小的模数,必须能够有效地找出大素数。(算导31.8节)下面将讨论这个问题。

为了效率,通常运用一种“混合的”或“密钥管理”模式的RSA、来实现快速的无公钥加密系统 non-public-key cryptosystem 。在这样一个系统中,加密密钥和解密密钥是相同的。如果 Alice 希望私下给 Bob 发送一条长信息 M M M ,她从快速无公钥加密系统中选取一把随机密钥 K K K ,然后运用 K K K M M M 进行加密,得到密文 C C C 。这里 C C C M M M 一样长,但 K K K 相当短。然后,她利用 Bob 的公开RSA密钥对 K K K 进行加密,因为 K K K 很短,所以计算 P B ( K ) P_B(K) PB(K) 的速度也很快(比计算 P B ( M ) P_B(M) PB(M) 的速度快很多)。接着,她把 ( C , P B ( K ) ) (C, P_B(K)) (C,PB(K)) 传送给 Bob ,Bob 对 P B ( K ) P_B(K) PB(K) 解密后得到 K K K ,再用 K K K C C C 进行解密,得到 M M M

类似地,可以使用一种混合的方法来提高数字签名的执行效率。在这种方法中,将RSA与一个公开的抗冲突散列函数 collision-resistant hash function h h h 相结合,这个函数是易于计算的,但是对这个函数来说,要找出两条消息 M M M M ′ M' M 、使得 h ( M ) = h ( M ′ ) h(M) = h(M') h(M)=h(M) ,在计算上是不可行的。 h ( M ) h(M) h(M) 的值是消息 M M M 的一个短(如 256 256 256 位)“指纹”。如果 Alice 希望签署一条消息 M M M她首先把函数 h h h 作用于 M M M 得到指纹 h ( M ) h(M) h(M) ,然后用她的私钥加密 h ( M ) h(M) h(M) 。她将 ( M , S A ( h ( M ) ) (M, S_A(h(M)) (M,SA(h(M)) 作为她签署的 M M M 的版本发送给 Bob 。而 Bob 可以通过计算 h ( M ) h(M) h(M) ,并将 P A P_A PA 应用于收到的 S A ( h ( M ) ) S_A(h(M)) SA(h(M)) 、验证其是否等于 h ( M ) h(M) h(M) 来验证签名的真实性。因为没有人能够创建出两条具有相同指纹的消息,所以在计算上不可能既改变签署的消息、又保持签名的合法性。

最后,我们注意到,利用证书 certificates 可以更轻松地分配公钥。例如,假设存在一个“可信的权威” T T T ,每个人都知道他的公钥。Alice 可以从 T T T 获取一条签署的消息(即她的证书),该消息声明“Alice 的公钥是 P A P_A PA ”。由于每个人都知道 P T P_{T} PT ,所以这个证书是“自我认证”。Alice 可以将她的证书包含在签名信息中,使得接收者可以立即得到 Alice 的公钥、以验证她的签名。因为她的密钥是被 T T T 签署的,所以接收者知道 Alice 的密钥确实是 Alice 本人的密钥。


8. 素数的测试

在本节中,我们要考虑寻找大素数的问题。首先讨论素数的密度,接着讨论一种似乎可行、但不完全可行的测试素数的方法,然后介绍一种由 MillerRabin 发现的、有效的随机素数测试算法。

8.1 素数的密度

在许多应用领域,如密码学中,需要找出大的“随机”素数。幸运的是,大素数并不少,因此测试适当大小的随机整数、直到找到素数的过程是可行的素数分布函数 prime distribution function π ( n ) \pi(n) π(n) 描述了:小于或等于 n n n 的素数的数目。例如 π ( 10 ) = 4 \pi(10) = 4 π(10)=4 ,因为小于等于 10 10 10 的素数有 4 4 4 个,分布为 2 , 3 , 5 , 7 2, 3, 5, 7 2,3,5,7 。素数定理给出了 π ( n ) \pi(n) π(n) 的一个有用近似。

定理31.37素数定理 Prime number theorem lim ⁡ n → ∞ π ( n ) n / ln ⁡ n = 1 ■ \lim_{n \to \infin} \dfrac{\pi(n)}{ n / \ln n} = 1\qquad \qquad \blacksquare nlimn/lnnπ(n)=1

即使对于较小的 n n n ,近似计算式 n / ln ⁡ n n / \ln n n/lnn 也可以相当精确地给出 ϕ ( n ) \phi(n) ϕ(n) 的估计值。例如,当 n = 1 0 9 n = 10^9 n=109 时, π ( n ) = 50 , 847 , 534 ,   n / ln ⁡ ( n ) = 48 , 254 , 942 \pi(n) = 50,847,534,\ n / \ln(n) = 48,254,942 π(n)=50,847,534, n/ln(n)=48,254,942 ,误差不超过 6 % 6\% 6% 。对数论研究者来说, 1 0 9 10^9 109 是一个小数字。

我们可以把「随机选取一个整数 n n n 、并判断它是否为素数」这一过程视作一个伯努利试验 Bernoulli trail(见算导C.4节)。通过素数定理,一次成功(即一个随机选取的整数 n n n 是素数)的概率为 1 ln ⁡ n \dfrac{1}{\ln n} lnn1 。这种几何分布告诉我们,为了获取一次成功、我们需要多少次试验,而由于等式 ( C . 32 ) (C.32) (C.32) ,试验的期望值近似为 ln ⁡ n \ln n lnn 。因此,为了找出一个长度与 n n n 相同的素数 find a prime that is of the same length as n ,要检查在 n n n 附近随机选取的 ln ⁡ n \ln n lnn 个整数。例如,我们期望:为了找出一个 1024-bit \textrm{1024-bit} 1024-bit 的素数,大约需要测试 ln ⁡ 2 1024 ≈ 710 \ln 2^{1024} \approx 710 ln21024710 个随机选取的、 1024 1024 1024 位长的整数的素性。当然,通过只选择奇数,就可以把这个数字减少一半。

在本节其余部分,将要考虑这个问题:确定一个大奇数 n n n 是否为素数。为了表示上的方便,我们假设 n n n 具有下列素数分解因子:
n = p 1 e 1 p 2 e 2 … p r e r (31.39) n = p_1^{e_1} p_2^{e_2} \dots p_r^{e_r} \tag{31.39} n=p1e1p2e2prer(31.39) 这里 r ≥ 1 r \ge 1 r1 p 1 , p 2 , … , p r p_1, p_2, \dots, p_r p1,p2,,pr n n n 的素数因子,且 e 1 , e 2 , … , e r e_1, e_2, \dots, e_r e1,e2,,er 是正整数。 n n n 是素数当且仅当 r = 1 r = 1 r=1 e 1 = 1 e_1 = 1 e1=1(即只有一个素数分解因子,且就是 n n n 本身时)。

解决这个素数测试问题的一种简便方法是试除 trial division ——试着用每个整数 2 , 3 , … , ⌊ n ⌋ 2, 3, \dots, \lfloor \sqrt{n} \rfloor 2,3,,n 分别去除 n n n(大于 2 2 2 的偶数可以跳过;即不用偶数来除,或极端点只用素数来除)。很容易看出来, n n n 是素数当且仅当没有一个试除数能整除 n n n 。假定每次试除需要常数时间,则最坏情况运行时间是 Θ ( n ) = Θ ( n 1 / 2 ) \Theta(\sqrt{n}) =\Theta(n^{1/2}) Θ(n )=Θ(n1/2) ,这是 n n n 的长度的指数 which is exponential in the length of n(如果 n n n 表示为 β \beta β 位的二进制数,则 β = ⌈ log ⁡ ( n + 1 ) ⌉ \beta = \lceil \log (n + 1) \rceil β=log(n+1) ,因此 n = Θ ( 2 β / 2 ) \sqrt{n} = \Theta(2^{\beta / 2}) n =Θ(2β/2) )。因此,只有当 n n n 很小或 n n n 恰好有小素数因子时,试除法才能较好地进行。当试除法可以执行时,它的优点是:不仅能确定 n n n 是素数还是合数、而且当 n n n 是合数时它能确定出 n n n 的一个素数因子

在本节中,我们感兴趣的仅仅是:确定一个给定的数 n n n 是否是素数;如果 n n n 是合数,我们不考虑找出其素数因子。正如将在(算导31.9节中)看到的那样,计算一个数的素数因子分解的计算开销是很高的。令人惊讶的是,确定一个数是否是素数,要比确定一个合适的素因子分解容易得多。

8.2 伪素数测试过程

现在来考察一种“几乎可行”的素数测试方法 primality testing ,事实上对于很多实际应用,这种方法已经足够好了。后面还将改进这种方法,以消除其中的小缺陷。令 Z n + \Z^+_n Zn+ 表示 Z n \Z_n Zn 中的非零元素:
Z n + = { 1 , 2 , … , n − 1 } \Z_n^+ = \{ 1, 2, \dots, n - 1\} Zn+={1,2,,n1} 如果 n n n 是素数,则 Z n + = Z n ∗ \Z_n^+ = \Z^*_n Zn+=Zn

我们称 n n n 是一个基于 a a a 的伪素数 base-a pseudoprime ,如果 n n n 是一个合数,且 a n − 1 ≡ 1 ( m o d n ) (31.40) a^{n - 1} \equiv 1 \pmod n \tag{31.40} an11(modn)(31.40) 费马小定理定理31.31)意味着:如果 n n n 是素数,则对 Z n + \Z^+_n Zn+(如上所述, n n n 是素数时 Z n + = Z n ∗ \Z_n^+ = \Z^*_n Zn+=Zn )中的每个 a a a n n n 都满足等式 ( 31.40 ) (31.40) (31.40) 。因此,如果能找出任一 a ∈ Z n + a \in \Z^+_n aZn+ 、使得 n n n 不满足等式 ( 31.40 ) (31.40) (31.40) ,那么 n n n 就当然是合数(费马小定理的逆否命题)。令人惊讶的是,费马小定理的逆命题几乎成立(对 Z n + \Z^+_n Zn+ 中的每个 a a a n n n 都满足等式 ( 31.40 ) (31.40) (31.40) ,则 n n n 是素数)——对于素数测试,这一标准几乎是完美的。我们对 a = 2 a = 2 a=2 ,测试看 n n n 是否满足等式 ( 31.40 ) (31.40) (31.40)如果不满足,则通过返回 COMPOSITE 声明 n n n 是合数根据费马小定理的逆否命题);否则返回 PRIME ,猜测 n n n 是素数(实际上,此时我们所知道的只是 n n n 或者是素数、或者是基于 2 2 2 的伪素数)。

下列过程就是用这种方法测试 n n n 的素性。它使用了(算导31.6节中的)MODULAR-EXPONENTIATION 过程。假设输入 n n n 是一个大于 2 2 2 的整数。
在这里插入图片描述
这个过程可能会产生错误,但是只有一种类型——也就是说,如果它判定 n n n 是合数,那么结果总是正确的;然而,如果它判定 n n n 是素数,那么只有当 n n n 是基于 2 2 2 的伪素数时、过程才会出错

这个过程出错的概率有多大?令人惊讶地少。在小于 10000 10000 10000 n n n 值中,只有在其中 22 22 22 个值上会产生错误。最靠前的四个这样的值分别为 341 , 561 , 645 , 1105 341, 561, 645, 1105 341,561,645,1105(基于 2 2 2 的伪素数)。我们不证明它,但是当 β → ∞ \beta \to \infin β 时该过程对随机选取的 β \beta β 位数进行测试,错误的概率趋近于 0 0 0 。根据 Pomerance 那样、更精确地估计一个给定规模下「基于 2 2 2 的伪素数的个数」,我们可以估计出:

  • 被上述过程判定为素数的、一个随机选取的 512 512 512 位数,是「基于 2 2 2 的伪素数」的概率不到 1 / 1 0 20 1 / 10^{20} 1/1020
  • 被上述过程判定为素数的、一个随机选取的 1024 1024 1024 位数,是基于 2 2 2 的伪素数的概率不到 1 / 1 0 41 1 / 10^{41} 1/1041

因此,如果只是尝试为某个应用找到一个大素数,通过随机选取大的数字、直到它们其中之一使得 PSEUDOPRIME 返回 PRIME ,这在所有实际使用中几乎永远不会出错。但是当「待测试素性的数字」不是随机选取时,我们需要一个更好的方法来进行素数测试。后面将会看到,如果稍微巧妙一点、再加上一些随机性,就会得到一个在所有输入情况下、都工作良好的素数测试程序。

遗憾的是,我们不能通过简单地选取另外一个基数(例如 a = 3 a = 3 a=3 )检查等式 ( 31.40 ) (31.40) (31.40) 的方法、来消除所有的错误,因为总存在正整数 n n n(称为 Carmichael 数)对所有 a ∈ Z n ∗ a \in \Z^*_n aZn 满足等式 ( 31.40 ) (31.40) (31.40) ——(我们注意到,当 g c d ( a , n ) > 1 gcd(a, n) > 1 gcd(a,n)>1 也就是当 a ∉ Z n ∗ a \notin \Z^*_n a/Zn 时,等式 ( 31.40 ) (31.40) (31.40) 不成立,但是我们希望解释:如果 n n n 只有大素数因子、其他数都和 n n n 互质时,就很难通过寻找这样的 a a a 来说明 n n n 是合数)。前三个 Carmichael 数是 561 , 1105 , 1729 561, 1105, 1729 561,1105,1729Carmichael 数极少;例如,在小于 100 , 000 , 000 100, 000, 000 100,000,000 的数中,只有 255 255 255Carmichael 数。(算导练习31.8-2)解释了这种数很少的原因。

下一步来说明,如何对素数测试方法进行改进,使得测试过程不会被 Carmichael 数欺骗。

8.3 Miller-Rabin 随机化素性测试

Miller-Rabin 素性测试方法对简单测试过程 PSEUDOPRIME 做了两点改进,克服了其中存在的问题:

  1. 它试验了多个随机选取的基值 n n n ,而非仅仅一个基值。
  2. 当计算每个模取幂的值时,在最后一组平方中 during the final set of squarings. ,它寻找一个 1 1 1 的模 n n n 非平凡平方根。如果发现一个,终止执行并输出结果 COMPOSITE 。(算导31.6节的推论31.35证明了用这种方法测试合数的正确性)

Miller-Rabin 素性测试的伪代码如下。输入 n > 2 n > 2 n>2 是一个等待素性测试的奇数, s s s 是「从 Z n + \Z^+_n Zn+ 中随机选取的、要进行试验的基值」的个数。

  • 代码运用随机数生成程序 RANDOMRANDOM(1, n - 1) 返回一个满足 1 ≤ a ≤ n − 1 1 \le a \le n -1 1an1 的随机选取的整数 a a a
  • 代码中还使用一个辅助过程 WITNESSWITNESS(a, n) = true 当且仅当 a a a 是「 n n n 为合数的一个证据」时——即用 a a a 来证明(证明方法见后面) n n n 为合数是可能的。测试 WITNESS(a, n) 是一个对「作为过程 PSEUDOPRIME 基础(用 a = 2 a = 2 a=2 )的测试 a n − 1 ≡   1 ( m o d n ) a^{n - 1} \cancel {\equiv }\ 1 \pmod n an1  1(modn) 」的扩展,但是更加有效。
    在这里插入图片描述

我们首先介绍并证明 WITNESS 的构造过程,然后展示如何把它应用于 Miller-Rabin 素性测试过程。

  • n − 1 = 2 t u n - 1 = 2^t u n1=2tu ,其中 t ≥ 1 t \ge 1 t1 u u u 是奇数;即 n − 1 n - 1 n1 的二进制表示是「奇整数 u u u 的二进制表示后面跟上恰好 t t t 个零」。因此, a n − 1 ≡ ( a u ) 2 t ( m o d n ) a^{n - 1} \equiv (a^u)^{2^t} \pmod n an1(au)2t(modn) ,所以可以通过先计算 a u   m o d   n a^u \bmod n aumodn ,然后对结果连续平方 t t t 次来计算 a n − 1   m o d   n a^{n - 1} \bmod n an1modn
  • WITNESS 的伪代码,通过首先在第二行计算值 x 0 = a u   m o d   n x_0 = a^u \bmod n x0=aumodn 、然后在第三至六行 for 循环中的一行中对结果平方 t t t 次,来计算 a n − 1   m o d   n a^{n - 1} \bmod n an1modn 。通过在 i i i 上归纳,被计算出的序列 x 0 , x 1 , … , x i x_0, x_1, \dots, x_i x0,x1,,xi 的值满足等式 x i ≡ a 2 i u ( m o d n )   ( i = 0 , 1 , … , t ) x_i \equiv a^{{2^i}u} \pmod n\ (i =0,1,\dots, t) xia2iu(modn) (i=0,1,,t) ,所以特别地, x t ≡ a 2 t u ( m o d n ) x_t \equiv a^{2^t u} \pmod n xta2tu(modn)
  • 然而,在第四行后执行一个平方步骤,如果第五至六行检测到一个 1 1 1 的非平凡平方根刚被发现,则循环可能提前结束(稍后解释)。如果这样,则算法终止并返回 TRUE
  • 如果 x ≡ a n − 1 ( m o d n ) x\equiv a^{n - 1} \pmod n xan1(modn) 所计算出的值不等于 1 1 1 ,则第七至八行返回 TRUE ,就像 PSEUDOPRIME 在这种情况中返回 COMPOSITE
  • 如果第六行或第八行没有返回 TRUE ,则第九行返回 FALSE

我们现在来论证,如果 WITNESS(a, n) 返回 TRUE ,则可以用 a a a 作为证据、构造出 n n n 是合数的证明。

  1. 如果 WITNESS 从第八行返回 TRUE ,则它已经发现 x t = a n − 1   m o d   n ≠ 1 x_t = a^{n - 1} \bmod n \ne 1 xt=an1modn=1 。然而,如果 n n n 是素数,则根据费马小定理定理31.31),对任何 a ∈ Z n + a \in \Z^+_n aZn+(当 n n n 为素数,则 Z n + = Z n ∗ \Z_n^+ = \Z_n^* Zn+=Zn )都有 a n − 1 ≡ 1 ( m o d n ) a^{n - 1} \equiv 1 \pmod n an11(modn) 成立。因此 n n n 不可能为素数,并且等式 a n − 1   m o d   n ≠ 1 a^{n - 1} \bmod n \ne 1 an1modn=1 证明了这个事实。
  2. 如果 WITNESS 从第六行返回 TRUE ,则它已经发现 x i − 1 x_{i-1} xi1 是一个 1 1 1 的以 n n n 为模的非平凡平方根,因为 x i − 1 ≠ ± 1 ( m o d n ) x_{i - 1} \ne \pm 1\pmod n xi1=±1(modn) ,但是 x i ≡ x i − 1 2 ≡ 1 ( m o d n ) x_i \equiv x_{i-1}^2 \equiv 1 \pmod n xixi121(modn)推论31.35说明,仅当 n n n 是合数时,才能存在 1 1 1 的以 n n n 为模的非平凡平方根,因此说明 x i − 1 x_{i - 1} xi1 是一个 1 1 1 的模 n n n 非平凡平方根,也就证明了 n n n 是合数。
  • 这样就完成了有关 WITNESS 正确性的证明。如果调用 WITNESS(a, n) 返回 TRUE ,则 n n n 必为合数——证据 a a a 、以及程序返回 TRUE 的原因(它是从第六行、还是第八行返回?),为 n n n 是合数提供了一个证明。

在这里,我们简短地展示 WITNESS 的行为的另一种描述,将 WITNESS 作为一个序列 X = ⟨ x 0 , x 1 , … , x t ⟩ X = \langle x_0, x_1, \dots, x_t\rangle X=x0,x1,,xt 的函数,稍后在分析 Miller-Rabin 素数测试的效率时,会发现它很有用。注意,如果对某个 0 ≤ i < t 0 \le i < t 0i<t x i = 1 x_i = 1 xi=1 ,则 WITNESS 可能不会计算序列的余下部分。然而如果计算,则 x i + 1 , x i + 2 , … , x t x_{i + 1}, x_{i + 2}, \dots, x_t xi+1,xi+2,,xt 的值都将是 1 1 1 ,并且我们考虑序列 X X X 中的这些位置都是 1 1 1 。我们有四种情况:

  1. X = ⟨ … ,   d ⟩ X = \langle \dots,\ d\rangle X=, d ,其中 d ≠ 1 d \ne 1 d=1 :序列 1 1 1 不是以 1 1 1 结尾。从第八行返回 TRUE a a a n n n 为合数的一个证据(由费马小定理) ;
  2. X = ⟨ 1 ,   1 ,   … ,   1 ⟩ X= \langle 1,\ 1,\ \dots,\ 1 \rangle X=1, 1, , 1 :序列 X X X 全都是 1 1 1 。返回 FALSE a a a 不是 n n n 为合数的证据。
  3. X = ⟨ … ,   − 1 ,   1 ,   … ,   1 ⟩ X = \langle \dots,\ -1,\ 1,\ \dots,\ 1 \rangle X=, 1, 1, , 1 :序列 X X X 1 1 1 结尾,而且最后一个非 1 1 1 的数等于 − 1 -1 1 。返回 FALSE a a a 不是 n n n 为合数的证据。
  4. X = ⟨ … ,   d ,   1 ,   … ,   1 ⟩ X = \langle \dots,\ d,\ 1,\ \dots,\ 1 \rangle X=, d, 1, , 1 ,其中 d ≠ ± 1 d \ne \pm 1 d=±1 :序列 X X X 1 1 1 结尾,但最后一个非 1 1 1 的数不是 − 1 -1 1 。返回 TRUE a a a n n n 为合数的证据,因为 d d d 是一个 1 1 1 的非平凡平方根。

我们现在检验使用了 WITNESSMILLER-RABIN 素性测试。再一次,假设 n n n 是一个大于 2 2 2 的奇数。
在这里插入图片描述
过程 MILLER-RABIN 是为了「证明 n n n 是合数」所进行的概率性搜索。主循环(从第一行开始)从 Z n + \Z^+_n Zn+ 中挑选 s s s a a a 的随机值(第二行)。

  • 如果所挑选的一个 a a a 值是 n n n 为合数的证据,则过程 MILLER-RABIN 在第四行返回 COMPOSITE 。这样的结果总是正确的,由 WITNESS 的正确性证明可以看出。
  • 如果在 s s s 次试验中没有发现证据,则 MILLER-RABIN 假定这是因为证据不存在,因此假设 n n n 为素数。我们将看到,如果 s s s 足够大,则这个输出结果很可能是正确的,但也存在这样一种微小的可能性,即过程在选择 a a a 时运气不佳,虽然过程没有发现证据,但证据确实存在

为了说明 MILLER-RABIN 的操作过程,令 n n nCarmichael 561 561 561 ,使得 n − 1 = 560 = 2 4 ⋅ 35 n - 1 = 560 = 2^4 \cdot 35 n1=560=2435 ,于是 t = 4 , u = 35 t = 4, u =35 t=4,u=35 。假定过程选择 a = 7 a = 7 a=7 作为基,则(算导31.6节的)图31-4说明 WITNESS 计算 x 0 ≡ a 35 ≡ 241 ( m o d 561 ) x_0 \equiv a^{35} \equiv 241 \pmod {561} x0a35241(mod561) ,因此计算序列 X = ⟨ 241 , 298 , 166 , 67 , 1 ⟩ X = \langle 241, 298, 166, 67, 1 \rangle X=241,298,166,67,1 。所以,在最后一次平方步骤中发现了一个 1 1 1 的非平凡平方根,因为 a 280 ≡ 67 ( m o d n ) ,   a 560 ≡ 1 ( m o d n ) a^{280} \equiv 67 \pmod n,\ a^{560} \equiv 1 \pmod n a28067(modn), a5601(modn) 。因此, a = 7 a = 7 a=7 n n n 为合数的一个证据,WITNESS(7, n) 返回 TRUE ,因而 MILLER-RABIN 返回 COMPOSITE

如果 n n n 是一个 β \beta β 位数,则 MILLER-RABIN 需要执行 O ( s β ) O(s\beta) O(sβ) 次算术运算和 O ( s β 3 ) O(s \beta^3) O(sβ3) 次位操作,因为从渐近意义上说,它需要执行的工作仅是 s s s 次模取幂运算。

8.4 Miller-Rabin 素性测试的出错率

如果 MILLER-RABIN 返回 PRIME ,则它仍有一种很小的可能性会产生错误。然而,不像 PSEUDOPRIME出错的可能性并不依赖于 n n n ;对该过程而言,也不存在坏的输入。相反,它取决于 s s s 的大小和在选取基值 a a a 时“抽签的运气”。另外,由于每次测试都比「简单地检查等式 ( 31.40 ) (31.40) (31.40) 」更严格,因此从总的原则上,对随机选取的整数 n n n ,其出错率应该是很小的。下列定理阐述了一个更精确的论点。

定理31.38 如果 n n n 是一个奇合数,则 n n n 为合数的证据的数目至少为 n − 1 2 \dfrac{n-1}{2} 2n1
证明:证明过程说明了非证据的个数最多为 n − 1 2 \dfrac{n - 1}{2} 2n1 ,这蕴含着定理成立。

首先我们断言,任何非证据都必须是 Z n ∗ \Z^*_n Zn 的一个成员。为什么呢?考虑任意的非证据 a a a ,它必须满足 a n − 1 ≡ 1 ( m o d n ) a^{n-1} \equiv 1 \pmod n an11(modn) ,或者等价地 a ⋅ a n − 2 ≡ 1 ( m o d n ) a \cdot a^{n - 2} \equiv 1 \pmod n aan21(modn) 。因此,方程 a x ≡ 1 ( m o d n ) ax \equiv 1\pmod n ax1(modn) 有一个解,即 a n − 2 a^{n - 2} an2 。由推论31.21可知, g c d ( a , n ) ∣ 1 gcd(a, n) \mid 1 gcd(a,n)1 ,这反过来蕴含着 g c d ( a , n ) = 1 gcd(a, n) = 1 gcd(a,n)=1 。因此, a a a Z n ∗ \Z^*_n Zn 的一个成员,所有的非证据都属于 Z n ∗ \Z^*_n Zn
在这里插入图片描述
为了完成证明,要说明:所有的非证据不仅都被包含在 Z n ∗ \Z^*_n Zn 中,而且它们都被包含在 Z n ∗ \Z^*_n Zn 的一个真子群 B B B(回顾:如果 B B B Z n ∗ \Z^*_n Zn 的一个子群、但 B ≠ Z n ∗ B \ne \Z^*_n B=Zn ,则 B B B Z n ∗ \Z^*_n Zn 的一个真子群)。根据推论31.16,有 ∣ B ∣ ≤ ∣ Z n ∗ ∣ / 2 |B| \le | \Z^*_n | / 2 BZn/2 。因为 ∣ Z n ∗ ∣ ≤ n − 1 |\Z^*_n| \le n - 1 Znn1 ,所以得到 ∣ B ∣ ≤ ( n − 1 ) / 2 |B| \le (n - 1) / 2 B(n1)/2 。因此,非证据的个数至多是 ( n − 1 ) / 2 (n - 1) / 2 (n1)/2 ,所以证据的个数必须至少有 ( n − 1 ) / 2 (n - 1) / 2 (n1)/2 。下面说明,如何找出一个「 Z n ∗ \Z^*_n Zn 的包含所有非证据的真子群 B B B 」。具体分为两种情况。

情况一:存在一个 x ∈ Z n ∗ x \in \Z^*_n xZn ,使得: x n − 1 ≡   1 ( m o d n ) x^{n - 1} \cancel{\equiv}\ 1 \pmod n xn1  1(modn) 即, n n n 不是一个 Carmichael 数。如我们先前注意到的,因为 Carmichael 数极少,情况一是由“实际”所产生的主要情况(例如,这里 n n n 已经被随机选取,而且在被测试其素性)。

B = { b ∈ Z n ∗ ∣ b n − 1 ≡ 1 ( m o d n ) } B= \{ b \in \Z^*_n \mid b^{n - 1} \equiv 1 \pmod n \} B={bZnbn11(modn)} 。显然, B B B 是非空的,因为 1 ∈ B 1 \in B 1B 。因为 B B B 在模 n n n 的乘法下是封闭的,所以由定理31.14 B B B Z n ∗ \Z^*_n Zn 的一个子群。注意,每个非证据都属于 B B B ,因为一个非证据 a a a 满足 a n − 1 ≡ 1 ( m o d n ) a^{n - 1} \equiv 1 \pmod n an11(modn) 。因为 x ∈ Z n ∗ − B x \in \Z^*_n - B xZnB ,所以 B B B Z n ∗ \Z^*_n Zn 的一个真子群。

情况二:对所有的 z ∈ Z n ∗ z \in \Z^*_n zZn x n − 1 ≡ 1 ( m o d n ) (31.41) x^{n - 1} \equiv 1 \pmod n \tag{31.41} xn11(modn)(31.41) n n n 是一个 Carmichael 数。这种情况实际上非常少。然而,正如现在要说明的,Miller-Rabin 测试(不同于伪素数测试)可以有效地确定 Carmichael 数是合数。

在这种情况下, n n n 不可能是一个素数幂。为了明白为什么,反之我们假设 n = p e n = p^e n=pe ,其中 p p p 是一个素数, e > 1 e > 1 e>1 ,按如下方式推出矛盾。因为 n n n 假设是奇数,所以 p p p 也必须是奇数。定理31.32蕴含 Z n ∗ \Z^*_n Zn 是一个循环群:它包含一个生成元 g g g ,使得 o r d n ( g ) = ∣ Z n ∗ ∣ = ϕ ( n ) = p e ( 1 − 1 / p ) = ( p − 1 ) p e − 1 ord_n(g) = | \Z^*_n | = \phi(n) = p^e(1 - 1/ p) = (p - 1)p^{e - 1} ordn(g)=Zn=ϕ(n)=pe(11/p)=(p1)pe1 ϕ ( n ) \phi(n) ϕ(n) 的公式来自于等式 ( 31.20 ) (31.20) (31.20) )。根据式 ( 31.41 ) (31.41) (31.41) ,有 g n − 1 ≡ 1 ( m o d n ) g^{n - 1} \equiv 1 \pmod n gn11(modn) 。则离散对数定理(定理31.33,取 y = 0 y =0 y=0 )蕴含着 n − 1 ≡ 0 ( m o d ϕ ( n ) ) n - 1\equiv 0 \pmod { \phi(n) } n10(modϕ(n)) ,或者: ( p − 1 ) p e − 1 ∣ p e − 1 (p - 1) p^{e - 1} \mid p^e - 1 (p1)pe1pe1 这对 e > 1 e > 1 e>1 是一个矛盾,因为 ( p − 1 ) p e − 1 (p - 1) p^{e - 1} (p1)pe1 可以被素数 p p p 整除,但是 p e − 1 p^e - 1 pe1 不能(?)。因此, n n n 不是一个素数幂。

因为奇合数 n n n 不是一个素数幂,我们把它分解为一个积 n 1 n 2 n_1n_2 n1n2 ,其中 n 1 , n 2 n_1, n_2 n1,n2 都是大于 1 1 1 的奇数、且互质(有多种方法来做这个分解,选择哪一种并没有关系。例如,如果 n = p 1 e 1 p 2 e 2 … p r e r n = p_1^{e_1} p_2^{e_2} \dots p_r^{e_r} n=p1e1p2e2prer ,则可以选择 n 1 = p 1 e 1 ,   n 2 = p 2 e 2 p 3 e 3 … p r e r n_1 = p_1^{e_1},\ n_2 = p_2^{e_2} p_3^{e_3} \dots p_r^{e_r} n1=p1e1, n2=p2e2p3e3prer )。

回顾一下,定义 t , u t ,u t,u 使得 n − 1 = 2 t u n - 1 = 2^t u n1=2tu ,其中 t ≥ 1 t \ge 1 t1 u u u 是奇数,且对于输入 a a a ,过程 WITNESS 计算序列: X = ⟨ a u , a 2 u , a 2 2 u , … , a 2 t u ⟩ X = \langle a^u, a^{2u}, a^{2^2 u} , \dots, a^{2^t u} \rangle X=au,a2u,a22u,,a2tu (所有的计算都是根据模 n n n 计算的)。

如果 v ∈ Z n ∗ ,   j ∈ { 0 , 1 , … , t } v \in \Z^*_n,\ j \in \{ 0, 1, \dots, t\} vZn, j{0,1,,t} v 2 j u ≡ − 1 ( m o d n ) v^{2^j u} \equiv -1 \pmod n v2ju1(modn) ,则称整数对 ( v , j ) (v, j) (v,j)可接受的 acceptable 。可接受的对是肯定存在的,因为 u u u 是奇数;我们能选择 v = n − 1 ,   j = 0 v = n - 1,\ j = 0 v=n1, j=0 ,使得 ( n − 1 , 0 ) (n - 1, 0) (n1,0) 是一个可接受对。现在挑选最大可能的 j j j 使得存在一个可接受对 ( v , j ) (v, j) (v,j) ,并调整 v v v 使得 ( v , j ) (v, j) (v,j) 是一个可接受对。令: B = { x ∈ Z n ∗ ∣ x 2 j u ≡ ± 1 ( m o d n ) } B = \{ x \in \Z^*_n \mid x^{2^j u} \equiv \pm 1\pmod n\} B={xZnx2ju±1(modn)}

因为 B B B 在模 n n n 的乘法下是封闭的,故它是 Z n ∗ \Z^*_n Zn 的一个子群。因此由定理31.15 ∣ B ∣ |B| B 整除 ∣ Z n ∗ ∣ | \Z^*_n | Zn 。每个非证据都必定是 B B B 的成员,因为由一个非证据产生的序列 X X X 必须或全为 1 1 1 、或在第 j j j 个位置及之前包含一个 − 1 -1 1(根据 j j j 的最大性 maximality )(如果 ( a , j ′ ) (a, j') (a,j) 是可接受的,其中 a a a 是一个非证据,根据我们选择 j j j 的方式,我们必有 j ′ ≤ j j' \le j jj )。

我们现在,利用 v v v 的存在性说明,存在一个 w ∈ Z n ∗ − B w \in \Z^*_n - B wZnB ,且因此 B B B Z n ∗ \Z^*_n Zn 的一个子群。因为 v 2 j u ≡ − 1 ( m o d n ) v^{2^j u} \equiv -1 \pmod n v2ju1(modn) ,根据中国余数定理的推论31.29,有 v 2 j u ≡ − 1 ( m o d n 1 ) v^{2^j u} \equiv -1 \pmod {n_1} v2ju1(modn1) 。根据推论31.28,存在一个 w w w ,同时满足 w ≡ v ( m o d n 1 ) w ≡ 1 ( m o d n 2 ) w \equiv v \pmod {n_1} \\ w \equiv 1 \pmod {n_2} wv(modn1)w1(modn2)

因此, w 2 j u ≡ − 1 ( m o d n 1 ) w 2 j u ≡ 1 ( m o d n 2 ) \begin{aligned}w^{2^j u} &\equiv -1 &\pmod {n_1 } \\ w^{2^j u } &\equiv 1 &\pmod{ n_2 }\end{aligned} w2juw2ju11(modn1)(modn2)

推论31.29 w 2 j u   ≡   1 ( m o d n 1 ) w^{2^j u}\ \cancel{\equiv}\ 1 \pmod {n_1} w2ju   1(modn1) 蕴含着 w 2 j u   ≡   1 ( m o d n ) w^{2^j u}\ \cancel{\equiv}\ 1 \pmod n w2ju   1(modn) ,而且 w 2 j u   ≡   − 1 ( m o d n 2 ) w^{2^j u }\ \cancel{\equiv}\ -1 \pmod {n_2} w2ju   1(modn2) 蕴含着 w 2 j u   ≡   − 1 ( m o d n ) w^{2^j u }\ \cancel{\equiv}\ -1 \pmod n w2ju   1(modn) 。因此,得到结论: w 2 j u   ≡   ± 1 ( m o d n ) w^{2^j u} \ \cancel{\equiv} \ \pm 1\pmod n w2ju   ±1(modn) ,所以 w ∉ B w \notin B w/B

接下来还要证明 w ∈ Z n ∗ w \in \Z^*_n wZn 。首先分别对模 n 1 n_1 n1 和模 n 2 n_2 n2 进行处理。对模 n 1 n_1 n1 ,注意到因为 v ∈ Z n ∗ v \in \Z^*_n vZn ,有 g c d ( v , n ) = 1 gcd(v, n) = 1 gcd(v,n)=1 ;如果 v v v n n n 没有任何公约数,它当然不会与 n 1 n_1 n1 有任何公约数。因为 w ≡ v ( m o d n 1 ) w \equiv v\pmod {n_1} wv(modn1) ,我们看到 g c d ( w , n 1 ) = 1 gcd(w, n_1 ) = 1 gcd(w,n1)=1 。对模 n 2 n_2 n2 ,观察到 w ≡ 1 ( m o d n 2 ) w \equiv 1 \pmod {n_2} w1(modn2) 蕴含着 g c d ( w , n 2 ) = 1 gcd(w, n_2) = 1 gcd(w,n2)=1 。结合这些结果,利用定理31.6,这蕴含着 g c d ( w , n 1 n 2 ) = g c d ( w , n ) = 1 gcd(w, n_1 n_2) = gcd(w, n) = 1 gcd(w,n1n2)=gcd(w,n)=1 。也就是 w ∈ Z n ∗ w \in \Z^*_n wZn

因此 w ∈ Z n ∗ − B w \in \Z^*_n - B wZnB ,而且以 B B B Z n ∗ \Z^*_n Zn 的一个真子群的结论,完成情况二。

在两种情况中的任何一个,我们发现, n n n 为合数的证据的数目都至少为 ( n − 1 ) / 2 (n - 1)/2 (n1)/2 ■ \blacksquare

定理31.39 对于任意奇数 n > 2 n > 2 n>2 和正整数 s s sMILLER-RABIN(n, s) 出错的概率至多为 2 − s 2^{-s} 2s
证明:利用定理31.38,可以看到如果 n n n 是合数,则每次执行第 1 ∼ 4 1 \sim 4 14 行的 for 循环,发现 n n n 为合数的证据的概率至少为 1 / 2 1 / 2 1/2 。只有当 MILLER-RABIN 运气太差,在主循环总共 s s s 次迭代中,每一次都没能发现 n n n 为合数的证据时,过程才会出错。而这种每次都错过发现证据 such a sequence of misses 的概率至多为 2 − s 2^{-s} 2s ■ \blacksquare

如果 n n n 是素数,MILLER-RABIN 总是输出 PRIME ,而如果 n n n 是合数,MILLER-RABIN 输出 PRIME 的概率至多为 2 − s 2^{-s} 2s

然而,对于一个大随机整数使用 MILLER-RABIN 时,为了正确解释 MILLER-RABIN 的结果,我们需要考虑 n n n 是素数的优先概率。假设固定一个位长度 β \beta β ,并随机选择了一个长度为 β \beta β 位的整数来检测素性。令 A A A 表示 n n n 是素数的事件。由素数定理定理31.37), n n n 是素数的概率接近: P r ( A ) ≈ 1 ln ⁡ n ≈ 1.443 β Pr(A) \approx \dfrac{1}{\ln n} \approx \dfrac{1.443} { \beta} Pr(A)lnn1β1.443

现在,令 B B B 表示 MILLER-RABIN 返回 PRIME 的事件,我们有 P r ( B ‾ ∣ A ) = 0 Pr( \overline{B} \mid A) = 0 Pr(BA)=0(或者等价地 P r ( B ∣ A ) = 1 Pr(B \mid A ) =1 Pr(BA)=1 )和 P r ( B ∣ A ‾ ) ≤ 2 − s Pr(B \mid \overline {A})\le 2^{-s} Pr(BA)2s(或者等价地 P r ( B ‾ ∣ A ‾ ) > 1 − 2 − s Pr( \overline {B} \mid \overline{A} ) > 1 - 2^{-s} Pr(BA)>12s )。但是,在 MILLER-RABIN 返回 PRIME 的情况下, n n n 是素数的概率 P r ( A ∣ B ) Pr(A \mid B) Pr(AB) 是多少呢?通过贝叶斯定理 Bayes's theorem 的变形(算导等式 C . 18 C.18 C.18 ),有: P r ( A ∣ B ) = P r ( A ) P r ( B ∣ A ) P r ( A ) P r ( B ∣ A ) + P r ( A ‾ ) P r ( B ∣ A ‾ ) ≈ 1 1 + 2 − s ( ln ⁡ n − 1 ) Pr(A \mid B) = \dfrac{ Pr(A) Pr(B \mid A) } { Pr(A) Pr(B \mid A) + Pr( \overline {A} ) Pr(B \mid \overline {A} ) } \approx \dfrac{1}{ 1+ 2^{-s} (\ln n - 1)} Pr(AB)=Pr(A)Pr(BA)+Pr(A)Pr(BA)Pr(A)Pr(BA)1+2s(lnn1)1

s s s 超过 log ⁡ ( ln ⁡ n − 1 ) \log (\ln n - 1) log(lnn1) 之前,这个概率不超过 1 / 2 1 / 2 1/2 。直观上,为了得到信心(由于不能找到 n n n 是合数的证据),来克服「对于 n n n 是合数的优先偏好 the prior bias in favor of n being composite 」,我们需要很多次初始测试。对于一个有 β = 1024 \beta = 1024 β=1024 位的数,初始测试大概需要 log ⁡ ( ln ⁡ n − 1 ) ≈ log ⁡ ( β / 1.443 ) ≈ 9 \log ( \ln n - 1)\approx \log (\beta / 1.443) \approx 9 log(lnn1)log(β/1.443)9 次。在任何情况下,对几乎所有可以想象到的应用,选取 s = 50 s = 50 s=50 应该是足够的。

事实上,情况要更好。如果我们尝试通过对随机选取的大奇整数应用 MILLER-RABIN 来找出大素数,则选取较小的 s s s 值(如 3 3 3 )也是相当程度上不太可能导致错误的结论(在此不做证明)。原因是,对一个随机选取的奇合数 n n n n n n 为合数的非证据的预计数目可能要比 ( n − 1 ) / 2 (n - 1) / 2 (n1)/2 少得多。

然而,如果整数 n n n 不是随机选取的,则运用改进版本的定理31.38,所能证明的最佳结论是非证据的数目至多为 ( n − 1 ) / 4 (n - 1) /4 (n1)/4 。并且,确实存在整数 n n n 、使得非证据的数目就是 ( n − 1 ) / 4 (n - 1)/ 4 (n1)/4


9. 整数的因子分解

假设希望将一个整数 n n n 进行因子分解,也就是分解为素数的积。通过上一节讨论的素数测试,可以知道 n n n 是否为合数,但它并不能指出 n n n 的素数因子。对一个大整数 n n n 进行因子分解,似乎要比仅确定 n n n 是素数还是合数要困难得多。即使用当今的超级计算机和现行的最佳算法,要对任意一个 1024 1024 1024 位的数进行因子分解也还是不可行的。

9.1 Pollardrho 启发式方法

对小于等于 R R R 的所有整数进行试除,保证完全获得小于等于 R 2 R^2 R2 的任意数的因子分解。下列过程 POLLARD-RHO 用相同的工作量,就能对小于等于 R 4 R^4 R4 的任意整数进行因子分解(除非运气不佳)。由于该过程仅仅是一种启发性方法,因此既不能保证其运行时间、也不能保证其运行成功,尽管该过程在实际应用中非常有效。POLLARD-RHO 过程的另一个优点是,它只使用常量的存储空间(如果愿意,可以很容易在计算机上实现 POLLARD-RHO 、找出小整数的因子)。

其执行过程如下。第一至二行把 i i i 初始化为 1 1 1 ,把 x 1 x_1 x1 初始化为 Z n \Z_n Zn 中一个随机选取的值、第五行开始的 while 循环将一直进行迭代来搜索 n n n 的因子。在 while 循环的每一次迭代中,第七行使用递归式: x i = ( x i − 1 2 − 1 )   m o d   n (31.43) x_i = (x_{i - 1} ^ 2 - 1) \bmod n \tag{31.43} xi=(xi121)modn(31.43) 计算无穷序列 x 1 , x 2 , x 3 , x 4 , … (31.44) x_1, x_2, x_3, x_4, \dots \tag{31.44} x1,x2,x3,x4,(31.44) x i x_i xi 的下一个值,其中 i i i 的值在第六行中进行相应的自增。为了清楚,伪代码使用了下标变量 x i x_i xi ,但即使去掉了所有的下标,程序也以同样的方式执行,因为仅需要保留最近计算出的 x i x_i xi 值。经过这个修改,此过程只使用了一个常量的存储空间。
在这里插入图片描述

程序不时地把最近计算出的 x i x_i xi 的值存入变量 y y y 中。具体来说,存储的值是那些下标为 2 2 2 的幂的变量:
x 1 , x 2 , x 4 , x 8 , x 16 , … x_1, x_2, x_4, x_8, x_{16}, \dots x1,x2,x4,x8,x16, 第三行保存至 x 1 x_1 x1 ,每当 i = k i = k i=k 时第 12 12 12 行就保存值 x k x_k xk ,并且每当第 12 12 12 行更新 y y y 、第十三行就将 k k k 的值加倍。因此, k k k 的值序列为 1 , 2 , 4 , 8 , … 1, 2, 4, 8, \dots 1,2,4,8, ,并且总是给出要存入 y y y 的下一个 x k x_k xk 的下标。

第八到十行尝试用「存入 y y y 的值和 x i x_i xi 的当前值」找出 n n n 的一个因子。特别地,第八行计算出最大公约数 d = g c d ( y − x i , n ) d = gcd(y - x_i, n) d=gcd(yxi,n) 。如果第九行中发现了 d d d n n n 的非平凡约数,则第十行输出 d d d 的值。

最初,这一寻找因子分解的过程似乎有点神秘,但是注意,POLLARD-RHO 绝不会输出错误的答案;它输出的任何数都是 n n n 的一个非平凡约数。尽管 POLLARD-RHO 可能不输出任何信息,也没有保证它能输出约数。不过我们将看到,我们有充足的理由预计:POLLARD-RHO 在 while 循环大约执行 Θ ( p ) \Theta( \sqrt{ p}) Θ(p ) 次迭代后,会输出 n n n 的一个因子 p p p 。因此,如果 n n n 是合数,我们可以期望这个过程在经过大约 n 1 / 4 n^{1/4} n1/4 次的更新后,找出足够多的约数来完全因子分解 n n n ,这是由于除了可能有的最大的一个素因子外、 n n n 的每个素因子 p p p 都小于 n \sqrt{n} n

9.2 算法分析

我们分析一下,要经过多久一个模 n n n 的随机序列中才会重复出现一个值,就可以了解这个过程的性能。由于 Z n \Z_n Zn 是有限的,并且序列 ( 31.44 ) (31.44) (31.44) 中的每个值仅仅取决于前一个值,所以序列 ( 31.44 ) (31.44) (31.44) 最终将产生自身重复。一旦我们达到一个 x i x_i xi ,它满足对某个 j < i j < i j<i x i = x j x_i = x_j xi=xj ,则我们处在一个回路中,因为 x i + 1 = x j + 1 x_{i + 1} = x_{j + 1} xi+1=xj+1 x i + 2 = x j + 2 x_{i + 2} = x_{j + 2} xi+2=xj+2 等等。该过程取名为 rho 启发式方法的原因就在于(如图31-7所示)序列 x 1 , x 2 , … , x j − 1 x_1, x_2, \dots, x_{j - 1} x1,x2,,xj1 可以画成 ρ \rho ρ 的尾,而回路 x j , x j + 1 , … , x i x_j, x_{j + 1}, \dots, x_i xj,xj+1,,xi 可以画成 ρ \rho ρ 的“体”。
在这里插入图片描述
下面考虑一个问题: x i x_i xi 的序列发生重复需要多久?实际上,这个问题的答案并不是我们恰好需要的,但我们将在后面看到如何修改这个论点。为了进行估算,假定函数: f n ( x ) = ( x 2 − 1 )   m o d   n f_n(x)= (x^2 - 1) \bmod n fn(x)=(x21)modn 像一个随机函数那样进行计算,当然它并不是一个真正的随机函数,但由这个假设所得的结论、与我们对 POLLARD-RHO 行为的观察是一致的。我们然后将每个 x i x_i xi 视为「根据 Z n \Z_n Zn 上的一个均匀分布」从 Z n \Z_n Zn 中独立选取的。根据(算导5.4.1节中)对生日悖论的分析,在序列出现回路之前期望要执行的步数为 Θ ( n ) \Theta(\sqrt{n}) Θ(n )

现在根据要求进行适当修改。令 p p p 是满足 g c d ( p , n / p ) = 1 gcd(p, n / p)= 1 gcd(p,n/p)=1 n n n 的一个非平凡因子。例如,如果 n n n 的因子分解为 n = p 1 e 1 p 2 e 2 … p r e r n = p_1^{e_1} p_2^{e_2} \dots p_r^{e_r} n=p1e1p2e2prer ,则可以取 p p p 的值为 p 1 e 1 p_1^{e_1} p1e1(如果 e 1 = 1 e_1 = 1 e1=1 ,则 p p p 就是 n n n 的最小素数因子,这是一个好的例子、可以牢记)。

序列 ⟨ x i ⟩ \langle x_i \rangle xi 导出 induces 一个相应的模 p p p 的序列 ⟨ x i ′ ⟩ \langle x_i' \rangle xi ,其中对所有 i i i ,有 x i ′ = x i   m o d   p x_i' = x_i \bmod p xi=ximodp

更进一步,因为 f n f_n fn 是仅使用模 n n n 算术操作(平方和减法)定义的,我们能从 x i ′ x_i' xi 来计算 x i + 1 ′ x_{i+1}' xi+1 ;这一序列从模 p p p 的角度看,是从模 n n n 的角度看的一个较小版本:
x i + 1 ′ = x i + 1   m o d   p = f n ( x i )   m o d   p = ( ( x i 2 − 1 )   m o d   n )   m o d   p = ( x i 2 − 1 )   m o d   p 根 据 练 习 31.1 − 7 = ( ( x i   m o d   p ) 2 − 1 )   m o d   p = ( ( x i ′ ) 2 − 1 )   m o d   p = f p ( x i ′ ) \begin{aligned} x_{i+1}' &= x_{i+1} \bmod p \\ &= f_n(x_i) \bmod p \\ &= (( x_i^2 - 1) \bmod n) \bmod p \\ &= ( x_i^2- 1) \bmod p \quad &根据练习31.1-7 \\ &= (( x_i \bmod p)^2 - 1) \bmod p \\ &= ((x_i') ^ 2 - 1) \bmod p \\ &= f_p(x_i') \end{aligned} xi+1=xi+1modp=fn(xi)modp=((xi21)modn)modp=(xi21)modp=((ximodp)21)modp=((xi)21)modp=fp(xi)31.17 因此,虽然我们没有显式计算序列 ⟨ x i ′ ⟩ \langle x_i' \rangle xi ,但这个序列是良定义的,而且与序列 ⟨ x i ⟩ \langle x_i \rangle xi 有相同的递归式。

像之前一样进行推论,我们可以发现在序列 ⟨ x ′ ⟩ \langle x' \rangle x 重复之前、预计执行的步数是 Θ ( p ) \Theta(\sqrt{ p}) Θ(p ) 。如果和 n n n 相比 p p p 更小,则序列 ⟨ x i ′ ⟩ \langle x_i' \rangle xi 的重复可能比序列 ⟨ x i ⟩ \langle x_i \rangle xi 的重复要快得多。事实上,只要序列 ⟨ x i ⟩ \langle x_i \rangle xi 中的两个元素仅模 p p p 等价、而非模 n n n 等价,序列 ⟨ x i ′ ⟩ \langle x_i' \rangle xi 就发生重复。图31-7(b)和c)说明了这一点。

t t t 表示 ⟨ x i ′ ⟩ \langle x'_i\rangle xi 序列中第一个重复出现的值的下标,让 u > 0 u > 0 u>0 表示这样产生的循环回路的长度。这就是说, t t t u > 0 u > 0 u>0 是对所有 i ≥ 0 i \ge 0 i0 满足条件 x t + i ′ = x t + u + i ′ x_{t +i}' = x_{t+u+i}' xt+i=xt+u+i 的最小值。根据上面的论证, t , u t, u t,u 的期望值都是 Θ ( p ) \Theta(\sqrt{p}) Θ(p ) 。注意,如果 x t + i ′ = x t + u + i ′ x_{t+i}' = x_{t + u + i}' xt+i=xt+u+i ,则 p ∣ ( x t + u + i − x t + i ) p \mid (x_{t + u + i} - x_{t + i}) p(xt+u+ixt+i) 。因此, g c d ( x t + u + i − x t + i , n ) > 1 gcd(x_{t + u + i} - x_{t + i}, n) > 1 gcd(xt+u+ixt+i,n)>1

因此,只要 POLLARD-RHO 把「使得 k ≥ t k \ge t kt 的任何值 x k x_k xk 」都存入变量 y y y ,则 y   m o d   p y \bmod p ymodp 总在模 p p p 的回路中 on the cycle modulo p(如果把一个新值存为 y y y ,则该值也在模 p p p 的回路中)。最终, k k k 将被赋予一个大于 u u u 的值,然后过程就在不改变 y y y 值的情况下,沿着模为 p p p 的回路完成整个一次循环。 x i x_i xi “遇到”以前存储在 y y y 中的模 p p p 的值时,即 x i ≡ y ( m o d p ) x_i \equiv y \pmod p xiy(modp) ,就发现了 n n n 的一个因子

假定发现的因子是因子 p p p ,尽管偶尔也可能是 p p p 的倍数。由于 t , u t, u t,u 的期望值都是 Θ ( p ) \Theta(\sqrt{p}) Θ(p ) ,所以产生因子 p p p 所要求的期望执行步数为 Θ ( p ) \Theta(\sqrt{p}) Θ(p )

该算法可能不会如期望地执行,有两个原因:

  1. 对运行时间的启发式分析并不严格,模 p p p 的值的回路有可能要比 p \sqrt{p} p 大得多。在这种情况下,虽然算法的执行正确,但其执行速度要比期望低得多。在实际应用中,这似乎还可以讨论。
  2. 第二,这一算法得出的 n n n 的约数可能总是平凡因子 1 1 1 n n n 。例如,假设 n = p q n = pq n=pq ,这里 p , q p, q p,q 为素数,可能会出现下面的情形:关于 p p p t , u t, u t,u 的值与关于 q q q t , u t, u t,u 的值相等,所以因子 p , q p, q p,q 总是在相同的 g c d gcd gcd 运算中被展现。由于两个因子同时被呈现,因此也就呈现出无用的平凡分解 p q = n pq = n pq=n the trivial factor pq D n is revealed, which is useless 。这在实际应用中似乎没有意义。如果需要,可用一个不同形式的递归式 x i + 1 = ( x i 2 − c )   m o d   n x_{i+1} = (x_i^2 - c) \bmod n xi+1=(xi2c)modn 来重新开始运行该启发式过程(值 c = 0 , c = 2 c = 0, c = 2 c=0,c=2 应该被避免,其原因这里不做说明,但对其他值没有问题)。

当然,上述分析过程是启发式的、而不是严格的,因为递归式并不真是随机的。然而,这个过程可以在实际应用中良好地运行,并且似乎和我们在上面的启发式分析中说明的一样有效。它是一种找出大整数的小素数因子的、可供选择的方法 It is the method of choice for finding small prime factors of a large number

为了对一个 β \beta β 位合数 n n n 完全分解因子,仅需找出所有小于 ⌊ n 1 / 2 ⌋ \lfloor n^{1/2} \rfloor n1/2 的素数因子就可以了,因此我们期望 POLLARD-RHO 需执行的算术运算至多为 n 1 / 4 = 2 β / 4 n^{1/4} = 2^{ \beta / 4} n1/4=2β/4 次,位操作至多为 n 1 / 4 β 2 = 2 β / 4 β 2 n^{1/4} \beta^2 = 2^{\beta / 4} \beta^2 n1/4β2=2β/4β2 次。POLLARD-RHO 最具吸引力的特点就是,它可以在期望的 Θ ( p ) \Theta(\sqrt{p}) Θ(p ) 次算术运算内,找出 n n n 的一个小因子 p p p

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

memcpy0

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值