PBKDF2 優於迭代 SHA2 的邏輯
我研究了 PBKDF2 以應用散列密碼,坦率地說,我不明白 PBKDF2 的複雜性比使用加密散列函式的迭代散列更複雜的理由。
這是一個範例:(顯然,如果您想要更長/更短的雜湊,請選擇更長/更短的摘要)
|| - concatenation operator let password be a user supplied byte sequence let salt be a random byte sequence supplied by the runtime let iteration_count be a positive integer in the millions Algorithm: iteration = SHA256( salt || password ) for ( 2 to iteration_count ) iteration = SHA256( iteration ) let hash = final value of iteration // Store hash, salt and iteration_count
只要將迭代調整為為安全策略佔用目標 CPU 量,那麼為了什麼目的可以證明使用比這更複雜的常式是合理的?
在我使用 Java 的電腦上,大約需要 200 萬次迭代來填充大約 1 秒的 CPU 時間來生成雜湊。
這種設計對我來說最大的好處是,明年當電腦執行得更快時,我可以靜態更新我的整個使用者表,從而進一步延長迭代次數。事實上,如果我有一個巨大的操作並且性能會成為問題,我可以執行雜湊的恆定深度擴展,即:
update table USERS set ITERATION_COUNT++, set hash = SHA256( hash )
除了簡單地告訴我不要自己動手之外,有經驗的專家能否說服我為什麼這種安全設計比受人尊敬的 PBKDF2 差?非常感謝您提前。我渴望在這裡學習新的東西。
我認為您誇大了 PBKDF2 的複雜性,並且在功能方面沒有將其與您的替代方案相匹配。讓我們先調度後者:正如 gammatester 的評論所提到的,PBKDF2 支持可變輸出大小。如果您將其納入您的提案中,它將變得更加複雜。
一旦我們控制了這一點,PBKDF2 幾乎不會比您的迭代 SHA-2 複雜。PBKDF2 的核心是偽隨機函式(PRF) 的迭代應用,以密碼作為其密鑰:
$$ F(\mathrm{Password}, \mathrm{Salt}, c, i) = U_1 \oplus U_2 \oplus \dots \oplus U_c $$ …在哪裡:
$$ \begin{align} U_1 &= PRF(\mathrm{Password}, \mathrm{Salt}, |, \mathrm{INT_32_BE}(i)) \ U_2 &= PRF(\mathrm{Password}, U_1) \ & \vdots \ U_c &= PRF(\mathrm{Password}, U_{c-1}) \end{align} $$ 值序列的方式 $ U_1, \dots, U_c $ 計算的方式與您建議迭代 SHA-256 的方式非常相似,除了每次迭代都使用密碼作為其密鑰。雖然這不一定是突破性的改進,但它確實意味著攻擊者看到中間 $ U_i $ 除非他們猜到密碼,否則無法從那裡獲取併計算序列的其餘部分。而對於您的構造,任何中間值
iteration
都足以計算所有後續值。第二個區別是最終值 $ F $ 不僅僅是 $ U_c $ ,而是序列中所有值的異或。 此問答深入探討了該問題的動機,並且答案提供了幾種替代方法。
第三個區別是選擇 PRF 作為原語而不是像您建議的散列函式。考慮到我們正在討論一個密碼扮演密鑰角色的場景,這在概念上是明智的;PBKDF2 所說的只是你應該迭代一個密鑰函式,使用密碼作為密鑰,並允許任何這樣的函式選擇。PRF 的常見選擇是 HMAC-SHA1,如果您錯過了將其 PRF 視為黑盒的觀察結果,它確實會使 PBKDF2 看起來有點複雜——它根本不關心 HMAC 的內部結構。
PBKDF2 的大多數實現都使用 HMAC-SHA1 作為 PRF。
正如維基百科上關於 SHA1 計算的指出:
PBKDF2 的一個弱點是,雖然它的迭代次數可以調整以使其花費任意大量的計算時間,但它可以用一個小電路和非常少的 RAM 來實現,這使得使用特定應用程序集成的蠻力攻擊電路或圖形處理單元相對便宜。
SHA2 也是如此。
目前 SHA2-256 的比特幣雜湊率為 41,024,492,542 GH/s,對於具有如此強大處理能力的人來說,對數據庫中的密碼進行詳盡的搜尋相對容易。真的,攻擊者將能夠做到 $ 2 * 10^{13} $ 每秒嘗試次數。
如果你想建立幾十年的安全方案,你需要使用類似
bcrypt
or的東西scrypt
。這兩種方案都是為消耗大量 RAM 而建構的,這使得在 ASIC 上實現它們變得更加困難,尤其是在具有強參數的情況下。UPD:另請查看https://password-hashing.net/。作為密碼雜湊競賽的結果,創建了 Argon2。它具有比 scrypt、bcrypt 更好的性能,是現在推薦的密碼散列算法。