偽隨機生成器具體實現——線性同餘法
一 點睛
線性同餘法是一種使用很廣泛的偽隨機數生成器演算法。然而,它並不能用於密碼技術。
演算法介紹如下:
假設我們要生成偽隨機數列為R0、R1、R2...。首先,我們根據偽隨機數的種子,用下列公式計算第一個偽隨機數R0
R0=(A*種子+C)mod M
在這裡,A、C、M都是常量,且A和C需要小於M
接下來,根據R0用相同的公式計算下一個偽隨機數R1
R1=(A*R0+C)mod M
接下來我們再用同樣的方法,根據當前的偽隨機數Rn來計算下一個偽隨機數R(n+1)
R(n+1)=(A*Rn+C)mod M
簡而言之,線性同餘法就是將當前的偽隨機數值乘以A再加上C,然後將除以M得到的餘數作為下一個偽隨機數。線上性同餘法中,最近一次生成的偽隨機數的值就是內部狀態,偽隨機數的種子被用來對內部狀態進行初始化。線性同餘法的結構如下圖:
二 實戰
A=3
C=0
M=7
然後將6作為偽隨機數的種子,根據線性同餘法,生成偽隨機數列的過程如下:
R0=(3*6+0)mod 7 =4
R1=(3*4+0)mod 7 =5
R2=(3*5+0)mod 7 =1
R3=(3*1+0)mod 7=3
以此類推,我們可以得到4、5、1、3、2、6、4、5、1、3、2、6...這樣的偽隨機數列。在這裡,數列是以4、5、1、3、2、6的順序不斷迴圈的,因此週期為6。
由於偽隨機數是除以M得到的餘數,因此其範圍必定是0~M-1,而且根據A、C、M的值,最終只能生成上述範圍中的一部分值(因此週期會縮短)。例如,當A=6、C=0、M=7,且種子為6時,所得到的偽隨機數列為1、6、1、6、1、6...週期為2。
如果改變A的值,生成的偽隨機數列又將如何變化呢?我們可以發現,如果樣讓週期為6,只有A=3和A=5才能滿足條件。
線上性同餘法中,只要謹慎選擇A、C、M的值,就能夠很容易地生成具備隨機性的偽隨機數列。
然而,線性同餘法不具備不可預測性,因此不可以將線性同餘法用於密碼技術。
很多偽隨機數生成器的庫函式都是採用線性同餘法編寫的。例如C語言的庫函式rand,以及Java的java.util.Random類等,都採用了線性同餘法。因此這些函式是不能用於密碼技術的。
我們可以很容易地證明線性同餘法不具備不可預測性。
假設攻擊者已經A=3、C=0、M=7。這時,攻擊者只要得到所生成的偽隨機數中的任意一個,就可以預測出下一個偽隨機。因為攻擊者只要用得到的偽隨機數R根據下來公式計算就可以了。
(A*R+C)mod M=(3*R+0)mod7
在這個過程中,攻擊者沒有必要知道種子6.此外,只要重複上述計算過程,就可以預測出之後生成的全部偽隨機數。