密码:IllegalBlockSizeException的原因是什么?
当我使用Cipher时,我观察到以下内容。
加密代码:
Cipher aes = Cipher.getInstance("AES"); aes.init(Cipher.ENCRYPT_MODE, generateKey()); byte[] ciphertext = aes.doFinal(rawPassword.getBytes());
解密代码:
Cipher aes = Cipher.getInstance("AES"); aes.init(Cipher.DECRYPT_MODE, generateKey()); byte[] ciphertext = aes.doFinal(rawPassword.getBytes());
在运行Decrypt代码时,我得到IllegalBlockSizeException(输入长度必须是16的倍数)。
但是,如果我将解密代码更改为
Cipher aes = Cipher.getInstance("AES/ECB/PKCS5Padding"); //I am passing the padding too aes.init(Cipher.DECRYPT_MODE, generateKey()); byte[] ciphertext = aes.doFinal(rawPassword.getBytes());
它工作正常。 我知道它是模式algorithm/mode/padding
。 所以我认为这是因为我没有提到填充。 所以我尝试在加密过程中给出模式和填充,
加密代码:
Cipher aes = Cipher.getInstance("AES/ECB/PKCS5Padding");//Gave padding during encryption too aes.init(Cipher.ENCRYPT_MODE, generateKey()); byte[] ciphertext = aes.doFinal(rawPassword.getBytes());
解密代码:
Cipher aes = Cipher.getInstance("AES/ECB/PKCS5Padding"); aes.init(Cipher.DECRYPT_MODE, generateKey()); byte[] ciphertext = aes.doFinal(rawPassword.getBytes());
但它失败了IllegalBlockSizeException。
是什么原因,为什么例外以及究竟发生了什么。 如果有人可以帮忙吗? 提前致谢
UPDATE
看起来问题在于我正在加密和解密的字符串。 因为,即使我说的代码有效,也并不总是有效。 我基本上是在加密UUID(例如:8e7307a2-ef01-4d7d-b854-e81ce152bbf6)。 它适用于某些字符串,而不适用于某些其他字符串。
加密String的长度为64,可以被16整除。是的,我在同一台机器上运行它。
密钥生成方法:
private Key generateKey() throws NoSuchAlgorithmException { MessageDigest digest = MessageDigest.getInstance("SHA"); String passphrase = "blahbl blahbla blah"; digest.update(passphrase.getBytes()); return new SecretKeySpec(digest.digest(), 0, 16, "AES"); }
在解密期间,如果输入数据不是块大小的倍数(AES为16字节),则只能获得IllegalBlockSizeException
。
如果密钥或数据无效(但长度正确),则会出现BadPaddingException
因为明文中PKCS#5填充错误。 偶尔填充看起来是正确的,你也不会有任何例外。
NB我建议你总是指定填充和模式。 如果不这样做,如果提供商更改默认值,您可能会感到惊讶。 Sun提供商AFAIK将"AES"
转换为"AES/ECB/PKCS5Padding"
。
虽然我还没有完全理解内部,但我发现了问题所在。
我将加密的字符串作为GET请求参数获取。 由于字符串包含不安全的字符,因此在请求中字符串会被破坏。 解决方案是进行URL编码和解码。
我能够使用URLEncoder和URLDecoder成功地完成它。
现在结果是一致的。 谢谢 :)
如果有人能为此做出更多贡献,我将不胜感激。