在 PHP 開發中,資料加密與解密是保護敏感資訊(如 API 金鑰、使用者密碼、個人資料)的基本技能。本文將介紹兩種常見的加密方式:自訂的對稱加密函數(基於 XOR 與 Base64)以及標準的 DES 加密演算法,並提供完整、可直接執行的程式碼範例。
這組函數採用「隨機金鑰 + XOR 運算 + Base64 編碼」的策略,適合簡單的資料混淆與傳輸。核心邏輯包含三個函數:
passport_encryptfunction passport_encrypt($str, $key) {
// 產生隨機加密種子
srand((double)microtime() * 1000000);
$encrypt_key = md5(rand(0, 32000));
$ctr = 0;
$tmp = '';
// 將明文與隨機種子進行 XOR 交織
for ($i = 0; $i < strlen($str); $i++) {
$ctr = ($ctr == strlen($encrypt_key)) ? 0 : $ctr;
$tmp .= $encrypt_key[$ctr] . ($str[$i] ^ $encrypt_key[$ctr++]);
}
// 經由輔助函數二次加密後 Base64 輸出
return base64_encode(passport_key($tmp, $key));
}
passport_decryptfunction passport_decrypt($str, $key) {
// 先 Base64 解碼,再經輔助函數還原
$str = passport_key(base64_decode($str), $key);
$tmp = '';
for ($i = 0; $i < strlen($str); $i++) {
$md5 = $str[$i];
$tmp .= $str[++$i] ^ $md5;
}
return $tmp;
}
passport_keyfunction passport_key($str, $encrypt_key) {
$encrypt_key = md5($encrypt_key);
$ctr = 0;
$tmp = '';
for ($i = 0; $i < strlen($str); $i++) {
$ctr = ($ctr == strlen($encrypt_key)) ? 0 : $ctr;
$tmp .= $str[$i] ^ $encrypt_key[$ctr++];
}
return $tmp;
}
$str = '作者:www.jb51.net';
$key = '123456';
$encrypt = passport_encrypt($str, $key);
$decrypt = passport_decrypt($encrypt, $key);
echo '原文:' . $str . '<br><hr>';
echo '密文:' . $encrypt . '<br><hr>';
echo '譯文:' . $decrypt . '<br><hr>;
DES (Data Encryption Standard) 是經典的區塊加密演算法。以下類別封裝了 CBC 模式、PKCS#5 填充、十六進制輸出,方便直接使用。
<?php
class DES {
var $key;
var $iv; // 初始向量
function __construct($key, $iv = 0) {
// 金鑰長度需為 8 位元組,例如 '1234abcd'
$this->key = $key;
$this->iv = ($iv == 0) ? $key : $iv;
}
// 加密:回傳大寫十六進制字串
function encrypt($str) {
$size = mcrypt_get_block_size(MCRYPT_DES, MCRYPT_MODE_CBC);
$str = $this->pkcs5Pad($str, $size);
return strtoupper(bin2hex(mcrypt_cbc(MCRYPT_DES, $this->key, $str, MCRYPT_ENCRYPT, $this->iv)));
}
// 解密
function decrypt($str) {
$strBin = $this->hex2bin(strtolower($str));
$str = mcrypt_cbc(MCRYPT_DES, $this->key, $strBin, MCRYPT_DECRYPT, $this->iv);
return $this->pkcs5Unpad($str);
}
// 十六進制轉二進制
function hex2bin($hexData) {
$binData = '';
for ($i = 0; $i < strlen($hexData); $i += 2) {
$binData .= chr(hexdec(substr($hexData, $i, 2)));
}
return $binData;
}
// PKCS#5 填充
function pkcs5Pad($text, $blocksize) {
$pad = $blocksize - (strlen($text) % $blocksize);
return $text . str_repeat(chr($pad), $pad);
}
// 移除填充
function pkcs5Unpad($text) {
$pad = ord($text[strlen($text) - 1]);
if ($pad > strlen($text)) return false;
if (strspn($text, chr($pad), strlen($text) - $pad) != $pad) return false;
return substr($text, 0, -1 * $pad);
}
}
?>
$str = '12345678';
$key = '1234abcd';
$crypt = new DES($key);
$mstr = $crypt->encrypt($str);
$str = $crypt->decrypt($mstr);
echo $str . ' <=> ' . $mstr;
當需要透過 GET 方式在 URL 中傳遞敏感參數時,可使用 Base64 編碼整個查詢字串:
// 編碼參數陣列
function args_encode($data) {
if (is_array($data)) {
$string = http_build_query($data);
return base64_encode($string);
}
return false;
}
// 解碼並還原 $_GET
function getargs() {
$string = base64_decode($_GET['args']);
parse_str($string, $g);
return $g;
}
mcrypt 擴充套件在 PHP 7.2+ 已棄用,新專案建議改用 OpenSSL 或 Sodium。