Web 介面資料傳輸安全需求日益增長。本文分享一個實用的 PHP 對稱加密類,特點是擁有公鑰機制、每次加密結果隨機不同、無正確公鑰無法解密,適合 API 簽名、敏感參數傳輸、Token 生成等場景。
<?php
/**
* PHP 對稱加密類 (含公鑰驗證機制)
* 特點:隨機鹽值導致每次加密結果不同、公鑰驗證解密權限
*/
class Jiami {
protected $key = 'lee'; // 預設公鑰
/**
* 核心 XOR 加密/解密邏輯
* @param string $txt 明文/密文
* @param string $encrypt_key 動態金鑰 (MD5 後)
* @return string 處理後字串
*/
private function _xorCrypt($txt, $encrypt_key) {
$encrypt_key = md5($encrypt_key);
$ctr = 0;
$tmp = '';
$len = strlen($txt);
$keyLen = strlen($encrypt_key);
for ($i = 0; $i < $len; $i++) {
if ($ctr == $keyLen) $ctr = 0;
$tmp .= $txt[$i] ^ $encrypt_key[$ctr];
$ctr++;
}
return $tmp;
}
/**
* 加密
* @param string $txt 明文
* @param string $key 公鑰 (可選,預設使用類別屬性)
* @return string 密文 (含隨機鹽值)
*/
public function encrypt($txt, $key = '') {
if (empty($key)) $key = $this->key;
// 產生隨機鹽值,確保每次加密結果不同
srand((double)microtime() * 1000000);
$encrypt_key = md5(rand(0, 32000));
$ctr = 0;
$tmp = '';
$len = strlen($txt);
$keyLen = strlen($encrypt_key);
for ($i = 0; $i < $len; $i++) {
if ($ctr == $keyLen) $ctr = 0;
// 密文格式:鹽值字元 ^ 明文字元,交替組合
$tmp .= $encrypt_key[$ctr] . ($txt[$i] ^ $encrypt_key[$ctr]);
$ctr++;
}
// 二次加密:使用公鑰對上述結果再次 XOR
return $this->_xorCrypt($tmp, $key);
}
/**
* 解密
* @param string $txt 密文
* @param string $key 公鑰 (必須與加密時相同)
* @return string 明文
*/
public function decrypt($txt, $key = '') {
if (empty($key)) $key = $this->key;
// 第一層:公鑰解密
$txt = $this->_xorCrypt($txt, $key);
// 第二層:提取鹽值並還原明文
$tmp = '';
$len = strlen($txt);
for ($i = 0; $i < $len; $i++) {
$saltChar = $txt[$i]; // 鹽值字元 (原加密時的 encrypt_key[$ctr])
$i++;
if ($i >= $len) break; // 防禦性檢查
$dataChar = $txt[$i]; // 混淆後的明文字元
$tmp .= $dataChar ^ $saltChar; // XOR 還原
}
return $tmp;
}
public function setKey($key) {
if (empty($key)) return null;
$this->key = $key;
}
public function getKey() {
return $this->key;
}
}
?>
<?php
require_once 'Jiami.class.php';
$string = 'https://www.example.com/api?user=123&token=abc';
// 實例化
$jiami = new Jiami();
// 設定公鑰 (雙方協商一致)
$jiami->setKey('my_secret_key_2024');
// 加密
$encrypted = $jiami->encrypt($string, $jiami->getKey());
// 解密
$decrypted = $jiami->decrypt($encrypted, $jiami->getKey());
echo '<meta charset="utf-8" />';
echo '原文: ' . $string . '<br/>';
echo '密文: ' . $encrypted . '<br/>';
echo '解密: ' . $decrypted . '<br/>';
// 驗證錯誤公鑰無法解密
$wrong = $jiami->decrypt($encrypted, 'wrong_key');
echo '錯誤公鑰解密: ' . $wrong . ' (亂碼)';
?>
原文: https://www.example.com/api?user=123&token=abc 密文: Xk... (每次執行結果完全不同) 解密: https://www.example.com/api?user=123&token=abc 錯誤公鑰解密: garbled...
md5(rand(0,32000)) 產生 32 字元動態金鑰鹽值字元 + (明文字元 XOR 鹽值字元) 交替組合,長度變為 2x| 優點 | 局限/風險 |
|---|---|
| 每次加密結果不同 (抗彩虹表) | 非標準加密演算法,未經密碼學驗證 |
| 公鑰機制提供存取控制 | XOR 加密屬流加密,若明文已知可推導金鑰 |
| 實作簡單、無需擴展 | 不提供完整性驗證 (HMAC/簽名) |
| 效能極佳 (純 PHP 位運算) | 金鑰管理機制簡單 (無輪換、無派發) |
openssl_encrypt($data, 'AES-256-CBC', $key, 0, $iv) - 標準、經驗證、支援硬體加速sodium_crypto_secretbox() - 現代、高效、抗旁路攻擊firebase/php-jwt - 標準化、自帶簽名驗證、支援非對稱加密此加密類展示了「隨機鹽值 + 公鑰驗證 + XOR 運算」的經典對稱加密模式。理解其原理有助於評估第三方加密庫、設計自定義安全協議。生產核心業務請務必採用經標準化驗證的加密庫 (OpenSSL/Sodium/JWT)。