從生日悖論談雜湊碰撞

2021-10-01 21:12:07 字數 4437 閱讀 2091

前幾天和乙個大佬交流了幾個問題,其中乙個關於id生成的問題推展到了雜湊衝突和乙個與之相關的乙個數學趣題生日悖論。

雜湊的對映壓縮和衝突

生日悖論

crc32的衝突分析

雜湊的本質就是數學,簡單來說雜湊函式實現了各種長度和形式的輸入經過公開的雜湊函式的運算生成乙個固定長度的串,並且這個過程是單向不可逆的,也就是無法從雜湊生成的串逆轉為最初的輸入。

聽起來確實很神奇且有用,像乙個萬能膠囊,在乙個小的範圍內裝了很多不一樣的東西,原來有10mb的檔案或者1gb的檔案經過雜湊運算後都會被對映到乙個固定長度的串,可見壓縮程度之大。

但是又不得不思考另外乙個問題:輸入是無窮盡的,生成的雜湊串長度是固定的,那麼必然面臨著多個不一樣的輸入被對映壓縮為乙個相同的雜湊串,就是無限集合對映有限集合導致的雜湊碰撞或者叫雜湊衝突。

舉個栗子:

假如雜湊串固定長度是二進位制10bit,那麼這個10bit空間可容納的最大數量為2^10=1024,先不說無限輸入集合,假如現在有2000個輸入,在雜湊函式均勻的前提下最少會有2000-1024=976個衝突。

看到這裡,肯定有人會說那不用雜湊了,但是雜湊的壓縮對映和不可逆性帶來的便利確實有很大的吸引力,所以知難而退並不是個好主意。

我們知道冪次**,所以如果把二進位制位數擴充套件到32bit->64bit->128bit->256bit呢,2^32約為42億,2^64約為1800多億億,128和256就更大了,貌似到了這裡開始柳暗花明了,我們將長度增加空間就冪次增加,有效降低了衝突的概率,這也是當前主流的思路和方向。

小結:

雜湊函式本身有很多種,底層的實現都有非常複雜的數學邏輯,均勻分布是雜湊函式的乙個重要特徵,筆者才疏學淺並沒有對雜湊函式的數學原理做過多研究。

無限輸入集合向有限集合的壓縮對映是必然會出現碰撞的,解決碰撞的乙個有效方法是增加對映空間長度,理解這一點就足夠進行後面的閱讀了,相信聰明的讀者一定get到筆者的意思了。

前面討論了雜湊衝突的必然性,那麼我們不禁要思考:那我該選擇多少bit的雜湊函式才能避免碰撞呢?

其實面對這個問題的時候,我最開始是這麼想的:使用32bit的雜湊函式這樣還有42億個空間呢,那麼產生雜湊碰撞豈不是42億分之一,貌似可以高枕無憂了,先看乙個有趣的問題:

來自網路

生日悖論是指在不少於 23 個人中至少有兩人生日相同的概率大於 50%。例如在乙個 30 人的小學班級中,存在兩人生日相同的概率為 70%。對於 60 人的大班,這種概率要大於 99%。從引起邏輯矛盾的角度來說,生日悖論並不是一種 「悖論」。但這個數學事實十分反直覺,故稱之為乙個悖論。
確實有一些違背直覺,一年365天怎麼會有那麼多人生日相同呢?然而這卻是個事實。

來實際算一下這個問題:

假設有n個人在同一班級內,在不考慮特殊因素的前提下,例如閏年、雙胞胎,假設一年365日出生概率是平均分布的,計算至少有兩個人在同一日出生的概率是多少?

計算分析過程:

我們從其對立事件進行求解,找到n不斷變化時對應的概率分布,p(n)表示n個人中每個人的生日都不同的概率,先考慮邊界條件當n>365根據鴿巢原理其概率為0,n ≤ 365,則概率為:

在維基百科也有通用計算公式,一起看下:

再看下這個曲線和具體的離散化資料:

來自 維基百科

來自 維基百科

結論:

人數n=23時至少有兩人生日相同的概率是50.7%,n=30時概率是70%,n=50時概率是97%,這麼看來確實有悖直覺,但是這就是事實。

我們暫且以32位長度的crc32演算法為例來描述雜湊碰撞的可能性。

簡單來想crc32的空間大小是42億,但是實際上並不**40億左右資料才會出現碰撞,事實這個資料規模並不需要很大就會出現碰撞。

crc32的碰撞問題本質上可以從生日悖論的角度來分析,相當於計算在有n個輸入的情況下出現碰撞的概率。假設現在有k個輸入,不出現衝突的概率計算(將42億用s表示):

這個計算過程和生日悖論基本是一樣的,隨著k的增加這個概率值下降非常快,筆者在網上找了乙份crc16-crc64的衝突測試報告,可以看下:

//

output.16 count 18134464/18200000

output.

17 count 18068928/18200000

output.

18 count 17937856/18200000

output.

19 count 17675712/18200000

output.

20 count 17151424/18200000

output.

21 count 16103198/18200000

output.

22 count 14061250/18200000

output.

23 count 10770169/18200000

output.

24 count 7092360/18200000

output.

25 count 4153742/18200000

output.

26 count 2259269/18200000

output.

27 count 1179721/18200000

output.

28 count 603421/18200000

output.

29 count 305089/18200000

output.

30 count 153722/18200000

output.

31 count 77254/18200000

output.

32 count 38638/18200000

output.

33 count 19232/18200000

output.

34 count 9652/18200000

output.

35 count 4914/18200000

output.

36 count 2343/18200000

output.

37 count 1204/18200000

output.

38 count 637/18200000

output.

39 count 302/18200000

output.

40 count 152/18200000

output.

41 count 75/18200000

output.

42 count 52/18200000

output.

43 count 21/18200000

output.

44 count 13/18200000

output.

45 count 7/18200000

output.

46 count 1/18200000

output.

47 count 1/18200000

output.

48 count 1/18200000

output.

49 count 0/18200000

output.

50 count 0/18200000

output.

51 count 0/18200000

output.

52 count 0/18200000

output.

53 count 0/18200000

output.

54 count 0/18200000

output.

55 count 0/18200000

output.

56 count 0/18200000

output.

57 count 0/18200000

output.

58 count 0/18200000

output.

59 count 0/18200000

output.

60 count 0/18200000

output.

61 count 0/18200000

output.

62 count 0/18200000

output.

63 count 0/18200000

output.

64 count 0/18200000

輸入時1820w隨機資料,上述資料給出了crcx情況下1820w輸入產生的碰撞數量,可以看到在crc32**現了38638個衝突,在crc49中才出現0碰撞,所以衝突率還是很高的。

python中生日悖論分析 從生日悖論談雜湊碰撞

1 前言 前幾天和乙個大佬交流了幾個問題,其中乙個關於id生成的問題推展到了雜湊衝突和乙個與之相關的乙個數學趣題生日悖論。雜湊的對映壓縮和衝突 生日悖論 crc32的衝突分析 2.雜湊對映壓縮和衝突 雜湊的本質就是數學,簡單來說雜湊函式實現了各種長度和形式的輸入經過公開的雜湊函式的運算生成乙個固定長...

什麼是生日悖論?

生日悖論 生日悖論是指在不少於 23 個人中至少有兩人生日相同的概率大於 50 例如在乙個 30 人的小學班級中,存在兩人生日相同的概率為 70 對於 60 人的大班,這種概率要大於 99 從引起邏輯矛盾的角度來說,生日悖論並不是一種 悖論 但這個數學事實十分反直覺,故稱之為乙個悖論。生日悖論的數學...

演算法問題 生日悖論

問題 乙個屋子裡人數必須要達到多少人,才能使其中兩人生日相同的機會達到50 為了回答這個問題,設 1 設k是屋子裡的總人數,對每乙個人進行編號,則編號為1,2,3 k 2 設所有年份都是365天,最大天數n 365 3 bi表示第i個人的生日天數,所以1 bi 360,1 i k public cl...