0

I need to download mp3 files, encrypt, when necessary, to decrypt a temporary mp3 and listen.

Used as reference this answer already done in StackOverflow

Encrypting files with AES on Android

All steps works. But when I send the generated mp3 file for the MediaPlayer does not recognize and break.

These are my download and encryption method

 public void executeAsyncDownload(String urlFile, String id, int position, HandlerCallback callback) {

    String encryptedName = Cypher.md5(id);

    if (MediaUtils.containsFile(encryptedName)) {
        callback.onDownloadFinish(position);
        return;
    }

    File dir = MediaUtils.getDestinationFolder(destination);

    if (!dir.exists()) {
        dir.mkdir();
    }

    try {
        if (canceled)
            return;

        callback.onDownloadStart(position);
        URL url = new URL(urlFile);
        URLConnection connection = url.openConnection();
        connection.connect();
        int tamFile = connection.getContentLength();
        String filePath = MediaUtils.getFilePath(MediaUtils.tempPath + encryptedName).toString();

        InputStream fis = new BufferedInputStream(url.openStream());
        OutputStream fos = new FileOutputStream(filePath);
        File file = new File(filePath);

        byte data[] = new byte[80192];
        int count;
        long total = 0;

        while ((count = fis.read(data)) != -1) {
            total += count;
            if (tamFile > 0) {
                int percentage = (int) (total * 100 / tamFile);
                if (percentage % 20 == 0)
                    callback.onDownloadProgress(percentage, position);
            }

            fos.write(data, 0, count);

            if (canceled) {
                MediaUtils.deleteFile(file);
                return;
            }
        }


        if (canceled)
            return;


        byte[] key = (salt + cryptPassword).getBytes("UTF-8");
        MessageDigest sha = MessageDigest.getInstance("SHA-1");
        key = sha.digest(key);
        key = Arrays.copyOf(key, 8);
        SecretKeySpec sks = new SecretKeySpec(key, "DES");
        Cipher cipher = Cipher.getInstance("DES/ECB/NoPadding");
        cipher.init(Cipher.ENCRYPT_MODE, sks);
        CipherOutputStream cos = new CipherOutputStream(fos, cipher);

        int b;
        byte[] d = new byte[8192];
        while ((b = fis.read(d)) != -1) {
            cos.write(d, 0, b);
        }

        OutputStream outputEncrypted = new FileOutputStream(dir + File.separator + encryptedName);
        outputEncrypted.write(d);
        outputEncrypted.close();


        fos.flush();
        fos.close();
        fis.close();

        MediaUtils.deleteFile(file);//delete temp file

        callback.onDownloadFinish(position);
    } catch (Exception e) {
        e.printStackTrace();
        callback.onDownloadError(position);
    }
}

This are my decryption method

 @SafeVarargs
@Override
protected final File doInBackground(HashMap<String, Object>... params) {
    String path = (String) params[0].get(FILE_PATH);
    String fileName = String.valueOf(params[0].get(FILE_NAME));
    boolean encrypted = (boolean) params[0].get(ENCRYPTED);

    File root = android.os.Environment.getExternalStorageDirectory();
    File dir = new File(root.getAbsolutePath() + File.separator + path + File.separator);
    File file;

    if (!encrypted) {
        file = new File(dir + File.separator + fileName);
        return file;
    }

    file = new File(dir + File.separator + Cypher.md5(fileName));
    File tempMp3 = null;
    try {
        tempMp3 = File.createTempFile(TEMP, MP3, context.getCacheDir());
        tempMp3.deleteOnExit();
    } catch (IOException e) {
        e.printStackTrace();
    }

    try {
        FileInputStream fis = new FileInputStream(file);
        byte[] key = (DownloadManager.salt + DownloadManager.cryptPassword).getBytes("UTF-8");
        MessageDigest sha = MessageDigest.getInstance("SHA-1");
        key = sha.digest(key);
        key = Arrays.copyOf(key, 8);
        SecretKeySpec sks = new SecretKeySpec(key, "DES");
        Cipher cipher = Cipher.getInstance("DES/ECB/NoPadding");
        cipher.init(Cipher.DECRYPT_MODE, sks);
        CipherInputStream cis = new CipherInputStream(fis, cipher);

        FileOutputStream fos = new FileOutputStream(tempMp3);

        int b;
        byte[] d = new byte[80192];
        while ((b = cis.read(d)) != -1) {
            fos.write(d, 0, b);
        }

        fos.flush();
        fos.close();
        cis.close();

    } catch (IOException e) {
        e.printStackTrace();
    } catch (NoSuchAlgorithmException e) {
        e.printStackTrace();
    } catch (NoSuchPaddingException e) {
        e.printStackTrace();
    } catch (InvalidKeyException e) {
        e.printStackTrace();
    }

    return tempMp3;
}
Community
  • 1
  • 1
André Dantas
  • 163
  • 1
  • 13
  • @petey The problem is that the mp3 file generated by the decryption does not work. Do not fall into the exception, does not crash in the encryption and decryption. Simply decryption generates a file that the MediaPlayer can't read. The mp3 file before encryption works, but the mp3 decrypted not – André Dantas Jan 20 '16 at 18:00

2 Answers2

0

You seem to have a typo in either your encrypt or decrypt method.

In encryption:

    int b;
    byte[] d = new byte[8192];
    while ((b = cis.read(d)) != -1) {
        fos.write(d, 0, b);
    }

In decryption:

    int b;
    byte[] d = new byte[80192];
    while ((b = cis.read(d)) != -1) {
        fos.write(d, 0, b);
    }

The byte array d in decryption is about 10x larger than the byte array in encryption.

PunDefeated
  • 566
  • 5
  • 18
  • While this is somewhat weird, how can it cause the mentioned problem? – Henry Jan 20 '16 at 20:15
  • If there are 72K uninitialized bytes at the end of the file, it might cause it to be unreadable. Not an expert on mp3, but it seems possible. – PunDefeated Jan 20 '16 at 21:51
  • @PunDefeated Ignore the 0 after 8, really the right is 8192. This 80192 was a last attempt to increase the bytes – André Dantas Jan 21 '16 at 12:20
0

After doing this:

    CipherOutputStream cos = new CipherOutputStream(fos, cipher);

    int b;
    byte[] d = new byte[8192];
    while ((b = fis.read(d)) != -1) {
        cos.write(d, 0, b);
    }

    OutputStream outputEncrypted = new FileOutputStream(dir + File.separator + encryptedName);
    outputEncrypted.write(d);
    outputEncrypted.close();

the outputEncrypted file will just contain the last buffer full of data. Furthermore, this data will not be encrypted.

Henry
  • 42,982
  • 7
  • 68
  • 84
  • Explain better. I don't understand – André Dantas Jan 21 '16 at 12:21
  • In the last 3 lines you open a new stream, write the contents of `d` to it and close it again. So it will just contain what `d` contained at the time, furthermore, no encryption is involved. – Henry Jan 21 '16 at 13:41