Android decryption: Error while finalizing cipher
Asked Answered
X

0

3

I am using Android to encrypt and encrypt images sent between apps.

The encryption works well but when the file arrives at the destination it will not decrypt. Now I have copied the file at the destination app and decrypted it successfully using 3rd-party software.

The error I get is:"Error while finalizing cipher" at CipherInputStream (CipherInputStream.java:107) caused by IllegalBlockSizeException.

The encryption & decryption code is below:

public static String encrypt(String plainFile, String encryptedFile) throws    IOException, NoSuchAlgorithmException,
NoSuchPaddingException, InvalidKeyException {
    // Here you read the cleartext.
    File extStore = Environment.getExternalStorageDirectory();
    FileInputStream fis = new FileInputStream(plainFile);
    // This stream write the encrypted text. This stream will be wrapped by
    // another stream.
    FileOutputStream fos = new FileOutputStream(encryptedFile);

    // Length is 16 byte
    SecretKeySpec sks = new SecretKeySpec("MyDifficultPassw".getBytes(), "AES");
    // Create cipher
    Cipher cipher = Cipher.getInstance("AES");
    cipher.init(Cipher.ENCRYPT_MODE, sks);
    // Wrap the output stream
    CipherOutputStream cos = new CipherOutputStream(fos, cipher);
    // Write bytes
    int b;
    byte[] d = new byte[8];
    while ((b = fis.read(d)) != -1) {
        cos.write(d, 0, b);
    }
    // Flush and close streams.
    cos.flush();
    cos.close();
    fis.close();

    return encryptedFile;
}   

static String decrypt(String plainFile, String encryptedFile) throws IOException, NoSuchAlgorithmException,
NoSuchPaddingException, InvalidKeyException {

    File encFile=new File(encryptedFile);
    FileInputStream fis = new FileInputStream(encFile);

    FileOutputStream fos = new FileOutputStream(plainFile);
    SecretKeySpec sks = new SecretKeySpec("MyDifficultPassw".getBytes(),
              "AES");
    Cipher cipher = Cipher.getInstance("AES");
    cipher.init(Cipher.DECRYPT_MODE, sks);
    CipherInputStream cis = new CipherInputStream(fis, cipher);
    int b;
    byte[] d = new byte[8];
    while ((b = cis.read(d)) != -1) {
        fos.write(d, 0, b);
    }
    fos.flush();
    fos.close();
    cis.close();

    return plainFile;
}    

Any ideas? Thanks!

Ronan

Update: The received encrypted file is consistently 1 byte smaller that the original file which seems to be generating the error. The error re block size is triggered at the code line while ((b = fis.read(d)) != -1) { in the decrypt function.

Update: Thanks for the feedback. The ultimate solution is as defined at last block incomplete with CipherInputStream/CipherOutputStream, even with padding AES/CBC/PKCS5Padding

Ronan

Xmas answered 17/10, 2014 at 13:30 Comment(4)
Works for me. One way to avoid surprises is to avoid defaults. You are are using default values for the mode and padding of the cipher transformation. There is no guarantee that different platforms will have the same default. There really is no reason or benefit to using defaults.Scrap
Thanks @GregS - it appears the encrypted file is 1 byte smaller than the unencrypted file. I have tried using Cipher.getInstance("AES/ECB/PKCS5Padding") to no avail. The code falls at while ((b = fis.read(d)) != -1) { in the decrypt function.Xmas
You should use a buffer much larger than 8 bytes. Try 8192. NB flush() before close() is redundant. There's no particular reason why the ciphertext should be the same length as the plaintext.Intimist
I think that if your encrypted file is shorter than your plaintext then something has happened during transit, e.g. you've transferred it as text and some "line feed" encoding has been altered (Android is a linux system).Deign

© 2022 - 2024 — McMap. All rights reserved.