android 中文件加密 解密 算法实战

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

思路:

首先下载文件,这个就不说了,java代码写个下载管理器。

下载完成后存储文件的时候不是直接存储,要加密存储,加密方法是将文件的每个字节与这个字节在流中的下标做异或运算。

在我们项目里面播放的时候要解密,方法也是将文件的每个字节与这个字节在流中的下标做异或运算。两次异或得到的就是没有加密的值。


/**
 * 加密解密管理类
 * 
 * 加密算法 : 将文件的数据流的每个字节与该字节的下标异或.
 * 解密算法 : 已经加密的文件再执行一次对文件的数据流的每个字节与该字节的下标异或
 * 
 * @author Administrator
 * 
 */
public class FileEnDecryptManager {

	private FileEnDecryptManager() {
	}

	private static FileEnDecryptManager instance = null;

	public static FileEnDecryptManager getInstance() {
		synchronized (FileEnDecryptManager.class) {
			if (instance == null)
				instance = new FileEnDecryptManager();
		}
		return instance;
	}

	/**
	 * 记录上次解密过的文件名
	 */
	private final String LastDecryptFile = Framework
			.getModule(DownloadModule.class).getDownloadDir().getAbsolutePath()
			+ "/LastDecryptFilename.ttt";

	/**
	 * LastDecryptFilename.ttt 文件是否被清空
	 */
	private boolean isClear = false;

	/**
	 * 加密入口
	 * 
	 * @param fileUrl
	 *            文件绝对路径
	 * @return
	 */
	public boolean InitEncrypt(String fileUrl) {
		encrypt(fileUrl);
		return true;
	}

	private final int REVERSE_LENGTH = 56;

	/**
	 * 加解密
	 * 
	 * @param strFile
	 *            源文件绝对路径
	 * @return
	 */
	private boolean encrypt(String strFile) {
		int len = REVERSE_LENGTH;
		try {
			File f = new File(strFile);
			RandomAccessFile raf = new RandomAccessFile(f, "rw");
			long totalLen = raf.length();

			if (totalLen < REVERSE_LENGTH)
				len = (int) totalLen;

			FileChannel channel = raf.getChannel();
			MappedByteBuffer buffer = channel.map(
					FileChannel.MapMode.READ_WRITE, 0, REVERSE_LENGTH);
			byte tmp;
			for (int i = 0; i < len; ++i) {
				byte rawByte = buffer.get(i);
				tmp = (byte) (rawByte ^ i);
				buffer.put(i, tmp);
			}
			buffer.force();
			buffer.clear();
			channel.close();
			raf.close();
			return true;
		} catch (Exception e) {
			e.printStackTrace();
			return false;
		}
	}

	/**
	 * 解密入口
	 * 
	 * @param fileUrl
	 *            源文件绝对路径
	 */
	public void Initdecrypt(String fileUrl) {
		try {
			if (isDecripted(fileUrl)) {
				decrypt(fileUrl);
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	private void decrypt(String fileUrl) {
		encrypt(fileUrl);
	}

	/**
	 * fileName 文件是否已经解密了
	 * 
	 * @param fileName
	 * @return
	 * @throws IOException
	 */
	private boolean isDecripted(String fileName) throws IOException {
		// 上次加密的文件
		File lastDecryptFile = new File(LastDecryptFile);
		if (lastDecryptFile.exists() && isClear == false) {
			String lastDecryptfilepath = getLastDecryptFilePath(LastDecryptFile);
			if (lastDecryptfilepath != null
					&& lastDecryptfilepath.equals(fileName)) {
				return false;
			} else {
				clear();
			}
		}
		StringBufferWrite(fileName);
		return true;
	}

	/**
	 * 将需要加密的文件绝对路径写入LastDecryptFile
	 * 
	 * @param filePath
	 *            需要加密的文件绝对路径
	 * @param content
	 * @throws IOException
	 */
	private void StringBufferWrite(String filePath) throws IOException {
		File lastDecryptFile = new File(LastDecryptFile);
		if (!lastDecryptFile.exists())
			lastDecryptFile.createNewFile();
		FileOutputStream out = new FileOutputStream(lastDecryptFile, true);
		StringBuffer sb = new StringBuffer();
		sb.append(filePath);
		out.write(sb.toString().getBytes("utf-8"));
		out.close();
	}

	/**
	 * 清空加密记录
	 */
	public synchronized void clear() {
		isClear = true;
		File decryptTempFile = new File(LastDecryptFile);
		if (decryptTempFile.exists()) {
			try {
				String fileName = getLastDecryptFilePath(LastDecryptFile);
				decrypt(fileName);
				new File(LastDecryptFile).delete();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		isClear = false;
	}

	/**
	 * 从LastDecryptFile中读取记录
	 * 
	 * @param filePath
	 * @return
	 * @throws IOException
	 */
	private String getLastDecryptFilePath(String filePath) throws IOException {
		BufferedReader br = new BufferedReader(new FileReader(filePath));
		String str = br.readLine();
		br.close();
		return str;
	}
}


代码就是这么多,都有注释。以后再有这种需求可以直接用。



评论 19
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值