【发布时间】:2014-12-18 05:10:07
【问题描述】:
所以这个特殊的异常很常见,但我的问题与通常问的略有不同。
我有一个 AES 解密和加密函数,定义如下:
public static byte[] encrypt(byte[] ivBytes, byte[] keyBytes, byte[] textBytes)
throws java.io.UnsupportedEncodingException,
NoSuchAlgorithmException,
NoSuchPaddingException,
InvalidKeyException,
InvalidAlgorithmParameterException,
IllegalBlockSizeException,
BadPaddingException {
AlgorithmParameterSpec ivSpec = new IvParameterSpec(ivBytes);
SecretKeySpec newKey = new SecretKeySpec(keyBytes, "AES");
Cipher cipher;
cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE, newKey, ivSpec);
return cipher.doFinal(textBytes);
}
public static byte[] decrypt(byte[] ivBytes, byte[] keyBytes, byte[] textBytes)
throws java.io.UnsupportedEncodingException,
NoSuchAlgorithmException,
NoSuchPaddingException,
InvalidKeyException,
InvalidAlgorithmParameterException,
IllegalBlockSizeException,
BadPaddingException {
AlgorithmParameterSpec ivSpec = new IvParameterSpec(ivBytes);
SecretKeySpec newKey = new SecretKeySpec(keyBytes, "AES");
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(Cipher.DECRYPT_MODE, newKey, ivSpec);
return cipher.doFinal(textBytes);
}
现在,如果我像这样执行一次解密:
System.out.println(Arrays.toString(
AES256Cipher.decrypt(ivBytes, HexBytePlainWriter.hexStringToByteArray(aKeys[a]),
AES256Cipher.encrypt(ivBytes, HexBytePlainWriter.hexStringToByteArray(aKeys[a]),
AES256Cipher.encrypt(ivBytes, HexBytePlainWriter.hexStringToByteArray(bKeys[b]), HexBytePlainWriter.hexStringToByteArray(zkeys[a^b]))
)
)));
字节数组输出就好了。而如果我执行双重加密/解密:
System.out.println("dec: " + HexBytePlainWriter.ByteToHexString(
AES256Cipher.decrypt(ivBytes, HexBytePlainWriter.hexStringToByteArray(aKeys[a]),
AES256Cipher.decrypt(ivBytes, HexBytePlainWriter.hexStringToByteArray(bKeys[b]),
AES256Cipher.encrypt(ivBytes, HexBytePlainWriter.hexStringToByteArray(aKeys[a]),
AES256Cipher.encrypt(ivBytes, HexBytePlainWriter.hexStringToByteArray(bKeys[b]), HexBytePlainWriter.hexStringToByteArray(zkeys[a^b]))
)
))));
我得到了著名的javax.crypto.BadPaddingException: Given final block not properly padded 异常。请注意a 和b 只是整数(假设它们都是0)。目前,IVBytes 只是一个大小为 16 的空字节数组,用new byte[16] 声明。 aKeys 和 bKeys 都是带有 AES 加密(随机)字符串(长度 32 字节)的字符串数组。
这些是我使用的辅助函数(将 byte[] 转换为十六进制字符串,反之亦然):
public static String ByteToHexString (byte[] data) {
StringBuilder buf = new StringBuilder();
for (byte b : data) {
int halfbyte = (b >>> 4) & 0x0F;
int two_halfs = 0;
do {
buf.append((0 <= halfbyte) && (halfbyte <= 9) ? (char) ('0' + halfbyte) : (char) ('a' + (halfbyte - 10)));
halfbyte = b & 0x0F;
} while (two_halfs++ < 1);
}
return buf.toString();
}
public static byte[] hexStringToByteArray(String s) {
int len = s.length();
byte[] data = new byte[len / 2];
for (int i = 0; i < len; i += 2) {
data[i / 2] = (byte) ((Character.digit(s.charAt(i), 16) << 4)
+ Character.digit(s.charAt(i+1), 16));
}
return data;
}
我怀疑第一次解密的输出使密文格式错误,导致外部抛出异常。我检查了大小,外部输出 32 个字节,所以应该没问题。这不符合 PKC5Padding 吗?
非常感谢任何帮助。
编辑:
看起来我的最小示例是错误的:我首先使用密钥 B 而不是 A。但 Jon Skeet 确实给了我一个想法。如果我有任何新内容,我会进行编辑。
编辑2:
这个想法是正确的。我正在遍历一个乱码真值表(对于那些感兴趣的人,请查看此Wikipedia article)并检查所有可能的密文(CT)。问题是如果你选择了一个不正确的 CT 并对其使用双重解密,它会抛出异常,因为第一次解密返回垃圾。对表中的键进行简单检查即可解决此问题。
【问题讨论】:
标签: java encryption cryptography aes padding