You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Java加密字符串无法被PHP解密,求匹配AES-128-CTR的解决方案

问题分析与解决方案

你的Java代码和PHP代码的加密参数存在多处不匹配,导致无法解密,以下是具体问题和修正后的代码:

不匹配的核心点

  • 加密模式不一致:PHP使用AES-128-CTR,Java默认用AES/ECB/PKCS5Padding,两者完全不兼容
  • IV未使用:PHP指定了固定IV,Java代码未传入IV(CTR模式必须使用IV)
  • 密钥填充规则不同:PHP自动用NULL字节补全16字节密钥,Java用空格补全,导致密钥不一致
  • Base64编码与URL处理:未确保Java生成的编码字符串符合PHP的解码预期

修正后的Java代码

import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import org.apache.commons.codec.binary.Base64;

// 配置与PHP完全一致的参数
String encryptionKey = "MyPassword";
String ivString = "1234567891011121"; // 和PHP的encryption_iv保持一致
JsonObject joParms = new JsonObject();
joParms.addProperty("id", invoiceId);
joParms.addProperty("db", db);
joParms.addProperty("archived", isArchive);

// 处理密钥:补NULL字节到16字节(和PHP行为对齐)
byte[] keyBytes = new byte[16];
byte[] originalKeyBytes = encryptionKey.getBytes();
System.arraycopy(originalKeyBytes, 0, keyBytes, 0, Math.min(originalKeyBytes.length, 16));
// 剩余位置默认填充0(等价于PHP的NULL字节)
SecretKeySpec secretKeySpec = new SecretKeySpec(keyBytes, "AES");

// 处理IV:转换为字节数组
byte[] ivBytes = ivString.getBytes();
IvParameterSpec ivSpec = new IvParameterSpec(ivBytes);

// 初始化CTR模式的Cipher(Java 1.6需确保JCE支持该模式)
Cipher cipher = Cipher.getInstance("AES/CTR/NoPadding");
cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec, ivSpec);

// 加密JSON字符串
byte[] jsonBytes = joParms.toString().getBytes();
byte[] encryptedBytes = cipher.doFinal(jsonBytes);

// 生成URL安全的Base64编码,避免URL转义问题
String encodedString = Base64.encodeBase64URLSafeString(encryptedBytes);

// 拼接最终消息
String message = messageTemplate.replace("{INVNO}", invNo)
                                .replace("{AMOUNT}", amount)
                                .concat(" ")
                                .concat(siteUrl)
                                .concat("?p=")
                                .concat(encodedString);

关键细节说明

  1. 加密模式:明确指定AES/CTR/NoPadding,与PHP的AES-128-CTR完全匹配(CTR模式无需填充)
  2. IV处理:直接使用PHP中相同的IV字符串转字节数组,确保两边IV完全一致
  3. 密钥对齐:PHP中密钥长度不足16字节时,会自动用NULL字节(\0)填充,Java通过创建16字节数组并拷贝原密钥,剩余位置默认填充0,保证密钥与PHP端一致
  4. Base64编码:使用URL安全的Base64编码,避免普通Base64中的+、/在URL中被转义,PHP端的urldecode可正确处理该编码;若使用普通Base64,需额外对结果执行URLEncoder.encode

PHP端兼容性验证

无需修改现有PHP代码,只要Java端参数匹配,openssl_decrypt即可正常解密:

  • $encryption_options = 0 会自动检测并解码Base64输入,URL安全的Base64也能被正确识别

内容的提问来源于stack exchange,提问作者Hussain Akbar

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.15 05:13:23