RSA 時序攻擊
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,但是性能是就會有折扣。
出處:
RSA的那些坑
RSA 時序攻擊