javax.crypto.BadPaddingException:解密时给定的最终块未正确填充错误

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/20297621/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-13 00:55:46  来源:igfitidea点击:

javax.crypto.BadPaddingException: Given final block not properly padded error while decryption

javaencryption

提问by Frankenstein

I am doing encryption and decryption of data as follows but getting error

我正在按如下方式对数据进行加密和解密,但出现错误

protected Cipher aes_Gen_with_Key(byte[] key)
    {
        Cipher cipher=null;
        try
        {
        byte[] key_hash = (key).toString().getBytes("UTF-8");
        key_hash = Arrays.copyOf(key_hash, 32); // use only first 256 bit
        SecretKeySpec secretKeySpec = new SecretKeySpec(key_hash, "AES"); 
        cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
        cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec);

        } catch (Exception e) {
            System.out.println("Error Occured");
        }
        return cipher;
    }

    protected Cipher aes_Dec_with_Key(byte[] key,byte[] iv)
    {
        Cipher cipher=null;
        try
        {
        byte[] key_hash = (key).toString().getBytes("UTF-8");
        key_hash = Arrays.copyOf(key_hash, 32); // use only first 256 bit
        SecretKeySpec secretKeySpec = new SecretKeySpec(key_hash, "AES");
        cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
        cipher.init(Cipher.DECRYPT_MODE,secretKeySpec,new IvParameterSpec(iv));
        }
        catch (Exception e) {
            System.out.println(e);
        }

        return cipher;
    }

With above 2 functions I am getting ciphers with which I am doing encryption and decryption, but getting javax.crypto.BadPaddingException: Given final block not properly padded as error. Length of decryption byte array is 752 and IV at decryption is 16 byte long. Can any one suggest?

通过以上 2 个函数,我得到了用于加密和解密的密码,但是得到 javax.crypto.BadPaddingException: Given final block not正确填充为错误。解密字节数组的长度为 752,解密时的 IV 长度为 16 字节。任何人都可以建议吗?

Here are few more relevant code blocks. Apologies for invalid use java naming conventions

这里有一些更相关的代码块。为无效使用java命名约定道歉

   // Key Class
    import java.io.Serializable;
    @SuppressWarnings("serial")
    public class Key implements Serializable{
        byte[] gsmodp_hash=null;
        byte[] iv_pass=null;
        byte[] Nonce_Enc=null;
        byte[] iv_non=null;
        public Key() {
        }

        public Key(byte[] gsmodp_hash,byte[] iv_pass,byte[] Nonce_Enc,byte[] iv_non) {
            this.gsmodp_hash=gsmodp_hash;
            this.iv_pass=iv_pass;
            this.Nonce_Enc=Nonce_Enc;
            this.iv_non=iv_non;
        }
    }

    // Client side code

            JSONObject auth_step_obj=new JSONObject();
            try {

                BigInteger gsmodp=get_modu_frm_server(receivePacket);
                BigInteger R2=get_R2_frm_server(receivePacket);
                BigInteger N2=get_N2_frm_server(receivePacket);
                N2=crypto.dec_NonceG(N2);
                BigInteger a=crypto.get_RandLong();
                BigInteger gamodp= crypto.dh_GenerationG(a, crypto.g, crypto.p);
                BigInteger key=crypto.dh_GenerationG(a, gsmodp, crypto.p);

                // Got hash of g^abmodp

                byte[] dhkey=crypto.sha256G(key.toString());
                key=null;
                //Mixing passwords

                SecretKey secretkey=(SecretKey) userCredentials.get("password");
                byte[] mixed_hash=crypto.passwordMixerG(R2, secretkey.getEncoded());

                //Working Fine Till now
                // Getting Cipher for encrypting gsmodp using password and nonce
                Cipher cipher_password=crypto.aes_Gen_with_Key(mixed_hash);
                Cipher cipher_key=crypto.aes_Gen_with_Key(dhkey);

                // Generating quantities for JSON Object        
                byte[] gsmodp_hash=cipher_password.doFinal(gamodp.toString().getBytes());
                byte[] gsmodp_hash_iv=cipher_password.getIV();
                byte[] nonce_enc=cipher_key.doFinal(N2.toString().getBytes());
                byte[] nonce_enc_iv=cipher_key.getIV();
                Key authetication_parameters=new Key(gsmodp_hash,gsmodp_hash_iv,nonce_enc,nonce_enc_iv);
                auth_step_obj.put("obj",authetication_parameters);

            } catch (Exception e) {
                // TODO Auto-generated catch block
                System.out.println("Hi:sec_DH_Step");
            } 
            // This sends JSONObject to calling method which generates UDP packet and sends to server 
            return auth_step_obj;
        }

    // Server side code
    // Once packet received on server following happens
    ds.receive(receivePacket);
    SecretKey userKey=cryptoObj.get_from_KeyStoreG(user_name);
    // Adding R2 and userKey byte by byte
    byte[] mixed_hash=cryptoObj.passwordMixerG(R2, userKey.getEncoded());
    JSONObject authentication_nonce=new JSONObject();
    authentication_nonce=cryptoObj.readRecievedPacket(receivePacket);
    Key obj=(Key)authentication_nonce.get("obj");
    Cipher cipher=cryptoObj.aes_Dec_with_Key(mixed_hash,obj.iv_pass);
    // I am getting error on do final
    System.out.println(new String(cipher.doFinal(obj.gsmodp_hash)));

采纳答案by Duncan Jones

The code you presented works just fine. The error must lie in the code you haven't shared with us (i.e. the code that actually uses the Cipherobjects).

您提供的代码工作正常。错误一定在于您没有与我们共享的代码(即实际使用Cipher对象的代码)。

I wrote the code below to test your question code:

我写了下面的代码来测试你的问题代码:

public static void main(String[] args) throws Exception {

  Random random = new Random();
  byte[] key = new byte[32];
  random.nextBytes(key);

  byte[] plaintext = new byte[100];
  random.nextBytes(plaintext);

  Cipher enc = aes_Gen_with_Key(key);

  byte[] ciphertext = enc.doFinal(plaintext);
  byte[] iv = enc.getIV();

  Cipher dec = aes_Dec_with_Key(key, iv);

  byte[] recoveredPlaintext = dec.doFinal(ciphertext);

  System.out.println(Arrays.equals(plaintext, recoveredPlaintext));    
}

Note, I made your two methods static. You should do the same, as they don't use any instance variables.

请注意,我将您的两个方法设为静态。您应该这样做,因为它们不使用任何实例变量。