自研AES_256加密值无法在线解密,求助排查原因
AES加密后无法用在线工具解密的问题排查与解决
核心问题1:密钥处理逻辑不匹配
你的代码对输入的密钥字符串做了SHA-256哈希,将哈希后的32字节结果作为AES-256的密钥:
private static SecretKeySpec getSecretKeySpec(String secretKey) throws Exception { byte[] keyBytes = secretKey.getBytes(StandardCharsets.UTF_8); MessageDigest sha = MessageDigest.getInstance("SHA-256"); keyBytes = sha.digest(keyBytes); // 此处执行SHA-256哈希 return new SecretKeySpec(keyBytes, "AES"); }
但绝大多数在线AES工具默认是直接将输入的密钥字符串按UTF-8转成字节作为密钥,不会额外执行SHA-256哈希。你使用的密钥字符串"my very secret key 000!!"仅22个字符(UTF-8下22字节),在线工具会自动补全或截断密钥,导致和你代码生成的密钥完全不一致,这就是解密时报填充错误的核心原因。
核心问题2:IV的传递方式不匹配
你的代码把16字节的IV直接拼接在密文前,再一起做Base64编码输出。但在线工具通常要求:
- 单独输入IV(Base64格式)
- 密文仅包含纯加密后的内容(不含IV)
你直接将拼接后的Base64字符串传入在线工具,它会把整个内容当成密文,用默认IV(比如全0)解密,自然会失败。
解决方法(让在线工具正常解密)
方法1:调整在线工具参数匹配你的代码逻辑
如果必须用在线工具,按以下步骤操作:
- 处理密钥:先将密钥字符串"my very secret key 000!!"做SHA-256哈希,把哈希结果(32字节)转成Base64或十六进制,作为在线工具的密钥输入(选择AES-256模式)。
- 拆分IV和密文:将代码输出的Base64字符串解码为字节数组,前16字节是IV,剩余部分是密文,分别将IV和密文转成Base64,在在线工具中单独输入。
- 匹配其他参数:加密模式选CBC,填充方式选PKCS5Padding,字符集用UTF-8。
方法2:修改代码适配在线工具常规逻辑
如果想让QA操作更便捷,可修改代码:
- 去掉密钥的SHA-256哈希步骤,直接用密钥字符串的UTF-8字节作为密钥(注意AES-256要求密钥必须是32字节,需调整密钥字符串长度)。
- 输出时分开返回IV的Base64和密文的Base64,或用明确分隔符标注IV与密文的边界。
示例修改后的密钥处理方法:
private static SecretKeySpec getSecretKeySpec(String secretKey) throws Exception { byte[] keyBytes = secretKey.getBytes(StandardCharsets.UTF_8); // AES-256要求密钥必须是32字节 if (keyBytes.length != 32) { throw new IllegalArgumentException("AES-256 requires 32-byte key"); } return new SecretKeySpec(keyBytes, "AES"); }
额外注意点
Android的Base64.DEFAULT会在输出中添加换行符,部分在线工具不支持带换行的Base64,建议改用Base64.NO_WRAP避免该问题:
return android.util.Base64.encodeToString(combined, android.util.Base64.NO_WRAP);
内容的提问来源于stack exchange,提问作者Nicholas
相关产品推荐
相关产品推荐

