PHP 內建 mhash() 函數需載入 php_mhash.dll 及 libmhash.dll,Windows 下配置繁瑣(需修改 httpd.conf 添加 LoadFile),Linux 亦需編譯參數 --with-mhash。若環境受限無法安裝擴展,可用純 PHP 實現 HMAC-MD5,達到相同加密效果。
php_mhash.dll 放入 PHP ext 目錄。libmhash.dll 放入系統路徑(如 C:\Windows\System32 或 Apache bin 目錄)。php.ini:extension=php_mhash.dll。httpd.conf 添加:LoadFile "C:/php/libmhash.dll"。以下函數完全兼容 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, '簽名不一致!');
hash_hmac('sha256', $data, $key)(PHP 5.1.2+ 內建 hash_hmac,無需擴展)。