Hash
32 個字節對於雜湊是否足夠,還有什麼是“過度工程”嗎?
為了數據完整性,特別是對於小數據塊,而不是使用 SHA-256 雜湊,或者簡單地截斷 SHA-512 雜湊,我正在使用以下想法:
function saferHash(data) { let hash1Entropy = 42; // sha512:42 let hash2Entropy = 4; // 4B extra possible protected outcomes in case of highly unlikely collision in hash 1 const hash1 = sha512(data).slice(0,hash1Entropy); // for 42 byte entropy, truncated to save space + prevent length extension vulnerabilities const hash2 = blake3(data).slice(0,hash2Entropy); // cheapest extra forgery prevention in case of sha512:42 hash collision, truncated to save space + prevent length extension vulnerabilities return new Uint8Array([...hash1,...hash2]); // 46 byte total hash }
這是否完全過度設計了整個事情,或者將熵增加到 +32 字節並使用額外的廉價散列函式 (blake3) 來進一步增加創建碰撞的難度實際上是不是太糟糕了?
- 是的,32 字節/256 位就足夠了(請認真閱讀這篇博文)。該長度提供 $ 2^{128} $ 抗碰撞性和 $ 2^{256} $ SHA256的原像和第二原像電阻等等。
- 48 字節/384 位或 64 字節/512 位提供了更高的安全性,在某些情況下使用起來更合理,但在其他情況下則不必要。例如,如果您要對Ed25519的消息進行預散列,則需要使用 512 位散列來最大化抗碰撞性。
- 這是過度工程。您所做的比使用正常 SHA512 弱,因為抗碰撞性取決於輸出的長度。4 字節的輸出太小,不應該使用。BLAKE3 的預設輸出長度為 32 字節/256 位,通常不應低於任何無鍵散列函式的長度。42 字節也是一個奇怪的選擇。無需使用多個雜湊函式或重新發明輪子。如果單個散列對於完善的現實世界協議來說足夠好,那麼它對您來說就足夠了。
- 為了防止長度擴展攻擊,要麼使用 SHA512/256,要麼使用更現代的散列函式,例如 BLAKE2、SHA3 或 BLAKE3(我認為按此順序)。你不需要截斷 BLAKE3 來避免長度擴展攻擊。
通過截斷散列,實際上增加了每個散列的衝突率。
最終對於一定數量的字節,並且考慮到算法是靜態的並且相對安全(通過具有接近一致的輸出),衝突率將或多或少保持不變。
您唯一要阻止的可能是彩虹表,如果某個雜湊表存在,對於您的特定組合,大多數都不會存在。
總而言之,我認為這是過度設計,並且完全使用 sha-512 比截斷每個並重新發明輪子更安全、更方便且絕對更快。
簡而言之,您正在截斷更慢且“更好”的算法,減少您從中獲得的“好”熵,並用“更便宜”的算法替換它。