密碼雜湊的核心概念
在當今的數位環境中,保護使用者密碼是開發者面臨的首要安全挑戰。許多初學者誤以為將密碼進行簡單的 MD5 或 SHA-1 雜湊處理就足夠安全,但事實上,這些演算法在現代硬體運算能力下已極其脆弱。
雜湊函數是一種單向函數,它將輸入的資料轉換為固定長度的字串。理想的雜湊函數應具備抗碰撞性與不可逆性。然而,對於密碼儲存而言,我們需要的不僅僅是單向性,更需要對抗暴力破解的運算延遲。
當攻擊者取得資料庫洩漏的雜湊值時,他們通常會使用預先計算好的表格,即所謂的「彩虹表」,來進行快速反查。如果我們沒有採取適當的防護措施,使用者的密碼將在幾秒鐘內被還原。
為什麼傳統雜湊演算法已不安全
MD5 和 SHA-1 的設計目標是快速產生雜湊值,以驗證檔案完整性。然而,這種「快速」的特性在密碼學中卻成了致命弱點。攻擊者可以利用強大的 GPU 運算能力,每秒嘗試數十億次可能的密碼組合。
除了運算速度過快之外,這些演算法也存在嚴重的碰撞風險。這意味著不同的輸入可能會產生相同的雜湊值,進而導致系統驗證邏輯出現漏洞,甚至允許未經授權的存取。
因此,現代安全架構嚴禁使用這些過時的演算法。我們必須轉向專為密碼儲存設計的「慢速」演算法,例如 Argon2、bcrypt 或 scrypt,這些演算法內建了運算負載參數,能夠有效拖慢暴力破解的速度。
加鹽(Salt)技術的實作價值
加鹽是在雜湊之前,在密碼中加入一段隨機產生的字串。這個動作確保了即使兩個使用者擁有完全相同的密碼,他們在資料庫中儲存的雜湊值也會大不相同。
鹽值不需要保密,但它必須是唯一的。每次使用者變更密碼時,系統都應該產生一個新的鹽值。透過這種方式,攻擊者無法使用單一彩虹表對整個資料庫進行批次破解。
實作加鹽的關鍵在於鹽值的儲存。通常我們將鹽值直接儲存在使用者資料表中的一個獨立欄位,並在驗證時取出該鹽值,與使用者輸入的密碼合併後進行雜湊運算,再與資料庫中的值比對。
Pepper 與進階防禦層
如果說鹽值是為了增加每個帳號的獨特性,那麼 Pepper 就是為了增加整體系統的破解難度。Pepper 是一段儲存在伺服器環境變數或硬體安全模組中的秘密字串。
即使資料庫被完整洩露,只要攻擊者無法取得存放在伺服器內部的 Pepper,他們就無法對雜湊後的密碼進行有效的離線破解。這為系統增加了一層額外的防護網。
結合加鹽與 Pepper 的策略,可以構成一個穩固的密碼儲存防禦體系。首先將密碼與鹽值結合,進行第一次雜湊,隨後加入 Pepper 進行第二次處理,最後儲存結果。
現代化演算法選擇表
| 演算法 | 安全性建議 | 適用場景 |
|---|---|---|
| Argon2id | 最高推薦 | 現代化 Web 應用與高安全性系統 |
| bcrypt | 高推薦 | 主流應用程式的成熟選擇 |
| scrypt | 推薦 | 需要大量記憶體限制的場景 |
| SHA-256 | 不推薦 | 僅限於一般資料驗證,不適合密碼 |
效能與安全的平衡點
設定雜湊演算法的負載參數(Cost Factor)是一個技術活。如果參數設定過高,伺服器驗證密碼的 CPU 使用率會飆升,導致使用者登入延遲;如果設定過低,則無法有效抵禦攻擊。
建議在開發環境進行壓力測試,找到一個既能確保驗證時間在 100-300 毫秒以內,又能最大化破解難度的平衡點。隨著硬體效能提升,應定期審查並調升這些參數。
此外,對於大規模系統,可以考慮將密碼驗證邏輯與應用程式主邏輯分離,使用專用的認證服務來處理這些高負載的運算任務,從而減輕主伺服器的負擔。
持續維護與定期汰換
安全防護並非一勞永逸。隨著量子計算或其他新型攻擊技術的出現,我們必須建立一套密碼升級機制。當使用者下次登入時,如果系統偵測到其密碼使用的是舊版雜湊演算法,應立即要求其重新輸入並以新演算法重新雜湊。
這種「懶惰更新」策略可以在不中斷使用者體驗的情況下,平滑地完成全系統的密碼加密升級。這對於維護長期運行的系統至關重要。
- 永遠使用隨機產生的鹽值(Salt)。
- 絕對不要使用 MD5 或 SHA-1 儲存密碼。
- 考慮引入 Pepper 增加離線破解難度。
- 使用 Argon2id 作為首選演算法。
- 確保鹽值長度至少為 16 位元組。
- 針對不同環境調整運算 Cost Factor。
- 定期執行密碼庫的安全審計。
- 實作懶惰升級機制以因應演算法演進。
- 避免在日誌中輸出任何與密碼相關的資訊。
- 使用強大的密碼產生器與管理工具。