GeezerVisonThe World Wide Web, restored to 800 pixels of glory. | |||||||||||||||
| Home|About|Gaming cabinet|Archives|How it works|Starter sites | |||||||||||||||
GeezerVison is showing python.github.io — hashlib --- 安全雜湊與訊息摘要 — Python 3.15.2 說明文件
|
雜湊 |
digest_size |
len(key) |
len(salt) |
len(person) |
|---|---|---|---|---|
BLAKE2b |
64 |
64 |
16 |
16 |
BLAKE2s |
32 |
32 |
8 |
8 |
備註
BLAKE2 規範定義了鹽和個人化參數的恆定長度,但為了方便起見,此實作接受任意大小的位元組字串,最多可達指定長度。如果參數的長度小於指定的長度,則用零補滿,所以像是 b'salt 和 b'salt\x00 是相同的值。(但 key 的情況並非如此。)
這些大小可作為模組常數使用,如下所述。
建構函式還接受以下樹狀雜湊參數:
fanout:扇出(0 到 255,如果無限制則為 0、順序模式為 1)。
depth:樹的最大深度(1 到 255,如果無限制則為 255、順序模式為 1)。
leaf_size:葉的最大位元組長度(0 到 2**32-1,如果無限制或處於順序模式則為 0)。
node_offset:節點偏移量(BLAKE2b 為 0 到 2**64-1,BLAKE2s 為 0 到 2**48-1,0 表示第一個、最左邊、葉子或在順序模式下)。
node_depth:節點深度(0 到 255,葉為 0,或在順序模式下)。
inner_size:內部摘要大小(BLAKE2b 為 0 到 64,BLAKE2s 為 0 到 32,順序模式為 0)。
last_node:布林值,代表處理的節點是否為最後一個(False 代表順序模式)。
關於樹狀雜湊的綜合回顧,請參閱 BLAKE2 規範中的第 2.10 節。
鹽長度(建構函式接受的最大長度)。
個人化字串長度(建構函式接受的最大長度)。
最大密鑰大小。
雜湊函式可以輸出的最大摘要大小。
要計算某些資料的雜湊值,你應該首先透過呼叫適當的建構函式(blake2b() 或 blake2s())以建構一個雜湊物件,然後透過於物件呼叫 update() 來以資料對它更新,最後透過呼叫 digest()(或對於十六進位編碼字串則為 hexdigest())從物件中獲得摘要。
>>> from hashlib import blake2b >>> h = blake2b() >>> h.update(b'Hello world') >>> h.hexdigest() '6ff843ba685842aa82031d3f53c48b66326df7639a63d128974c5c14f31a0f33343a8c65551134ed1ae0f2b0dd2bb495dc81039e3eeb0aa1bb0388bbeac29183'
作為一個快捷方式,你可以將要更新的第一個資料塊作為位置引數直接傳遞給建構函式:
>>> from hashlib import blake2b >>> blake2b(b'Hello world').hexdigest() '6ff843ba685842aa82031d3f53c48b66326df7639a63d128974c5c14f31a0f33343a8c65551134ed1ae0f2b0dd2bb495dc81039e3eeb0aa1bb0388bbeac29183'
你可以根據需求來多次呼叫 hash.update() 以疊代更新雜湊:
>>> from hashlib import blake2b >>> items = [b'Hello', b' ', b'world'] >>> h = blake2b() >>> for item in items: ... h.update(item) ... >>> h.hexdigest() '6ff843ba685842aa82031d3f53c48b66326df7639a63d128974c5c14f31a0f33343a8c65551134ed1ae0f2b0dd2bb495dc81039e3eeb0aa1bb0388bbeac29183'
BLAKE2 有可調整的摘要大小,BLAKE2b 最多為 64 位元組,BLAKE2s 最多為 32 位元組。例如,要在不改變輸出大小的情況下用 BLAKE2b 替換 SHA-1,我們可以指定 BLAKE2b 生成 20 位元組的摘要:
>>> from hashlib import blake2b >>> h = blake2b(digest_size=20) >>> h.update(b'Replacing SHA1 with the more secure function') >>> h.hexdigest() 'd24f26cf8de66472d58d4e1b1774b4c9158b1f4c' >>> h.digest_size 20 >>> len(h.digest()) 20
具有不同摘要大小的雜湊物件具有完全不同的輸出(較短的雜湊值不是較長雜湊值的前綴);即使輸出長度相同,BLAKE2b 和 BLAKE2s 也會產生不同的輸出:
>>> from hashlib import blake2b, blake2s >>> blake2b(digest_size=10).hexdigest() '6fa1d8fcfd719046d762' >>> blake2b(digest_size=11).hexdigest() 'eb6ec15daf9546254f0809' >>> blake2s(digest_size=10).hexdigest() '1bf21a98c78a1c376ae9' >>> blake2s(digest_size=11).hexdigest() '567004bf96e4a25773ebf4'
密鑰雜湊可用於身份驗證,作為基於雜湊的訊息驗證碼 (Hash-based message authentication code) (HMAC) 的更快、更簡單的替代方案。由於繼承自 BLAKE 的不可微特性 (indifferentiability property),BLAKE2 可以安全地用於 prefix-MAC 模式。
此範例示範了如何使用密鑰 b'pseudorandom key' 取得訊息 b'message data' 的(十六進位編碼)128 位元驗證碼:
>>> from hashlib import blake2b >>> h = blake2b(key=b'pseudorandom key', digest_size=16) >>> h.update(b'message data') >>> h.hexdigest() '3d363ff7401e02026f4a4687d4863ced'
舉一個實際的例子,網頁應用程式可以對發送給使用者的 cookie 進行對稱簽名 (symmetrically sign),然後驗證它們以確保它們沒有被篡改:
>>> from hashlib import blake2b >>> from hmac import compare_digest >>> >>> SECRET_KEY = b'pseudorandomly generated server secret key' >>> AUTH_SIZE = 16 >>> >>> def sign(cookie): ... h = blake2b(digest_size=AUTH_SIZE, key=SECRET_KEY) ... h.update(cookie) ... return h.hexdigest().encode('utf-8') >>> >>> def verify(cookie, sig): ... good_sig = sign(cookie) ... return compare_digest(good_sig, sig) >>> >>> cookie = b'user-alice' >>> sig = sign(cookie) >>> print("{0},{1}".format(cookie.decode('utf-8'), sig)) user-alice,b'43b3c982cf697e0c5ab22172d1ca7421' >>> verify(cookie, sig) True >>> verify(b'user-bob', sig) False >>> verify(cookie, b'0102030405060708090a0b0c0d0e0f00') False
儘管有原生密鑰雜湊模式,BLAKE2 還是可以透過 hmac 模組用於建構 HMAC:
>>> import hmac, hashlib >>> m = hmac.new(b'secret key', digestmod=hashlib.blake2s) >>> m.update(b'message') >>> m.hexdigest() 'e3c8102868d28b5ff85fc35dda07329970d1a01e273c37481326fe0c861c8142'
透過設定 salt 參數,使用者可以向雜湊函式引入隨機化。隨機雜湊在防止針對數位簽章中雜湊函式的碰撞攻擊 (collision attacks) 非常有用。
隨機雜湊是為這樣的情況而設計的:一方(訊息準備者)生成全部或部分訊息並由另一方(訊息簽名者)簽名。如果訊息準備者能夠發現加密雜湊函式發生碰撞(collision,即兩條訊息產生相同的雜湊值),那麼他們可能會準備有意義的訊息版本,該版本將產生相同的雜湊值和數位簽章,但結果不同(例如,將 $1,000,000 轉入賬戶,而不是 $10)。加密雜湊函式的設計以抗碰撞性為主要目標,但目前對加密雜湊函式攻擊的關注可能會導致給定的加密雜湊函式所提供的抗碰撞性低於預期。隨機雜湊透過降低準備者在數位簽章生成過程中生成最終產生相同雜湊值的兩個或多個訊息的可能性,為簽名者提供額外的保護 —— 即便嘗試去找到雜湊函式碰撞的發生是實際可行的。然而,若訊息的所有部分都是由簽名者所準備好的,使用隨機雜湊可能會降低數位簽章提供的安全性。
(NIST SP-800-106 「數位簽章的隨機雜湊 (Randomized Hashing for Digital Signatures)」)
在 BLAKE2 中,鹽在初始化期間作為雜湊函式的一次性輸入被處理,而不是作為每個壓縮函式的輸入。
警告
使用 BLAKE2 或任何其他通用加密雜湊函式(例如 SHA-256)的加鹽雜湊 (或單純雜湊)不適合對密碼進行雜湊處理。有關更多資訊,請參閱 BLAKE2 FAQ 。
>>> import os >>> from hashlib import blake2b >>> msg = b'some message' >>> # Calculate the first hash with a random salt. >>> salt1 = os.urandom(blake2b.SALT_SIZE) >>> h1 = blake2b(salt=salt1) >>> h1.update(msg) >>> # Calculate the second hash with a different random salt. >>> salt2 = os.urandom(blake2b.SALT_SIZE) >>> h2 = blake2b(salt=salt2) >>> h2.update(msg) >>> # The digests are different. >>> h1.digest() != h2.digest() True
有時候強制雜湊函式為不同目的的相同輸入生成不同的摘要是很有用的。引用 Skein 雜湊函式的作者的話:
我們建議所有應用程式設計者認真考慮這樣做;我們已經看到許多協定,其中在協定的一個部分中計算的雜湊可以在完全不同的部分中使用,因為兩次雜湊計算是在相似或相關的資料上完成的,並且攻擊者可以強制應用程式將雜湊輸入設為相同的。對協定中使用的每個雜湊函式進行個人化可以立即阻止此類攻擊。
(Skein 雜湊函式系列,第 21 頁)
BLAKE2 可以透過將位元組傳遞給 person 引數來做個人化:
>>> from hashlib import blake2b >>> FILES_HASH_PERSON = b'MyApp Files Hash' >>> BLOCK_HASH_PERSON = b'MyApp Block Hash' >>> h = blake2b(digest_size=32, person=FILES_HASH_PERSON) >>> h.update(b'the same content') >>> h.hexdigest() '20d9cd024d4fb086aae819a1432dd2466de12947831b75c5a30cf2676095d3b4' >>> h = blake2b(digest_size=32, person=BLOCK_HASH_PERSON) >>> h.update(b'the same content') >>> h.hexdigest() 'cf68fb5761b9c44e7878bfb2c4c9aea52264a80b75005e65619778de59f383a3'
個人化與密鑰模式還可以一起用於從單個密鑰得出不同的密鑰。
>>> from hashlib import blake2s >>> from base64 import b64decode, b64encode >>> orig_key = b64decode(b'Rm5EPJai72qcK3RGBpW3vPNfZy5OZothY+kHY6h21KM=') >>> enc_key = blake2s(key=orig_key, person=b'kEncrypt').digest() >>> mac_key = blake2s(key=orig_key, person=b'kMAC').digest() >>> print(b64encode(enc_key).decode('utf-8')) rbPb15S/Z9t+agffno5wuhB77VbRi6F9Iv2qIxU7WHw= >>> print(b64encode(mac_key).decode('utf-8')) G9GtHFE1YluXY1zWPlYk1e/nWfu0WSEb0KRcjhDeP/o=
下面是對具有兩個葉節點的最小樹進行雜湊處理的範例:
10 / \ 00 01
此範例使用 64-byte 內部摘要,並回傳 32-byte 最終摘要:
>>> from hashlib import blake2b >>> >>> FANOUT = 2 >>> DEPTH = 2 >>> LEAF_SIZE = 4096 >>> INNER_SIZE = 64 >>> >>> buf = bytearray(6000) >>> >>> # Left leaf ... h00 = blake2b(buf[0:LEAF_SIZE], fanout=FANOUT, depth=DEPTH, ... leaf_size=LEAF_SIZE, inner_size=INNER_SIZE, ... node_offset=0, node_depth=0, last_node=False) >>> # Right leaf ... h01 = blake2b(buf[LEAF_SIZE:], fanout=FANOUT, depth=DEPTH, ... leaf_size=LEAF_SIZE, inner_size=INNER_SIZE, ... node_offset=1, node_depth=0, last_node=True) >>> # Root node ... h10 = blake2b(digest_size=32, fanout=FANOUT, depth=DEPTH, ... leaf_size=LEAF_SIZE, inner_size=INNER_SIZE, ... node_offset=0, node_depth=1, last_node=True) >>> h10.update(h00.digest()) >>> h10.update(h01.digest()) >>> h10.hexdigest() '3ad2a9b37c6070e374c7a8c508fe20ca86b6ed54e286e93a0318e95e881db5aa'
BLAKE2 由 Jean-Philippe Aumasson、Samuel Neves、Zooko Wilcox-O'Hearn 和 Christian Winnerlein 設計,基於由 Jean-Philippe Aumasson、Luca Henzen、Willi Meier 和 Raphael C.-W. Phan 所建立的 SHA-3 最終版本 BLAKE。
它使用 Daniel J. Bernstein 設計的 ChaCha 密碼的核心演算法。
標準函式庫實作是基於 pyblake2 模組。它是由 Dmitry Chestnykh 在 Samuel Neves 的 C 版本實作為基礎所編寫的。該文件是由 Dmitry Chestnykh 編寫並從 pyblake2 複製過來的。
Christian Heimes 為 Python 重寫了部分 C 程式碼。
以下公開領域貢獻適用於 C 雜湊函式實作、擴充程式碼和此文件:
在法律允許的範圍內,作者已將該軟體的所有版權以及相關和鄰接權利奉獻給全球的公開領域。該軟體的發布沒有任何授權 (warranty)。
你應會隨本軟體一起收到一份 CC0 公眾領域貢獻宣告 (CC0 Public Domain Dedication) 的副本。如果沒有,請參閱 https://creativecommons.org/publicdomain/zero/1.0/ 。
以下人員根據創用 CC 通用公眾領域貢獻宣告 1.0 (Creative Commons Public Domain Dedication 1.0 Universal) 於專案和公開領域做出了開發或貢獻:
Alexandr Sokolovskiy
也參考
hmac 模組使用雜湊生成訊息驗證程式碼的模組。
base64 模組另一種在非二進位環境中編碼二進位雜湊的方法。
有關安全雜湊演算法的 FIPS 180-4 出版物。
有關 SHA-3 標準的 FIPS 202 出版物。
BLAKE2 官方網站。
包含有關哪些演算法存在已知問題以及這些問題對其使用意味著什麼資訊的維基百科文章。
PKCS #5:基於密碼的加密規範版本 2.1
NIST(美國國家標準技術研究院)針對基於密碼的密鑰衍生的建議。