為什麼是H(k∥x)H(k‖x)H(kmathbinVert x)不是一個安全的 MAC 結構?
如果 $ H(m) $ 是一個安全的散列函式,我們不能使用 MAC 來實現嗎 $ H(k\mathbin\Vert m) $ ?
然而,似乎更廣泛使用的 MAC,例如 NMAC 和HMAC(最初都在Keying hash functions for message authentication中定義)使用了更複雜的方案。為什麼這種串聯方案不安全?
“安全雜湊函式”這個詞通常意味著(對於一個函式 $ H $ )
- 原像電阻:給定一個值 $ h $ , 很難找到消息 $ x $ 以便 $ h = H(x) $ .
- 第二原像抗性:給定消息 $ x $ , 很難找到消息 $ x’ \neq x $ 這樣 $ H(x) = H(x’) $ .
- 防撞:很難找到兩條消息 $ x $ , $ x’ $ 這樣 $ H(x) = H(x’) $ .
用於安全 MAC 功能 $ M $ , 我們想要:
- 不可偽造性:不知道密鑰 $ k $ , 很難找到消息 $ x $ 和認證標籤 $ m $ 這樣 $ m = M(k, x) $ ,即使給出了其他一些這樣的有效消息標籤對(不允許作為答案)。
不幸的是,定義 $ M(k,x) = H(k \mathbin\Vert x) $ 對於安全散列函式,並不保證 MAC 函式是不可偽造的。
事實上,使用實踐中使用的散列結構(即沒有終結輪的 Merkle-Damgård 結構,用於 MD5、SHA-1 和 SHA-2 系列),只要給定一個有效的對,這很容易 $ (x,m) $ , 創建一個 $ (x’, m’) $ 這仍然有效:
為了使用 Merkle-Damgård 創建散列,將消息填充到某個塊大小,然後依次將每個塊饋送到壓縮函式,該函式更新內部狀態。然後將最終狀態作為散列輸出。
所以, $ H(k\mathbin\Vert x) $ 是輸入後雜湊機的狀態 $ k\mathbin\Vert x\mathbin\Vert\mathit{pad}_x $ . 如果我們將我們的雜湊機設置為這個狀態,然後輸入任意其他數據 $ y $ ,然後是另一個墊 $ \mathit{pad}_y $ ,我們到達狀態 $ m’ = H(k\mathbin\Vert x\mathbin\Vert\mathit{pad}_x\mathbin\Vert y) = M(k, x\mathbin\Vert\mathit{pad}_x\mathbin\Vert y) $ .
偽造完成,與 $ x’ = x \mathbin\Vert \mathit{pad}_x \mathbin\Vert y $ .
這也適用於 SHA-2 的全形變體,即 SHA-256 和 SHA-512。對於 SHA-2 的截斷變體(SHA-384、SHA-224、SHA-512/224 和 SHA-512/256),此攻擊不起作用,因為輸出不是完整的雜湊狀態。(雖然對於長度擴展攻擊,只需要猜測截斷的位,因此安全性比輸出大小的預期要低一些。)
HMAC 結構不會受到這種攻擊的懷疑,因為密鑰 $ k $ 在主消息之前和之後都應用,這使得內部狀態不可重構。 HMAC ( $ H(k_2, H(k_1, M)) $ ) 首先對消息進行雜湊處理,並在前面添加一個版本的密鑰,因此無法“從頭開始”(從消息)重建內部狀態。然後(現在是秘密的)輸出再次被散列,並在前面加上第二個版本的密鑰。這也使得“從頭到尾”(即從輸出+消息)重建主散列的內部狀態也是不可能的。具有類似效果的結構將是 $ H(k_1 || M || k_2) $ (帶有適當的填充),但這不是 HMAC。
HMAC 也不保證一般安全散列函式的不可偽造性,但如果內部壓縮函式是抗碰撞的,則它為 Merkle-Damgård 構造提供安全證明。
SHA-3 (Keccak) 基於不同的模型:我們有一個相當大的狀態,密鑰和消息都混合在一起,然後進一步混合以輸出雜湊。狀態本身永遠不會完全輸出。因此,長度擴展需要狀態恢復,並且容量(狀態的隱藏部分)應該足夠大以至於這是不可行的(並且密鑰空間需要足夠大以至於猜測密鑰也不起作用) .