PHP的MCRYPT_RIJNDAEL_256加密转Java实现求助
解决PHP Rijndael-256 CBC加密转Java实现的问题
我来帮你搞定这个对接遗留API的加密问题!你遇到的报错本质是PHP和Java对Rijndael算法的定义差异,以及参数配置没对齐导致的,下面给你拆解原因+完整实现:
首先得明确PHP代码里的几个关键细节,这是踩坑核心:
MCRYPT_RIJNDAEL_256指的是**块大小为256位(32字节)**的Rijndael算法,不是你以为的密钥长度256(刚好你的密钥是32字节=256位,这是巧合)。- Java标准库的
AES只支持128位块大小,所以直接用javax.crypto会因为IV长度(32字节)不符合16字节要求报错。 - BouncyCastle支持完整的Rijndael算法(包括256位块大小),你之前用它报错是因为没正确指定块大小参数。
正确实现步骤
1. 先加BouncyCastle依赖
如果用Maven,在pom.xml里添上这个依赖(版本可以用最新稳定版):
<dependency> <groupId>org.bouncycastle</groupId> <artifactId>bcprov-jdk15on</artifactId> <version>1.70</version> </dependency>
2. 完整Java代码实现
下面的代码完全对齐PHP的加密逻辑,复制过去就能用:
- 用Rijndael-256(32字节块大小)
- CBC模式
- IV和密钥完全相同(和PHP逻辑一致)
- 零填充(PHP的
mcrypt_encrypt默认填充方式,你的输入是32的倍数,不会额外补零) - 最终输出Base64编码结果
import org.bouncycastle.crypto.BlockCipher; import org.bouncycastle.crypto.CipherParameters; import org.bouncycastle.crypto.engines.RijndaelEngine; import org.bouncycastle.crypto.modes.CBCBlockCipher; import org.bouncycastle.crypto.paddings.ZeroBytePadding; import org.bouncycastle.crypto.paddings.PaddedBufferedBlockCipher; import org.bouncycastle.crypto.params.KeyParameter; import org.bouncycastle.crypto.params.ParametersWithIV; import java.nio.charset.StandardCharsets; import java.util.Base64; public class LegacyApiEncryptor { public static void main(String[] args) throws Exception { // 替换成你要加密的32倍数长度字符串 String plainText = "****需加密的字符串,长度为32的倍数********************"; // 替换成你的32字节密钥 String secretKey = "32ByteKey-asdcxzasdsadasdasdasda"; byte[] keyBytes = secretKey.getBytes(StandardCharsets.UTF_8); byte[] ivBytes = keyBytes; // IV和密钥完全相同,和PHP保持一致 byte[] inputBytes = plainText.getBytes(StandardCharsets.UTF_8); // 初始化Rijndael引擎,必须指定块大小为256位(32字节) BlockCipher rijndaelEngine = new RijndaelEngine(256); // 组合CBC模式+零填充 PaddedBufferedBlockCipher cipher = new PaddedBufferedBlockCipher(new CBCBlockCipher(rijndaelEngine), new ZeroBytePadding()); // 构建加密参数:密钥+IV CipherParameters params = new ParametersWithIV(new KeyParameter(keyBytes), ivBytes); cipher.init(true, params); // true表示加密模式 // 处理加密输出 byte[] outputBuffer = new byte[cipher.getOutputSize(inputBytes.length)]; int processedLength = cipher.processBytes(inputBytes, 0, inputBytes.length, outputBuffer, 0); // 完成加密,处理最后一块 processedLength += cipher.doFinal(outputBuffer, processedLength); // 转Base64编码,和PHP的base64_encode结果一致 String encryptedBase64 = Base64.getEncoder().encodeToString(outputBuffer, 0, processedLength); System.out.println("加密结果:" + encryptedBase64); } }
几个必须注意的细节
- 块大小必须指定256:如果忘记在
RijndaelEngine构造函数传256,默认会用128位块大小,和PHP的MCRYPT_RIJNDAEL_256完全不匹配,解密肯定失败。 - 填充方式必须用零填充:PHP的
mcrypt_encrypt默认用零填充,千万别用PKCS7/PKCS5填充,否则后端解密会报错。 - 字符集要对齐:PHP里字符串转字节默认是环境编码,如果你PHP代码里是UTF-8,Java用
StandardCharsets.UTF_8就没问题,如果是其他编码(比如GBK),要对应修改。 - IV长度必须32字节:因为块大小是256位,所以IV必须和块大小一致,这里直接用密钥当IV,完全符合PHP逻辑。
内容的提问来源于stack exchange,提问作者AnupRai
相关产品推荐
相关产品推荐

