android中对文件加密解密的实现

所属分类: 软件编程 / Android 阅读数: 31
收藏 0 赞 0 分享

现在项目里面有一个需求,本项目里面下载的视频和文档都不允许通过其他的播放器播放,在培训机构里面这样的需求很多。防止有人交一份钱,把所有的课件就拷给了别人。这样的事情培训机构肯定是不愿意的。现在我项目里面也出了这么个需求。下面介绍一下我的实现。

文件加解密的流程及原理

1、加密方法:存储文件时,从输入流中截取文件的字节数组,对字节数组进行加密,至于加密的方式和算法就可以视需求而定了,然后把加密后的字节数组写入到文件中,最后生成加密后的文件;

2、解密方法:同加密方法一样,只不过是对字节数据进行解密,最后生成明文文件;

3、加密算法:Android系统本身引入了javax包的Cipher类,这个类里提供了各种各样的通用的加密方式,如AES对称加密等;该程序中有个CipherUtil工具类,里面有一些简单的使用Cipher进行AES加解密的方法;当然最好还是好好学习一下Cipher类的使用;

4、注意事项:

  1. 如何判断一个文件是加密后的文件,最简单的方法就是对加密后的文件统一增加一个后缀名,然后在解密之后将这个后缀名去除,还原回原有文件格式;如:密文文件的统一后缀名为“.cipher”,明文文件名为"测试.txt",加密后的密文文件应该为“测试.txt.cipher”;
  2. 加密文件时还有一个重要的注意事项,就是加密后的密文和明文的长度是否相同,如果文件时一次读取出所有字节数组进行加密的话不用担心这个问题,但是当对文件分次读取加密或分段加密的话,就不得不考虑这个问题了,最方便的方法就是保证明文和加密后的密文长度相同;如果长度不同,由于是分段加密的,密文是由一段一段子密文拼接成的,解密时会找不到每段子密文,因为不知道每段子密文的长度是多少;

主要代码

/**自定义实现简单的文件加密解密工具 
 * 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); 
  } 
} 

效果如图:

代码就是这么多,都有注释。以后再有这种需求可以直接用。以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。

更多精彩内容其他人还在看

Android中加入名片扫描功能实例代码

这篇文章主要介绍了Android中加入名片扫描功能实例代码的相关资料,需要的朋友可以参考下
收藏 0 赞 0 分享

Android仿微信发表说说实现拍照、多图上传功能

这篇文章主要为大家详细介绍了Android仿微信发表说说实现拍照、多图上传功能,使用Retrofit2.0技术,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
收藏 0 赞 0 分享

设置Android系统永不锁屏永不休眠的方法

在进行Android系统开发的时候,有些特定的情况需要设置系统永不锁屏,永不休眠。本篇文章给大家介绍Android 永不锁屏,开机不锁屏,删除设置中休眠时间选项,需要的朋友一起学习吧
收藏 0 赞 0 分享

Android Retrofit 2.0框架上传图片解决方案

这篇文章主要介绍了Android Retrofit 2.0框架上传一张与多张图片解决方案,感兴趣的小伙伴们可以参考一下
收藏 0 赞 0 分享

Android自定义等待对话框

这篇文章主要为大家详细介绍了Android自定义等待对话框的实现方法,感兴趣的小伙伴们可以参考一下
收藏 0 赞 0 分享

Android中Window添加View的底层原理

这篇文章主要介绍了Android中Window添加View的底层原理,需要的朋友可以参考下
收藏 0 赞 0 分享

Android调用系统默认浏览器访问的方法

这篇文章主要介绍了Android调用系统默认浏览器访问的方法的相关资料,需要的朋友可以参考下
收藏 0 赞 0 分享

Android开发退出程序的方法汇总

Android程序有很多Activity,比如说主窗口A,调用了子窗口B,子窗口B又调用子窗口C,back返回子窗口B后,在B中如何关闭整个Android应用程序呢? 下面脚本之家小编就给大家介绍android开发退出程序的几种方法,感兴趣的朋友参考下吧
收藏 0 赞 0 分享

Android程序开发中单选按钮(RadioGroup)的使用详解

在android程序开发中,无论是单选按钮还是多选按钮都非常的常见,接下来通过本文给大家介绍Android程序开发中单选按钮(RadioGroup)的使用,需要的朋友参考下吧
收藏 0 赞 0 分享

Android实现仿网易今日头条等自定义频道listview 或者grideview等item上移到另一个view中

这篇文章主要介绍了Android实现仿网易今日头条等自定义频道listview 或者grideview等item上移到另一个view中 的相关资料,需要的朋友可以参考下
收藏 0 赞 0 分享
查看更多