RSA的密鑰d計算(輾轉相除法) c++算法實現
先亮劍,c++的代碼實現:
int calc_d(int e, int n) {
if (e == 1||n==1) return 1;
int d1 = calc_d(e%n, n%e);
return d1 - n / e * ((1 - e * d1) / (n%e));
}
RSA算法規定:
p*q =N
(p-1) * (q-1) = n
e*d ≡(1 mod n)
其中在e和n已知的情況下,求d
例:令p=47,q=71,求用RSA算法加密的公鑰和私鑰。
計算如下:
(1)n=pq=47*71=3337;
(2)φ(n)=(p-1)*(q-1)=46*70=3220;
(3)隨機選取e=79(滿足與3220互質的條件);
(4)則私鑰d應該滿足:79*d mod 3220 = 1;
d如何解??
79*d mod 3220 = 1等價於存在一個整數k,使得79*d+3220*k=1
79*d+3220*k=1 拆解爲 79*d+(79*40+60)*k=1 化簡爲79*(d+40*k)+60*k=1 記爲79*d1+60*k=1 且d = d1-40*k
也就是說,我只要計算出79*d1+60*k=1的d1和k,就可以計算出79*d+3220*k=1的d和k,計算出d1,d即爲d1-40*k
好,我們繼續碾轉
79*d1+60*k=1 拆解爲 (60+19)*d1+60*k=1 化簡爲19*d1+60*(k+d1)=1 記爲19*d1+60*k1=1 且k=k1-d1
19*d1+60*k1=1 拆解爲 19*d1+(3*19+3)*k1=1 化簡爲19*(d1+3*k1)+3*k1=1記爲19*d2+3*k1=1 且d1=d2-3*k1
19*d2+3*k1=1 拆解爲 (3*6+1)*d2+3*k1=1 化簡爲d2+3*(k1+6*d2)=1 記爲d2+3*k2=1 且k1=k2-6*d2
到此就結束了,最終化爲d2+3*k2=1,當k2取0時候,d2其值爲1,滿足該式子
因此k2=0,d2=1,將其值帶入,計算易得k1=0-6*1=-6,d1=1-3*-6=19,k=-6-19=-25,d=19-40*-25=1019
驗算下:k=-25,d=1019帶入79*d+3220*k=1 ,驗算成立
上面的實例是爲了入手,現在進行純粹的公式推導
要想計算關於e,n的對應的d,n和e肯定是互質的,因此不會有0或者n=e這些情況的
問題爲:存在整數k,使得e*d+n*k=1,求d
記函數f(e,n)是求d函數,所以d=f(e,n)
下面的/是指整數除法,計算的商向下取整
當假設n比e大
e*d+n*k=1拆解爲e*d+(n/e*e+n%e)*k=1 化簡爲e*(d+n/e*k)+(n%e)*k=1,記爲e*d1+(n%e)*k=1,且d=d1-n/e*k
e*d1+(n%e)*k=1用函數表示爲d1=f(e,n%e),由於n比e大,可以寫爲d1 = f(e%n,n%e),d=d1-n/e*k
因爲e*d1+(n%e)*k=1,所以k=(1-e*d1)/(n%e), 所以d=d1-n/e*((1-e*d1)/(n%e))
因此d=d1-n/e*((1-e*d1)/(n%e)) => f(e,n)=f(e%n,n%e)-n/e*((1-e*f(e%n,n%e))/(n%e))
當假設n比e小:
e*d+n*k=1拆解爲(e/n*n+e%n)*d+n*k=1化簡爲(e%n)*d+n*(e/n*d+k)=1, 記爲(e%n)*d+n*k1=1,且k=k1-e/n*d+k
(e%n)*d+n*k1=1用函數表示爲d=f(e%n,n), 由於e比n大,可以寫爲d=f(e%n,n%e)
因此d=f(e%n,n%e),因爲e比n大,所以n/e爲0,即d=f(e%n,n%e)=f(e%n,n%e)-n/e*((1-e*f(e%n,n%e))/(n%e))
由此,無論n比e大還是e比n大,其公式都可以用f(e,n)=f(e%n,n%e)-n/e*((1-e*f(e%n,n%e))/(n%e)) 表示
那什麼時候結束呢?
這個就是什麼時候是顯而易見,一眼就可以看出d值的時候,
如e爲1時候,k只要取0,e*d+n*k=1,顯然d的值爲1
如果n爲1時候,d取啥整數值都可以,因爲都存在k=1-e*d使公式成立,爲了方便,d取1好了
因此因爲e和n是互質的,e和n在碾轉相除的時候,比然會出現一個爲1,此時d值取1即可
推導結論:
當n或者e爲1時候:d=1
否則d=f(e%n,n%e)-n/e*((1-e*f(e%n,n%e))/(n%e)) ,其中f(e,n)是求d函數,/是除法的商向下取整