RSA公钥加密
RSA原理
RSA是最早提出并被广泛接受的公钥加密算法之一,其步骤如下
第一步,选择两个大素数$p,q$
第二步,计算$n=pq$和$\phi(n)=(p-1)(q-1)$
第三步,随机选择正整数$e<\phi(n)$满足$e$与$\phi(n)$互素
第四步,计算$e$在模$\phi(n)$意义下的逆元$d$,即$ed\equiv 1(\mod \phi(n))$
最后,公钥为${d,n}$,私钥为${e,n}$
加密和解密过程分别为 $C=M^e \mod n$ 和 $M=C^d\mod n=M^{ed}\mod n$
显然该算法要求$M<n$,应此实际应用中要将明文分组,每一分组转换成十进制数后要小于n
RSA实现
RSA的实现有很多计算上的问题需要考虑
首先是大素数$p,q$的选择问题,目前为止还没有有效的方法可以产生任意大素数
一般的做法是随机选择一个期望位数的奇数,然后测试它是否为素数,若不是则继续随机
一般的确定性素性测试需要$O(\sqrt n)$进行试除,这样的复杂度并不能被接受
基于概率性测试的Miller-Rabin算法是被广泛使用的素性检测算法
算法原理和cpp实现可参考Miller-Rabin素数测试与Pollard Rho大整数分解,此处给出python实现
1 | def witness(a, n, u, t): |
RSA实现所需考虑的另一个问题是乘法逆元的计算
基于扩展欧几里得算法的乘法逆元原理可以参考 扩展欧几里得和乘法逆元求解
RSA为了保证对穷举攻击的安全性,一般密钥都很大(至少1024位),因此扩展欧几里得最好用非递归形式
此处再给出RSA计算公钥和私钥的主体部分
1 | class RSA: |
RSA的安全性
RSA的安全性来源于对大整数进行因数分解的困难性
然而随机计算能力的不断增强和因子分解算法的不断改进,即使是大密钥的RSA也开始受到威胁
从2010年代开始,1024位的RSA也开始被建议逐步淘汰
选择密文攻击也是对RSA的一种有效攻击,其利用了RSA的如下性质
具体来说,攻击者截获了密文$C_1$,希望获得其对应明文$M_1$
攻击者可以选取明文$M$,构造$C_2=C_1\times C=C_1\times M^e\mod n$,并将$C_2$发送给接收者
接收者对$C_2$解密得到明文$M_2$,则攻击者可计算出$M_1=\frac{M_2}{M}\mod n$
抵御选择密文攻击的一种方法是最优非对称加密填充OAEP,该方法较为复杂,此处不展开说明
此外对RSA的攻击还有计时攻击,实际上计时攻击也可以用来攻击其他公钥加密算法,对于RSA来说则可以使用随机延时、隐蔽等手段进行防御