[英]Double encryption / decryption fails but single does not - AES 256 bit
因此,这种特殊情况非常普遍,但是我的问题与通常提出的问题略有不同。
我已经定义了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
Exception。 请注意, a
和b
只是整数(假设它们都为0)。 当前,IVBytes只是一个大小为16的空字节数组,用new byte[16]
。 aKeys
和bKeys
都是带有AES加密(随机)字符串(长度为32个字节)的String数组。
这些是我使用的辅助函数(将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确实给了我一个主意。 如果我有什么新东西,我会编辑。
这个想法是正确的。 我正在遍历一个乱码的真值表(对于那些感兴趣的人,请查看Wikipedia文章 )并检查所有可能的密文(CT)。 问题是,如果您选择了不正确的CT并对其进行了双重解密,则它将抛出异常,因为第一次解密会返回垃圾。 只需检查表中的键即可解决此问题。
您使用错误的密钥进行解密。 您正在使用密钥B加密,然后使用密钥A加密结果。然后尝试使用密钥B解密该结果,并使用密钥A解密最终结果。
每次解密时,都应指定用于执行“最新”加密操作的相同密钥。 所以:
Encrypt Encrypt Decrypt Decrypt
with B with A with A with B
Plain text -> encrypted I -> encrypted II -> encrypted I -> plain text
我还建议,在同一时间执行这些操作的一个声明,而不是从下往上由于在单个语句做的一切阅读,就会使人们更方便明白发生了什么事情。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.