![](/img/trans.png)
[英]PHP Warning: Use of undefined constant PASSWORD_ARGON2ID when using password_hash() in php 7.3
[英]How do I use the Argon2 algorithm with password_hash?
所以聽說 PHP 7.2 引入了新的Argon2 算法。 但是我對如何將它與現有代碼一起使用感到困惑。 例如,我有這個
$password = password_hash('somepassword', PASSWORD_DEFAULT, ['cost' => 12]);
PASSWORD_DEFAULT
現在是否使用 Argon2? 如果有的話,我需要使用password_verify
更改什么? bcrypt 現在被認為不安全嗎?
在 PHP 7.2 之前,唯一使用的散列算法password_hash
是 bcrypt。 在撰寫本文時,bcrypt 仍然被認為是一種強哈希,尤其是與其前輩md5
和sha1
(這兩個都是不安全的,因為它們很快)。 Argon2 只是一種更昂貴的蠻力算法
Argon2i 使用與數據無關的內存訪問。 它更慢,因為它會在內存上進行更多的傳遞以防止權衡攻擊。 強烈推薦用於密碼散列和基於密碼的密鑰派生。
Bcrypt 仍然是可接受的密碼散列。 如果您不想切換,則無需切換(從 7.2.0 版本開始)。 此外, PASSWORD_DEFAULT
應該只在下一個完整版本(7.3.0 或更高版本)中更改(根據PHP 內部政策)。 如果您想確保僅繼續使用 bcrypt,則可以改用PASSWORD_BCRYPT
。 然而,這是不必要的,我們將在下面討論。
首先,我們將password_hash
的第二個參數切換為常量之一
PASSWORD_ARGON2I
- PHP 7.2.0+PASSWORD_ARGON2ID
- PHP 7.3.0+(如果可用,首選,請參閱下面的注釋) 然后我們需要改變我們的選擇。 bcrypt 使用cost
作為參數,它對密碼進行了多少次迭代(更高的成本 = 更長的散列時間)。 然而,有不同的成本因素
password_hash('somepassword', PASSWORD_ARGON2I, ['memory_cost' => 2048, 'time_cost' => 4, 'threads' => 3]);
從手冊中我們可以看到這些選項的作用
memory_cost
- 可用於計算 Argon2 哈希的最大內存(以千字節為單位)(默認為 1024)time_cost
- 計算 Argon2 哈希可能需要的最長時間(默認為 2)threads
- 用於計算 Argon2 哈希的線程數(默認為 2)了解,在您更改這些之前,此處較高的成本會減慢您的腳本速度。 您需要在服務器上運行測試以找到最適合您的設置。 這通常是通過循環給定成本的幾次迭代。 如果您需要,PHP 手冊給出了一個示例。
另請注意,雖然 bcrypt 存儲 60 個字符,但 Argon2 可能需要更多。 理想情況下,您應該讓密碼字段存儲 255 個字符。
password_verify
更改了什么? 這里的答案是……沒什么。 了解password_verify
足夠聰明,可以找出使用的算法並適當地處理它。 如上所述,這意味着如果您使用的是PASSWORD_DEFAULT
,默認值可以更改並且不會對您產生負面影響(盡管您可能需要調整成本參數)。 password_verify
只需要它支持的算法。 如果您從 bcrypt 切換到 Argon2,兩者都會以相同的方式進行驗證,因為所有必要的數據(salt、hash 和 cost)都已為您存儲。
//Works for both bcrypt and Argon2
if(password_verify($user_password, $stored_hash)) {
// password validated
}
如果您想從 bcrypt 升級散列,您可以在用戶成功登錄時執行此操作(從而為您提供未散列的密碼)。 只需檢查您的哈希值是否以$2y$
(bcrypt 標記)開頭。 如果是,再次將提供的密碼傳遞給password_hash
,但使用 Argon2 參數,並將其保存到登錄用戶的密碼字段。
如Crypto.SE question 所述,Argon2ID在 PHP 7.3 中引入,對 Argon2I 進行了一些改進
對 1-pass Argon2id 的最佳權衡攻擊是組合低存儲攻擊(針對內存的前半部分)和排名攻擊(針對后半部分),它們結合了大約 2.1 的因子。
Argon2ID 使用與 Argon2I 相同的參數。
僅當您使用 PHP 7.3 時:我創建了 2 個簡單而精簡的函數來將 Argon2ID 與 PHP 結合使用:
function argon2idHash($plaintext, $password, $encoding = null) {
$plaintextsecured = hash_hmac("sha256", $plaintext, $password);
return $encoding == "hex" ? bin2hex(password_hash($plaintextsecured, PASSWORD_ARGON2ID)) : ($encoding == "base64" ? base64_encode(password_hash($plaintextsecured, PASSWORD_ARGON2ID)) : password_hash($plaintextsecured, PASSWORD_ARGON2ID));
}
function argon2idHashVerify($plaintext, $password, $hash, $encoding = null) {
$plaintextsecured = hash_hmac("sha256", $plaintext, $password);
return password_verify($plaintextsecured, $encoding == "hex" ? hex2bin($hash) : ($encoding == "base64" ? base64_decode($hash) : $hash)) ? true : false;
}
要使用散列值(最后一個參數是可選的,您可以選擇hex 、 base64或什么都不選)[return => string]:
$salt = "LALALA";
argon2idHash($clearvalue, $salt, "hex"); // with encoding
argon2idHash($clearvalue, $salt); // without encoding
要驗證散列值的使用(參數 $salt 必須與散列時設置的鹽相匹配,如果使用同樣的規則也適用於編碼)[return => bool]:
$salt = "LALALA";
argon2idHashVerify($clearvalue, $salt, $hashtoverify, "hex") ? "match" : "dont match"; // with encoding
argon2idHashVerify($clearvalue, $salt, $hashtoverify) ? "match" : "dont match"; // without encoding
最后,如果您了解 PHP,您可以根據自己的喜好修改這些函數,但就目前而言,這是我所知道的將密碼安全地存儲在數據庫中的最佳方式。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.