1

I have a test function that returns a byte[] in one Java class, FirstClass:

public static byte[] testA(){
        CipherClass crypto = new CipherClass();
        byte[] a = crypto.encrypt("helloWorld");
        return a;
    }

Where CipherClass contains my java.crypto.Cipher methods to encrypt and decrypt inputs.

In another Java class, SecondClass, I instantiate my previous FirstClass and call its testA() method which I save to a byte[] variable and then try to decrypt it:

FirstClass fc = new FirstClass();
byte[] b = fc.testA();
System.out.println(crypto.decrypt(b)); //Outputs BadPaddingError

Why does encrypting a String in one Java file and then passing the resulting byte[] into another Java file to decrypt it causes a BadPaddingError?

What can be done to fix a way around this?

Why does the Cipher only work if both encryption and decryption are in the same class as follows?:

CipherClass crypto = new CipherClass();
byte[] a = crypto.encrypt("helloWorld"); //Outputs [B@5474c6c
byte[] b = a;
System.out.println(crypto.decrypt(b));  //Outputs "helloWorld"

EDIT: My CipherClass code as requested below.

SecretKey and IVParameterSpec generator:

public List<KeyGenerator> getKeyGenerator(){

        List<KeyGenerator> list = new ArrayList<KeyGenerator>();
        KeyGenerator keyGenerator;
        int keyBitSize = 128;

        try 
        {
            SecureRandom secureRandom = new SecureRandom();
            keyGenerator = KeyGenerator.getInstance("AES");
            keyGenerator.init(keyBitSize, secureRandom);

            list.add(keyGenerator);

            return list;
        } 
        catch (NoSuchAlgorithmException e)
        {
            e.printStackTrace();
        }

        return list;
    }

    public List<SecretKey> getSecretKey(List<KeyGenerator> keygen) {

        List<SecretKey> list = new ArrayList<SecretKey>();
        KeyGenerator keyGenerator;
        SecretKey secretKey;

        keyGenerator = keygen.get(0);
        secretKey = keyGenerator.generateKey();

        list.add(secretKey);

        return list;
    }

    public List<IvParameterSpec> getIvSpec(List<SecretKey> secretKey) {

        List<IvParameterSpec> list = new ArrayList<IvParameterSpec>();
        Cipher cipher;

        byte[] iv;

        try 
        {
            cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
            iv = new byte[cipher.getBlockSize()];           
            IvParameterSpec ivSpec = new IvParameterSpec(iv);

            list.add(ivSpec);
        } 

        catch (NoSuchAlgorithmException e) 
        {       
            e.printStackTrace();
        } 

        catch (NoSuchPaddingException e) 
        {
            e.printStackTrace();
        }

        return list;
    }

    List<KeyGenerator> kgList = getKeyGenerator();
    List<SecretKey> skList = getSecretKey(kgList); //skList.get(0) is the SecretKey
    List<IvParameterSpec> ivList = getIvSpec(skList); //ivList.get(0) is the IVParameterSpec

My encrypt() method:

    public byte[] encrypt(String inputStr) {

            Cipher cipher;

            SecretKey secretKey = skList.get(0);
            IvParameterSpec ivSpec = ivList.get(0);

            byte[] plainText;
            byte[] cipherText = new byte[]{};       

            try 
            {
                cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");

                try 
                {
                    secretKey = skList.get(0);
                    ivSpec = ivList.get(0);
                    cipher.init(Cipher.ENCRYPT_MODE, secretKey, ivSpec);                

                    try 
                    {
                        plainText = inputStr.getBytes("UTF-8");

                        cipherText = cipher.doFinal(plainText);

                        return cipherText;
                    }

                    catch (IllegalBlockSizeException e) 
                    {
                        e.printStackTrace();
                    } 

                    catch (BadPaddingException e) 
                    {
                        e.printStackTrace();
                    }

                    catch (UnsupportedEncodingException e) 
                    {
                        e.printStackTrace();
                    }                
                } 

                catch (InvalidKeyException e) 
                {
                    e.printStackTrace();
                }

                catch (InvalidAlgorithmParameterException e1) 
                {
                    e1.printStackTrace();
                }
            } 

            catch (NoSuchAlgorithmException e) 
            {       
                e.printStackTrace();
            } 

            catch (NoSuchPaddingException e) 
            {
                e.printStackTrace();
            }

            return cipherText;
        }

My decrypt() method:

public String decrypt(byte[] cipherText){
        Cipher cipherDe;

        SecretKey secretKey = skList.get(0);
        IvParameterSpec ivSpec = ivList.get(0);

        byte[] deciByte;

        String decryptText = "";

        try 
        {
            cipherDe = Cipher.getInstance("AES/CBC/PKCS5Padding");

            try 
            {           
                secretKey = skList.get(0);
                ivSpec = ivList.get(0);
                cipherDe.init(Cipher.DECRYPT_MODE, secretKey, ivSpec);              

                try 
                {               
                    //De-cryption
                    deciByte = cipherDe.doFinal(cipherText);

                    decryptText = new String(deciByte);

                    return decryptText;
                }

                catch (IllegalBlockSizeException e) 
                {
                    e.printStackTrace();
                } 

                catch (BadPaddingException e) 
                {
                    e.printStackTrace();
                } 
            } 

            catch (InvalidKeyException e) 
            {
                e.printStackTrace();
            }

            //De-cryption
            catch (InvalidAlgorithmParameterException e1) 
            {
                e1.printStackTrace();
            }
        } 

        catch (NoSuchAlgorithmException e) 
        {       
            e.printStackTrace();
        } 

        catch (NoSuchPaddingException e) 
        {
            e.printStackTrace();
        }

        return decryptText;
    }
Jae Bin
  • 49
  • 1
  • 2
  • 10
  • In `FirstClass fc = new FirstClass(); byte[] b = fc.testA(); System.out.println(crypto.decrypt(b)); //Outputs BadPaddingError` - what is `crypto` defined as? – Scary Wombat Oct 23 '18 at 00:46
  • 1
    That's not what causes a BadPaddingError. What's causing it is a bug in your code, but you haven't shown your code so we're left to guess. – President James K. Polk Oct 23 '18 at 00:47
  • @JamesKPolk Updated. – Jae Bin Oct 23 '18 at 00:54
  • On your last question you were told that not generating random IVs for each encryption operation to be stored with the ciphertext is a security issue, but you ignored the advice (as seen in your code). I'm not trying to be mean or rude, just genuinely curious, why did you ignore that advice? Was it not made clear enough or obvious enough? I'm trying to figure out for my own understanding. – Luke Joshua Park Oct 23 '18 at 01:07
  • @LukeJoshuaPark I was only following this online tutorial: http://tutorials.jenkov.com/java-cryptography/cipher.html since I'm trying to learn how to do encryption/decryption in Java with no previous experience. Hence, all the various tests I've been doing. – Jae Bin Oct 23 '18 at 01:15
  • Hmmm okay. Well it's really important that you generate a new IV for each encryption operation. You really should change your code to do that. What is the point in using encryption if it isn't actually secure right?! – Luke Joshua Park Oct 23 '18 at 01:16
  • @LukeJoshuaPark How should a new IV be generated each time? According to this: https://stackoverflow.com/questions/26369350/aes-256-decryption-is-iv-safe-to-share IVs can be publicly shared info as long as the secret key is private. – Jae Bin Oct 23 '18 at 01:21
  • Yep that is 100% correct. But they must also be unpredictable. Ergo, if you don't generate a random new one each time you encrypt, then you've introduced a security vulnerability. IVs aren't secret values, they just have to be unpredictable. Yours are not. – Luke Joshua Park Oct 23 '18 at 01:24
  • don't you accidentally create a few instance of the CipherClass effectively generating different iv and keys? – gusto2 Oct 23 '18 at 06:18
  • You should use the same key for decrypt as you used for encrypting. The same goes for IV. It looks like you are generating a new key each time you instantiate a CipherClass .. If you decrypt with wrong key you usually will end up with a padding error .. – Ebbe M. Pedersen Oct 23 '18 at 07:58

0 Answers0