Authentication

MySQL 的 sha256_password 散列方案背後的算法是什麼?

  • February 6, 2020

MySQL 的舊mysql_native_password散列方案與 PHP 中的這種方案等效:

sha1(sha1('password', true));

這是密碼的二進制 SHA-1 雜湊的十六進制編碼 SHA-1 雜湊,沒有任何加鹽。

MySQL 8.0 引入了基於 SHA256 的新雜湊方案的兩個變體,稱為caching_sha2_passwordand sha256_password,前者是預設值 ( docs )。儘管有他們的名字,但似乎都不是普通的 SHA256。

(是的,我知道 SHA256 不是密碼散列的好選擇,但它比 SHA-1 好得多,這不取決於我!)

這是一個例子。我為密碼創建了一個雜湊password,它創建了一個 mysql.users 密碼雜湊,如下所示:

$A$005$wU"H/k5|5;f!kP_&N4cvqu6bppuYjCvqhg2blU.NcJHkkhaVj.QNt7pipg4p3

我猜這(由$字元分隔)A意味著它是 SHA256(該方案將來可能支持其他 SHA2 變體),並且005是鹽,但字元串的其餘部分不是通用格式 - 它不是看起來像正常的十六進制輸出或 base64,也不是原始二進製文件。

誰能告訴我這些新方案的實際算法,用 PHP 或類似程式碼?

更新

感謝 @kelalaka 提供的一些重要指示,我在 PHP 中編寫了這個程式碼:

$originalhash = 'wU"H/k5|5;f!kP_&N4cvqu6bppuYjCvqhg2blU.NcJHkkhaVj.QNt7pipg4p3';
$binaryhash = base64_decode($originalhash);
$salt_length = 20;
$hash_length = 43;
$rawsalt = substr($binaryhash, 0, $salt_length);
$rawhash = substr($binaryhash, $salt_length);

$password = 'password';
$iterations = 5;
$iteration_multiplier = 1000;
$it = $iterations * $iteration_multiplier;
$hash = $rawsalt . $password;
for ($i = 0; $i < $it; $i++) {
   $hash = substr(hash('sha256', $hash, true), 0, $hash_length);
}
$hashoutput = base64_encode($rawsalt . $hash);
var_dump($originalhash, $hashoutput);

但是,這不會產生匹配的輸出:

string(61) "wU"H/k5|5;f!kP_&N4cvqu6bppuYjCvqhg2blU.NcJHkkhaVj.QNt7pipg4p3"
string(72) "wUH/k55fkPN4cvqu6bppuYjCvqgx75cg5UeVzAVpx0OzU7KS2Klujh3rbHzrAena3/MBAA=="
  • 它太長了
  • 我懷疑編碼方案不是base64;注意鹽與原來的不同,即使它沒有改變。
  • 我不確定起始字元串應該是鹽+密碼還是密碼+鹽。
  • 我不清楚何時應該執行二進制雜湊的截斷 - 在循環中還是之後?

根據MySQL 伺服器部落格,它是:

mysql_native_password 的優點是它支持質詢-響應機制,速度非常快,不需要加密連接。但是,mysql_native_password 依賴於 SHA1 算法,NIST 建議停止使用它。

cache_sha2_password 試圖結合兩全其美。

XOR( SHA256(pwd),SHA256(SHA256SHA256(pwd)) , Nonce)

在此處輸入圖像描述

$ A $ 005 $ wU"H/k5|5;f!kP_&N4cvqu6bppuYjCvqhg2blU.NcJHkkhaVj.QNt7pipg4p3

來自原始碼sha2_password.cc

  • >

預期格式

分隔符

$$ digest_type $$分隔符$$ iterations $$分隔符$$ salt $$$$ digest $$

分隔符在哪裡$

  • >

摘要類型:

A => SHA256

  • >

迭代:

005 => 5*ITERATION_MULTIPLIER

  • >

鹽:

隨機字元串。長度 SALT_LENGTH

  • >

消化:

SHA2 摘要。長度 STORED_SHA256_DIGEST_LENGTH

從文件i_sha2_password.h

  • >

#define CRYPT_SALT_LENGTH 20

常量無符號整數 STORED_SHA256_DIGEST_LENGTH = 43;

引用自:https://crypto.stackexchange.com/questions/77427