3
votes

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?

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

   // 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)));
1
I'd suggest looking at the Java naming conventions..christopher
Was editting code continuously for finding error. Will take care. ThanksFrankenstein

1 Answers

3
votes

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 Cipher objects).

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.