3

I have a file (mp3) that i Encrypt, my intention is then to download this file to an android device and decrypt it, but during decryption i get an IOException:

java.io.IOException: last block incomplete in decryption

I am aware of the obvious security flaws in the following code, I'm just trying to get it to work first.

Any help on this is appreciated and I am quite a newcomer to coding in general so excuse me in advance if this is a stupid question!

Encryption class(Not done in Android, works):

public class EncryptFile {
public static void main(String args[]) {
    if (args.length < 1) {
        System.out.println("Usage: java EncryptFile <file name>");
        System.exit(-1);
    }
    try {
        File aesFile = new File("encodedfile.enc");
        FileInputStream fis;
        FileOutputStream fos;
        CipherInputStream cis;
         //Creation of Secret key
        String key = "mysecretkey";
        int length=key.length();
        if(length>16 && length!=16){
            key=key.substring(0, 15);
        }
        if(length<16 && length!=16){
            for(int i=0;i<16-length;i++){
                key=key+"0";
            }
        }
        SecretKeySpec secretKey = new SecretKeySpec(key.getBytes(),"AES");
         //Creation of Cipher objects
        Cipher encrypt =Cipher.getInstance("AES/CBC/PKCS5Padding");

        byte[] aByte = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};


            IvParameterSpec ivSpec = new IvParameterSpec(aByte);

        encrypt.init(Cipher.ENCRYPT_MODE, secretKey, ivSpec);
        try {
            fis = new FileInputStream(args[0]);
            cis = new CipherInputStream(fis,encrypt);
            // Write to the Encrypted file
            fos = new FileOutputStream(aesFile);
            byte[] b = new byte[8];
            int i = cis.read(b);
            while (i != -1) {
                fos.write(b, 0, i);
                i = cis.read(b);
            }
            fos.flush();
            fos.close();
            cis.close();
            fis.close();
        } catch(IOException err) {
            System.out.println("Cannot open file!");
            System.exit(-1);
        }
    } catch(Exception e){
        e.printStackTrace();
    }
}

}

Decryption (In Android device):

    public class DecryptFile {  
  public static File main(String args[], File encFile, Context context) { 
      for (int i = 0; i < args.length; i++) {
        Log.i("ARGS", args[i]);
    }
       try {  
            File aesFile = new File(args[0]);  

            aesFile= encFile;  
            Log.d("AESFILELENGTH", "aes length: " + aesFile.length());
            File aesFileBis = new File(context.getFilesDir(), args[0]);

            FileInputStream fis;  
            FileOutputStream fos;  
            CipherInputStream cis;  

 //Creation of Secret key  
            String key = "mysecretkey";  
            int length=key.length();  
            if(length>16 && length!=16){  
                 key=key.substring(0, 15);  
            }  
            if(length<16 && length!=16){  
                 for(int i=0;i<16-length;i++){  
                      key=key+"0";  
                 }  
            }  
            SecretKeySpec secretKey = new SecretKeySpec(key.getBytes(),"AES");  
             //Creation of Cipher objects  
            Cipher decrypt =Cipher.getInstance("AES/CBC/PKCS5Padding");  

            byte[] aByte = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};


            IvParameterSpec ivSpec = new IvParameterSpec(aByte);

            decrypt.init(Cipher.DECRYPT_MODE, secretKey, ivSpec);  

 // Open the Encrypted file  

            fis = new FileInputStream(aesFile);  

            cis = new CipherInputStream(fis, decrypt);  

            // Write to the Decrypted file  
            fos = new FileOutputStream(aesFileBis);  
            try {

                byte[] mByte = new byte[8];  
                int i = cis.read(mByte); 
                Log.i("MBYTE", "mbyte i: " + i);
                while (i != -1) {  
                    fos.write(mByte, 0, i);  
                    i = cis.read(mByte);  
                }  
            } catch (IOException e) {
                e.printStackTrace();
            }


            fos.flush();  
            fos.close();  
            cis.close();  
            fis.close(); 
            return aesFileBis;
       } catch(Exception e){  
            e.printStackTrace();  
       }
    return null;  
  }  
}
Pontus Backlund
  • 1,017
  • 1
  • 10
  • 17
  • possible duplicate of [How to handle "last block incomplete in decryption"](http://stackoverflow.com/questions/4598873/how-to-handle-last-block-incomplete-in-decryption) – Simon Oct 24 '13 at 15:14
  • 1
    Check the length of the non-Android encrypted file you are producing. Compare it with the length of the encrypted file you are reading in Android. The two lengths should, obviously, be the same. If they are not then you probably have a file transfer problem, not a decryption problem. – rossum Oct 25 '13 at 11:44
  • I checked the file length and the encrypted file is 2 bytes larger than the original file, but this is due to the padding right? I also did a byte[] mBytebase = Base64.encodeBase64(key.getBytes()); and used it in my SecretKeySpec based on the "duplicate". Nothing seems to help – Pontus Backlund Oct 28 '13 at 11:01
  • As you say, padding will ensure that the plain and encrypted files are different lengths. You need to check that the two **encrypted** files, on the non-Android and Android sides, are the same length. You need to ensure that the file transfer between the two systems is not messing up the data. – rossum Oct 29 '13 at 12:26
  • Ah right, sorry misunderstood the answer. Right now I'm putting the encrypted file in assets for testing, so the transfer is not the issue – Pontus Backlund Oct 30 '13 at 12:18

1 Answers1

7

Here is the code:

public class MainActivity extends Activity {

   @Override
   protected void onCreate(Bundle savedInstanceState) {
          super.onCreate(savedInstanceState);
          setContentView(R.layout.activity_main);

          Button encryptButton = (Button) findViewById(R.id.button1);
          Button DecryptButton = (Button) findViewById(R.id.button2);
          encryptButton.setOnClickListener(new OnClickListener() {

                 @Override
                 public void onClick(View v) {
                       // TODO Auto-generated method stub
                       try {
                              encrypt();
                       } catch (InvalidKeyException e) {
                              // TODO Auto-generated catch block
                              e.printStackTrace();
                       } catch (NoSuchAlgorithmException e) {
                              // TODO Auto-generated catch block
                              e.printStackTrace();
                       } catch (NoSuchPaddingException e) {
                              // TODO Auto-generated catch block
                              e.printStackTrace();
                       } catch (IOException e) {
                              // TODO Auto-generated catch block
                              e.printStackTrace();
                       }
                 }
          });

          DecryptButton.setOnClickListener(new OnClickListener() {

                 @Override
                 public void onClick(View v) {
                       // TODO Auto-generated method stub
                       try {
                              decrypt();
                       } catch (InvalidKeyException e) {
                              // TODO Auto-generated catch block
                              e.printStackTrace();
                       } catch (NoSuchAlgorithmException e) {
                              // TODO Auto-generated catch block
                              e.printStackTrace();
                       } catch (NoSuchPaddingException e) {
                              // TODO Auto-generated catch block
                              e.printStackTrace();
                       } catch (IOException e) {
                              // TODO Auto-generated catch block
                              e.printStackTrace();
                       }
                 }
          });

   }

   /**
    * Here is Both function for encrypt and decrypt file in Sdcard folder. we
    * can not lock folder but we can encrypt file using AES in Android, it may
    * help you.
    *
    * @throws IOException
    * @throws NoSuchAlgorithmException
    * @throws NoSuchPaddingException
    * @throws InvalidKeyException
    */

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

          // 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();
   }

   static void decrypt() throws IOException, NoSuchAlgorithmException,
                 NoSuchPaddingException, InvalidKeyException {

          File extStore = Environment.getExternalStorageDirectory();
          FileInputStream fis = new FileInputStream(extStore + "/encrypted");

          FileOutputStream fos = new FileOutputStream(extStore + "/decrypted");
          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();
   }

} 
user2342558
  • 5,567
  • 5
  • 33
  • 54
Hasan Masud
  • 982
  • 9
  • 17