名詞概念解釋
Hash函數
也叫哈希函數,散列函數,雜湊函數,壓縮函數。
雜湊函數是雜湊算法的基礎。
簡單來說就是將做任意長度的消息壓縮到某一固定長度的消息摘要的函數。
Hash值
也叫消息摘要,指散列算法通過一系列的變化和運算獲得輸出的大小固定的字符串。
特征
主要特征
算法公開,不需要密鑰。經過加密的數據無法被解密(單向加密)。將任意長度的消息壓縮到某一固定長度的值。
容易計算
給出消息M,容易計算出該消息的雜湊值h(M)
輸入敏感
如果輸入的數據信息被輕微修改,輸出的Hash值也會有很明顯的變化。能夠保證文件或值的安全
抗碰撞性
不易發生不同消息雜湊值相同的情況,但不是絕對
PS:弱抗碰撞是指在給定字符串和散列值的前提下找到另一個有相同散列值的字符串,難度極高
強抗碰撞性實質找到散列值相同的兩個字符串,散列值是什么沒有限制,難度很低,sha1也只需要263次即可嘗試出來
應用
密碼安全認證,數字簽名,數據完整性認證,秒速雲上傳文件等
數字簽名
概念
上鎖(私鑰簽名)的消息摘要。
具體流程
對發送方甲而言整個發送過程如下:
-
創建對稱密鑰 ( 相應軟件生成,並且是一次性的 ) ,用其加密合同,並用乙的公鑰打包對稱密鑰。
-
創建數字簽名,對合同進行散列算法並產生原始摘要,甲用自己的私鑰加密該摘要。
-
最后,甲將加密后的合同(數字簽名)、打包后的密鑰、原始摘要,以及甲的數字證書一起發給乙。
而接收方乙接收加密文件后,需要完成以下動作:
- 接收后,用乙的私鑰解密得到對稱密鑰,並用對稱密鑰解開加密的合同,得到合同明文。對合同明文使用和發送者同樣的散列算法來創建摘要(稱做摘要2) 。
- 通過甲的數字證書獲得屬於甲的公鑰,並用其解開摘要(稱做摘要1)。
- 比較摘要1和摘要2,若相同,則表示信息未被篡改 , 且來自於甲。
流程圖如下:
雜湊算法
設計方法
分為三大類,即基於模數運算的,基於分組加密的,定制的
目前最流行的是定制
基於模數運算:計算速度很慢,不實用
定制:不基於任何假設和密碼體制,而是通過直接構造復雜的非線性關系達到單向要求,設計單向雜湊函數
具體如下圖:
輸出長度概念理解
MD5 SHA1 SHA256 這3種本質都是摘要函數,MD5 是 128 位,SHA1 是 160 位 ,SHA256 是 256 位。
比特(bit),即一個二進制位 ,例如100011就是6比特;
電腦技術中對CPU在單位時間內(同一時間)能一次處理的二進制數的位數叫字長,所以能處理字長為8位數據的CPU通常就叫8位的CPU。即八位代表能處理八比特數據
十六位字符串表示十六個字符
而1字節=8bit
ASCII碼編碼下,一個英文字母(不分大小寫)占一個字節的空間。
所以,MD5加密后為16位字符串,SHA1是20位字符串,SHA256是32位字符串
安全雜湊函數的一般結構
首先把消息分組,分為固定長度的a bit,最后一個分組不足a bit需要填充為a bit,最后一個分組還包含輸入長度,反復使用壓縮函數M
如下圖:
雜湊算法的實例——MD5
md5存在問題
php漏洞
PHP在處理哈希字符串時會利用”!=”或”==”來對哈希值進行比較,它把每一個以”0E”開頭的哈希值都解釋為0,所以如果兩個不同的密碼經過哈希以后,其哈希值都是以”0E”開頭的,那么PHP將會認為他們相同,都是0。
數組繞過
md5不能加密數組,傳入數組會報錯,但會繼續執行並且返回結果為null
php代碼如下:
md5(a[]=1) === md5(b[]=1)
值為null===null,返回true
需要注意的是0e繞過只能繞過弱類型比較(),而數組繞過不只可以繞過弱類型比較,還可以繞過強類型比較(=)
弱類型比較(==),只判斷內容是否相等,如果是字符串類型,則轉換成數值型后進行判斷
強類型比較(===),判斷內容的基礎上,還會判斷類型是否相同
MD5碰撞
MD5碰撞也叫哈希碰撞,即兩個不同的值的散列值相同
MD5-SQL注入
ffifdyop 的MD5加密結果是 276f722736c95d99e921722cf9ed621c
經過MySQL編碼后會變成'or'6xxx,使SQL恆成立,相當於萬能密碼,可以繞過md5()函數的加密
“構造前綴碰撞法”
幾位密碼學家使用的是“構造前綴碰撞法”(chosen-prefix collisions)來進行此次攻擊,他們得出的結論是:MD5算法不應再被用於任何軟件完整性檢查或代碼簽名的用途。
另:現在,如果僅僅是想要生成 MD5 相同而內容不同的文件的話,在任何主流配置的電腦上用幾秒鍾就可以完成了。
md5加密代碼實現
#md5進行數據的加密
import hashlib
#md5加密
def md5sum(str):
m = hashlib.md5() #創建一個hashlib.md5()對象
m.update(name.encode("utf8")) #將參數轉換為UTF8編碼
print(m.hexdigest()) #用十六進制輸出加密后的數據
print md5sum(raw_input('Please string:') #用來獲取控制台的 輸入
參考&學習鏈接
MD5加密漏洞(MD5繞過方式-0e繞過/數組繞過/MD5碰撞/MD5SQL注入)
深入理解加密、解密、數字簽名(簽名證書、加密證書)的組成和數字證書
《應用密碼學(第四版)》