我编写了一个简单的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,如果一个人解密失败,他会知道解密失败,但不是像我认为的那样从解密中获取错误的字节?这太可怕了...
您的代码没有任何问题(尽管您可以通过为字符和字节之间的转换指定编码而不是依赖平台编码来使其更加健壮(。填充具有一定的格式,因此可以在解密后将其删除。当您使用错误的密钥解密时,填充也会乱码,无法删除。这会导致异常。
在大多数情况下,攻击者会知道他得到了错误的密钥,而不仅仅是因为填充。数据字节通常也具有某种结构(例如某种文件格式(,或者在您的情况下,他会检测异常字符或无效字符编码。如果以 UTF-8 为例,并非每个二进制字符串都是有效的 UTF-8 编码。