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

Java HMAC-MD5 加密演算法移植到 PHP 完整對照實作

     編輯:程式設計綜合問答

Java 原始邏輯 (RFC 2104 HMAC-MD5)

public String cryptMd5(String source, String key) {
    byte[] k_ipad = new byte[64];
    byte[] k_opad = new byte[64];
    byte[] keyb = key.getBytes("UTF-8");
    byte[] value = source.getBytes("UTF-8");
    Arrays.fill(k_ipad, keyb.length, 64, (byte) 0x36); // 54
    Arrays.fill(k_opad, keyb.length, 64, (byte) 0x5C); // 92
    for (int i = 0; i < keyb.length; i++) {
        k_ipad[i] = (byte) (keyb[i] ^ 0x36);
        k_opad[i] = (byte) (keyb[i] ^ 0x5C);
    }
    MessageDigest md = MessageDigest.getInstance("MD5");
    md.update(k_ipad); md.update(value);
    byte[] dg = md.digest(); md.reset();
    md.update(k_opad); md.update(dg, 0, 16);
    dg = md.digest();
    return toHex(dg);
}

PHP 等效實作 (逐行對照)

function cryptMd5(string $source, string $key): string {
    // 確保 UTF-8
    if (!mb_check_encoding($source, 'UTF-8')) $source = mb_convert_encoding($source, 'UTF-8', 'auto');
    if (!mb_check_encoding($key, 'UTF-8')) $key = mb_convert_encoding($key, 'UTF-8', 'auto');

    // k_ipad / k_opad 初始化 (64 bytes)
    $k_ipad = str_pad($key, 64, chr(0x36)); // 0x36 = 54
    $k_opad = str_pad($key, 64, chr(0x5C)); // 0x5C = 92

    // XOR 前 keyb.length 位元組
    for ($i = 0; $i < strlen($key); $i++) {
        $k_ipad[$i] = $k_ipad[$i] ^ chr(0x36);
        $k_opad[$i] = $k_opad[$i] ^ chr(0x5C);
    }

    // MD5(k_ipad || source) -> 16 bytes raw binary
    $dg = md5($k_ipad . $source, true);

    // MD5(k_opad || dg[0..15]) -> 16 bytes raw binary
    $dg = md5($k_opad . substr($dg, 0, 16), true);

    // 輸出十六進制小寫
    return bin2hex($dg);
}

驗證測試

// Java
System.out.println(cryptMd5("hello", "secret")); 
// PHP
echo cryptMd5("hello", "secret"); 
// 兩者輸出應完全一致

關鍵細節對照表

步驟JavaPHP注意
編碼getBytes("UTF-8")mb_convert_encoding(..., 'UTF-8')預設編碼不一致會導致結果不同
填充Arrays.fill(..., 0x36/0x5C)str_pad(..., chr(0x36/0x5C))PHP str_pad 字串長度不足時填充
XORkeyb[i] ^ 0x36$k_ipad[$i] ^ chr(0x36)PHP 字串按字元操作,需 chr()
MD5 更新md.update(k_ipad); md.update(value)md5($k_ipad . $source, true)PHP md5 直接拼接字串,true 回傳 raw binary
第二輪md.update(k_opad); md.update(dg,0,16)md5($k_opad . substr($dg,0,16), true)只取前 16 bytes (128 bits)
輸出toHex(dg)bin2hex($dg)皆為小寫十六進制

安全性提醒

  • MD5 已被碰撞攻擊破解,**新系統請改用 HMAC-SHA256 或更強**。
  • PHP 7.2+ 可用 hash_hmac('sha256', $source, $key) 一行實現,標準庫經過優化且恆定時間比對。
  • 金鑰管理:使用隨機 32 位元組金鑰,定期輪換,儲存於 Vault/KMS 而非程式碼。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved