哈希函數有關知識

1.現在的問題是有各種類型的數據,有一些是高度隨機的,有一些有包含高緯度的圖形結構,這些都使得找到一個通用的哈希函數變得十分困難,即使是某一特定類型的數據,找到一個比較好的哈希函數也不是意見容易的事。我們所能做的就是通過試錯方法來找到滿足我們要求的哈希函數。可以從下面兩個角度來選擇哈希函數:
1.數據分佈
 一個衡量的措施是考慮一個哈希函數是否能將一組數據的哈希值進行很好的分佈。要進行這種分析,需要知道碰撞的哈希值的個數,如果用鏈表來處理碰撞,則可以分析鏈表的平均長度,也可以分析散列值的分組數目。
2.哈希函數的效率
另個一個衡量的標準是哈希函數得到哈希值的效率。通常,包含哈希函數的算法的算法複雜度都假設爲O(1),這就是爲什麼在哈希表中搜索數據的時間複雜度會被認爲是"平均爲O(1)的複雜度",而在另外一些常用的數據結構,比如圖(通常被實現爲紅黑樹),則被認爲是O(logn)的複雜度。
一個好的哈希函數必修在理論上非常的快、穩定並且是可確定的。通常哈希函數不可能達到O(1)的複雜度,但是哈希函數在字符串哈希的線性的搜索中確實是非常快的,並且通常哈希函數的對象是較小的主鍵標識符,這樣整個過程應該是非常快的,並且在某種程度上是穩定的。(來自 http://blog.csdn.net/eaglex/article/details/6310727#下載)


2.哈希函數的構造方法

 1.直接定址法

  取關鍵字或關鍵字的某個線性函數值爲哈希地址,H(key)=a.key+b

 2.數字分析法

  選關鍵字的若干位組成哈希地址

3.平方取中法

4.摺疊法

5.除留餘數法

   H(key)=key MOD p,p是素數、



3.處理衝突的方法

1.開放定址法

(1)線性探測再散列,(2)二次探測再散列,(3)僞隨機數探測再散列

2.再哈希法

3.鏈地址法



4.針對字符串哈希函數的構造方法

有兩種主要的方法:
1.基於加法和乘法的散列
這種方式是通過遍歷數據中的元素然後每次對某個初始值進行加操作,其中加的值和這個數據的一個元素相關。通常這對某個元素值的計算要乘以一個素數。

基於加法和乘法的散列

 

2.基於移位的散列

和加法散列類似,基於移位的散列也要利用字符串數據中的每個元素,但是和加法不同的是,後者更多的而是進行位的移位操作。通常是結合了左移和右移,移的位數的也是一個素數。每個移位過程的結果只是增加了一些積累計算,最後移位的結果作爲最終結果。


基於移位的散列

 

 6.常用的哈希函數


通用的哈希函數庫有下面這些混合了加法和一位操作的字符串哈希算法。下面的這些算法在用法和功能方面各有不同,但是都可以作爲學習哈希算法的實現的例子。(其他版本代碼實現見下載

1.RS 
從Robert Sedgwicks的 Algorithms in C一書中得到了。我(原文作者)已經添加了一些簡單的優化算法,以加快散列過程。
  1. public long RSHash(String str)  
  2.    {  
  3.       int b     = 378551;  
  4.       int a     = 63689;  
  5.       long hash = 0;  
  6.       for(int i = 0; i < str.length(); i++)  
  7.       {  
  8.          hash = hash * a + str.charAt(i);  
  9.          a    = a * b;  
  10.       }  
  11.       return hash;  
  12.    }  
 
2.JS
Justin Sobel寫的一個位操作的哈希函數。
  1. public long JSHash(String str)  
  2.    {  
  3.       long hash = 1315423911;  
  4.       for(int i = 0; i < str.length(); i++)  
  5.       {  
  6.          hash ^= ((hash << 5) + str.charAt(i) + (hash >> 2));  
  7.       }  
  8.       return hash;  
  9.    }  
 
3.PJW 
該散列算法是基于貝爾實驗室的彼得J溫伯格的的研究。在Compilers一書中(原則,技術和工具)建議採用這個算法的散列函數的哈希方法。
  1. public long PJWHash(String str)  
  2.    {  
  3.       long BitsInUnsignedInt = (long)(4 * 8);  
  4.       long ThreeQuarters     = (long)((BitsInUnsignedInt  * 3) / 4);  
  5.       long OneEighth         = (long)(BitsInUnsignedInt / 8);  
  6.       long HighBits          = (long)(0xFFFFFFFF) << (BitsInUnsignedInt - OneEighth);  
  7.       long hash              = 0;  
  8.       long test              = 0;  
  9.       for(int i = 0; i < str.length(); i++)  
  10.       {  
  11.          hash = (hash << OneEighth) + str.charAt(i);  
  12.          if((test = hash & HighBits)  != 0)  
  13.          {  
  14.             hash = (( hash ^ (test >> ThreeQuarters)) & (~HighBits));  
  15.          }  
  16.       }  
  17.       return hash;  
  18.    }  
 
4.ELF 
和PJW很相似,在Unix系統中使用的較多。
  1. public long ELFHash(String str)  
  2.    {  
  3.       long hash = 0;  
  4.       long x    = 0;  
  5.       for(int i = 0; i < str.length(); i++)  
  6.       {  
  7.          hash = (hash << 4) + str.charAt(i);  
  8.          if((x = hash & 0xF0000000L) != 0)  
  9.          {  
  10.             hash ^= (x >> 24);  
  11.          }  
  12.          hash &= ~x;  
  13.       }  
  14.       return hash;  
  15.    }  
 
5.BKDR
這個算法來自Brian Kernighan 和 Dennis Ritchie的 The C Programming Language。這是一個很簡單的哈希算法,使用了一系列奇怪的數字,形式如31,3131,31...31,看上去和DJB算法很相似。(參照我之前一篇博客,這個就是Java的字符串哈希函數)
  1. public long BKDRHash(String str)  
  2.    {  
  3.       long seed = 131// 31 131 1313 13131 131313 etc..  
  4.       long hash = 0;  
  5.       for(int i = 0; i < str.length(); i++)  
  6.       {  
  7.          hash = (hash * seed) + str.charAt(i);  
  8.       }  
  9.       return hash;  
  10.    }  
 
6.SDBM
這個算法在開源的SDBM中使用,似乎對很多不同類型的數據都能得到不錯的分佈。
  1. public long SDBMHash(String str)  
  2.    {  
  3.       long hash = 0;  
  4.       for(int i = 0; i < str.length(); i++)  
  5.       {  
  6.          hash = str.charAt(i) + (hash << 6) + (hash << 16) - hash;  
  7.       }  
  8.       return hash;  
  9.    }  
 
7.DJB
這個算法是Daniel J.Bernstein 教授發明的,是目前公佈的最有效的哈希函數。
  1. public long DJBHash(String str)  
  2.    {  
  3.       long hash = 5381;  
  4.       for(int i = 0; i < str.length(); i++)  
  5.       {  
  6.          hash = ((hash << 5) + hash) + str.charAt(i);  
  7.       }  
  8.       return hash;  
  9.    }  
 
8.DEK
由偉大的Knuth在《編程的藝術 第三卷》的第六章排序和搜索中給出。
  1. public long DEKHash(String str)  
  2.    {  
  3.       long hash = str.length();  
  4.       for(int i = 0; i < str.length(); i++)  
  5.       {  
  6.          hash = ((hash << 5) ^ (hash >> 27)) ^ str.charAt(i);  
  7.       }  
  8.       return hash;  
  9.    }  
 
9.AP
這是本文作者Arash Partow貢獻的一個哈希函數,繼承了上面以旋轉以爲和加操作。代數描述:AP

  1. public long APHash(String str)  
  2.    {  
  3.       long hash = 0xAAAAAAAA;  
  4.       for(int i = 0; i < str.length(); i++)  
  5.       {  
  6.          if ((i & 1) == 0)  
  7.          {  
  8.             hash ^= ((hash << 7) ^ str.charAt(i) * (hash >> 3));  
  9.          }  
  10.          else  
  11.          {  
  12.             hash ^= (~((hash << 11) + str.charAt(i) ^ (hash >> 5)));  
  13.          }  
  14.       }  
  15.       return hash;  
  16.    }  
 

7.MD5和SHA-1

 1.MD5算法

  • MD5即Message-Digest Algorithm 5(信息-摘要算法 5),用於確保信息傳輸完整一致。是計算機廣泛使用的散列算法之一(又譯摘要算法、哈希算法),主流編程語言普遍已有MD5實現。 將數據(如漢字)運算爲另一固定長度值,是散列算法的基礎原理,MD5的前身有MD2、MD3和MD4。
  • MD5一度被廣泛應用於安全領域。但是由於MD5的弱點被不斷髮現以及計算機能力不斷的提升,現在已經可以構造兩個具有相同MD5的信息[2],使本算法不再適合當前的安全環境。目前,MD5計算廣泛應用於錯誤檢查。例如在一些BitTorrent下載中,軟件通過計算MD5和檢驗下載到的碎片的完整性。
  • MD5是輸入不定長度信息,輸出固定長度128-bits的算法。經過程序流程,生成四個32位數據,最後聯合起來成爲一個128-bits散列。基本方式爲,求餘、取餘、調整長度、與鏈接變量進行循環運算。得出結果。

原理

對MD5算法簡要的敘述可以爲:MD5以512位分組來處理輸入的信息,且每一分組又被劃分爲16個32位子分組,經過了一系列的處理後,算法的輸出由四個32位分組組成,將這四個32位分組級聯後將生成一個128位散列值。
2.SHA-1算法
安 全哈希算法(Secure Hash Algorithm)主要適用於數字簽名標準 (Digital Signature Standard DSS)裏面定義的數字簽名算法(Digital Signature Algorithm DSA)。對於長度小於2^64位的消息,SHA1會產生一個160位的消息摘要。當接收到消息的時候,這個消息摘要可以用來驗證數據的完整性。在傳輸的過程中,數據很可能會發生變化,那麼這時候就會產生不同的消息摘要。 SHA1有如下特性:不可以從消息摘要中復原信息;兩個不同的消息不會產生同樣的消息摘要。
該算法輸入報文的長度不限,產生的輸出是一個160位的報文摘要。輸入是按512 位的分組進行處理的。SHA-1是不可逆的、防衝突,並具有良好的雪崩效應。

SHA-1與MD5的比較

因爲二者均由MD4導出,SHA-1和MD5彼此很相似。相應的,他們的強度和其他特性也是相似,但還有以下幾點不同:
l 對強行攻擊的安全性:最顯著和最重要的區別是SHA-1摘要比MD5摘要長32 位。使用強行技術,產生任何一個報文使其摘要等於給定報摘要的難度對MD5是2^128數量級的操作,而對SHA-1則是2^160數量級的操作。這樣,SHA-1對強行攻擊有更大的強度。
l 對密碼分析的安全性:由於MD5的設計,易受密碼分析的攻擊,SHA-1顯得不易受這樣的攻擊。
l 速度:在相同的硬件上,SHA-1的運行速度比MD5慢。





 


發佈了26 篇原創文章 · 獲贊 1 · 訪問量 4萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章