标签:0ms 安全性 bit 函数 target 比较 ret amp 循环
RSA的破解从理论上来讲是大数质数分解,可是就是有一些人另辟蹊径,根据你解密的时间长短就能破解你的RSA私钥。
举一个不恰当但是比较容易理解的例子:
密文0101
私钥0110
明文0100
问题的关键来了,进行&运算时如果有一个0,那么运算的时间为1ms,如果两个都是1,运算的时间是10ms(只是个假设)。
基于以上假设,就可以破解私钥了。先构造一个0001的密文,获取解密的时间,如果是1ms左右,那么对应的位就是0,
如果是10ms左右,对应的1,依次类推,就把整个私钥推断出来了。
如何防范这种攻击呢?
一种最简单有效的方法,每次过来一个密文,先用一个随机数与它&一下,然后再与私钥&,只要随机数是真正的随机数,那么
是无法破解的。注意,是真正的随机数而不是伪随机数。
RSA解密的本质就是幂模运算,也就是x = a ^ b mod n ,其中a是明文,b是私钥,n是两个大质数(p-1)(q-1)的积。由于这些
数都特别大,比如b可能有2048位,直接计算是不可行的。计算x的最经典的算法是蒙哥马利算法,用代码表示如下:
int mod(int a,int b,int n){ int result = 1; int base = a; while(b>0){ if(b & 1==1){ result = (result*base) % n; } base = (base*base) %n; b>>=1; } return result; }
这个算法从b的最低位循环到最高位,如果是1,需要进行两次模乘运算,如果是0的话则只需要一次。由于这个操作是比较耗时的,所以
0和1对应的时间差别较大。攻击者可以通过观察不同输入对应的解密时间,通过分析统计推断出私钥。而防范RSA时序攻击的方法也是在
解密时加入随机因素,让攻击者无法获取准确的解密时间。
真正意义上的随机数,是很难产生的,因为即使小到原子,它的规律也是有迹可循的。所以我们产生的随机数都是伪随机数,但是伪随机数的
随机性也是不一样的,如果产生的随机数规律性很强,那就很容易被预测到,而如果产生的随机数被预测的难度特别大,那么我们就可以认为
它是真随机数了,只有强度高的随机数用来加解密等操作上才是安全的。
目前大部分操作系统都会提供两种随机数的产生方式,以Linux为例,它提供了/dev/urandom和/dev/random两个特殊设备,可以从里面读
取一定长度的随机数。
(1)/dev/random是blocking pseudo random number generator (阻塞式伪随机数产生器),它是通过网络事件,键盘敲
击事件等物理上随机的事件,收集一些随机bit到熵池来产生随机数。这个随机生成函数可能因为熵池为空而等待,所以需要大量随机数的情
况下它会显得很慢,但诸如产生证书之类的操作需要这种强度的随机数。
(2)/dev/urandom就是unblocking,它不会阻塞,但是产生的随机数不够高,是以时间戳之类的种子来产生随机数。
Java可以用SecureRandom产生随机数,而且可以在JVM参数里配置是使用/dev/random还是/dev/urandom,如果安全性要求改,就用
/dev/random,但是性能是就会有折扣。
出处:
标签:0ms 安全性 bit 函数 target 比较 ret amp 循环
原文地址:http://www.cnblogs.com/yuyutianxia/p/7666923.html