簡體   English   中英

如何將 Argon2 算法與 password_hash 結合使用?

[英]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 現在被認為不安全嗎?

什么是氬氣2? bcrypt 現在不好了嗎?

在 PHP 7.2 之前,唯一使用的散列算法password_hash是 bcrypt。 在撰寫本文時,bcrypt 仍然被認為是一種強哈希,尤其是與其前輩md5sha1 (這兩個都是不安全的,因為它們很快)。 Argon2 只是一種更昂貴的蠻力算法

Argon2i 使用與數據無關的內存訪問。 它更慢,因為它會在內存上進行更多的傳遞以防止權衡攻擊。 強烈推薦用於密碼散列和基於密碼的密鑰派生。

Bcrypt 仍然是可接受的密碼散列。 如果您不想切換,則無需切換(從 7.2.0 版本開始)。 此外, PASSWORD_DEFAULT應該只在下一個完整版本(7.3.0 或更高版本)中更改(根據PHP 內部政策)。 如果您想確保僅繼續使用 bcrypt,則可以改用PASSWORD_BCRYPT 然而,這是不必要的,我們將在下面討論。

你如何使用 Argon2?

首先,我們將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 參數,並將其保存到登錄用戶的密碼字段。

什么是 Argon2ID?

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;
}

要使用散列值(最后一個參數是可選的,您可以選擇hexbase64或什么都不選)[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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM