分解因子算法——Pollard rho算法

分解因子算法——Pollard ρ \rhoρ 算法

攻击RSA密码体制最明显的方法就是分解大整数。关于大整数分解的算法有许多,常见的有试除法、p ± 1 p\pm1p±1算法、Pollard ρ \rhoρ算法、数域筛法、二次筛法等等。这篇分享的就是其中之一的Pollard ρ \rhoρ算法。

我们说因子分解,很多时候并不一定要把大整数n nn彻底分解成素数乘积,而是求出n nn的某个非平凡因子即可。求大整数的一个因子固然困难,但是Euclidean算法告诉我们求两个数的最大公因子是可以在O ( log ⁡ n ) O(\log n)O(logn)的时间得到的。Pollard ρ \rhoρ算法利用的就是这个思想。

问题描述

设大整数为n nn,我们要找到n nn的一个因子p pp

Pollard ρ \rhoρ 算法

为了利用Euclidean算法找到p pp,我们设想存在两个整数x , x ′ ∈ Z n x,x'\in \mathbb{Z}_{n}xxZn,满足x ≡ x ′ ( m o d p ) x\equiv x'\pmod{p}xx(modp),这样的话就有p ∣ ( x − x ′ ) p|(x-x')p(xx),又因为p ∣ n p|npn,所以有p ≤ g c d ( x − x ′ , n ) < n p\le gcd(x-x',n)<npgcd(xx,n)<n——这句话的意思是:g c d ( x − x ′ , n ) gcd(x-x',n)gcd(xx,n)一定是n nn的非平凡因子。这就完成了因子分解。问题归结为:如何找到满足条件的x xxx ′ x'x

一个朴素的想法就是:随机选择一个子集X ⊂ Z n X\subset \mathbb{Z}_{n}XZn,然后对所有不同的x , x ′ ∈ X x,x'\in Xx,xX,判断g c d ( x − x ′ , n ) gcd(x-x',n)gcd(xx,n)是否为1。这个方法能够成功当且仅当映射x → x ( m o d p ) x \rarr x\pmod{p}xx(modp)X XX中至少存在一个碰撞。根据生日攻击可以分析:如果∣ X ∣ ≈ 1.71 p |X| \approx 1.71\sqrt{p}X1.71p时,至少存在一个碰撞的概率是50%,为了找到X XX中存在的这个碰撞,我们需要求( ∣ X ∣ 2 ) \begin{pmatrix}|X|\\2 \end{pmatrix}(X2)次gcd。

Pollard ρ \rhoρ算法减少了求解gcd的次数。它并不是随机产生一个子集X XX,而是事先确定一个整系数多项式f ff,并取x 1 ∈ Z n x_{1}\in \mathbb{Z}_{n}x1Zn,令
x i + 1 = f ( x i ) m o d n , i = 1 , 2 , 3 ⋯ x_{i+1}=f(x_{i})\mod{n},i=1,2,3\cdotsxi+1=f(xi)modni=1,2,3
这就产生了集合X = { x 1 , x 2 , ⋯ , x m } X=\lbrace x_{1},x_{2},\cdots,x_{m} \rbraceX={x1,x2,,xm}。下面描述这个集合是如何减少gcd计算次数的。

核心思想:如果x i ≡ x j ( m o d p ) x_{i}\equiv x_{j} \pmod{p}xixj(modp),由于f ff是整系数多项式,所以f ( x i ) ≡ f ( x j ) ( m o d p ) f(x_{i})\equiv f(x_{j}) \pmod{p}f(xi)f(xj)(modp) 。又因为p ∣ n p|npn,所以
x i + 1 m o d p = ( f ( x i ) m o d n ) m o d p = f ( x i ) m o d p x_{i+1}\mod{p}=(f(x_{i})\mod{n})\mod{p}=f(x_{i})\mod{p}xi+1modp=(f(xi)modn)modp=f(xi)modp
同理有x j + 1 m o d p = f ( x j ) m o d p x_{j+1}\mod{p}=f(x_{j})\mod{p}xj+1modp=f(xj)modp。因此x i + 1 ≡ x j + 1 ( m o d p ) x_{i+1} \equiv x_{j+1}\pmod{p}xi+1xj+1(modp)

进一步有:如果x i ≡ x j ( m o d p ) x_{i}\equiv x_{j} \pmod{p}xixj(modp),则对∀ δ ≥ 0 \forall \delta \ge0δ0 ,有x i + δ ≡ x j + δ ( m o d p ) x_{i+\delta}\equiv x_{j+\delta} \pmod{p}xi+δxj+δ(modp)

l = j − i l=j-il=ji,可知x i ′ ≡ x j ′ ( m o d p ) x_{i'} \equiv x_{j'} \pmod{p}xixj(modp)如果j ′ ≥ i ′ ≥ i j'\ge i'\ge ijiij ′ − i ′ ≡ 0 ( m o d l ) j'-i'\equiv0\pmod{l}ji0(modl)

这样序列X就可以看成带有一个“尾巴”
x 1 → x 2 → ⋯ → x i ( m o d p ) x_{1}\rarr x_{2} \rarr \cdots \rarr x_{i} \pmod{p}x1x2xi(modp)
和一个“环”
x i → x i + 1 → ⋯ → x j = x i ( m o d p ) x_{i} \rarr x_{i+1} \rarr \cdots \rarr x_{j}=x_{i} \pmod{p}xixi+1xj=xi(modp)
看成图的话就像希腊字母ρ \rhoρ,这正是算法名字的由来。

对这个算法,我们需要计算( j − 1 2 ) + i \begin{pmatrix}j-1\\2 \end{pmatrix}+i(j12)+i次gcd才能得到第一个碰撞x i , x j x_{i},x_{j}xi,xj

进一步改进:我们只要求得一个碰撞即可,不一定是x i x_{i}xix j x_{j}xj,也可以是x i + δ x_{i+\delta}xi+δx j + δ x_{j+\delta}xj+δ。所以在找碰撞的时候,不必逐个逐个求gcd,可以跳跃着求。我们断言:在第一个“环”x i → x i + 1 → ⋯ → x j = x i ( m o d p ) x_{i} \rarr x_{i+1} \rarr \cdots \rarr x_{j}=x_{i} \pmod{p}xixi+1xj=xi(modp)中,一定存在i ′ i'i满足x 2 i ′ ≡ x i ′ ( m o d p ) x_{2i'} \equiv x_{i'}\pmod{p}x2ixi(modp)。事实上,只要2 i ′ − i ′ = i ′ = k l 2i'-i'=i'=kl2ii=i=kl,就有x 2 i ′ ≡ x i ′ ( m o d p ) x_{2i'} \equiv x_{i'}\pmod{p}x2ixi(modp)成立;而i ≤ i ′ = k l ≤ j − 1 i\le i'=kl\le j-1ii=klj1,所以最多找j jj次就可以得到i ′ i'i

算法流程

Pollard ρ \rhoρ (n,x 1 x_{1}x1)

x = x 1 , x ′ = f ( x ) m o d n x=x_{1},x'=f(x)\mod{n}x=x1x=f(x)modn

p = g c d ( x − x ′ , n ) p=gcd(x-x',n)p=gcd(xx,n)

while p = = 1 p==1p==1

      //第i次迭代

​      x = x i , x ′ = x 2 i x=x_{i},x'=x_{2i}x=xi,x=x2i

​       x = f ( x ) m o d p x=f(x)\mod{p}x=f(x)modp

​       x ′ = f ( x ′ ) m o d p x'=f(x')\mod{p}x=f(x)modp

​       x ′ = f ( x ′ ) m o d p x'=f(x')\mod{p}x=f(x)modp

​       p = g c d ( x − x ′ , n ) p=gcd(x-x',n)p=gcd(xx,n)

end

if p==n

​       return “failure”

else

​      return p

算法性能分析

假设f = x 2 + 1 f=x^{2}+1f=x2+1,则j jj的最大值为p \sqrt{p}p(因为x j x_{j}xj是第一个环中的数),所以最多需要p \sqrt{p}p次gcd计算。而p < n p<\sqrt{n}p<n,所以算法的期望复杂度是O ( n 1 4 ) O(n^{\frac{1}{4}})O(n41)。需要强调的是,这是一个启发式算法,不是严格的数学证明。算法可能会失败,此时是因为子集X XX中没有碰撞,需要重新选择初始值x 1 x_{1}x1或者选择不同的函数f ff产生新的集合X XX

例子

n = 7171 n=7171n=7171f ( x ) = x 2 + 1 , x 1 = 1 f(x) = x^{2}+1,x_{1} = 1f(x)=x2+1x1=1

计算集合X XX部分元素为:
1 , 2 , 5 , 26 , 677 , 6557 , 4105 , 6347 , 4903 , 2218 , 219 , 4936 , 4210 , 4560 , 4872 , 375 , 4377 , 4389 , 2016 , 5471 , 88 ⋯ 1,2,5,26,677,6557,4105,6347,4903,2218,219,4936,4210,4560,4872,375,4377,4389,2016,5471,88\cdots1,2,5,26,677,6557,4105,6347,4903,2218,219,4936,4210,4560,4872,375,4377,4389,2016,5471,88
计算g c d ( x 1 − x 2 , n ) , g c d ( x 2 − x 4 , n ) , g c d ( x 3 − x 6 , n ) ⋯ gcd(x_{1}-x_{2},n),gcd(x_{2}-x_{4},n),gcd(x_{3}-x_{6},n)\cdotsgcd(x1x2n),gcd(x2x4,n),gcd(x3x6,n),发现g c d ( x 11 − x 22 , n ) = 71 gcd(x_{11}-x_{22}, n)=71gcd(x11x22,n)=71,这就找到了n nn的一个因子71。

参考书籍:Stinson D , 斯廷森, 冯登国. 密码学原理与实践[M]. 电子工业出版社, 2009.


版权声明:本文为weixin_46395886原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。