Java AES BadPaddingException

Java AES BadPaddingException,java,aes,Java,Aes,如果我使用错误的密钥或错误的salt进行解密,则会引发BadPaddingException。 我希望返回不正确的字符串。 doFinal()导致decrypt方法中出现异常 信息:这只是一个示例 取消模板:“崮ÙΩ”SåF?V®S.k˚HèF∫ÙÕ Exception in thread "main" javax.crypto.BadPaddingException: Given final block not properly padded at com.sun.crypto.pro

如果我使用错误的密钥或错误的salt进行解密,则会引发BadPaddingException。 我希望返回不正确的字符串。 doFinal()导致decrypt方法中出现异常

信息:
这只是一个示例

取消模板:
“崮ÙΩ”SåF?V®S.k˚HèF∫ÙÕ

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)

publicstaticvoidmain(字符串[]args)引发异常{
//加密
AES encr=新AES();
附件设置键(“键”);
附件固定盐(“盐”);
encr.setup();
String message=“这只是一个示例”;
System.out.println(“Message:+Message”);
字节[]代码=加密(消息);
System.out.println(“加密字符串:+新字符串(代码,“UTF-8”);
//解密
AES dec=新AES();

dec.setKey(“不正确”);//您应该将AES与隐式填充声明一起使用(请参阅),或者强制加密/解密数据的长度(以字节为单位)为16的倍数


此外,默认情况下,java使用ECB模式,这可能是真正不安全的,具体取决于您使用的数据类型,您可能应该使用CBC模式。

填充是一种良好的健全性检查。假设解密错误的数据是均匀分布的,则每255 incor只会正确填充一次PKCS5/PKCS7rect密码。(1/256+1/256^2+1/256^3…)

因此,它是有帮助的,但它不是您应该依赖的东西——实际上,几乎8位的消息摘要并不能充分测试数据完整性

还有一件事:如果攻击者可以反复修改密文并让您解密(例如,存储在cookie中的加密数据),并且如果他们能够区分您在解密数据引发错误填充异常时的行为和仅是垃圾时的行为,那么他们可以通过“甲骨文攻击”


顺便说一句,如果您确实想要预期的行为,您可以使用“AES/CTR/NoPadding”,它不需要精确的块大小,并且无论密钥是否匹配,都将始终返回解密的字节[]。

SecretKeySpec以独立于提供程序的方式指定密钥


我已将密码的initline更改为:cipher=cipher.getInstance(“AES/CBC/PKCS5Padding”);但引发了相同的异常..为了获得正确的长度,我使用了SHA哈希-我认为这应该足够了。此外,我第一次使用setup()时方法没有例外thrown@Frederik:您必须了解填充的工作原理:填充模式将在加密前向纯文本数据附加一些填充内容。解密后,此填充将再次剥离。但要知道要剥离多少字节,填充的内容很重要,如果使用错误的密钥解密,则t最后的一些字节不是填充算法添加的格式之一。如前所述,使用
NoPadding
,但您必须确保数据长度是块长度的倍数。对于
PKCS5Padding
,它与DES CBC中描述的格式相同。抱歉,我仍然不明白这个问题。我的加密数据的长度是32。块长度是16,不是吗?如果我继续,让密码在长度无效时抛出异常,这是安全漏洞吗?
     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);
    }