1
votes

I am trying to write encrypt/decrypt methods for AES 256 CBC encryption using PKCS5Padding in java. I am currently trying to decrypt some encrypted text from another source which is Base64 encoded.

Code below: (This is just test data so it isn't sensitive)

// JUnit Test
    @Test
    public void testDecrypt() {
        String cipherText = "rrAwZQCAIj19XauZE6tQEg/HQuWB7gw+1uVO0hylyWyCSJo/y7uB6Xj4BRVi+a3qY9GQ/ahjPdUF/kSHptt6QttkvQf89JS13Mo3mRAnaDK/8uoRur8TDuKzLtCSjaMAg72LqObx04+yLd9hI2krtCaWd2saCLP/cWvTQ9oc1xQ=";
        String iv = "o1clHzdEkUV4sFj72VwDFQ==";
        String syncKey = "gbh7teqqcgyzd65svjgibd7tqy";

        SecretKeySpec key = new SecretKeySpec(convertFromBase32(syncKey), "AES");
        byte[] cipherBytes = convertFromBase64(cipherText);
        System.out.println(cipherBytes.length);
        Encrypted d = Crypto.decrypt(new Encrypted(cipherBytes, key,
                convertFromBase64(iv)));
        String decryptedText = new String(d.getCipherText());
    }

// Actual Code
public static Encrypted decrypt(Encrypted encrypted) {
        // Initialize the Cipher
        Cipher cipher = null;
        IvParameterSpec ivParam = new IvParameterSpec(
                encrypted.getInitializationVector());
        try {
            cipher = Cipher.getInstance(TRANSFORMATION);
            cipher.init(Cipher.DECRYPT_MODE, encrypted.getSymmetricKey(),
                    ivParam);
        } catch (NoSuchAlgorithmException e1) {
            e1.printStackTrace();
        } catch (NoSuchPaddingException e1) {
            e1.printStackTrace();
        } catch (InvalidKeyException e) {
            e.printStackTrace();
        } catch (InvalidAlgorithmParameterException e) {
            e.printStackTrace();
        }

        byte[] outputBytes = cryptCommon(cipher, encrypted.getCipherText());
        Encrypted decrypted = new Encrypted(outputBytes,
                encrypted.getSymmetricKey(), cipher.getIV());
        return decrypted;
    }

    private static byte[] cryptCommon(Cipher cipher, byte[] inputBytes) {
        byte[] outputBytes = null;
        try {
            outputBytes = cipher.doFinal(inputBytes);
        } catch (IllegalBlockSizeException e) {
            e.printStackTrace();
        } catch (BadPaddingException e) {
            e.printStackTrace();
        }
        return outputBytes;
    }

The I've check the lengths of the byte[] after decoding from Base64 and they are of length divisible by block size (128 bytes for a 16 byte block size).

Here is the stack trace I'm getting:

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 com.mozilla.android.sync.Crypto.cryptCommon(Crypto.java:77)
    at com.mozilla.android.sync.Crypto.decrypt(Crypto.java:69)
    at com.mozilla.android.sync.test.CryptoTests.testDecrypt(CryptoTests.java:71)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
    at java.lang.reflect.Method.invoke(Method.java:597)
    at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:44)
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15)
    at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:41)
    at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:20)
    at org.junit.runners.BlockJUnit4ClassRunner.runNotIgnored(BlockJUnit4ClassRunner.java:79)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:71)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:49)
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:193)
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:52)
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:191)
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:42)
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:184)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:236)
    at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50)
    at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)

Any help is much appreciated. Thanks!

1
What is the value of TRANSFORMATION?Paŭlo Ebermann
Sorry, TRANSFORMATION = "AES/CBC/PKCS5Padding"jvoll

1 Answers

0
votes

In cryptography everything has to be exact. Have you set both encrypt and decrypt methods to PKCS5 padding? Have you checked that the bytes produced by the encryption method exactly match the bytes consumed by the decryption function?

Have you checked that the two keys exactly match, byte for byte? You are using Base32 at one point, and that is a bit unusual.

I would suggest breaking down your test into much smaller pieces, so you can explicitly check the match for every parameter for both encryption and decryption. Make sure that you check each parameter as a byte array, i.e. not involving conversion to or from Base64 or whatever.