使用 Ed25519 對消息雜湊進行簽名是否更高效、更安全?
根據Ed25519 論文,(可能很長的)輸入消息被散列兩次(參見第 4 節第 12 頁第 1 步和第 3 步)。 這個網頁的底部有一個很好的圖表來說明這一點,我在 Supercop 的參考程式碼中確認了這一點(參見 supercop-20141124/crypto_sign/ed25519/ref/sign.c,函式呼叫
crypto_hash_sha512(nonce, sm+32, mlen+32)
和crypto_hash_sha512(hram,sm,mlen + 64)
)。我的問題是,對於長消息,只對整個消息進行一次散列處理,然後使用 64 字節散列作為簽名算法的輸入,不是更有效、更安全嗎?換句話說,程式碼看起來像:
crypto_hash_sha512(mhash, m, mlen); crypto_sign(output, mhash, 64, key);
在我看來,對於 mlen > 大約 128 字節,這似乎更快,而不會損失任何安全性。
我在這裡錯過了什麼嗎?使用 mhash 作為簽名輸入而不是原始消息 m 是否存在潛在的安全性損失?
Ed25519 的作者之一 Peter Schwabe 將我帶到了最近的一篇題為“ EdDSA for more curve ”的論文。第 5 頁的“關於預散列的安全說明”部分說,沒有預散列消息的 Ed25519 算法可以抵抗散列函式中的衝突,而使用預散列算法則不能。當然散列函式不應該有衝突,但如果有,不預散列可以提供額外的保護。
該方法的目標是實現碰撞恢復(抗碰撞攻擊)。第二個雜湊可以看作 $ H(R || M) $ 對於消息 M 和一些攻擊者未知的隨機性 R。現在,即使攻擊者可以有效地發現衝突 $ H $ ,他不能使用這種能力來執行標準的偽造攻擊,其工作原理如下:
- 尋找碰撞 $ M,M’ $ 為了 $ H $ ,
- 要求籤名者簽名 $ \sigma $ 留言 $ M $ ,
- 輸出偽造 $ (\sigma, M’) $ .
這種攻擊通常有效,因為簽名實際上只簽名 $ H(M) $ 和 $ H(M) = H(M’) $ . 現在,如果攻擊者不知道 $ R $ 他無法有效地搜尋碰撞 $ H(R||M) = H(R||M’) $ . 尤其是碰撞 $ M,M’ $ 為了 $ H $ 不會導致碰撞 $ H(R||M) = H(R||M’) $ 對於隨機 $ R $ 以壓倒性的機率。
現在,為什麼他們要散列兩次?原因是避免在簽名算法中使用“真正的”隨機性。一個動機是,在過去幾年中,存在許多與不良隨機源/錯誤實現有關的問題,人們試圖盡可能避免使用隨機性。第一個雜湊生成一個偽隨機值 $ R $ 使用消息和秘密值 $ S $ 這是密鑰的一部分: $ R = H(S||M) $ .
現在,為什麼你的提議不那麼安全了?因為它很容易受到上述碰撞攻擊。
當然,加密散列函式應該提供抗衝突性。然而,抗碰撞性是一個相當強的假設,它比其他屬性(如抗二次原像性、單向性或偽隨機性)更容易被打破。一方面,針對完全安全散列函式的碰撞攻擊的複雜性已經只是針對其他屬性的攻擊的平方根。另一方面,在打破抗碰撞性(例如,參見對 MD5 和 SHA1 的攻擊)方面取得的進展比在打破其他屬性方面取得的進展要大得多。因此,盡可能避免碰撞阻力的要求似乎是一個不錯的選擇。
PS:有人可能會認為使用 $ R = H(M||S), OUT = H(M || R) $ 將提供相同的好處,同時允許重用大部分計算(狀態 $ H $ 處理後 $ M $ )。但這恰恰使事情再次容易受到(內部)碰撞的影響:如果我發現消息 $ M,M’ $ 導致相同的內部狀態 $ H $ 處理後,它們也會產生相同的值 $ OUT $ . 因此,我可以使用這種內部碰撞來偽造簽名。