一开始使用的是BlankJ工具类进行解密
val content = "......." // 后台返回的一串加密后的数据
val key = "jdkjdkjdjkdj" // 本地存储的密钥
EncryptUtils.decryptAES(content.toByteArray(Charsets.UTF_8), key.toByteArray(Charsets.UTF_8),"AES/ECB/PKCS7Padding", null)
但是解密后发现一直报错,提示 error:1e00007b:Cipher functions:OPENSSL_internal:WRONG_FINAL_BLOCK_LENGTH
我寻思着是不是后台的加密算法有问题,找了后台的同事问了下,后台给了个地址
https://the-x.cn/cryptography/Aes.aspx
我将数据填进去后,发现解密可以啊,那这就是我的问题了,于是我打开BlankJ的代码进行查看,关键代码是这里
private static byte[] symmetricTemplate(final byte[] data,
final byte[] key,
final String algorithm,
final String transformation,
final byte[] iv,
final boolean isEncrypt) {
if (data == null || data.length == 0 || key == null || key.length == 0) return null;
try {
SecretKey secretKey;
if ("DES".equals(algorithm)) {
DESKeySpec desKey = new DESKeySpec(key);
SecretKeyFactory keyFactory = SecretKeyFactory.getInstance(algorithm);
secretKey = keyFactory.generateSecret(desKey);
} else {
secretKey = new SecretKeySpec(key, algorithm);
}
Cipher cipher = Cipher.getInstance(transformation);
if (iv == null || iv.length == 0) {
cipher.init(isEncrypt ? Cipher.ENCRYPT_MODE : Cipher.DECRYPT_MODE, secretKey);
} else {
AlgorithmParameterSpec params = new IvParameterSpec(iv);
cipher.init(isEncrypt ? Cipher.ENCRYPT_MODE : Cipher.DECRYPT_MODE, secretKey, params);
}
return cipher.doFinal(data);
} catch (Throwable e) {
e.printStackTrace();
return null;
}
}
打了断点后查看发现这里的 data 它的数组长度是491,而我在网站上解密后显示的长度应该是361,所以这里就报错了,提示数组长度不对。
至于为什么不对,是因为加密字符串需要先经过BASE64解密后,于是我把代码修改了下
EncryptUtils.decryptAES(CipherUtils.BASE64Decrypt(content), Constants.APP_SCRECT_KU.toByteArray(StandardCharsets.UTF_8),"AES/ECB/PKCS7Padding", null)
这里的BASE64Decrypt方法我贴一下:
public static byte[] BASE64Decrypt(String str) {
try {
return Base64.decode(str.getBytes("utf-8"),0);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
这样就可以了。
另外,我也遇到了另外一个问题,javax.crypto.BadPaddingException: pad block corrupted 出现这个错误的问题主要是因为你填入的参数不对
比如 解密类EncryptUtils 用到的参数 transformation,这个你需要看你后台加密用的,不要乱填,像我刚刚发的那个网站
这里的 transformation 的组合就是 AES/ECB/PKCS7Padding ,这个不要乱填,不然会报错的。
另外,EncryptUtils 的参数iv,由于我用到的是 ECB算法,不需要iv,所以你填null就行了。如果是用别的算法,那就要填上了。反正我们后台算法暂时没涉及到。
这个问题搞了我一天了,终于是解决了。方法也比较简洁,用BlankJ工具类就OK了,也是很方便简洁。