MySQL 的 sha256_password 散列方案背後的算法是什麼?
MySQL 的舊
mysql_native_password
散列方案與 PHP 中的這種方案等效:sha1(sha1('password', true));
這是密碼的二進制 SHA-1 雜湊的十六進制編碼 SHA-1 雜湊,沒有任何加鹽。
MySQL 8.0 引入了基於 SHA256 的新雜湊方案的兩個變體,稱為
caching_sha2_password
andsha256_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
- >
#define CRYPT_SALT_LENGTH 20
常量無符號整數 STORED_SHA256_DIGEST_LENGTH = 43;