0

I'm having a problem to encode and decode a file with the AES algorithm. I'm recording audio with android and encrypting the recorded file, sent to another app via webservice and another app, the file is decrypted. The key is also sent and arrives normally.

The problem is that, to decipher the file with the key that amounted, the file appears corrupted when open with the android player and VLC Media Player.

Recalling that the unencrypted file reaches the other side with no problem and the key.

The key is a string of 32 characters randomly generated for each file recorded. Below is the class that encrypts and decrypts files.

The format is .3 gp. I am using android only formed as mp4 and 3gp.

What to do in this situation?

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;

import javax.crypto.Cipher;
import javax.crypto.CipherInputStream;
import javax.crypto.CipherOutputStream;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.SecretKeySpec;

import android.content.Context;

public class AES extends Cripto {

public static void encrypt(Context c, String nomeArquivo)
        throws IOException, NoSuchAlgorithmException,
        NoSuchPaddingException, InvalidKeyException {



    String key = GenerateKey(); //key 32 character randomly generated


    String pathFilePure = new _Path().getPathFilePure();
    String pathFileCripted = new _Path().getPathFileCripto();

    FileInputStream fis = new FileInputStream(pathFilePure + "/"
            + nomeArquivo);
    FileOutputStream fos = new FileOutputStream(pathFileCripted + "/"
            + nomeArquivo);


    SecretKeySpec sks = new SecretKeySpec(key.getBytes(), "AES");

    Cipher cipher = Cipher.getInstance("AES");
    cipher.init(Cipher.ENCRYPT_MODE, sks);

    CipherOutputStream cos = new CipherOutputStream(fos, cipher);

    int b;
    byte[] d = new byte[8];

    while ((b = fis.read(d)) != -1) {
        cos.write(d, 0, b);
    }

    cos.flush();
    cos.close();
    fis.close();        
}

public static void decrypt(Context c, String fileName, String key)
        throws IOException, NoSuchAlgorithmException,
        NoSuchPaddingException, InvalidKeyException {
    FileInputStream fis = new FileInputStream(
            new _Path().getPathFileDownload() + "/" + fileName);

    FileOutputStream fos = new FileOutputStream(
            new _Path().getPathFileDescripto() + "/" + fileName);
    SecretKeySpec sks = new SecretKeySpec(key.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();
}

}
Elton da Costa
  • 1,279
  • 16
  • 27

2 Answers2

1

There is no such thing as a 32 character AES key. AES keys are 256 bits or 32 bytes for AES-256. If you create random bytes - as you should - then not every byte will represent a printable character. So if you "decode" the bytes to a String instance (e.g. using new String(bytes) then you may lose data.

If you require Strings, please take a look at my answer here. Note that you should not use ECB mode encryption, which is the default if you specify "AES" as algorithm for Cipher. Never use defaults either.

Community
  • 1
  • 1
Maarten Bodewes
  • 90,524
  • 13
  • 150
  • 263
0

I've been researching and managed to solve the problem with the class below works right now, encrypts and decrypts.

 package com.infovale.cripto;

 import java.io.File;
 import java.io.FileInputStream;
 import java.io.FileOutputStream;
 import java.math.BigInteger;
 import java.util.Arrays;

 import javax.crypto.Cipher;
 import javax.crypto.CipherInputStream;
 import javax.crypto.CipherOutputStream;
 import javax.crypto.KeyGenerator;
 import javax.crypto.SecretKey;
 import javax.crypto.spec.SecretKeySpec;

 import android.content.Context;

 public class AES extends Cripto {

public static String encrypt(Context c, String nomeArquivo) {
    String caminhoArquivoPuro = new _Path().getPathFilePure() + "/"
            + nomeArquivo;
    String caminhoArquivoCriptografado = new _Path().getPathFileCripto()
            + "/" + nomeArquivo;

    String key = null;
    ;

    try {
        FileInputStream fis = new FileInputStream(new File(
                caminhoArquivoPuro));
        File outfile = new File(caminhoArquivoCriptografado);

        int read;
        if (!outfile.exists())
            outfile.createNewFile();

        FileOutputStream fos = new FileOutputStream(outfile);
        FileInputStream encfis = new FileInputStream(outfile);

        Cipher encipher = Cipher.getInstance("AES");

        KeyGenerator kgen = KeyGenerator.getInstance("AES");
        SecretKey skey = kgen.generateKey();
        encipher.init(Cipher.ENCRYPT_MODE, skey);
        CipherInputStream cis = new CipherInputStream(fis, encipher);

        key = bytesToString(skey.getEncoded());

        byte[] b = stringToBytes(key);

        while ((read = cis.read()) != -1) {
            fos.write((char) read);
            fos.flush();
        }
        fos.close();

    } catch (Exception e) {
        e.printStackTrace();
    } finally {
        entityFiles file = new entityFiles();

        file.setCaminhoArquivoPuro(caminhoArquivoPuro);
        file.setCaminhoArquivoCriptografado(caminhoArquivoCriptografado);
        file.setKeyArquivo(key);
        file.setNomeArquivo(nomeArquivo);

        ArquivoDataSource datasource = new ArquivoDataSource(c);

        datasource.open();

        file = datasource.createRegistro(file);

        datasource.close();
    }

    return key;
}

public static void decrypt(Context c, String nomeArquivo, String key) {

    String caminhoArquivoPuro = new _Path().getPathFileCripto() + "/"
            + nomeArquivo;
    String caminhoArquivoCriptografado = new _Path().getPathFileDescripto()
            + "/" + nomeArquivo;

    try {
        FileInputStream fis = new FileInputStream(new File(
                caminhoArquivoPuro));
        File outfile = new File(caminhoArquivoPuro);

        int read;
        if (!outfile.exists()) {
            outfile.createNewFile();
        }

        File decfile = new File(caminhoArquivoCriptografado);

        if (!decfile.exists()) {
            decfile.createNewFile();
        }

        FileInputStream encfis = new FileInputStream(outfile);
        FileOutputStream decfos = new FileOutputStream(decfile);

        Cipher decipher = Cipher.getInstance("AES");            



        SecretKey originalKey = new SecretKeySpec(stringToBytes(key), 0,
                stringToBytes(key).length, "AES");


        decipher.init(Cipher.DECRYPT_MODE, originalKey);
        CipherOutputStream cos = new CipherOutputStream(decfos, decipher);

        while ((read = encfis.read()) != -1) {
            cos.write(read);
            cos.flush();
        }
        cos.close();

    } catch (Exception e) {
        e.printStackTrace();
    }
}

public static String bytesToString(byte[] b) {
    byte[] b2 = new byte[b.length + 1];
    b2[0] = 1;
    System.arraycopy(b, 0, b2, 1, b.length);
    return new BigInteger(b2).toString(36);
}

public static byte[] stringToBytes(String s) {
    byte[] b2 = new BigInteger(s, 36).toByteArray();
    return Arrays.copyOfRange(b2, 1, b2.length);
}

 }
Elton da Costa
  • 1,279
  • 16
  • 27
  • 1
    You don't need `if (!outfile.exists()) outfile.createNewFile();`. You're just repeating work that `new FileOutputStream()` also does, and it will still do it anyway, and in addition it will now have to delete the file you created, so you're actually wasting even more time. – user207421 May 22 '14 at 01:34