關於隨機數,你的用法可能一直都是錯誤的

一般我們使用隨機數會使用srand和rand函數,但是很多時候我們的用法是不夠安全的,比如你用他們來生成一個加密祕鑰的時候。

看下下面兩行代碼的內部工作原理:

srand(123);
printf(rand())

srand執行做的事非常簡單:把123存放到線程環境變量裏作爲起始隨機種子
rand的僞代碼如下:

function rand() 
{
a = get srand 保存的值
b = (0x343FD*a+0x269EC3);  //關鍵公式
srand(b) //保存新的種子
return (b>>10) & 0x7FFF
}

這個函數算法比較簡單,取出當前保存的隨機種子,放到一個公式計算出b,然後把b作爲新的種子,最後取高16位作爲返回值

根據上面的算法我們可以得出幾點結論:

  1. 知道了起始隨機種子,每個人都可以獲取到一樣的隨機序列
  2. 已知一段隨機數序列,應該可以推算出後面的隨機數(已知隨機序列雖然不等同於已知上面代碼中的b,但根據足夠多的高16位應該是可以推算出完整的b的)

在來看一個實際例子,下面這樣的祕鑰生成函數相信很多人都寫過,請問你看出他有什麼問題了嗎?

	BYTE key[32];

	srand(time(nullptr));
	for (int i = 0; i < 32; i++) {
		key[i] = (BYTE)rand();
	}

問題1:不要以爲生成的key是32字節的就以爲祕鑰是256位的強度,上面的算法key的強度不是 2^256 種組合 , 而是 2^32種組合,因爲種子是 2^32 種可能,種子固定了key就固定了。
問題2:再看下srand(time(nullptr))這行代碼,這行代碼帶來的問題是隨機種子可以被猜測,如果知道你執行代碼的大概時間,我就可以直接取時間區間進行爆破。

上面的代碼是之前某知名安全軟件犯過這樣的錯誤,他的防破解算法祕鑰是像上面那樣生成的,被人猜出了私鑰,進而寫出了keygen。


那如何才能安全的生成生成key,下回有空通過從openssl的源碼再分解!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章