當前位置: 首頁> 最新文章列表> 使用hash_pbkdf2函數生成密鑰後,如何確保其安全存儲?

使用hash_pbkdf2函數生成密鑰後,如何確保其安全存儲?

gitbox 2025-07-02

1. 理解hash_pbkdf2函數

hash_pbkdf2是PHP 提供的一個函數,用於使用密碼基於密鑰的哈希函數(PBKDF2)生成密鑰。 PBKDF2 是一種通過多次哈希和加鹽技術增強安全性的算法,可以有效防止暴力破解和字典攻擊。

 <span><span><span class="hljs-variable">$hash</span></span><span> = </span><span><span class="hljs-title function_ invoke__">hash_pbkdf2</span></span><span>(</span><span><span class="hljs-string">"sha256"</span></span><span>, </span><span><span class="hljs-variable">$password</span></span><span>, </span><span><span class="hljs-variable">$salt</span></span><span>, </span><span><span class="hljs-variable">$iterations</span></span><span>, </span><span><span class="hljs-variable">$length</span></span><span>, </span><span><span class="hljs-literal">false</span></span><span>);
</span></span>

參數解析:

  • "sha256" : 選擇的哈希算法,這裡使用SHA-256。

  • $password : 用戶輸入的密碼。

  • $salt : 隨機生成的鹽值,用來增加加密的安全性。

  • $iterations : 哈希迭代次數,迭代次數越高,破解難度越大。

  • $length : 生成密鑰的長度。

  • false : 是否輸出二進制結果,通常設置為false ,輸出十六進製字符串。

PBKDF2的安全性依賴於鹽值和迭代次數,合理設置這些參數能夠極大提升密鑰存儲的安全性。


2. 安全存儲生成的密鑰

2.1 使用加鹽與多次迭代增強安全性

生成密鑰時,首先要確保使用隨機生成的鹽值( $ salt )。鹽值的作用是避免相同的密碼生成相同的密鑰,進一步增加暴力破解的難度。鹽值的長度通常建議至少為16字節,以確保其隨機性。

hash_pbkdf2中設置足夠的迭代次數也是至關重要的。理論上,迭代次數越多,生成密鑰的時間就越長,破解的難度也越大。一般推薦的迭代次數至少為100,000次。通過這種方式,攻擊者需要更多的時間和計算資源來暴力破解密鑰。

 <span><span><span class="hljs-variable">$salt</span></span><span> = </span><span><span class="hljs-title function_ invoke__">bin2hex</span></span><span>(</span><span><span class="hljs-title function_ invoke__">random_bytes</span></span><span>(</span><span><span class="hljs-number">16</span></span><span>)); </span><span><span class="hljs-comment">// 生成16字節的隨機鹽值</span></span><span>
</span><span><span class="hljs-variable">$iterations</span></span><span> = </span><span><span class="hljs-number">100000</span></span><span>; </span><span><span class="hljs-comment">// 至少100,000次迭代</span></span><span>
</span><span><span class="hljs-variable">$key</span></span><span> = </span><span><span class="hljs-title function_ invoke__">hash_pbkdf2</span></span><span>(</span><span><span class="hljs-string">"sha256"</span></span><span>, </span><span><span class="hljs-variable">$password</span></span><span>, </span><span><span class="hljs-variable">$salt</span></span><span>, </span><span><span class="hljs-variable">$iterations</span></span><span>, </span><span><span class="hljs-number">64</span></span><span>, </span><span><span class="hljs-literal">false</span></span><span>); </span><span><span class="hljs-comment">// 64字節的密鑰</span></span><span>
</span></span>

2.2 不存儲原始密碼

直接存儲用戶的原始密碼是非常不安全的做法。在PHP中,應該始終存儲密鑰的哈希值,而不是原始的密碼字符串。通過hash_pbkdf2生成的密鑰已經經過多次加密和處理,理論上無法從中恢復出原始的密碼。

例如,生成的密鑰值可以存儲在數據庫中,並與用戶的其他信息一起保存:

 <span><span><span class="hljs-comment">// 將密鑰哈希值和鹽值存入數據庫</span></span><span>
</span><span><span class="hljs-variable">$stmt</span></span><span> = </span><span><span class="hljs-variable">$pdo</span></span><span>-&gt;</span><span><span class="hljs-title function_ invoke__">prepare</span></span><span>(</span><span><span class="hljs-string">"INSERT INTO users (username, password_hash, salt) VALUES (?, ?, ?)"</span></span><span>);
</span><span><span class="hljs-variable">$stmt</span></span><span>-&gt;</span><span><span class="hljs-title function_ invoke__">execute</span></span><span>([</span><span><span class="hljs-variable">$username</span></span><span>, </span><span><span class="hljs-variable">$key</span></span><span>, </span><span><span class="hljs-variable">$salt</span></span><span>]);
</span></span>

2.3 使用獨立的加密存儲

為了進一步增強密鑰的安全性,可以考慮使用更強的加密算法來加密存儲的密鑰。例如,可以使用對稱加密算法(如AES)對生成的密鑰進行加密存儲。在這種情況下,密鑰存儲不僅依賴於PBKDF2生成的哈希,還依賴於額外的加密層。

 <span><span><span class="hljs-variable">$encryption_key</span></span><span> = </span><span><span class="hljs-string">'your-secure-encryption-key'</span></span><span>;
</span><span><span class="hljs-variable">$encrypted_key</span></span><span> = </span><span><span class="hljs-title function_ invoke__">openssl_encrypt</span></span><span>(</span><span><span class="hljs-variable">$key</span></span><span>, </span><span><span class="hljs-string">'AES-256-CBC'</span></span><span>, </span><span><span class="hljs-variable">$encryption_key</span></span><span>, </span><span><span class="hljs-number">0</span></span><span>, </span><span><span class="hljs-variable">$iv</span></span><span>);
</span></span>

注意,在加密密鑰時,必須確保加密密鑰( $encryption_key )的安全存儲。加密密鑰本身應該存儲在一個高度安全的地方,如硬件安全模塊(HSM)或密鑰管理服務中。


3. 防止密碼洩露

3.1 數據庫的安全

除了對密鑰本身進行保護外,整個數據庫的安全也至關重要。確保數據庫的訪問權限受到嚴格控制,使用強密碼和加密連接(如SSL/TLS)來防止中間人攻擊和數據洩露。

數據庫應該採取最小權限原則,只允許授權用戶訪問敏感數據。

3.2 定期更新密鑰和鹽值

為了提高長期安全性,定期更新密鑰和鹽值也是一種有效的安全措施。雖然更新密鑰並不簡單,但如果能週期性地重新哈希並更換鹽值,就可以防止洩露的風險。

例如,可以在用戶登錄後,定期提示用戶更改密碼,並使用新的鹽值和密鑰重新加密存儲。

3.3 防止SQL注入和暴力破解攻擊

防止SQL注入攻擊是確保密鑰安全存儲的基本步驟。確保數據庫查詢中的用戶輸入經過充分的轉義,或者使用預處理語句來避免SQL注入漏洞。

對於暴力破解攻擊,可以通過限制登錄嘗試次數、引入驗證碼機制以及監控可疑的登錄行為等手段來減少風險。