1

我写了一个简单的Java AES加密和解密如下(用于学习目的):

//Encryption 
Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");  
SecretKeySpec secretKey = new SecretKeySpec(key, "AES");
cipher.init(Cipher.ENCRYPT_MODE, secretKey);
 String encryptedString = Base64.encodeBase64String(cipher.doFinal(strToEncrypt.getBytes()));
return encryptedString;

//Decryption
Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5PADDING");
SecretKeySpec secretKey = new SecretKeySpec(key, "AES");
cipher.init(Cipher.DECRYPT_MODE, secretKey);
String decryptedString = new String(cipher.doFinal(Base64.decodeBase64(strToDecrypt)));
return decryptedString;

密码密钥是一个可变长度的字符串,我对字符串进行 MD5 哈希处理得到 128 位密钥。

我可以使用相同的密钥成功地加密和解密数据。但是如果我用错误的密钥解密数据,我会得到以下异常:

javax.crypto.BadPaddingException: Given final block not properly padded

实际上我所期望的是,错误的密钥解密产生了错误的字节,但不会像上面那样抛出异常,因为如果产生错误的字节,黑客可能不知道解密是否正确。如果像上面那样抛出异常,蛮力的输出将变得更容易确定。

那么,我的代码会发生什么?

编辑:

我想我在这里犯了一个错误。黑客可能不会使用我的程序来解密。所以对于AES,如果一个人解密失败,他会知道解密失败,但不是我认为从解密中得到错误字节?这真糟糕...

4

1 回答 1

5

您的代码没有任何问题(尽管您可以通过为字符和字节之间的转换指定编码而不是依赖平台编码来使其更加健壮)。填充具有一定的格式,以便在解密后可以将其删除。当您使用错误的密钥解密时,填充也会出现乱码,无法删除。这会导致异常。

在大多数情况下,攻击者会知道他得到了错误的密钥,这不仅仅是因为填充。数据字节通常也有一些结构(例如,某种文件格式),或者在你的情况下,他会检测到不寻常的字符或无效的字符编码。如果以 UTF-8 为例,并非每个二进制字符串都是有效的 UTF-8 编码。

于 2013-10-04T04:31:25.470 回答