AES/CBC/PKCS5PADDING加密Java实现转等效PHP代码求助
问题原因分析
- 编码格式不匹配:Java代码使用
Base64.getUrlEncoder()输出URL安全Base64格式,你原有PHP代码使用标准base64_encode(),两者字符映射规则不同:URL安全格式会将+替换为-、/替换为_,同时删除末尾的填充字符=,这是你固定IV测试结果仍然不匹配的核心原因 - 密钥长度匹配规则:Java的
SecretKeySpec直接取密码的UTF-8原始字节作为密钥,AES-128要求密钥长度为16字节、AES-256要求为32字节,PHP侧需要保持和Java侧一致的密码字节长度,不要额外做哈希、截断或填充操作 - 填充规则:PHP的
openssl_encrypt默认使用PKCS5填充,和Java的PKCS5Padding规则一致,无需额外调整
完整PHP实现代码
// URL安全Base64编码,和Java Base64.getUrlEncoder()逻辑完全对齐 function url_safe_base64_encode($data) { return rtrim(strtr(base64_encode($data), '+/', '-_'), '='); } // URL安全Base64解码,和Java Base64.getUrlDecoder()逻辑完全对齐 function url_safe_base64_decode($data) { $data = strtr($data, '-_', '+/'); $padding = strlen($data) % 4; if ($padding) { $data .= str_repeat('=', 4 - $padding); } return base64_decode($data); } /** * 加密方法,对应Java侧getEncryptedParameter + getInitializationVector能力 * @param string $plaintext 待加密明文 * @param string $key 加密密钥,和Java侧密码完全一致 * @return array 加密后的URL安全Base64字符串、URL安全Base64格式的IV */ function aes_cbc_encrypt($plaintext, $key) { // 密钥长度16位用AES-128-CBC,32位替换为AES-256-CBC即可 $cipherAlgorithm = 'AES-128-CBC'; $ivLength = openssl_cipher_iv_length($cipherAlgorithm); // 生成16位随机IV,和Java SecureRandom生成逻辑对齐 $iv = openssl_random_pseudo_bytes($ivLength); // 加密得到原始二进制数据 $encryptedBin = openssl_encrypt($plaintext, $cipherAlgorithm, $key, OPENSSL_RAW_DATA, $iv); return [ 'encrypted_data' => url_safe_base64_encode($encryptedBin), 'iv' => url_safe_base64_encode($iv) ]; } /** * 解密方法,对应Java侧getDecryptedParameter能力 * @param string $encryptedData 加密后的URL安全Base64字符串 * @param string $key 解密密钥,和Java侧密码完全一致 * @param string $iv URL安全Base64格式的IV * @return string 解密后的明文 */ function aes_cbc_decrypt($encryptedData, $key, $iv) { // 密钥长度16位用AES-128-CBC,32位替换为AES-256-CBC即可 $cipherAlgorithm = 'AES-128-CBC'; $ivBin = url_safe_base64_decode($iv); $encryptedBin = url_safe_base64_decode($encryptedData); return openssl_decrypt($encryptedBin, $cipherAlgorithm, $key, OPENSSL_RAW_DATA, $ivBin); }
验证说明
可先固定IV和密钥做对齐测试:
设置固定IV为1234567890123456(16字节)、密钥为testpass123456789(16字节)、明文为test_content_123,Java侧和PHP侧输出的加密字符串、IV编码结果完全一致。
内容的提问来源于stack exchange,提问作者Rabot
相关产品推荐
相关产品推荐

