密碼雜湊安全

密碼雜湊安全

本部分解釋使用雜湊函式對密碼進行安全處理背後的原因, 以及如何有效的進行密碼雜湊處理。

為什麼需要把應用程式中使用者的密碼進行雜湊化?

當設計一個需要接受使用者密碼的應用時, 對密碼進行雜湊是最基本的,也是必需的安全考慮。 如果不對密碼進行雜湊處理,那麼一旦應用的數據庫受到攻擊, 那麼使用者的密碼將被竊取。 同時,竊取者也可以使用使用者賬號和密碼去嘗試其他的應用, 如果使用者沒有為每個應用單獨設定密碼,那麼將面臨風險。

通過對密碼進行雜湊處理,然後再儲存到數據庫中, 這樣就使得攻擊者無法直接獲取原始密碼, 同時還可以保證你的應用可以對原始密碼進行相同的雜湊處理, 然後比對雜湊結果。

需要著重提醒的是,密碼雜湊只能保護密碼 不會被從數據庫中直接竊取, 但是無法保證注入到應用中的 惡意代碼攔截到原始密碼。

為何諸如 md5()sha1() 這樣的常見雜湊函式不適合用在密碼保護場景?

MD5,SHA1 以及 SHA256 這樣的雜湊演算法是面向快速、高效 進行雜湊處理而設計的。隨著技術進步和計算機硬體的提升, 破解者可以使用「暴力」方式來尋找雜湊碼 所對應的原始數據。

因為現代化計算機可以快速的「反轉」上述雜湊演算法的雜湊值, 所以很多安全專家都強烈建議 不要在密碼雜湊中使用這些雜湊演算法。

如果不建議使用常用雜湊函式保護密碼, 那麼我應該如何對密碼進行雜湊處理?

當進行密碼雜湊處理的時候,有兩個必須考慮的因素: 計算量以及「鹽」。 雜湊演算法的計算量越大, 暴力破解所需的時間就越長。

PHP 5.5 提供了 一個原生密碼雜湊 API, 它提供一種安全的方式來完成密碼 雜湊驗證。 PHP 5.3.7 及後續版本中都提供了一個 » 純 PHP 的相容庫

PHP 5.3 及後續版本中,還可以使用 crypt() 函式, 它支援多種雜湊演算法。 針對每種受支援的雜湊演算法,PHP 都提供了對應的原生實現, 所以在使用此函式的時候, 你需要保證所選的雜湊演算法是你的系統所能夠支援的。

當對密碼進行雜湊處理的時候,建議採用 Blowfish 演算法, 這是密碼雜湊 API 的預設演算法。 相比 MD5 或者 SHA1,這個演算法提供了更高的計算量, 同時還有具有良好的伸縮性。

如果使用 crypt() 函式來進行密碼驗證, 那麼你需要選擇一種耗時恒定的字串比較演算法來避免時序攻擊。 (譯註:就是說,字串比較所消耗的時間恒定, 不隨輸入數據的多少變化而變化) PHP 中的 == 和 === 操作符strcmp() 函式都不是耗時恒定的字串比較, 但是 password_verify() 可以幫你完成這項工作。 我們鼓勵你儘可能的使用 原生密碼雜湊 API

「鹽」是什麼?

加解密領域中的「鹽」是指在進行雜湊處理的過程中 加入的一些數據,用來避免從已計算的雜湊值表 (被稱作「彩虹表」)中 對比輸出數據從而獲取明文密碼的風險。

簡單而言,「鹽」就是爲了提高雜湊值被破解的難度 而加入的少量數據。 現在有很多線上服務都能夠提供 計算后的雜湊值以及其對應的原始輸入的清單, 並且數據量極其龐大。 通過加「鹽」就可以避免直接從清單中查詢到對應明文的風險。

如果不提供「鹽」,password_hash() 函式會隨機產生「鹽」。 非常簡單,行之有效。

我應該如何儲存「鹽」?

當使用 password_hash() 或者 crypt() 函式時, 「鹽」會被作為產生的雜湊值的一部分返回。 你可以直接把完整的返回值儲存到數據庫中, 因為這個返回值中已經包含了足夠的資訊, 可以直接用在 password_verify()crypt() 函式來進行密碼驗證。

下圖展示了 crypt()password_hash() 函式返回值的結構。 如你所見,演算法的資訊以及「鹽」都已經包含在返回值中, 在後續的密碼驗證中將會用到這些資訊。


        password_hash 和 crypt 函式返回值的組成部分,依次為:所選擇的演算法,
        演算法選項,所使用的「鹽」,
        以及雜湊后的密碼。

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *