md5() 預設回傳 32 字元十六進位字串md5($str, true) 回傳 16 字節原始二進位字串(非可列印字元)<?php
$hash32 = md5('admin'); // 21232f297a57a5a743894a0e4a801fc3
$hash16 = substr($hash32, 8, 16); // 7a57a5a743894a0e (第 9-24 字元)
echo $hash16; // 7a57a5a743894a0e
echo $hash32; // 21232f297a57a5a743894a0e4a801fc3
關鍵點:這不是真正的 128 位 MD5,只是 32 字元十六進位字串的中間 16 字元。碰撞概率大幅增加(從 2^128 降至 2^64 等級),不安全。
<?php
$raw16 = md5('admin', true); // 16 字節二進位字串 (不可直接顯示)
// 如需儲存/傳輸,通常轉為:
$hex32 = bin2hex($raw16); // 32 字元十六進位 (標準)
$b64 = base64_encode($raw16); // 24 字元 Base64 (緊湊)
var_dump($raw16, $hex32, $b64);
| 弱點 | 說明 |
|---|---|
| 碰撞攻擊 | 2004 年王小雲團隊破解,可構造不同輸入產生相同 MD5 |
| 預像攻擊 | 理論可行,計算成本持續降低 |
| 無鹽值 | 相同輸入恆產生相同輸出,易建立彩虹表 |
| 速度過快 | GPU 可達 1000 億次/秒,暴力破解極快 |
| 長度擴展攻擊 | Merkle-Damgård 結構固有弱點 |
<?php
// 註冊:雜湊密碼
$hash = password_hash($password, PASSWORD_ARGON2ID); // PHP 7.2+
// 或 PASSWORD_BCRYPT (PHP 5.5+)
// $hash 格式:$argon2id$v=19$m=65536,t=4,p=1$... (含演算法、參數、鹽值、雜湊)
// 登入:驗證
if (password_verify($inputPassword, $hash)) {
// 成功
// 選擇性:檢查是否需重新雜湊(參數更新)
if (password_needs_rehash($hash, PASSWORD_ARGON2ID)) {
$newHash = password_hash($inputPassword, PASSWORD_ARGON2ID);
// 更新資料庫
}
}
<?php
// HMAC (需密鑰)
$signature = hash_hmac('sha256', $data, $secretKey);
// 純雜湊 (無密鑰,如檔案校驗)
$hash = hash('sha256', $fileContent);
// 更安全:SHA-3 / BLAKE2
$hash = hash('sha3-256', $data);
<?php
// 登入時檢測舊 MD5 雜湊並升級
function verifyAndUpgrade(string $input, string $storedHash): bool {
// 偵測 MD5 (32 字元十六進位,無 $ 開頭)
if (strlen($storedHash) === 32 && ctype_xdigit($storedHash) && $storedHash[0] !== '$') {
if (md5($input) === $storedHash) {
// 正確,升級為 argon2id
$newHash = password_hash($input, PASSWORD_ARGON2ID);
// UPDATE users SET password = ? WHERE id = ?
return true;
}
return false;
}
// 新格式直接驗證
return password_verify($input, $storedHash);
}
admin --- 16位加密 --- 7a57a5a743894a0e // substr(md5, 8, 16)
admin --- 32位加密 --- 21232f297a57a5a743894a0e4a801fc3 // 標準 MD5
admin --- 40位加密 --- 7a57a5a743894a0e4a801fc343894a0e4a801fc3 // 16位+後16位拼接?
ASP MD5 通常輸出 32 字元十六進位。「16 位」可能指 Mid(MD5, 9, 16) 類似操作。跨語言對接時,必須確認雙方具體演算法、編碼、大小寫、截取範圍,建議雙方改用標準 HMAC-SHA256 或 JWT。
password_hash() + password_verify()hash_hmac('sha256', ...)hash('sha256', ...) 或 hash_file('sha256', ...)