理解RSA算法需要了解的数论定理全家桶
前言
本文为理解RSA算法的数学逻辑和相关定理做了梳理。RSA的相关介绍不在本文讨论范围之内。
本文的证明和表述都力求清晰简明,无论是文章的谬误还是费解的地方,都可以留言告诉我。
" ≡ \equiv ≡"符号的使用和模运算的规律简述
许多同学习惯于 a a a % b = r b=r b=r这样的写法,但是为了证明过程简洁(不用把 % 写上一万遍),本文将使用 a ≡ r ( m o d b ) a \equiv r \pmod{b} a≡r(modb) 的写法。这种写法代表着一种关系: a − r = k b a-r=kb a−r=kb,也就是说 a − r a-r a−r 能被 b b b 整除,中间的 ≡ \equiv ≡读作“等价于”。
举个栗子吧,以下几个式子都是成立的: 11 ≡ 1 ( m o d 5 ) 11\equiv1\pmod{5} 11≡1(mod5) 11 ≡ 6 ( m o d 5 ) 11\equiv6\pmod{5} 11≡6(mod5) 11 ≡ 11 ( m o d 5 ) 11\equiv11\pmod{5} 11≡11(mod5) 16 ≡ 11 ( m o d 5 ) 16\equiv11\pmod{5} 16≡11(mod5)
但是本文应该会尽量采用第一种护脑模式。
有了这种写法,我们就可以把四则运算的运算规律引入模运算,已知 a ≡ b ( m o d n ) a\equiv b\pmod{n} a≡b(modn) c ≡ d ( m o d n ) c\equiv d\pmod{n} c≡d(modn)
容易证得 a ∗ c ≡ b ∗ d ( m o d n ) a*c\equiv b*d\pmod{n} a∗c≡b∗d(modn)
甚至幂运算也可以任性使用 a k ≡ b k ( m o d n ) a^k\equiv b^k\pmod{n} ak≡bk(modn)
RSA算法
RSA算法的加密解密过程
RSA
1. 选取两个较大的素数 p p p 和 q q q,令 n = p ∗ q n=p*q n=p∗q
2. 根据欧拉函数求出 1 到 n 里有多少个数与 n 互质 ϕ ( n ) = ( p − 1 ) ( q − 1 ) \phi(n)=(p-1)(q-1) ϕ(n)=(p−1)(q−1)
3. 找到一个公钥 e e e,使得 1 < e < ϕ ( n ) 1<e<\phi(n) 1<e<ϕ(n),同时保证 e 和 ϕ ( n ) \phi(n) ϕ(n) 互质
4. 求出私钥 d d d,满足 e ∗ d ≡ 1 ( m o d ϕ ( n ) ) e*d\equiv 1\pmod{\phi(n)} e∗d≡1(modϕ(n))
5. 使用阶段,发送者对信息明文 m ( 1 < m < n ) m(1<m<n) m(1<m<n) 进行加密 m e % n = C m^e\;\%\;n = C me%n=C
6. 密文 C C C,公钥 e e e 和 n n n 都可以明目张胆的发送给接收者,收到后使用自己藏好的私钥d进行解密 C d % n = m C^d\;\%\;n=m Cd%n=m
神奇的事情发生了,信息明文 m m m 经过一波操作后又被还原了回来。而攻击者虽然能轻松获得 n n n 和 e e e,但分解质因数极其困难( n n n 通常是大于1024位的二进制数),通过 n n n 反求 d d d 对于普通PC来说通常需要数百万年时间。
RSA算法的加密解密实例
RSA example
1. 令 p = 7 , q = 13 p=7,\;q=13 p=7,q=13(因为是演示,所以选小一点的数) n = 7 ∗ 13 = 91 n=7*13=91 n=7∗13=91
2. ϕ ( n ) = ( p − 1 ) ( q − 1 ) = 6 ∗ 12 = 72 \phi(n)=(p-1)(q-1)=6*12=72 ϕ(n)=(p−1)(q−1)=6∗12=72
3. 确定公钥为 5 5 5,满足 1 < 5 < 72 1<5<72 1<5<72 且 5 5 5 与 72 72 72 互质
4. 求出私钥为 29 29 29,因为 5 ∗ 29 = 145 ≡ 1 ( m o d 72 ) 5*29=145\equiv1\pmod{72} 5∗29=145≡1(mod72)
5. 现在有一个信息 m m m 需要发送,比如 m = 6 m=6 m=6,加密后得到密文 C C C C = 6 5 % 91 = 41 C=6^5\;\%\;91=41 C=65%91=41
6. 再将密文C进行解密得到明文 m m m m = 4 1 29 % 91 = 6 m=41^{29}\;\%\;91=6 m=4129%91=6
这个求幂过大了,所以我们可以用运算规则拆成几个小的余数的乘积,比如 4 1 29 = ( 4 1 5 ) 5 ∗ 4 1 4 ≡ 6 5 ∗ 29 = C ∗ 29 = 1189 ≡ 6 ( m o d 91 ) 41^{29}=(41^5)^5*41^4\equiv6^5*29=C*29=1189\equiv6\pmod{91} 4129=(415)5∗414≡65∗29=C∗29=1189≡6(mod91)
当然在程序里我们可以用平方求模的思路将其拆成二进制的形式,比如 a 7 = a 4 a 2 a 1 = a 11 1 2 a^7=a^4a^2a^1=a^{111_2} a7=a4a2a1=a1112
故从左往右遍历,每个循环开始先平方,遇到当前位为'1'
时则乘以底数的余数。这个算法简单而高效,以下是Java实现
public class ModBySquaring {
public static int modBySquaring(int base, int exponent, int modulus) {
String bin = Integer.toBinaryString(exponent);
int res = 1;
for (int i = 0; i < bin.length(); i++) {
res = (res * res) % modulus;
if (bin.charAt(i) == '1')
res = (res * base) % modulus;
}
return res;
}
}
RSA算法的证明
RSA proof
已知加密过程 m e % n = C m^e\;\%\;n = C me%n=C 和解密过程 C d % n = m C^d\;\%\;n=m Cd%n=m,用 m m m 替换 C C C 代入,得到我们需要证明的公式 m e d ≡ m ( m o d n ) m^{ed}\equiv m\pmod{n} med≡m(modn)
已知 e d ≡ 1 ( m o d ϕ ( n ) ) ed\equiv1\pmod{\phi(n)} ed≡1(modϕ(n)),所以 e d = k ∗ ϕ ( n ) + 1 ( k ∈ Z ) = k ∗ ( p − 1 ) ( q − 1 ) + 1 ed=k*\phi(n)+1\;( k\in \Bbb Z)=k*(p-1)(q-1)+1 ed=k∗ϕ(n)+1(k∈Z)=k∗(p−1)(q−1)+1,把 e d ed ed 代入到公式左边,得到 m e d = m k ∗ ( p − 1 ) ( q − 1 ) + 1 m^{ed}=m^{k*(p-1)(q-1)+1} med=mk∗(p−1)(q−1)+1
根据费马小定理,当
- m m m 与 p p p 互质时,有 m p − 1