MD5是被廣泛使用的密碼散列函數,曾被廣泛應用於計算機安全領域。在2004年,MD5被證實無法防止碰撞,因此不適用於安全性認證。那麽MD5碰撞是什麽意思,我們如何處理Hash碰撞呢?
簡單來說,就是先得出壹個字符串的MD5值,在根據這個值,逆算出另外壹個不同的字符串,但是它們的MD5值是壹致的。這就是MD5碰撞,幾率很小的。
我們常見的碰撞法:暴力碰撞(窮舉法、字典法),就是利用計算機的資源嘗試碰撞已知的MD5碼。
1、窮舉法
窮舉法就是不停地嘗試各種字符的排列組合,看哪壹個組合的MD5碼能對上。缺點是太耗費時間。舉個例子,假設我們要破解壹個6位大小寫字母和數字混合的密碼,那麽壹***有 (26 + 26 + 10) ^ 6 種組合。這個數的大小超過500億。
2、字典法
字典法就是把計算結果以映射表的形式存放起來,壹個原文對應著壹個MD5值。將已知的MD5碼查表,就可直接反查出原文。字典法體現了算法設計的“以空間換時間”的思想。缺點是比較耗費空間,而且實際上還是要窮舉壹遍所有的輸入,只不過把窮舉的結果存了起來。
壹個用字典法實現md5解密的網站:/
通常有兩類方法處理碰撞:開放尋址(Open Addressing)法和鏈接(Chaining)法。前者是將所有結點均存放在散列表T[0..m-1]中;後者通常是把散列到同壹槽中的所有元素放在壹個鏈表中,而將此鏈表的頭指針放在散列表T[0..m-1]中。
1、開放尋址法
所有的元素都在散列表中,每壹個表項或包含動態集合的壹個元素,或包含NIL。這種方法中散列表可能被填滿,以致於不能插入任何新的元素。在開放尋址法中,當要插入壹個元素時,可以連續地檢查或探測散列表的各項,直到有壹個空槽來放置待插入的關鍵字為止。有三種技術用於開放尋址法:線性探測、二次探測以及雙重探測。
線性探測法適用場景
在 Java 中的 ThreadLocalMap 就是采用了開放尋址法來解決哈希沖突,因為開放尋址法在極端環境下時間復雜度會退化成 O(n),所以適用於數據量較少的場景。
2、鏈地址法
鏈地址法也叫鏈表法,這種方法比較常見也比較簡單,就是插入壹個元素時,如果發現當前位置已經有元素,則以當前節點為頭節點(尾插法)或者尾結點(頭插法)構造壹個鏈表,如果進壹步優化的話,可以將鏈表修改為紅黑樹等數組結構,比如 jdk 1.8 之後的 HashMap 就是采用的這種方式進行優化。
鏈地址法適用場景
基於鏈表的哈希沖突處理方法比較適合存儲大對象、大數據量的哈希表,因為鏈表本身就需要額外的空間來存儲指針地址,所以如果壹個節點存儲的數據大小還沒有指針大,那就會造成很大空間浪費;相反,如果指針的大小相對於數據大小可以忽略,那用鏈地址法解決沖突會是壹個比較好的選擇,而且鏈地址法會更加靈活,支持更多的優化策略,比如 HashMap 中當鏈表節點數大於 8 就會轉化為紅黑樹來進行優化。
本文介紹了MD5碰撞是什麽意思,以及Hash碰撞處理的方法:開放尋址法和鏈地址法。並且,介紹了線性探測法和鏈地址法的應用場景。通過以上的介紹,大家應該對這些問題有了壹定的了解,更多關於MD5的知識可以在往期文章中查閱哦。