android中對(duì)文件加密解密的實(shí)現(xiàn)
現(xiàn)在項(xiàng)目里面有一個(gè)需求,本項(xiàng)目里面下載的視頻和文檔都不允許通過其他的播放器播放,在培訓(xùn)機(jī)構(gòu)里面這樣的需求很多。防止有人交一份錢,把所有的課件就拷給了別人。這樣的事情培訓(xùn)機(jī)構(gòu)肯定是不愿意的?,F(xiàn)在我項(xiàng)目里面也出了這么個(gè)需求。下面介紹一下我的實(shí)現(xiàn)。
文件加解密的流程及原理
1、加密方法:存儲(chǔ)文件時(shí),從輸入流中截取文件的字節(jié)數(shù)組,對(duì)字節(jié)數(shù)組進(jìn)行加密,至于加密的方式和算法就可以視需求而定了,然后把加密后的字節(jié)數(shù)組寫入到文件中,最后生成加密后的文件;
2、解密方法:同加密方法一樣,只不過是對(duì)字節(jié)數(shù)據(jù)進(jìn)行解密,最后生成明文文件;
3、加密算法:Android系統(tǒng)本身引入了javax包的Cipher類,這個(gè)類里提供了各種各樣的通用的加密方式,如AES對(duì)稱加密等;該程序中有個(gè)CipherUtil工具類,里面有一些簡單的使用Cipher進(jìn)行AES加解密的方法;當(dāng)然最好還是好好學(xué)習(xí)一下Cipher類的使用;
4、注意事項(xiàng):
- 如何判斷一個(gè)文件是加密后的文件,最簡單的方法就是對(duì)加密后的文件統(tǒng)一增加一個(gè)后綴名,然后在解密之后將這個(gè)后綴名去除,還原回原有文件格式;如:密文文件的統(tǒng)一后綴名為“.cipher”,明文文件名為"測試.txt",加密后的密文文件應(yīng)該為“測試.txt.cipher”;
- 加密文件時(shí)還有一個(gè)重要的注意事項(xiàng),就是加密后的密文和明文的長度是否相同,如果文件時(shí)一次讀取出所有字節(jié)數(shù)組進(jìn)行加密的話不用擔(dān)心這個(gè)問題,但是當(dāng)對(duì)文件分次讀取加密或分段加密的話,就不得不考慮這個(gè)問題了,最方便的方法就是保證明文和加密后的密文長度相同;如果長度不同,由于是分段加密的,密文是由一段一段子密文拼接成的,解密時(shí)會(huì)找不到每段子密文,因?yàn)椴恢烂慷巫用芪牡拈L度是多少;
主要代碼
/**自定義實(shí)現(xiàn)簡單的文件加密解密工具 * Created by zhangshuo on 2016/6/28. */ public class CustomFileCipherUtil { /** * 加密后的文件的后綴 */ public static final String CIPHER_TEXT_SUFFIX = ".cipher"; /** * 加解密時(shí)以32K個(gè)字節(jié)為單位進(jìn)行加解密計(jì)算 */ private static final int CIPHER_BUFFER_LENGHT = 32 * 1024; /** * 加密,這里主要是演示加密的原理,沒有用什么實(shí)際的加密算法 * * @param filePath 明文文件絕對(duì)路徑 * @return */ public static boolean encrypt(String filePath, CipherListener listener) { try { long startTime = System.currentTimeMillis(); File f = new File(filePath); RandomAccessFile raf = new RandomAccessFile(f, "rw"); long totalLenght = raf.length(); FileChannel channel = raf.getChannel(); long multiples = totalLenght / CIPHER_BUFFER_LENGHT; long remainder = totalLenght % CIPHER_BUFFER_LENGHT; MappedByteBuffer buffer = null; byte tmp; byte rawByte; //先對(duì)整除部分加密 for(int i = 0; i < multiples; i++){ buffer = channel.map( FileChannel.MapMode.READ_WRITE, i * CIPHER_BUFFER_LENGHT, (i + 1) * CIPHER_BUFFER_LENGHT); //此處的加密方法很簡單,只是簡單的異或計(jì)算 for (int j = 0; j < CIPHER_BUFFER_LENGHT; ++j) { rawByte = buffer.get(j); tmp = (byte) (rawByte ^ j); buffer.put(j, tmp); if(null != listener){ listener.onProgress(i * CIPHER_BUFFER_LENGHT + j, totalLenght); } } buffer.force(); buffer.clear(); } //對(duì)余數(shù)部分加密 buffer = channel.map( FileChannel.MapMode.READ_WRITE, multiples * CIPHER_BUFFER_LENGHT, multiples * CIPHER_BUFFER_LENGHT + remainder); for (int j = 0; j < remainder; ++j) { rawByte = buffer.get(j); tmp = (byte) (rawByte ^ j); buffer.put(j, tmp); if(null != listener){ listener.onProgress(multiples * CIPHER_BUFFER_LENGHT + j, totalLenght); } } buffer.force(); buffer.clear(); channel.close(); raf.close(); //對(duì)加密后的文件重命名,增加.cipher后綴 // f.renameTo(new File(f.getPath() + CIPHER_TEXT_SUFFIX)); Log.d("加密用時(shí):", (System.currentTimeMillis() - startTime) /1000 + "s"); return true; } catch (Exception e) { e.printStackTrace(); return false; } } /** * 解密,這里主要是演示加密的原理,沒有用什么實(shí)際的加密算法 * * @param filePath 密文文件絕對(duì)路徑,文件需要以.cipher結(jié)尾才會(huì)認(rèn)為其實(shí)可解密密文 * @return */ public static boolean decrypt(String filePath, CipherListener listener) { try { long startTime = System.currentTimeMillis(); File f = new File(filePath); // if(!f.getPath().toLowerCase().endsWith(CIPHER_TEXT_SUFFIX)){ // //后綴不同,認(rèn)為是不可解密的密文 // return false; // } RandomAccessFile raf = new RandomAccessFile(f, "rw"); long totalLenght = raf.length(); FileChannel channel = raf.getChannel(); long multiples = totalLenght / CIPHER_BUFFER_LENGHT; long remainder = totalLenght % CIPHER_BUFFER_LENGHT; MappedByteBuffer buffer = null; byte tmp; byte rawByte; //先對(duì)整除部分解密 for(int i = 0; i < multiples; i++){ buffer = channel.map( FileChannel.MapMode.READ_WRITE, i * CIPHER_BUFFER_LENGHT, (i + 1) * CIPHER_BUFFER_LENGHT); //此處的解密方法很簡單,只是簡單的異或計(jì)算 for (int j = 0; j < CIPHER_BUFFER_LENGHT; ++j) { rawByte = buffer.get(j); tmp = (byte) (rawByte ^ j); buffer.put(j, tmp); if(null != listener){ listener.onProgress(i * CIPHER_BUFFER_LENGHT + j, totalLenght); } } buffer.force(); buffer.clear(); } //對(duì)余數(shù)部分解密 buffer = channel.map( FileChannel.MapMode.READ_WRITE, multiples * CIPHER_BUFFER_LENGHT, multiples * CIPHER_BUFFER_LENGHT + remainder); for (int j = 0; j < remainder; ++j) { rawByte = buffer.get(j); tmp = (byte) (rawByte ^ j); buffer.put(j, tmp); if(null != listener){ listener.onProgress(multiples * CIPHER_BUFFER_LENGHT + j, totalLenght); } } buffer.force(); buffer.clear(); channel.close(); raf.close(); //對(duì)加密后的文件重命名,增加.cipher后綴 // f.renameTo(new File(f.getPath().substring(f.getPath().toLowerCase().indexOf(CIPHER_TEXT_SUFFIX)))); Log.d("解密用時(shí):", (System.currentTimeMillis() - startTime) / 1000 + "s"); return true; } catch (Exception e) { e.printStackTrace(); return false; } } /** * 用于加解密進(jìn)度的監(jiān)聽器 */ public interface CipherListener{ void onProgress(long current, long total); } }
效果如圖:
代碼就是這么多,都有注釋。以后再有這種需求可以直接用。以上就是本文的全部內(nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
- Android數(shù)據(jù)加密之Aes加密
- Android編程加密算法小結(jié)(AES、Base64、RAS加密算法)
- Android AES加密工具類分享
- Java加密解密工具(適用于JavaSE/JavaEE/Android)
- Android實(shí)現(xiàn)短信加密功能(發(fā)送加密短信、解密本地短信)
- Android 加密解密字符串詳解
- android md5加密與rsa加解密實(shí)現(xiàn)代碼
- Android獲取apk簽名指紋的md5值(防止重新被打包)的實(shí)現(xiàn)方法
- Android編程之MD5加密算法實(shí)例分析
- android中AES加解密的使用方法
相關(guān)文章
Android?webView加載數(shù)據(jù)時(shí)內(nèi)存溢出問題及解決
這篇文章主要介紹了Android?webView加載數(shù)據(jù)時(shí)內(nèi)存溢出問題及解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-12-12Pagerslidingtabstrip菜單標(biāo)題欄制作方法
這篇文章主要為大家詳細(xì)介紹了Pagerslidingtabstrip菜單標(biāo)題欄的制作方法,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-10-10Android TreeView實(shí)現(xiàn)帶復(fù)選框樹形組織結(jié)構(gòu)
這篇文章主要為大家詳細(xì)介紹了Android TreeView實(shí)現(xiàn)帶復(fù)選框樹形組織結(jié)構(gòu),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2019-07-07android studio編譯jar包或者aar包的方法教程詳解
這篇文章主要介紹了android studio編譯jar包或者aar包的方法教程,本文通過圖文并茂的形式給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-03-03讓Android應(yīng)用不被殺死(killer)的方法
這篇文章主要介紹了讓Android應(yīng)用不被殺死(killer)的方法,本文講解了實(shí)現(xiàn)方法和原理分析,需要的朋友可以參考下2015-04-04詳解Android XML中引用自定義內(nèi)部類view的四個(gè)why
本篇文章主要介紹了詳解Android XML中引用自定義內(nèi)部類view,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。2016-12-12Android 動(dòng)畫之RotateAnimation應(yīng)用詳解
本節(jié)講解旋轉(zhuǎn)動(dòng)畫效果RotateAnimation方法的應(yīng)用,有需要的朋友可以參考下2012-12-12Flexbox+ReclyclerView實(shí)現(xiàn)流式布局
這篇文章主要為大家詳細(xì)介紹了Flexbox+ReclyclerView實(shí)現(xiàn)流式布局,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-11-11