最近在作一个项目,须要将资源文件(包括图片、动画等类型)进行简单的加密后再上传至云上的服务器,而在应用程序中对该资源使用前先将读取到的文件数据进行解密以获得真正的文件信息。此策略的缘由与好处是将准备好的资源存储在云上,使用时经过网络进行读取便可,减小了应用程序自己的大小。这一点对于移动应用尤为重要,特别是在资源量较大且须要对其进行保护的时候。毕竟在目前所处的大环境下,要想复制一款软件不难,那真正宝贵的就是不容易找到的资源了。java
先对文件与加密的相关知识作一个极为简单的科普(知道的能够跳过)。mysql
文件与字串面试
A、文件的操做流程通常为:打开-->读取-->对内容进行变换-->写入-->关闭。算法
B、常规性文件操做会用到的类有五个:File,InputStream,OutputStream,FileInoutStream,FileOutputStream,均包含在java.io下面。注意,在使用前必须对类文件进行导入,方法为import java.io.File(实现时须要分号结尾)。spring
C、建立InputStream类和OutputStream类的对象时,new关键字后边的类分别是FileInputStream和FileOutputStream(而不是其自身),如InputStream fin = new FileInputStream(File objectFile)。能够看出构造参数是File类型对象,其建立方式为File file = new File(String fileName)。sql
D、当String类对象做为函数参数时,能够直接传入常量字符串,如“D:\source.jpg”。String类对象构造方法中比较简单也是最经常使用的一种是String string = “string content”,固然,最终执行的是String string = new String(“string content”)。其实String是很是重要的类(能够说无处不在),提供了一套完善、高效操做字串的方法,使得开发者受益不浅。服务器
E、常规性文件操做涉及到的方法有五个:exist(),read(),write(),flush(),close()。exist()判断文件是否存在,调用者为File类对象;read()读取输入流中的内容,调用者为InputStream类对象;write()、flush()、close()的做用分别为向输出流中写内容、强制发送缓冲区中数据、保存并关闭文件,调用者为OutputStream类对象,不过InputStream类对象在操做完成后也须要close()。网络
加密算法jvm
SHA:接收一段明文,而后以一种不可逆的方式将它转换成一段(一般更小)密文,也能够简单的理解为取一串输入码(称为预映射或信息),并把它们转化为长度较短、位数固定的输出序列即散列值(也称为信息摘要或信息认证代码)的过程。
DES:把64位的明文输入块变为64位的密文输出块,它所使用的密钥也是64位,主要分为两步:
(1)初始置换,把输入的64位数据块按位从新组合,并把输出分为L0、R0两部分,每部分各长32位,其置换规则为将输入的第58位换到第一位,第50位换到第2位......依此类推,最后一位是原来的第7位。L0、R0则是换位输出后的两部分,L0是输出的左32位,R0是右32位。
(2)逆置换,通过16次迭代运算后,获得L1六、R16,将此做为输入,进行逆置换,逆置换正好是初始置换的逆运算,由此即获得密文输出。
3-DES:使用3条56位的密钥对数据进行三次加密,是DES向AES过渡的加密算法(1999年,NIST将3-DES指定为过渡的加密标准)。
AES:使用12八、19二、和256位密钥,而且用128位分组加密和解密数据。
异或:与其说这是一种加密算法,倒不如称其为文件信息的简单变换,将每个数据与某给定数据进行异或操做便可完成加密或解密,如dataEncrypt = dataSource^dataSecret。
OK,是时候回到文件加密与解密的具体实现这个主题上来了。后续的举例均采用图片(包括GIF动画)类型,而其余类型资源的实现原理相同,就不一一给出了。首先来看对一幅JPG类型图片进行异或加密的Java实现,因为是第一次给出代码,因此贴上了Java文件“FileEncAndDec.java”的全部内容。
1 import java.io.File;
2 import java.io.InputStream;
3 import java.io.OutputStream;
4 import java.io.FileInputStream;
5 import java.io.FileOutputStream;
6
7 public class FileEncAndDec {
8 private static final int numOfEncAndDec = 0x99; //加密解密秘钥
9 private static int dataOfFile = 0; //文件字节内容
10 public static void main(String[] args) {
11
12 File srcFile = new File("桌面.jpg"); //初始文件
13 File encFile = new File("encFile.tif"); //加密文件
14 File decFile = new File("decFile.bmp"); //解密文件
15
16 try {
17 EncFile(srcFile, encFile); //加密操做
18 } catch (Exception e) {
19 e.printStackTrace();
20 }
21 }.
22
23 private static void EncFile(File srcFile, File encFile) throws Exception {
24 if(!srcFile.exists()){
25 System.out.println("source file not exixt");
26 return;
27 }
28
29 if(!encFile.exists()){
30 System.out.println("encrypt file created");
31 encFile.createNewFile();
32 }
33 InputStream fis = new FileInputStream(srcFile);
34 OutputStream fos = new FileOutputStream(encFile);
35
36 while ((dataOfFile = fis.read()) > -1) {
37 fos.write(dataOfFile^numOfEncAndDec);
38 }
39
40 fis.close();
41 fos.flush();
42 fos.close();
43 }
44 }
从代码能够看出,给定的加密秘钥(异或数据,能够在合法范围内随便定义)为十六进制数0x99。图片资源为以中文命名的“桌面.jpg”,加密文件为“encFile.png”,还有值为“decFile.bmp”的String类对象做为解密文件名称。
相对应地,解密的实现几乎和加密相同,只是输入与输出文件不一样,看下面代码。
1 private static void DecFile(File encFile, File decFile) throws Exception {
2 if(!encFile.exists()){
3 System.out.println("encrypt file not exixt");
4 return;
5 }
6
7 if(!decFile.exists()){
8 System.out.println("decrypt file created");
9 decFile.createNewFile();
10 }
11
12 InputStream fis = new FileInputStream(encFile);
13 OutputStream fos = new FileOutputStream(decFile);
14
15 while ((dataOfFile = fis.read()) > -1) {
16 fos.write(dataOfFile^numOfEncAndDec);
17 }
18
19 fis.close();
20 fos.flush();
21 fos.close();
下面给出初始、加密及解密后的图标截图:
和预想的一致,经测试发现以上方法对GIF动画(不是GIF图片,而是能够播放的动画资源)的加密与解密一样适用,代码和截图也就没有区别了,不过仍是贴上来:
1 File srcFile = new File("srcFile.gif"); //初始文件
2 File encFile = new File("encFile.gif"); //加密文件
3 File decFile = new File("decFile.gif"); //解密文件
有两点须要注意:
一、在调用加密与解密方法时,必须加上异常处理块(try{...}catch{...},不然编译不经过)。
二、对用来加密或解密的源文件进行打开(读取)操做以前,最好判断其是否存在,省得形成意想不到的错误和时间的浪费。由于若文件不存在,后续的操做都是没有意义的。
今天就先写到这,总结一下吧。文件加密简单地说就是对数据进行变换,虽然一千种方法可能会有一千种一种结果,可是思想是通用的。关键是加密所采用的算法的难易,有时间会对文中提到的算法用Java进行实现。