基於 XOR 位元運算與動態金鑰的對稱加密類 Ender,特點:密鑰衍生 (MD5)、隨機種子混淆、Base64 編碼、等號替換 (避免 URL/表單傳輸問題)、可設定密鑰。適合輕量級資料加密 (非軍用級)。
class Ender {
private $key = '';
private $repChar = '#'; // 替換 Base64 中的 =
public function __construct($key = '') { $this->key = $key; }
public function setKey($key) { $this->key = $key; }
// 核心 XOR 加密/解密 (對稱)
private function xorCrypt($txt, $key) {
$key = md5($key);
$out = '';
for ($i = 0, $k = 0; $i < strlen($txt); $i++, $k++) {
if ($k === strlen($key)) $k = 0;
$out .= $txt[$i] ^ $key[$k];
}
return $out;
}
public function encrypt($txt, $key = '') {
$key = $key ?: $this->key;
// 隨機種子混淆:每字元前插入一個隨機字元
$seed = md5(rand(0, 32000));
$mixed = '';
for ($i = 0, $k = 0; $i < strlen($txt); $i++, $k++) {
if ($k === strlen($seed)) $k = 0;
$mixed .= $seed[$k] . ($txt[$i] ^ $seed[$k]);
}
// 密鑰二次加密 + Base64 + 替換 =
$b64 = base64_encode($this->xorCrypt($mixed, $key));
return str_replace('=', $this->repChar, $b64);
}
public function decrypt($txt, $key = '') {
$key = $key ?: $this->key;
$txt = str_replace($this->repChar, '=', $txt);
$decoded = base64_decode($txt);
$xored = $this->xorCrypt($decoded, $key);
// 還原:每兩字元一組,第一個是種子,第二個是混淆後資料
$out = '';
for ($i = 0; $i < strlen($xored); $i += 2) {
$seedChar = $xored[$i];
$dataChar = $xored[$i+1] ?? '';
$out .= $dataChar ^ $seedChar;
}
return $out;
}
}
$ender = new Ender('my-secret-key');
$plain = '{"user_id":123,"token":"abcxyz"}';
$encrypted = $ender->encrypt($plain);
echo "加密: $encrypted\n";
$decrypted = $ender->decrypt($encrypted);
echo "解密: $decrypted\n";
// 驗證
var_dump($plain === $decrypted); // true
| 層面 | 評估 | 建議 |
|---|---|---|
| 算法強度 | XOR + MD5 非標準加密,易受已知明文攻擊、重放攻擊 | **嚴禁用於敏感資料** (密碼、Token、金流)。改用 openssl_encrypt (AES-256-GCM) 或 libsodium (XChaCha20-Poly1305) |
| 隨機性 | rand() 非加密安全,PHP 7.1+ 建議 random_bytes() | 替換為 random_bytes(16) 生成種子 |
| 完整性 | 無認證標籤 (MAC/Tag),密文可被竄改 | 使用 AEAD 模式 (GCM/Poly1305) 自帶完整性驗證 |
| 金鑰管理 | 硬編碼/配置檔明文存儲 | 使用環境變數、金鑰管理系統 (HashiCorp Vault、AWS KMS) |
// AES-256-GCM (OpenSSL)
function encryptAes($data, $key) {
$iv = random_bytes(12); // GCM 建議 12 字節
$ct = openssl_encrypt($data, 'aes-256-gcm', $key, OPENSSL_RAW_DATA, $iv, $tag);
return base64_encode($iv . $tag . $ct);
}
function decryptAes($b64, $key) {
$raw = base64_decode($b64);
$iv = substr($raw, 0, 12);
$tag = substr($raw, 12, 16);
$ct = substr($raw, 28);
return openssl_decrypt($ct, 'aes-256-gcm', $key, OPENSSL_RAW_DATA, $iv, $tag);
}
// libsodium (推薦)
function encryptSodium($data, $key) {
$nonce = random_bytes(SODIUM_CRYPTO_AEAD_XCHACHA20POLY1305_IETF_NPUBBYTES);
$ct = sodium_crypto_aead_xchacha20poly1305_ietf_encrypt($data, '', $nonce, $key);
return base64_encode($nonce . $ct);
}
本類僅供學習對稱加密原理、非敏感資料混淆 (如前端參數防篡改) 參考。