AES Decryption ERROR: android pad block corrupted

4.8k views Asked by At

I've looked around stack to find an answer to my problem and yet nothing did work. What im trying to achive is to encrypte XML file that is downloaded in ASYNCtask and later on decrypt it.

What I've already checked:

-Generated key is the same when encrypring and decrypting and saved in sharedpreferenced with Base64.

-IV is the same since at the moment its in static variable for testing purposes.

-Cipher is set to AES/CBC/PKCS5Padding

-Key is set to AES

The error appear in decryptXml() at line:
byte[] decrypted = cipher.doFinal(bytes);

Im all out of ideas and nothing seems to work. I hope some of u can find mistake in my code. Thanks for help!

CODE:

genetateKey()

    SharedPreferences sharedPreferences = context.getSharedPreferences(GENERATED_KEY, Context.MODE_PRIVATE);
    String keyStr = sharedPreferences.getString(GENERATED_KEY, null);
    if (keyStr == null) {
        final int outputKeyLength = 128;
        SecureRandom secureRandom = new SecureRandom();
        KeyGenerator keyGenerator = KeyGenerator.getInstance("AES");
        keyGenerator.init(outputKeyLength, secureRandom);
        SecretKey key = keyGenerator.generateKey();
        byte[] bytes = key.getEncoded();
        keyStr = Base64.encodeToString(bytes, Base64.DEFAULT);
        SharedPreferences.Editor editor = sharedPreferences.edit();
        editor.putString(GENERATED_KEY, keyStr);
        editor.commit();
        return key.toString();
    }  else {
        return keyStr;
    }

XML encryption:

    connection = (HttpURLConnection) url.openConnection();
    connection.connect();
    SecretKey secretKey = getSecretKey(context);
    SecretKeySpec secretKeySpec = new SecretKeySpec(secretKey.getEncoded(), "AES");
    Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
    spec = generateIv(cipher.getBlockSize());
    cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec, spec);

    input = connection.getInputStream();
    cis = new CipherInputStream(input, cipher);

    String FILEPATH = context.getFilesDir().getParentFile().getPath();
    File file = new File(FILEPATH, "/download/" + id + "/");
       if (!file.exists()) {
    file.mkdirs();
    }

    xmlFile = new File(FILEPATH + "/download/" + id + "/", "xmldata.xml");
    output = new FileOutputStream(xmlFile);
    cos = new CipherOutputStream(output, cipher);
    byte data[] = new byte[4096];
    int count;
    while ((count = cis.read(data)) != -1) {
       if (isCancelled()) throw new TaskCanceledException();
          cos.write(data, 0, count);
          progress = -1;
          publishProgress();
    }
    if (isCancelled()) throw new TaskCanceledException();

Decryption:

public String decryptXml() {
    String data = null;
    File file = new File(context.getFilesDir().getParentFile().getPath() + "/download/" + id + "/xmldata.xml");
    int size = (int) file.length();
    byte[] bytes = new byte[size];
 try {
        SecretKeySpec secretKeySpec = new SecretKeySpec(getSecretKey(context).getEncoded(), "AES");
        Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
        cipher.init(Cipher.DECRYPT_MODE, secretKeySpec, DownloadBookAsyncTask.spec);
        BufferedInputStream bis = new BufferedInputStream(new FileInputStream(file));
        bis.read(bytes, 0, bytes.length);
        bis.close();
        byte[] decrypted = cipher.doFinal(bytes);
    }

getSecretKey():

public SecretKey getSecretKey(Context context){
    SharedPreferences sharedPreferences = context.getSharedPreferences(DashboardFragment.GENERATED_KEY, Context.MODE_PRIVATE);
    String stringKey = sharedPreferences.getString(DashboardFragment.GENERATED_KEY, null);
    byte[] encodedKey = Base64.decode(stringKey, Base64.DEFAULT);
    return new SecretKeySpec(encodedKey, 0, encodedKey.length, "AES");
}

EDIT

Adding IV generator method

public AlgorithmParameterSpec generateIv(int size) throws NoSuchAlgorithmException {
    AlgorithmParameterSpec ivspec;
    byte[] iv = new byte[size];
    new SecureRandom().nextBytes(iv);
    ivspec = new IvParameterSpec(iv);
    return ivspec;
}
2

There are 2 answers

1
JakubW On BEST ANSWER

Ok I've found the problem. The reason my code did not work was that I have used CipherInputStream in my encryption and I shouldn't have done that. I have also redo whole decryption method which looks like this now:

  byte[] wholeFileByte = null;
    Cipher cipher = Cipher.getInstance("AES/CBC/PKCS7Padding");
    cipher.init(Cipher.DECRYPT_MODE, key, DownloadBookAsyncTask.ivspec);
    File file = new File(context.getFilesDir().getParentFile().getPath() + "/download/" + id + "/xmldata.xml");
    FileInputStream fis = new FileInputStream(file);
    ByteArrayOutputStream bos = new ByteArrayOutputStream();
    CipherInputStream cis = new CipherInputStream(fis, cipher);
    byte data[] = new byte[4096];
    int count;
    while ((count = cis.read(data)) != -1) {
        bos.write(data, 0, count);
    }

    if(cis != null)
        cis.close();
    if(bos != null)
        bos.close();
    if(fis != null)
        fis.close();

    wholeFileByte = bos.toByteArray();
    String kk = new String(wholeFileByte, "UTF-8");

I think other mistake that I made was that I used doFinal in the decryption even tho the Cipher did the decryption already and that was source of some of my errors.

Thanks to @GariBN because u put me in right tracks and will upvote you when my rep allow me to :)

5
Gari BN On

You create IV to encrypt the plaintext. I'm not sure that you use the same IV in order to decrypt the ciphertext.

Usually, you want to concatenate the IV to the ciphertext, and when decrypting, read it (the first 16 bytes), and then decrypt all the other bytes (the ciphertext) with cipher that was initialized with the IV used for the encryption.

For example, if you encrypt with:

cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec, spec);

First, try to decrypt (right later) with:

cipher.init(Cipher.DECRYPT_MODE, secretKeySpec, spec);
cipher.doFinal(bytes)

If you succeed, then the problem is probably because inappropriate IV, and you can fix it easily.