Created
June 16, 2016 06:55
-
-
Save KishorFlutter/fb2025792f4e666d6a0ed034db779556 to your computer and use it in GitHub Desktop.
AES data source for real-time decryption of media content
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.google.android.exoplayer.demo; | |
import android.content.Context; | |
import android.util.Log; | |
import com.google.android.exoplayer.C; | |
import com.google.android.exoplayer.upstream.DataSpec; | |
import com.google.android.exoplayer.upstream.TransferListener; | |
import com.google.android.exoplayer.upstream.UriDataSource; | |
import java.io.EOFException; | |
import java.io.File; | |
import java.io.FileInputStream; | |
import java.io.IOException; | |
import java.io.InputStream; | |
import java.security.InvalidAlgorithmParameterException; | |
import java.security.InvalidKeyException; | |
import java.security.NoSuchAlgorithmException; | |
import java.security.NoSuchProviderException; | |
import javax.crypto.Cipher; | |
import javax.crypto.CipherInputStream; | |
import javax.crypto.NoSuchPaddingException; | |
import javax.crypto.spec.IvParameterSpec; | |
import javax.crypto.spec.SecretKeySpec; | |
public class AesDataSource implements UriDataSource { | |
private static final String KEY = "1234567890123456"; | |
private static final String TAG = AesDataSource.class.getSimpleName(); | |
private final TransferListener listener; | |
private String uriString; | |
private InputStream inputStream; | |
private CipherInputStream cipherInputStream; | |
private long bytesRemaining; | |
private boolean opened; | |
public static final class AesDataSourceException extends IOException { | |
public AesDataSourceException(IOException cause) { | |
super(cause); | |
} | |
} | |
public AesDataSource(Context context) { | |
this(context, null); | |
} | |
public AesDataSource(Context context, TransferListener listener) { | |
this.listener = listener; | |
} | |
@Override | |
public String getUri() { | |
return uriString; | |
} | |
@Override | |
public long open(DataSpec dataSpec) throws IOException { | |
try { | |
uriString = dataSpec.uri.toString(); | |
String path = dataSpec.uri.getPath(); | |
uriString = dataSpec.uri.toString(); | |
File file = new File(path); | |
inputStream = new FileInputStream(file); | |
//Decrypt Logic | |
key = new SecretKeySpec(KEY.getBytes(), "AES"); | |
cipher = Cipher.getInstance("AES/CTR/NoPadding", "BC"); | |
cipher.init(Cipher.DECRYPT_MODE, key, new IvParameterSpec(new byte[16])); | |
cipherInputStream = new CipherInputStream(inputStream, cipher); | |
long cipherInputStreamSkipped = cipherInputStream.skip(dataSpec.position); | |
long skipped = inputStream.skip(dataSpec.position); | |
if (skipped < dataSpec.position) { | |
// assetManager.open() returns an AssetInputStream, whose skip() implementation only skips | |
// fewer bytes than requested if the skip is beyond the end of the asset's data. | |
throw new EOFException(); | |
} | |
if (dataSpec.length != C.LENGTH_UNBOUNDED) { | |
bytesRemaining = dataSpec.length; | |
} else { | |
bytesRemaining = inputStream.available(); | |
if (bytesRemaining == Integer.MAX_VALUE) { | |
// assetManager.open() returns an AssetInputStream, whose available() implementation | |
// returns Integer.MAX_VALUE if the remaining length is greater than (or equal to) | |
// Integer.MAX_VALUE. We don't know the true length in this case, so treat as unbounded. | |
bytesRemaining = C.LENGTH_UNBOUNDED; | |
} | |
} | |
} catch (IOException e) { | |
} catch (NoSuchAlgorithmException e) { | |
e.printStackTrace(); | |
} catch (InvalidKeyException e) { | |
e.printStackTrace(); | |
} catch (InvalidAlgorithmParameterException e) { | |
e.printStackTrace(); | |
} catch (NoSuchPaddingException e) { | |
e.printStackTrace(); | |
} catch (NoSuchProviderException e) { | |
e.printStackTrace(); | |
} | |
opened = true; | |
if (listener != null) { | |
listener.onTransferStart(); | |
} | |
return bytesRemaining; | |
} | |
@Override | |
public void close() throws IOException { | |
uriString = null; | |
if (inputStream != null) { | |
try { | |
inputStream.close(); | |
} catch (IOException e) { | |
throw new AesDataSourceException(e); | |
} finally { | |
inputStream = null; | |
if (opened) { | |
opened = false; | |
if (listener != null) { | |
listener.onTransferEnd(); | |
} | |
} | |
} | |
} | |
} | |
SecretKeySpec key; | |
Cipher cipher; | |
@Override | |
public int read(byte[] buffer, int offset, int readLength) throws IOException { | |
Log.d(TAG, "Offset : " + offset + " readLength : " + readLength); | |
if (bytesRemaining == 0) { | |
return -1; | |
} else { | |
int bytesRead = 0; | |
try { | |
int bytesToRead = bytesRemaining == C.LENGTH_UNBOUNDED ? readLength | |
: (int) Math.min(bytesRemaining, readLength); | |
bytesRead = cipherInputStream.read(buffer, offset, bytesToRead); | |
//bytesRead = inputStream.read(buffer, offset, bytesToRead); | |
} catch (IOException e) { | |
throw new AesDataSourceException(e); | |
} | |
if (bytesRead > 0) { | |
if (bytesRemaining != C.LENGTH_UNBOUNDED) { | |
bytesRemaining -= bytesRead; | |
} | |
if (listener != null) { | |
listener.onBytesTransferred(bytesRead); | |
} | |
} | |
return bytesRead; | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment