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

PHP 實現增強型 HMAC-MD5 函數:無需 mhash 擴展的跨平台方案

     編輯:PHP 綜合知識

問題背景

PHP 內建 mhash() 函數需載入 php_mhash.dll 及 libmhash.dll,Windows 下配置繁瑣(需修改 httpd.conf 添加 LoadFile),Linux 亦需編譯參數 --with-mhash。若環境受限無法安裝擴展,可用純 PHP 實現 HMAC-MD5,達到相同加密效果。

方案一:載入 mhash 擴展(傳統方式)

  1. 將 php_mhash.dll 放入 PHP ext 目錄。
  2. 將 libmhash.dll 放入系統路徑(如 C:\Windows\System32 或 Apache bin 目錄)。
  3. 修改 php.ini:extension=php_mhash.dll。
  4. Apache 下另需在 httpd.conf 添加:LoadFile "C:/php/libmhash.dll"。
  5. 重啟 Apache/Php-fpm。

方案二:純 PHP 實現 HMAC-MD5(推薦,零依賴)

以下函數完全兼容 mhash(MHASH_MD5, $data, $key) 的輸出格式(十六進制字符串),優先嘗試使用擴展,不可用時自動回退至純演算法:

/**
 * HMAC-MD5 簽名(兼容 mhash 輸出格式)
 * @param string $key 密鑰
 * @param string $data 待簽名數據
 * @return string 十六進制簽名字符串
 */
function hmac_md5($key, $data) {
    // 若 mhash 擴展可用,直接調用(效能最佳)
    if (extension_loaded('mhash')) {
        return bin2hex(mhash(MHASH_MD5, $data, $key));
    }

    // --- 純 PHP 實現 RFC 2104 HMAC-MD5 ---
    $b = 64; // MD5 區塊大小(位元組)
    
    // 密鑰長度超過區塊大小則先哈希
    if (strlen($key) > $b) {
        $key = pack('H*', md5($key));
    }
    
    // 密鑰補零至 64 位元組
    $key = str_pad($key, $b, chr(0x00));
    
    // 內部/外部填充常數
    $ipad = str_pad('', $b, chr(0x36)); // 0x36 = 54
    $opad = str_pad('', $b, chr(0x5c)); // 0x5c = 92
    
    // XOR 運算生成內外鍵
    $k_ipad = $key ^ $ipad;
    $k_opad = $key ^ $opad;
    
    // HMAC = MD5(K_opad || MD5(K_ipad || data))
    return md5($k_opad . pack('H*', md5($k_ipad . $data)));
}

參數對應說明

  • mhash(MHASH_MD5, $data, $key) → hmac_md5($key, $data)
  • 注意參數順序:mhash 為 (algo, data, key),本函數為 (key, data),調用時請調整。

驗證測試

$key = 'secret_key';
$data = 'message_to_sign';

// 方式一:mhash(若可用)
if (extension_loaded('mhash')) {
    $sign1 = bin2hex(mhash(MHASH_MD5, $data, $key));
    echo "mhash: $sign1\n";
}

// 方式二:純 PHP
$sign2 = hmac_md5($key, $data);
echo "純PHP: $sign2\n";

// 兩者輸出應完全一致
assert($sign1 === $sign2, '簽名不一致!');

應用場景

  • API 請求簽名(如支付回調驗證、開放平台授權)。
  • Token 生成與驗證(JWT 簽名部分可用 HS256,但 MD5 仍用於簡單場景)。
  • 跨語言系統互通(Java、Python、Go 均有標準庫支援 HMAC-MD5)。

安全提示

  1. MD5 已不適合高安全性場景(碰撞攻擊風險),新項目建議改用 hash_hmac('sha256', $data, $key)(PHP 5.1.2+ 內建 hash_hmac,無需擴展)。
  2. 密鑰長度建議 ≥ 32 位元組,定期輪換。
  3. 避免在 URL 參數中直接傳輸簽名,優先使用 Header 或 Body。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved