PHP实现AES-256-CBC加密后Java解密失败该如何处理?
问题根因
- 密钥原文不匹配:PHP加密时参与SHA256哈希的原始密钥字符串是
keyssss,但Java解密代码中makeKey方法使用的是secretKeys,密钥错误直接导致解密后数据校验填充失败。 - 未显式指定字符集:字符串转字节数组时依赖JVM默认字符集,若和PHP环境字符集不一致,会导致密钥哈希结果、解密后明文编码异常。
修正后的完整代码
import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestParam; import javax.crypto.Cipher; import javax.crypto.SecretKey; import javax.crypto.spec.IvParameterSpec; import javax.crypto.spec.SecretKeySpec; import javax.xml.bind.DatatypeConverter; import java.nio.charset.StandardCharsets; import java.security.MessageDigest; import java.util.Base64; @GetMapping("/verify") public String tokenFB(@RequestParam("accessToken") String accessToken) { try { String[] accessTokenSplit = accessToken.split("::"); if (accessTokenSplit.length < 2) { throw new BadRequestException("accessTokenInvalid"); } String token = accessTokenSplit[0]; String iv = accessTokenSplit[1]; byte[] tokenByte = Base64.getDecoder().decode(token); Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); SecretKey secretKey = makeKey(); IvParameterSpec ivParameterSpec = makeIv(iv); cipher.init(Cipher.DECRYPT_MODE, secretKey, ivParameterSpec); byte[] plainText = cipher.doFinal(tokenByte); // 显式指定UTF-8编码转字符串 return new String(plainText, StandardCharsets.UTF_8); } catch (Exception e) { throw new RuntimeException(e); } } private IvParameterSpec makeIv(String iv) { byte[] ivHex = DatatypeConverter.parseHexBinary(iv); return new IvParameterSpec(ivHex); } private SecretKey makeKey() { try { MessageDigest dg = MessageDigest.getInstance("SHA-256"); // 修正密钥原文,显式指定UTF-8转字节数组 byte[] keyByte = dg.digest("keyssss".getBytes(StandardCharsets.UTF_8)); return new SecretKeySpec(keyByte, "AES"); } catch (Exception e) { e.printStackTrace(); } return null; }
补充说明
如果项目是Java 9及以上版本,javax.xml.bind.DatatypeConverter已被移除,可以改用第三方工具类或者自行实现十六进制转字节数组逻辑即可,核心解密逻辑无需调整。
内容的提问来源于stack exchange,提问作者user2239283
相关产品推荐
相关产品推荐

