設計目標
- PHP 端 AES-128-CBC-NoPadding 加解密。
- 密鑰長度 16 字節(128 位),與 Java
AES/CBC/NoPadding 互通。
- 可作 Yii 擴展使用,非 Yii 專案只需替換
Yii::app()->params['encryptKey'] 為固定密鑰。
完整類代碼
params['encryptKey'] : $key, 0, mcrypt_enc_get_key_size($module));
$iv = substr(md5($key), 0, mcrypt_enc_get_iv_size($module));
mcrypt_generic_init($module, $key, $iv);
$encrypted = mcrypt_generic($module, $plaintext);
mcrypt_generic_deinit($module);
mcrypt_module_close($module);
return base64_encode($encrypted);
}
public static function AesDecrypt($encrypted, $key = null) {
if ($encrypted === '') return '';
if (!extension_loaded('mcrypt')) throw new CException('需開啟 mcrypt 擴展');
$ciphertext_dec = base64_decode($encrypted);
$module = mcrypt_module_open(MCRYPT_RIJNDAEL_128, '', MCRYPT_MODE_CBC, '');
$key = self::substr($key === null ? Yii::app()->params['encryptKey'] : $key, 0, mcrypt_enc_get_key_size($module));
$iv = substr(md5($key), 0, mcrypt_enc_get_iv_size($module));
mcrypt_generic_init($module, $key, $iv);
$decrypted = mdecrypt_generic($module, $ciphertext_dec);
mcrypt_generic_deinit($module);
mcrypt_module_close($module);
return rtrim($decrypted, "\0");
}
private static function strlen($string) {
return extension_loaded('mbstring') ? mb_strlen($string, '8bit') : strlen($string);
}
private static function substr($string, $start, $length) {
return extension_loaded('mbstring') ? mb_substr($string, $start, $length, '8bit') : substr($string, $start, $length);
}
}
?>
使用示例
// Yii 專案
$encrypted = PhpAes::AesEncrypt('敏感數據');
$decrypted = PhpAes::AesDecrypt($encrypted);
// 非 Yii 專案(修改類中默認密鑰獲取邏輯)
$key = '16byteslongkey!'; // 必須 16 字節
$encrypted = PhpAes::AesEncrypt('敏感數據', $key);
$decrypted = PhpAes::AesDecrypt($encrypted, $key);
Java 端對應代碼 (參考)
Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding");
SecretKeySpec keySpec = new SecretKeySpec(keyBytes, "AES");
IvParameterSpec ivSpec = new IvParameterSpec(MD5(keyBytes).substring(0,16).getBytes());
cipher.init(Cipher.ENCRYPT_MODE, keySpec, ivSpec);
byte[] encrypted = cipher.doFinal(plainText.getBytes());
String base64 = Base64.getEncoder().encodeToString(encrypted);
注意事項
- PHP 7.1+
mcrypt 已棄用,建議遷移至 openssl_encrypt/decrypt (支援 OPENSSL_ZERO_PADDING 實現 NoPadding)。
- IV 衍生方式
substr(md5($key),0,16) 雙端必須一致。
- 嚴禁在客戶端代碼/前端暴露密鑰,密鑰應存儲於配置文件/環境變量/密鑰管理服務。