2013年4月12日 星期五

[Android]Android MediaPlayer 影片加解密+播放

最近因為工作需求又開始研究這個老議題 - - -DRM
原來業界真的會用到這個技術,而且不是特定企業、特定產品
只要產品跟版權扯上關係,Solution幾乎都會聽到這個名詞!
有關DRM的介紹:http://zh.wikipedia.org/wiki/%E6%95%B0%E5%AD%97%E7%89%88%E6%9D%83%E7%AE%A1%E7%90%86

很多人會認為DRM是一個標準有其規範,只要其中一個環節不符合規範,就不符合DRM。
但其實這都是無稽之談,不過大致應用都大同小異,還是那張老圖(差不多如此)。

DRM是一種機制、一種技術:這技術可以只是簡單的hash function或是AES加密技術,更複雜的話可以到AES或3DES + RSA的混合型,想更安全架個CA 再加上時戳或是想弄個組合型金鑰都可以,更甚至有些混合型結合Smart Card等中介元件 或是生物識別。只是越安全的系統,實作上有一定的難度之外,他還無法吸引消費者使用。

正題開始:
本實驗我們使用既定AES加密的Sample code,主要探討其中的可行跟教學。
在影片保護中我們無法針對整個影片做對稱式加密(考量效能問題),Android環境下超過五秒建議用thread或service完成,更會增加整個實作複雜度。
有鑑於此,我們用FileInputStream 讀取檔案存成byte,並只針對前端部分的byte作加密並組合成保護的檔案。

宣告變數:


public class MainActivity extends Activity implements SurfaceHolder.Callback {
//宣告 按鈕及影音播放相關元件.
private Button enc_btn;
private Button dec_btn;
private SurfaceView suf_view;
private SurfaceHolder suf_holder;
private String playpath="/sdcard/abc.3gp";
private MediaPlayer m_player = new MediaPlayer();

//宣告 AES加密相關資料.
private String key_value = "g7dohju42837lz9b";
private byte[] bytesKey = key_value.getBytes();
private AESAlgorithm alg = new AESAlgorithm(AESAlgorithm.KEY_SIZE_128);
private int[] wordsKeyExpansion = alg.createKeyExpansion(bytesKey);
private byte[] bytesPlaintext,bytesEncrypted;

//宣告 影片讀取byte_code之存放容器
private byte[] enc_plaintext,enc_head,enc_target;//第一段加密需要使用的 byte_code之宣告.
private byte[] dec_cipher,dec_head,dec_target;//第二段解密需要使用的 byte_code之宣告.



=======================
宣告按鈕及加密段

enc_btn = (Button)this.findViewById(R.id.encode);
dec_btn = (Button)this.findViewById(R.id.decode);
dec_btn.setEnabled(false);
suf_view = (SurfaceView)this.findViewById(R.id.sview);
suf_holder = suf_view.getHolder();
suf_holder.addCallback(this);
suf_holder.setFixedSize(176, 144);
suf_holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
enc_btn.setOnClickListener(new OnClickListener(){
public void onClick(View view){  
FileInputStream fi = null;
FileOutputStream fo = null;
try {
fi = new FileInputStream(playpath);
BufferedInputStream bfin = new BufferedInputStream(fi);
int fileSize = fi.available();
enc_plaintext = new byte[fileSize];
enc_head = new byte[128];
bfin.read(enc_plaintext,0,fileSize);
//載入前 128byte並加密
System.arraycopy(enc_plaintext, 0, enc_head, 0, 128);
bytesPlaintext = enc_head;
bytesEncrypted = alg.cipher(bytesPlaintext,wordsKeyExpansion);
System.out.println("byresEncrypted.length:"+bytesEncrypted.length);//印出後發現加密後的檔頭長度從128變為144
//合併檔案到 enc_target
enc_target = new byte[bytesEncrypted.length + fileSize-128];
System.arraycopy(bytesEncrypted,0, enc_target, 0, bytesEncrypted.length);
System.arraycopy(enc_plaintext,128,enc_target,bytesEncrypted.length,fileSize-128);
//將加密的檔頭及後續 並覆蓋回存
File filetemp = new File(playpath);
fo = new FileOutputStream(filetemp);
fo.write(enc_target);
fo.close();
enc_btn.setEnabled(false);
dec_btn.setEnabled(true);
} catch (IOException e) {
e.printStackTrace();
}
}});


=======================




未完待續...





1 則留言:

  1. 您好 Kun-hsien Lee大師,可以請教這有完整專案,還是現有專案可以給我參考一下媽>< 最近幾天都弄不出來...不好意思麻煩您了

    回覆刪除