簡介
概念
雜湊演算法(Hash Algorithm),又稱雜湊演算法,雜湊演算法,是一種從任意檔案中創造小的數字「指紋」的方法。與指紋一樣,雜湊演算法就是一種以較短的資訊來保證檔案唯一性的標誌,這種標誌與檔案的每一個位元組都相關,而且難以找到逆向規律。因此,當原有檔案發生改變時,其標誌值也會發生改變,從而告訴檔案使用者當前的檔案已經不是你所需求的檔案
Hash簡單點講就是把任意一段資料經過某種演算法生成一段唯一的固定長度的資料
也可以把雜湊值當做是檔案指紋,因為它是檔案唯一性的標誌,與每一個位元組都有關,當檔案發生改變是,指紋值也會改變
-
如果把hash演算法比喻為一座工廠
-
那傳給hash演算法的內容就是原材料
-
生成的hash值就是生產出的產品
特點
- 正向快速:給定明文和 Hash 演算法,在有限時間和有限資源內能計算得到 Hash 值
- 只要傳入的內容一樣,得到的hash值必然一樣
- 逆向困難:給定 Hash 值,在有限時間內很難逆推出明文
- 輸入敏感:原始輸入資訊發生任何變化,新的 Hash 值都應該出現很大變化
- 衝突避免:很難找到兩段內容不同的明文,使得它們的 Hash 值一致
- 長度固定:只要我們使用是hash演算法固定,無論傳入的內容有多大,得到的hash值的長度是固定
- 資訊摘要:hash只是資訊的摘要,資訊指紋,是用來做資料識別的
hash有哪些
常見 Hash 演算法有 MD5 和 SHA 系列,目前 MD5 和 SHA1 已經被破解,一般推薦至少使用 SHA2-256 演算法
雜湊演算法 | 輸出長度(bit) | 輸出長度(位元組) |
---|---|---|
MD5 | 128 bit | 16 bytes |
RipeMD160 | 160 bits | 20 bytes |
SHA-1 | 160 bits | 20 bytes |
SHA-256 | 256 bits | 32 bytes |
SHA-512 | 512 bits | 64 bytes |
演算法碰撞
稍微想一下就可以發現,既然輸入資料長度不固定,而輸出的雜湊值卻是固定長度的,這意味著雜湊值是一個有限集合,而輸入資料則可以是無窮多個,那麼建立一對一關係明顯是不現實的。所以“碰撞”是必然會發生的,所以一個成熟的雜湊演算法會有較好的抗衝突性,同時在實現雜湊表的結構時也要考慮到雜湊衝突的問題
-
比如“666”經過 Hash 後是“fae0b27c451c728867a567e8c1bb4e53”,相同 Hash 演算法得到的值是一樣的。比如 WiFi 密碼如果是 8 位純數字的話,頂多就是 99999999 種可能性,破解這個密碼需要做的就是提前生成好 0 到 1 億數字的 Hash 值,然後做 1 億次布林運算(就是 Bool 值判斷,0 或者 1),而現在普通 I5 四核 CPU 每秒能到達 200 億次浮點數計算,做 1 億次布林運算也就是秒級別的時間就破解了
-
8位大小寫字母、數字、特殊符號組成的密碼,若按照MD5加密,則hash值大概10000千億,i9算力每秒1千億。也需要至少24h。這只是極端情況下,如果加上加密演算法不確定(比如3),請求時間(比如3),查詢時間(比如3),這就已經需要半年左右,倘若再加上錯誤等待時間(比如輸入5次錯誤等待24小時),那就已經需要50年。。。
當然,如果有三萬臺電腦同時破解,也還是一天 -_-|||。
不過道高一尺,魔高一丈。誰又會傻乎乎的一個站著打一個等著挨。都是相對的
所以密碼儘量不要用純數字,因為根本沒有任何安全性
加鹽防碰撞
對數字內容進行 Hash 運算,獲取唯一的摘要值來指代原始完整的數字內容,利用 Hash 函式的抗碰撞性來確保內容未被篡改
常用於使用者名稱和密碼來確保使用者資訊保安,為了防止攻擊會採用加鹽的方法,就是原來的明文加上一個隨機數之後的 Hash 值,Hash 值和鹽會儲存在兩個地方,只要不是同時洩漏就很難被破解
加密
如果在Python中需要對使用者輸入的密碼或者其他內容進行加密,首選的方法是生成hash值
在Python中可以利用二個模組來進行:
- crypt
- hashlib
hashlib
主要方法
使用:hashlib.md5()
名稱 | 描述 |
---|---|
md5(…) | 利用md5演算法加密 |
sha1(…) | 利用sha1演算法加密 |
sha224(…) | 利用sha224演算法加密 |
sha256(…) | 利用sha256演算法加密 |
sha384(…) | 利用sha384演算法加密 |
sha512(…) | 利用sha512演算法加密 |
特有方法
如果你利用hashlib
生成了一個Hash物件,那麼這個Hash物件會包含如下方法
名稱 | 描述 |
---|---|
update(arg) | 可以重複利用指定了特殊加密演算法的Hash物件,對arg 進行加密 |
digest(…) | 以字元形式返回加密內容 |
hexdigest(…) | 以16進位制形式返回加密內容 |
copy(…) | 為了達到重複利用Hash物件的目的,而克隆Hash物件 |
使用方法
-
直接使用hashlib方法
import hashlib hashlib.sha224("Nobody inspects the spammish repetition".encode("utf-8")) # 加密 hashlib.sha224("Nobody inspects the spammish repetition".encode("utf-8")).hexdigest() # 返回加密內容
-
直接使用Hash物件中的方法
import hashlib # 造出工廠 m = hashlib.md5() # 放入原料 m.update("Nobody inspects".encode('utf-8')) # 產出hash值 m.digest() m.update("the spammish repetition".encode("utf-8")) m.digest() m.hexdigest()
加鹽
import hashlib
# 造出工廠
m = hashlib.md5("this is salt".encode("utf-8"))
# 放入原料
m.update("Nobody inspects".encode('utf-8'))
# 產出hash值
m.digest()
m.update("the spammish repetition".encode("utf-8"))
m.digest()
m.hexdigest()
crypt
主要方法
名稱 | 型別 | 描述 |
---|---|---|
crypt(…) | 方法 | 對指定內容進行hash加密 |
mksalt(…) | 方法 | 根據加密演算法生成salt |
methods | list | 返回可用加密演算法的列表 |
MOTHOD_CRYPT | 常量 | 加密演算法 |
METHOD_MD5 | 常量 | md5加密演算法 |
METHOD_SHA256 | 常量 | sha256加密演算法 |
METHOD_SHA512 | 常量 | sha512加密演算法 |
使用說明
使用crypt.crypt(…)進行hash加密的時候,需要提供二個引數:
- 加密內容
- salt
import crypt
salt = crypt.mksalt(crypt.METHOD_SHA512)
hash = crypt.crypt("helloworld",salt)
應用
密碼加密
m=hashlib.md5()
m.update('key'.encode('utf-8')) #新增個其他元素,提升密碼複雜度,不是加鹽
m.update(password.encode('utf-8'))
print(m.hexdigest())
應用一致性校驗
m = hashlib.md5()
with open(r'E:\01.mp4','rb') as f:
for line in f:
m.update(line)
print(m.hexdigest)