Link to home
Start Free TrialLog in
Avatar of JohnOAI
JohnOAI

asked on

javax.crypto.BadPaddingException: Given final block not properly padded

javax.crypto.BadPaddingException: Given final block not properly padded

I am currently working on an encryption and decryption utility application in Java using the Java Cryptography Extension (JCE).
I have successfully encrypted and decrypted data with the DES encryption algorithm, confirming that I know the steps involved and can access the library/API methods correctly and in the right sequence.
I would like to be able to save the encrypted text (ciphertext), read it later, decrypt it and get the plain text. To this end, I encoded the ciphertext in base64 format to make it human readable.
Before decrypting the base64 encoded ciphertext, I decode it (base64 decoding) to get the original ciphertext back. I have encountered the following problems.

Error 1.      
When I attempted to decrypt with desCipher.doFinal(input), I got the following error javax.crypto.IllegalBlockSizeException: Input length must be multiple of 8 when decrypting with padded cipher
at com.sun.crypto.provider.CipherCore.doFinal(CipherCore.java:749)

As a solution to Error 1 above, I wrote a method with takes a byte of data as input and pads it into a multiple of 8 using the PKCS5Padding algorithm. After adopting this new method, I know longer get Error 1. I now get the following error.

Error 2.
javax.crypto.BadPaddingException: Given final block not properly padded
      at com.sun.crypto.provider.CipherCore.doFinal(CipherCore.java:810)
      at com.sun.crypto.provider.CipherCore.doFinal(CipherCore.java:675)
      at com.sun.crypto.provider.DESCipher.engineDoFinal(DESCipher.java:314)
      at javax.crypto.Cipher.doFinal(Cipher.java:2087)
      at com.nvl.utils.DESCrypt.decrypt(DESCrypt.java:169)

It becomes obvious that the error is no longer the number of bytes of data, but the manner in which the contents have been padded into the correct length.
Find below the contents of my padding method

byte[] padInputToMultipleOf8(byte[] inputBytes) {
        int size = (inputBytes.length / 8 ) + ( (inputBytes.length % 8 == 0) ? 0 : 1 ) ;
        int newLength = size * 8;
        int lengthOfPad = newLength - inputBytes.length;
        
        // set the pad character according to PKCS5Padding algorithm
        byte padByte = 0;
        switch (lengthOfPad) {
            case 7 : padByte = (byte) 0x07; break;
            case 6 : padByte = (byte) 0x06; break;
            case 5 : padByte = (byte) 0x05; break;
            case 4 : padByte = (byte) 0x04; break;         
            case 3 : padByte = (byte) 0x03; break;        
            case 2 : padByte = (byte) 0x02; break;      
            case 1 : padByte = (byte) 0x01; break;               
        }
        ByteBuffer byteBuffer = ByteBuffer.allocate(newLength);
        byteBuffer.put(inputBytes);
        byte[] paddedUp = new byte[size * 8];
        
        for (int j=0;j<inputBytes.length;j++) {
            paddedUp[j]=byteBuffer.get(j);
        }
        for (int k=inputBytes.length;k<paddedUp.length;k++) {
            paddedUp[k]=padByte;
        }        
        return paddedUp;
    }

Open in new window


Additional useful information
Key generator was instantiated with code below:
keyGenerator = KeyGenerator.getInstance("DES");

Open in new window

Cipher was instantiated with code below:
desCipher = Cipher.getInstance("DES/ECB/PKCS5Padding");

Open in new window

Bytes were obtained with code below :
inBytes = inText.getBytes("UTF8");

Open in new window

Decryption was done with code lines below:
               desCipher.init(Cipher.DECRYPT_MODE, originalDESKey);
               byte[] inputInBase64 = inText.getBytes("UTF8");
               inBytes = Base64.decodeBase64(inputInBase64);
               // @todo: pad the input to a multiple of 8 here...
               byte[] paddedInput = padInputToMultipleOf8(inBytes);
			   // Decrypt the text, with Base64 encoding removed
               outBytes = desCipher.doFinal(paddedInput);

Open in new window


I would appreciate any help in resolving this PKCS5Padding padding errors as it has become impossible to move forward on my current project without resolving it. Many thanks in advance.

John OAI
Avatar of CEHJ
CEHJ
Flag of United Kingdom of Great Britain and Northern Ireland image

Why are you attempting to do your own padding?
Avatar of JohnOAI
JohnOAI

ASKER

I asked for a solution CEHJ, not a question.
Unsubscribing ..
ASKER CERTIFIED SOLUTION
Avatar of mccarl
mccarl
Flag of Australia image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of JohnOAI

ASKER

Thanks a lot mccarl, especially for bothering to help! You have a point, and I appreciate that. I looked at the base64 encoding/decoding potential bug, before, but now I will look at that in more detail and provide more details if that doesn't solve the problem.

However, I was of the view, and I remain so, that even if there is a problem with base64 encoding/decoding, all I would expect is for the decryption to return gibberish, and not to fail with a bad padding exception. That is the main source of confusion.

Thanks for your help so far!
Avatar of JohnOAI

ASKER

mccarl,

I compared the contents of the two arrays as you suggested and I found the bug, as the contents should match but they did not.

Thank you for your invaluable advice. Now I can move on to other pressing tasks.
I asked for a solution CEHJ, not a question.

Hmm . . . you got away with murder there. And you probably threw away more than you think you have gained from this question - although your dice luckily rolled in your favour with mccarl this time. :/