现在项目里面有一个需求,本项目里面下载的视频和文档都不允许通过其他的播放器播放,在培训机构里面这样的需求很多。防止有人交一份钱,把所有的课件就拷给了别人。这样的事情培训机构肯定是不愿意的。现在我项目里面也出了这么个需求。下面介绍一下我的实现。
文件加解密的流程及原理
1、加密方法:存储文件时,从输入流中截取文件的字节数组,对字节数组进行加密,至于加密的方式和算法就可以视需求而定了,然后把加密后的字节数组写入到文件中,最后生成加密后的文件;
2、解密方法:同加密方法一样,只不过是对字节数据进行解密,最后生成明文文件;
3、加密算法:Android系统本身引入了javax包的Cipher类,这个类里提供了各种各样的通用的加密方式,如AES对称加密等;该程序中有个CipherUtil工具类,里面有一些简单的使用Cipher进行AES加解密的方法;当然最好还是好好学习一下Cipher类的使用;
4、注意事项:
主要代码
/**自定义实现简单的文件加密解密工具 * Created by zhangshuo on 2016/6/28. */ public class CustomFileCipherUtil { /** * 加密后的文件的后缀 */ public static final String CIPHER_TEXT_SUFFIX = ".cipher"; /** * 加解密时以32K个字节为单位进行加解密计算 */ private static final int CIPHER_BUFFER_LENGHT = 32 * 1024; /** * 加密,这里主要是演示加密的原理,没有用什么实际的加密算法 * * @param filePath 明文文件绝对路径 * @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; //先对整除部分加密 for(int i = 0; i < multiples; i++){ buffer = channel.map( FileChannel.MapMode.READ_WRITE, i * CIPHER_BUFFER_LENGHT, (i + 1) * CIPHER_BUFFER_LENGHT); //此处的加密方法很简单,只是简单的异或计算 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(); } //对余数部分加密 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(); //对加密后的文件重命名,增加.cipher后缀 // f.renameTo(new File(f.getPath() + CIPHER_TEXT_SUFFIX)); Log.d("加密用时:", (System.currentTimeMillis() - startTime) /1000 + "s"); return true; } catch (Exception e) { e.printStackTrace(); return false; } } /** * 解密,这里主要是演示加密的原理,没有用什么实际的加密算法 * * @param filePath 密文文件绝对路径,文件需要以.cipher结尾才会认为其实可解密密文 * @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)){ // //后缀不同,认为是不可解密的密文 // 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; //先对整除部分解密 for(int i = 0; i < multiples; i++){ buffer = channel.map( FileChannel.MapMode.READ_WRITE, i * CIPHER_BUFFER_LENGHT, (i + 1) * CIPHER_BUFFER_LENGHT); //此处的解密方法很简单,只是简单的异或计算 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(); } //对余数部分解密 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(); //对加密后的文件重命名,增加.cipher后缀 // f.renameTo(new File(f.getPath().substring(f.getPath().toLowerCase().indexOf(CIPHER_TEXT_SUFFIX)))); Log.d("解密用时:", (System.currentTimeMillis() - startTime) / 1000 + "s"); return true; } catch (Exception e) { e.printStackTrace(); return false; } } /** * 用于加解密进度的监听器 */ public interface CipherListener{ void onProgress(long current, long total); } }
效果如图:
代码就是这么多,都有注释。以后再有这种需求可以直接用。以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持呐喊教程。
声明:本文内容来源于网络,版权归原作者所有,内容由互联网用户自发贡献自行上传,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任。如果您发现有涉嫌版权的内容,欢迎发送邮件至:notice#nhooo.com(发邮件时,请将#更换为@)进行举报,并提供相关证据,一经查实,本站将立刻删除涉嫌侵权内容。