4

How would I go about playing a set of encrypted audio files in a audio player android app?

I have an app project where I would have a set of encrypted audio content stored on a users device. A single audio content (example: podcast) would in this case consist of multiple encrypted files. The app acts as a audio player, through which users listen to this audio content. For good user experience the whole content (podcast) should play seamlessly from one file to another. This works perfectly for normal audio files using android's MediaPlayer class.

For security measures, no decrypted file should at any point be present on the users device storage in a way that a user can access this file any other way than through my app (even on rooted devices).

The type of encryption to be used is not fixed yet, so I am open to any algorithm that would work best for this case.

I thought about decrypting each file before playing it. Files are a maximum of 25MB in size, and a AES encryption/decryption for such file takes some 300 milliseconds, so this does not disturb the user experience too much.

There are two problems I see here with two different approaches to decryption:

  1. If I decrypt a file and store it on device as a normal audio file, the user will be able to get to it (rooted devices) and use it outside my app.
  2. If I decrypt a file and keep it in system memory as lets say a byte array, how do I play this back to the user? I have found no way to do this using MediaPlayer, or have found any other library that would allow this out of the box. Maybe some audio streaming library could be modified to play out of a decrypted file stream?
ak93
  • 1,135
  • 16
  • 27

3 Answers3

4

The simples way, IMO, is to use ExoPlayer, which is an open-source media player developed by Google. They dealt on this project with lots of edge cases and it's a nice and reliable player.

On top of that your needs are easy to achieve pretty much out-of-the-box.

You'll just load your player using a AesCipherDataSource wrapping a FileDataSource.

So your file is encryped locally using AesCihper and decrypted on the fly, chunk by chunk by the player itself.

Here is the link to their dev-guide: https://google.github.io/ExoPlayer/guide.html and to the AesCipher http://google.github.io/ExoPlayer/doc/reference/com/google/android/exoplayer2/upstream/crypto/AesCipherDataSource.html

Budius
  • 39,391
  • 16
  • 102
  • 144
  • curious to see if you actually seen this working? I used ExoPlayer 1 in the past with a custom DataSource and was able to get RC4 Ciphers, working, but not AES - now it looks like they've added a custom AesCipher specifically for that, but I still haven't got it to work... – mdd-sbo Feb 16 '17 at 21:21
  • 1
    This looks like the best solution. At the moment I'm implementing a bit different approach, where I will be decrypting files into a byte array that I will than pass through a DataSource to ExoPlayer. If I were to use the AesCipherDataSource, how do I pass the AES IV parameters to it? The linked documentation only lists the option to pass a secretKey to it `AesCipherDataSource(byte[] secretKey, DataSource upstream) ` – ak93 Mar 11 '17 at 23:54
  • I found this thread that is on topic for exoPlayer and AES encryption: https://github.com/google/ExoPlayer/issues/2467 It seems that getting this to work is not that simple and brings up problems such as slow seeking. – ak93 Mar 12 '17 at 00:20
  • I have been trying to `AesCipherDataSource` from last 3 days but not able to initialise the player, how do I call it. Can you please show an example to prepare the mediaSource using `AesCipherDataSource` – MrinmoyMk Jul 01 '20 at 19:24
1

There are many ways to do achieve your goal some of them are given below:

  1. Stream your file from a given URL using MediaPlayer.setDataSource(Context, Uri)
  2. Use HttpURLConnection.getInputStream() to get local InputStream create FileInputStream and use MediaPlayer.setDataSource(FileInputStream.getFD()).
  3. Download your audio file using HTTP request but before saving apply some encryption. When you want to play, apply your decryption algorithm, retrieve stream from saved file convert into FileInputStream and use MediaPlayer.setDataSource(FileInputStream.getFD()).

Update: There is also an alternative to MediaPlayer that might be useful to be used for your needs*: https://github.com/google/ExoPlayer

Rock_Artist
  • 555
  • 8
  • 14
Haris Qurashi
  • 2,104
  • 1
  • 13
  • 28
0
  1. Since you're dealing with encrypted data if you don't want to expose anything best way would be implement the MediaPlayer yourself... So basically you'd be the one decoding it. might be worth looking at some open source media players for Android

  2. Instead of using memory a different approach would be streaming as localhost. setting up a small HTTP server. that way you'll keep the smallest amount of decrypted data on the device at a time.

Community
  • 1
  • 1
Rock_Artist
  • 555
  • 8
  • 14