為什么要有單向散列函數
- 作為接收者,如果將得到的密文正確解密,看到了明文。是否意味著這次加密傳輸是完全安全和正確的?可以肯定的說,不是。
這里面有很多原因,其中一個理由是:我們如何判定,我們看到的這個明文,就是發送者發送的明文?如何判定沒有被篡改過? - 我們假設一個例子:
- A發送兩個消息給B。 第一個消息是讓B匯款給C,第二個消息是讓B匯款給D。
- 攻擊者截獲了第一個消息,并保存C對應的字節。
- 當攻擊者截獲第二段時,將D替換成C。
- 假設密鑰沒變,B看到的明文就是匯款給C兩次,而且B完全無法察覺這是被篡改過的。
- 所以我們需要一種技術來校驗文件是否被篡改,保證消息的完整性,或者叫一致性。實現這種功能的技術叫做“單向散列函數”。
什么是單向散列函數
- 單向散列函數有一個輸入和一個輸出,輸入被稱為消息,輸出被稱為散列值。
- 消息的類型不受限制,可以是聲音或者圖片或者人類無法讀懂的消息。因為單向散列函數會將任何輸入作為單純的比特序列來處理,即根據比特序列計算出散列值。
- 輸入有可能書很巨大的文件,如果單向散列值計算出的散列值跟文件長度相關,那么在實際使用中可能會出現效率問題。所以,無論輸入是多長,計算出的散列值長度固定,也被稱為指紋。
- 根據上面的信息,可以得出:比對兩份文件的散列值,就能比對出兩份文件是否相同,從而保證了文件的完整性。
單向散列值的性質
- 根據任意長度的消息計算出固定長度的散列值
- 能夠快速計算出散列值
-
消息不同散列值也不同
- 碰撞。就是如果兩份不同的輸入,卻產生相同的散列值,則稱為"碰撞"。
- 抗碰撞性。難以發現碰撞的性質稱為"抗碰撞性"。
- 弱抗碰撞性。當給定某條消息的散列值時,單向散列函數必須確保要找到和該條消息具有相同散列值的另外一條消息是非常困難的。單向散列函數都必須具備弱抗碰撞性。
-
強抗碰撞性。指要找到散列值相同的兩條不同的消息是非常困難的,這里的散列值可以是任意值。
密碼技術中所使用的單向散列函數,必須同時具備"抗弱碰撞性"和"抗強碰撞性"。
- 具備單向性。指的是無法通過散列值反推出消息的性質。
相關術語
因為單向散列函數里有很多術語指的其實是一個東西,所以有必要做出說明。
- 單向散列函數 = 消息摘要函數 = 哈希函數 = 雜湊函數
- 輸入的消息 = 原像(pre-image)
- 輸出的散列值 = **消息摘要(message digest) = 指紋(fingerprint)
- 完整性 = 一致性
- 散列的英文就是hash,古法語的意思為"斧子",后引申為"剁碎的肉末"。這里的意思估計就是把消息剁碎而無法還原的意思吧。
單向散列函數的實際應用
-
檢測軟件是否被篡改。
這個上面講解由來的時候已經介紹到了,一般具體的做法是軟件發布者將散列值公開發布到網上,使用軟件的人就可以根據這個來判斷獲得的軟件是否已經被篡改。 -
基于口令的加密。
PBE(Password Based Encryption)基于口令的加密,是將口令和salt(隨機數)混合后計算其散列值,作為加密的密鑰。這樣可以抵御針對口令的字典攻擊。 -
消息認證碼。
消息認證碼是將"發送者和接收者之間的共享密鑰"和"消息"進行混合計算出的散列值。使用消息認證碼可以檢測并防止通信過程中的錯誤、篡改以及偽裝。在SSL/TLS中得到了運用。 -
數字簽名。
數字簽名非常的耗時,所以不會對整個消息進行數字簽名。一般先計算出消息的散列值,然后再針對散列值進行數字簽名。 -
偽隨機數生成器。
偽隨機數需要具備"事實上不可能根據過去的隨機數列預測未來的隨機數列"這樣的性質。為了保證不可預測性,可以利用單向散列函數的單向性。 -
一次性口令。
一次性口令通常被用于服務器對客戶端的合法性認證。這種方式中,通過使用單向散列函數可以保證口令只在通信鏈路上傳送一次,因此即使竊聽者竊取了口令,也無法使用。
單向散列函數使用的算法
-
MD4、MD5。
這兩種都是產生128比特的散列值。MD5的強抗碰撞性已經被攻破,所以不再是安全的。 -
SHA-1、SHA-256、SHA-384、SHA-512。
SHA-1產生上限為接近264比特的散列值。
SHA-256、SHA-384、SHA-512分別產生256比特、384比特和512比特的散列值。這些合稱為SHA-2。
SHA-1的強抗碰撞性已經被攻破,不再安全。SHA-2目前還未被攻破。 -
RIPEMD-160。
RIPEMD-160是歐盟所設計的RIPEMD的修訂版,散列值為160比特。
RIPEMD已經被攻破,RIPEMD-160還未被攻破。 -
AHS與SHA-3*
NIST在SHA-1被攻破的背景下開始著手準備下一代的SHA-3標準,2012年此標準已經晚成選型。
單向散列函數SHA-1
整體流程
-
填充。
將消息填充處理,使其長度為512比特的整數倍。 -
計算W0 - W79。
將每個512比特分組計算得出80個32比特的值(W0 - W79)。 -
分組處理。
針對輸入分組進行80個步驟的處理,計算出5個32比特的值(A-E),作為SHA-1的內部狀態。 - 單步處理。
詳細處理過程
說實話太復雜,暫時也用不上,此處省略。。。。。很多字。
對單向散列函數的攻擊
-
暴力破解
- 攻擊場景是:A向B發送一條消息,內容是"A向B要求支付金額為1百萬元。",攻擊者截獲此消息后,想要篡改此消息而不會被B發現。
- 這種攻擊場景實際上就是破解弱抗碰撞性,就是針對某一特定的消息找到與其相同的散列值的消息進行替換。
- 使用暴力破解法,從文檔文件的冗余性入手。即在不改變文檔意思的前提下能夠對文件內容進行修改的程度。例如:
想要修改成B給A1億元。可以列舉出相同意思的多份修改后的消息:
A向B要求支付金額為1億元。
A向B要求支付金額為1000000000元。
..........
只要找到一份跟原文相同的散列值即可。
-
生日攻擊
- 攻擊場景是:編寫消息的人是攻擊者。攻擊者首先生成兩份散列值相同,但內容不同的文件。其中一份要B支付1百萬的合同給了A,A生成散列值后發送給B。攻擊者截獲此報文后,替換成散列值相同的要B支付1億元的合同。這樣就達成了攻擊。
- 這種攻擊場景的實質是要破解強抗碰撞性,即只要任何兩份文檔存在相同的散列值時,即可達成攻擊。
- 攻擊的概率計算涉及到生日攻擊方法。
- 所謂的生日攻擊就是:隨機選出N個人,其中任意兩個人的生日相同的概率大于二分之一,請問N為多少?
- 這個問題的解題訣竅是,不要正向的去想先選定一個人,再找另外一個人的生日和他相同。這就完全改變了題目的意思,是任意而不是特定,只要選中一個人就是特定。解題的技巧是,先計算N個人的生日全都不一樣的概率,再用1去減去那個概率即可,這個過程沒有選定任何一個生日,這才是任意。
- 任意N個人的生日不一樣的組合數量計算很簡單,365一直乘到(365-N+1)即可。所有的可能性組合數量是365的N次方。上下一除就是N個人生日不一樣的概率。1減去這個概率就是任意兩人生日相同的概率,要大于二分之一的話,N為23。
- 將生日問題轉化成一般問題:假設一年為Y天,那么N人中生日相同的概率大于二分之一,N至少為多少?
當Y非常大時,結果類似等于 N = 根號Y - 找出任意散列值相同的文件的概率大于二分之一,其中Y天數就是散列值的組合數量。假設散列值的比特長度為M ,則N = 2的M次方開平方根。
- 假設160比特的散列值,暴力破解需要2160次,而生日攻擊只需要280次。
單向散列函數無法解決的問題
單向散列函數只能解決篡改問題,無法解決偽裝問題。也就是說此技術無法判斷出,發送消息的人是否是正確的。