AES BadPaddingException [英] AES BadPaddingException
问题描述
如果我使用错误的密钥或错误的盐进行解密,则会引发BadPaddingException。
我希望返回不正确的字符串。
doFinal()在解密方法中导致异常
if I use a wrong key or wrong salt for decryption an BadPaddingException is thrown. I would expect an incorrect string to be returned. The doFinal() causes the exception in the decrypt-method
消息:这只是一个示例
Unfug:'ΩÙΩ„SåF?V®ßs.k˚·ºç€èhHf∫ÙÉÕ
Exception in thread "main" javax.crypto.BadPaddingException: Given final block not properly padded
at com.sun.crypto.provider.SunJCE_f.b(DashoA13*..)
at com.sun.crypto.provider.SunJCE_f.b(DashoA13*..)
at com.sun.crypto.provider.AESCipher.engineDoFinal(DashoA13*..)
at javax.crypto.Cipher.doFinal(DashoA13*..)
at casino.AES.decryptString(AES.java:130)
at casino.AES.main(AES.java:172)
public static void main(String[] args) throws Exception {
//Encryption
AES encr = new AES();
encr.setKey("KEY");
encr.setSalt("SALT");
encr.setup();
String message = "This is just an example";
System.out.println("Message : " + message);
byte[] code = encr.encrypt(message);
System.out.println("Encrypted Strinng : "+ new String(code, "UTF-8"));
//Decryption
AES dec = new AES();
dec.setKey("INCORRECT"); //<--- incorrect
dec.setSalt("SALT");
dec.setup();
System.out.println(dec.decryptString(code));
}
public synchronized void setKey(String key) throws UnsupportedEncodingException {
this.key = key.getBytes("UTF-8");
isPasswordAlreadySet = true;
}
public synchronized void setSalt(String salt) throws UnsupportedEncodingException {
this.salt = salt.getBytes("UTF-8");
}
public synchronized void setup() throws Exception {
MessageDigest digest = MessageDigest.getInstance("SHA-256");
digest.update(key);
digest.update(salt);
byte[] raw = digest.digest();
skeySpec = new SecretKeySpec(raw, "AES");
cipher = Cipher.getInstance("AES");
}
public synchronized byte[] encrypt(byte[] klartext) throws Exception {
cipher.init(Cipher.ENCRYPT_MODE, skeySpec);
byte[] encrypted = cipher.doFinal(klartext);
return encrypted;
}
public synchronized byte[] encrypt(String klartext) throws Exception{
return encrypt(klartext.getBytes("UTF-8"));
}
public synchronized byte[] decrypt(byte[] code) throws Exception {
cipher.init(Cipher.DECRYPT_MODE, skeySpec);
byte[] original = cipher.doFinal(code);
return original;
}
public synchronized double decryptDouble(byte[] code) throws Exception {
cipher.init(Cipher.DECRYPT_MODE, skeySpec);
byte[] original = cipher.doFinal(code);
return doubleFromBytes( original);
}
谢谢!
Frederik
Thank you! Frederik
推荐答案
填充是一项完善的检查。假设错误解密的数据是均匀分布的,那么对于每255个错误的密码,它只会被正确地填充PKCS5 / PKCS7大约1次。 (1/256 + 1/256 ^ 2 + 1/256 ^ 3 ...)
The padding is a fine sanity check. Assuming the incorrectly decrypted data is uniformly distributed, it will only appear to be correctly PKCS5/PKCS7 padded about 1 time for every 255 incorrect passwords. (1/256 + 1/256^2 + 1/256^3 ...)
所以它很有用,但这不是您应该依靠的东西-有效的将近8位消息摘要实际上不足以测试数据完整性。
So it's helpful, but it's not something you should rely on --- what is effectively an almost-8-bit message digest is not a sufficient test of data integrity.
还有一件事:如果攻击者可以反复更改密文并让您解密,(例如,存储在cookie中的加密数据)以及是否可以区分解密的数据引发错误填充错误和纯垃圾时的行为,然后他们可以通过填充Oracle攻击确定纯文本。
One more thing: If an attacker can repeatedly alter the ciphertext and get you to decrypt it, (an example might be encrypted data stored in a cookie) and if they can distinguish between your behavior when the decrypted data throws an exception for bad padding and when it is simply garbage, then they can determine the plaintext via a "padding oracle attack".
顺便说一句,如果您实际上想要您想要的行为,则可以使用 AES / CTR / NoPadding,它不需要确切的块大小,并且始终返回解密的字节[],无论键是否匹配。
By the way, if you actually want the behavior you expected, you can use "AES/CTR/NoPadding", which will not require an exact block size and will always return a decrypted byte[], whether or not the keys match.
这篇关于AES BadPaddingException的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!