從前面兩篇的內容可以知道對於RSA密碼體制,最為明顯的攻擊方式就是試圖分解模數。對於大整數分解目前最為有效的三種算法是二次篩法、橢圓曲線分解算法以及數域篩法,其他作為先驅的著名包括Pollard的$\rho$算法和$p-1$算法、Willian的$p+1$算法、連分式算法,當然還有試除法,這篇文章就根據課本的介紹總結這些算法。首先假定要分解的整數n為奇數。
一、試除法
試除法的思想是最為簡單的,假設n為合數,那么它肯定有一個素因子滿足$\rho \leq \lfloor \sqrt{n} \rfloor$,因此,只要利用$\lfloor \sqrt{n} \rfloor$的每個奇數去除n,這就足以判斷n是素數還是合數。該算法在$n < 10^{12}$時還是不錯的算法。
二、Pollard p-1算法
這個算法有兩個輸入,待分解的奇整數以及一個預先指定的階B,本質來源是一個簡單的數學證明,我們來先看看算法。
Alg1 Pollard p-1 Factoring Algorithm(n,B)
$ a \leftarrow 2$
for $j \leftarrow 2$ to B
$a \leftarrow a^{j} mod \, n$
$d \leftarrow gcd(a-1 , n)$
if $1 < d < n$
then return(d)
else return("failure")
算法的證明過程如下,關鍵是在for循環中的操作以及之后的求最大公約數。假定p是n的一個素因子,又假定對每一個素數冪$q | (p-1)$,有$q \leq B$,那么在這種情形下必須有$$ (p-1) | B! \quad (因為B!包含有q)$$
在for循環結束時,我們有$$a \equiv 2^{B!} (mod \, n)$$
由於$p | n$,一定有$$a \equiv 2^{B!} (mod \, p)$$
現在,由Fermat定理可知$$2^{p-1} \equiv 1 (mod \, p)$$
由於$(p-1) | B!$可知,得$$a \equiv 1 (mod \, p)$$
因此有$p|(a-1)$,由於已經有$p|n$,可以看到$p | d$,其中$d = gcd(a-1 , n)$,因此整數d就是n的一個非平凡因子。
接下來要討論的是B值,這個算法中,一共有B-1個模指數,利用“平方-乘”算法計算每一個模指數需要至多$2lbB$個模乘法,gcd的計算可以利用Euclidean算法在時間$o((logn)^{3})$內完成,因此整個算法的時間復雜度是$o(BlogB(logn)^{2}+(logn)^{3})$。如果B也是$o((logn)^{i})$,那么該算法就是關於$logn$的多項式時間算法,只是這樣子選擇的B,算法想要得到的d的概率是很小的。另一方面,如果B迅速增大,算法的執行效率不會比試除法快。
對於B值還要討論的一個問題是,我們不能使B值太大,否則B!會是一個很可觀的數字,換言之它要求對於p值不僅為n的素因子,而且$p-1$只有小的素因子。因此很容易構造出RSA模$n=pq$使得$p-1$分解算法失效。一般的方法是選擇兩個大素數$p_{1}$和$q_{1}$,使得$p = 2p_{1}+1$和$q=2q_{1}+1$也是素數,此時,RSA模$n=pq$將能抵抗$p-1$方法的分解。
三、Pollard ρ算法
設p為n的最小素因子,假定存在兩個整數$x,x^{'} \in Z_{n}$,使得$x \neq x^{'}$且$x \equiv x^{'} (mod \, p)$,那么有$p \leq gcd(x-x^{'} , n) < n$,所以,我們通過計算最大公因子得到n的一個非平凡因子,注意到並不需要事先知道p的值。
由於不知道p值,那么我們怎么選擇這兩個值呢,可以通過先選擇一個隨機子集$X \subseteq Z_{n}$來分解n,然后對所有不同的$x , x^{'} \in X$計算$gcd(x-x^{'},n)$,這個方法能夠成功當且僅當映射$x \longrightarrow x (mod \, p)$對於$x \in X$得到至少一個碰撞,利用生日悖論,我們可以發現當X達到一定程度時,發生碰撞的概率還是非常大的。然而為了尋找這個碰撞,我們要計算$gcd(x-x^{'} , n)$,這就陷入了一個死循環,意味着,在找到p因子之前,至少要做$\binom{|x|}{2} > \frac{p}{2} $次的gcd。
Pollard $\rho$算法集成了這個技巧的一個變形,僅僅需要較少的gcd計算,假定f為一個具有整系數的多項式,比如$f(x) = x^{2} + a$,其中a為一個小常數,假定映射$x \longrightarrow f(x) mod \, p$類似於一個隨機映射,考慮序列$x_{1},x_{2},…,x_{n},…… \in Z_{n}$其中有$$x_{j} = f(x_{j-1}) mod \, n$$對於所有的$j \geq 2$,令m為一個整數,且定義$X=\{ x_{1},x_{2},…,x_{m} \}$,為了簡單起見,假定X直接包含了m個不同的模n剩余,希望X為$Z_{n}$的m個元素的隨機子集。
我們來尋找兩個不同的值$x_{i},x_{j} \in X$使得$gcd(x_{j} - x_{i} , n) > 1$,每次計算序列中的一個新項$x_{j}$,對所有的$i < j$計算$gcd(x_{j} - x_{i},n)$,這樣子就做到了大大減少gcd計算的次數,但是要證明一下為什么可以這么做。
假定$x_{i} \equiv x_{j} (mod \, p)$,利用f為整系數多項式這個事實,有$f(x_{i}) \equiv f(x_{j}) (mod \, p)$,由於$x_{i+1} = f(x_{i}) (mod \, n)$且$x_{j+1} = f(x_{j}) (mod \, n)$,那么有$$x_{i+1} mod \, p = (f(x_{i}) mod \, n)mod \, p = f(x_{i}) mod \, p$$因為$p | n$,類似的$$x_{j+1} mod \, p = f(x_{j}) mod \, p$$因此有$x_{i+1} \equiv x_{j+1} (mod \, p)$。重復上述過程就可以得到結論:
如果$x_{i} \equiv x_{j} (mod \, p)$,那么有$x_{i+ \delta} \equiv x_{j + \delta} (mod \, p)$,對於所有的整數$\delta \geq 0$,記$l = j - i$,得到$x_{i^{'}} \equiv x_{j^{'}} (mod \, p)$如果$ j^{'} > i^{'} \geq i$且$j^{'} - i^{'} \equiv 0 (mod \, l)$。
假定我們利用頂點集$Z_{p}$構造一個圖G,其中對於$ i \geq 1$,從點$x_{i} (mod \, p)$向點$x_{i+1} (mod \, p)$做一條邊,存在第一個點對$x_{i},x_{p}$且$i < j$使得$x_{i} \equiv x_{j} (mod \, p)$,因此可以構造出這樣子的一個圖$$x_{1} (mod \, p) \rightarrow x_{2} (mod \, p) \rightarrow x_{3} (mod \, p) \rightarrow … \rightarrow x_{i} (mod \, p) $$ $$ x_{i} (mod \, p) \rightarrow x_{i+1} (mod \, p) \rightarrow x_{i+2} (mod \, p) \rightarrow …… \rightarrow x_{j} (mod \, p) \rightarrow x_{i} (mod \, p) $$
從而這條鏈看上去就是一個字母$\rho$。
通常在算法中會取$j = 2i$來尋找碰撞,算法如下所示。
Alg2 Pollard $\rho$ Factoring Algorithm(n,x_{1})
external f
$x \leftarrow x_{1}$
$x^{'} \leftarrow f(x) mod \, n$
$p \leftarrow gcd(x - x^{'} , n)$
while p = 1
// in the ith iteration, $x = x_{i}$ and $x^{'} = x_{2i}$
$x \leftarrow f(x) (mod \, n)$
$x^{'} \leftarrow f(x^{'}) (mod \, n)$
$p \leftarrow gcd(x - x^{'} , n)$
if $p = n$
then return ("failure")
else return (p)
前面有$l = j - i$,如果$x_{i} \equiv x_{j} (mod \, p)$,那么對於所有滿足$i^{'} \equiv 0 (mod \, l),i^{'} \geq i$有$x_{i^{'}} \equiv x_{(2i)^{'}} (mod \, l)$,在$l$個連續整數$i,i+1,…,j-1$,必然存在一個數可以被$l$整除,滿足上面兩個最小值$i^{'}$不超過$j-1$,因此找到一個因子$p$的循環次數最多為$j$,而$j$的值最大為$\sqrt{p}$。換言之,對於很大的數,只要找到那個圈,就意味着成功。
算法可能因為沒有找到n的非平凡因子而失敗,當且僅當找到$x \equiv x^{'} (mod \, n)$,這等價於$x = x^{'}$,這種情況發生的概率大致為$\frac {p}{n}$,當n很大時這種情況概率變得很小,這時候可以選擇一個不同的初值重新運行或者選擇一個不同的函數f。
四、Dixon的隨機平方算法
這個分解因子算法的理論是基於如下的簡單事實,假定我們可以找到$x \neq \pm y (mod \, n)$使得$x^{2} \equiv y^{2} (mod \, n)$,那么有$$ n | (x+y)(x-y)$$,但是$x-y$和$x+y$均不能被n整除,換言之,這兩個式子中必然至少有一個使得$gcd(f , n) > 1 f=x+y 或者f =x-y$。
隨機平方算法使用一個因子基B,它是b個最小素數的集合(b是適當選取的數值),首先得到幾個整數z,使得$z^{2} (mod \, n)$的所有素因子都在B中,將某些z相乘使得每一個在B中的素數出現偶數次,這樣就建立起了一個所期望的類型的同余方程$x^{2} \equiv y^{2}(mod \, n)$,這個方程可能導出n的一個分解。
說起來很復雜,需要舉一個被仔細設計的例子來配合說明。
Exm3 假定n=15770708441,令$b=6$,那么$B=\{ 2,3,5,7,11,13 \}$,考慮如下三個同余方程$$ \begin{align} 8340934156^{2} & \equiv 3×7(mod \, n) \\ 12044942944^{2} & \equiv 2×7×13(mod \, n) \\ 2773700011^{2} & \equiv 2×3×13(mod \, n) \\ \end{align}
如果取上面同余方程兩邊的乘積,有$$(8340934156×12044942944×2773700011)^{2} \equiv (2×3×7×13)^{2}(mod \, n)$$
在兩邊表達式的括號模n約化,有$$9503435785^{2} \equiv 546^{2}(mod \, n)$$
利用Euclidean算法,計算$$gcd(9503435785-546,15770708441) = 115759$$得出$n$的因子115759。
下面來說明當已經有這些整數z的時候,怎么構造相乘式子使得因子基中的素數出現偶數次,假定$B=\{ p_{1},…,p_{b} \}$為因子基,設$c$為稍大於$b$的整數,且假定已經得到了$c$個同余方程:$$z_{j}^{2} \equiv p_{1}^{\alpha_{1j}} × p_{2}^{\alpha_{2j}}× p_{3}^{\alpha_{3j}} ×… × p_{b}^{\alpha_{bj}} (mod \, n)$$
其中$1 \leq j \leq c$,對於每一個$j$,考慮向量$$a_{j} = (\alpha_{1j} mod \, 2,…,\alpha_{bj} mod \, 2) \in (Z_{2})^{b}$$
如果我們可以找到$a_{j}$的子集使得其模2的和為向量(0,…,0),那么對應的$z_{j}$的乘積將會使得B中的每個因子偶數次。
於是,問題就轉化成尋找$c$個向量$a_{1},…,a_{c}$的一個子集使得其和模2為零向量,即找一個線性相關,當$c>b$時,這樣的線性相關一定存在,我們選取$c>b+1$(c為稍大於b的整數)的原因是,不能保證任一給定的同余方程$x^{2} \equiv y^{2} (mod \, n)$一定能得到n的分解。從上一篇的定理告訴我們,假定$x^{2} \equiv y^{2} \equiv a (mod \, n)$,其中$gcd(a,n) = 1$,那么$a$有$2^{l}$個模$n$的平方根,其中$l$為$n$的素因子的個數,如果$l \geq 2$,那么$a$至少有4個平方根,如果x和y隨機選取,那么$x \equiv \pm y(mod \, n)$出現的概率最多為$\frac {1}{2}$。
有了這個估計,我們希望根據這些形如$x^{2} \equiv y^{2} (mod \, n)$並且$x \neq \pm y(mod \, n)$,得到$n$的一個非平凡因子,這根本的來源是要如何選取整數z,一種方法是簡單隨機選擇z,另一種是試用形如$j + \lceil \sqrt{kn} \rceil$和形如$\lfloor \sqrt{kn} \rfloor$的整數,其中$j = 0 , 1 ,2 , …,k =1,2,…$
最后一個問題就是,因子基要選取多大,顯然,當b越大時,似乎更有可能找到B上的分解,但是帶來的問題是同余式會很多,我們需要一些數論中的結果幫助選取b的值。
Def4 (m-光滑)假定n和m為正整數,我們稱n是m光滑的,如果n的任何一個素因子都小於等於m,並且同時定義$\psi (n,m)$定義為小於等於n且是m光滑的正整數的個數。
數論當中有一個重要的結果列舉如下。
Thm5 如果$n >> m$,那么有$$\frac {\psi (n,m)}{n} \approx \frac{1}{u^{u}}$$其中有$u = \frac {log n}{log m}$,注意到$\frac {\psi (n,m)}{n}$表示從集合$\{ 1,…, n \}$中隨機選取一個整數為m-光滑的概率。
假定$n \approx 2^{r}$和$m \approx 2^{s}$,那么有$$u= \frac{logn}{logm} \approx \frac{r}{s}$$一個$r$比特的整數除以一個$s$比特的整數的執行時間為$o(rs)$,如果假定了$r<m$,可以在時間$o(rsm)$內判斷集合$\{ 1,2,…,n \}$中一個整數是否為$m$光滑的。
因子基B可以選取為包含了所有小於等於m的素數,應用素數定理,我們有$$|B| = b = π(m) \approx \frac{m}{ln m}$$為了算法成功,需要找出略多於$b$個的$m$光滑的模$n$平方數,我們期望測試$bu^{u}$個整數就可以得到$b$個$m$光滑的整數,因此,找到所需$m$光滑的平方數的期望時間為$o(bu^{u}×rsm)$,我們已經有$b$為$o(\frac{m}{s})$,算法的第一部分運行時間為$o(rm^{2}u^{u})$
在算法的第二部分,需要化簡模2的系列矩陣,構造出形如$x^{2} \equiv y^{2} (mod \, n)$的同余式,再應用歐幾里得算法,這幾步所需的時間是$r$和$m$的多項式,即$o(r^{i}m^{j})$
現在,我們給定了$n \approx 2^{r}$和$m \approx 2^{s}$,上面是針對$n$進行的優化,下面對$m$進行優化,一個好的選擇是取$s \approx \sqrt{rlbr}$,那么有$$u \approx \frac{r}{s} \approx \sqrt{\frac{r}{lbr}}$$現在開始估計
$$\begin{align} lbu^{u} =& ulbu \\ \approx & \sqrt{\frac{r}{lbr}} lb \lgroup \sqrt{\frac{r}{lbr}} \rgroup \\ < & \sqrt{\frac{r}{lbr}} lb \sqrt{r} \\ = & \sqrt{\frac{r}{lbr}} × \frac{lbr}{2} \\ = & \frac{\sqrt{rlbr}}{2} \\ \end{align}$$
於是有$$u^{u} \leq 2^{0.5 \sqrt{rlbr}}$$
因此,所有的運行時間可以寫成如下形式$$o(2^{c \sqrt{rlbr}})$$其中$c$為一個常數,再利用$r \approx lb n$,最終可以導出如下通常的期望時間為$o(e^{(1+o(1))\sqrt{lnn lnlnn}})$。
五、實際中的分解因子算法
二次篩法的來源於判斷$z^2 (mod \, n)$在B上的分解的一個篩法過程,數域篩法是構造同余式$x^{2} \equiv y^{2} (mod \, n)$來分解n,但這是在代數整數環中進行計算的,二次篩法、橢圓篩法和數域篩法的漸進運行時間均有上面討論的形式,詳細可以尋找更多的參考文獻。
在下一篇文章中,我們討論除了分解$n$以外是否有其他體制對RSA密碼體制進行攻擊。