首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 網頁程式設計 >> PHP 程式設計 >> PHP 綜合知識

PHP MD5 16 位與 32 位實作原理解析與安全性警示

     編輯:PHP 綜合知識

MD5 基礎知識

  • MD5 (Message Digest Algorithm 5) 產生 128 位 (16 字節) 雜湊值
  • 習慣以 32 字元十六進位字串 表示(每字節 2 字元)
  • PHP md5() 預設回傳 32 字元十六進位字串
  • md5($str, true) 回傳 16 字節原始二進位字串(非可列印字元)

文中「16 位」實為 32 位截取

<?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 等級),不安全。

真正的 16 位元組二進位輸出

<?php
$raw16 = md5('admin', true); // 16 字節二進位字串 (不可直接顯示)
// 如需儲存/傳輸,通常轉為:
$hex32 = bin2hex($raw16);     // 32 字元十六進位 (標準)
$b64   = base64_encode($raw16); // 24 字元 Base64 (緊湊)
var_dump($raw16, $hex32, $b64);

為什麼不應使用 MD5?

弱點說明
碰撞攻擊2004 年王小雲團隊破解,可構造不同輸入產生相同 MD5
預像攻擊理論可行,計算成本持續降低
無鹽值相同輸入恆產生相同輸出,易建立彩虹表
速度過快GPU 可達 1000 億次/秒,暴力破解極快
長度擴展攻擊Merkle-Damgård 結構固有弱點

現代密碼雜湊最佳實踐

密碼儲存:argon2id / bcrypt(PHP 內建)

<?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);
        // 更新資料庫
    }
}

資料完整性/簽名:HMAC-SHA256 / SHA-256

<?php
// HMAC (需密鑰)
$signature = hash_hmac('sha256', $data, $secretKey);
// 純雜湊 (無密鑰,如檔案校驗)
$hash = hash('sha256', $fileContent);
// 更安全:SHA-3 / BLAKE2
$hash = hash('sha3-256', $data);

遷移策略:從 MD5 升級

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

文中 ASP 對照表說明

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。

總結建議

  1. 新專案嚴禁使用 MD5 於任何安全相關場景
  2. 密碼儲存:password_hash() + password_verify()
  3. API 簽名/完整性:hash_hmac('sha256', ...)
  4. 檔案校驗:hash('sha256', ...) 或 hash_file('sha256', ...)
  5. 若必須對接舊系統 MD5,隔離在適配器層,並規劃遷移時間表
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved