password_needs_rehash函數用於檢查現有密碼的哈希值是否需要使用新的算法或加密參數進行更新。它會對比當前密碼的哈希與所指定的加密參數(如算法、成本因子等),如果現有密碼哈希不符合新要求,則返回true ,否則返回false 。
<span><span><span class="hljs-keyword">if</span></span><span> (</span><span><span class="hljs-title function_ invoke__">password_needs_rehash</span></span><span>(</span><span><span class="hljs-variable">$hashedPassword</span></span><span>, PASSWORD_BCRYPT, [</span><span><span class="hljs-string">'cost'</span></span><span> => </span><span><span class="hljs-number">12</span></span><span>])) {
</span><span><span class="hljs-variable">$newHash</span></span><span> = </span><span><span class="hljs-title function_ invoke__">password_hash</span></span><span>(</span><span><span class="hljs-variable">$password</span></span><span>, PASSWORD_BCRYPT, [</span><span><span class="hljs-string">'cost'</span></span><span> => </span><span><span class="hljs-number">12</span></span><span>]);
</span><span><span class="hljs-comment">// 更新數據庫中的密碼</span></span><span>
}
</span></span>在這個例子中, password_needs_rehash檢查$hashedPassword是否符合指定的加密參數(如cost參數),如果不符合,密碼就需要重新加密。
隨著密碼哈希算法的不斷更新和升級,使用較舊算法加密的密碼可能會面臨安全隱患。例如,PHP 最初使用MD5 和SHA-1 等算法進行加密,但這些算法已被證明易受攻擊。隨著bcrypt 和Argon2 等現代加密算法的出現,使用這些算法加密的密碼更加安全。
password_needs_rehash函數的引入,允許開發者在密碼存儲時靈活地進行更新。例如,當我們決定將bcrypt 更換為Argon2 時,原本使用bcrypt 加密的密碼可以通過password_needs_rehash來檢測並更新到新的加密方式。這樣,即便是之前存儲在數據庫中的密碼,也能在用戶下次登錄時自動遷移到新的加密算法。
加密算法本身的安全性不僅僅依賴於算法本身,還與算法的參數設置(如bcrypt 中的cost參數)有關。 cost參數決定了哈希計算的時間複雜度,較高的值能提供更高的安全性,但也會導致更長的計算時間。
假設你在最初使用cost為10 的bcrypt 算法存儲密碼,但隨著時間的推移,你發現服務器的處理能力更強,可以使用更高的cost值以提升安全性。使用password_needs_rehash ,可以檢查存儲在數據庫中的舊密碼是否使用了較低的cost ,並根據需要進行更新。
<span><span><span class="hljs-keyword">if</span></span><span> (</span><span><span class="hljs-title function_ invoke__">password_needs_rehash</span></span><span>(</span><span><span class="hljs-variable">$hashedPassword</span></span><span>, PASSWORD_BCRYPT, [</span><span><span class="hljs-string">'cost'</span></span><span> => </span><span><span class="hljs-number">14</span></span><span>])) {
</span><span><span class="hljs-variable">$newHash</span></span><span> = </span><span><span class="hljs-title function_ invoke__">password_hash</span></span><span>(</span><span><span class="hljs-variable">$password</span></span><span>, PASSWORD_BCRYPT, [</span><span><span class="hljs-string">'cost'</span></span><span> => </span><span><span class="hljs-number">14</span></span><span>]);
</span><span><span class="hljs-comment">// 更新數據庫中的密碼</span></span><span>
}
</span></span>在這個例子中,如果原始哈希的cost低於14,則需要重新加密。
儘管password_needs_rehash提供了一種檢測哈希是否需要更新的簡單方法,但這一過程仍然可能對性能產生一定影響。特別是在用戶量較大或數據庫訪問頻繁的情況下,每次用戶登錄時都進行哈希檢查可能會增加服務器的負擔。
為了降低性能影響,推薦在密碼登錄成功時,在後台異步處理密碼的重新加密。這意味著,密碼重新加密並不影響用戶的即時體驗,而是在後台逐步更新數據庫中的密碼哈希。
通過定期檢查密碼的哈希是否符合當前的安全標準,使用password_needs_rehash可以顯著提升系統的安全性。如果不進行更新,可能會有以下風險:
舊算法的安全性問題:老舊的加密算法如MD5 和SHA1 已經不再安全,攻擊者可能通過彩虹表或其他方式輕鬆破解這些密碼。
參數設置不當:如果cost設置過低,可能會讓密碼容易受到暴力破解攻擊,攻擊者通過試驗大量可能的密碼組合來破解哈希。
定期檢測並更新密碼哈希,有助於確保密碼存儲始終符合當前的最佳安全實踐。