最近在做一个项目,需要将资源文件(包括图片、动画等类型)进行简单的加密后再上传至云上的服务器,而在应用程序中对该资源使用前先将读取到的文件数据进行解密以得到真正的文件信息。此策略的原因与好处是将准备好的资源存储在云上,使用时通过网络进行读取即可,减少了应用程序本身的大小。这一点对于移动应用尤其重要,特别是在资源量较大且需要对其进行保护的时候。毕竟在目前所处的大环境下,要想复制一款软件不难,那真正宝贵的就是不容易找到的资源了。

  先对文件与加密的相关知识做一个极为简单的科普(知道的可以跳过)。

  文件与字串

  A、文件的操作流程一般为:打开-->读取-->对内容进行变换-->写入-->关闭。

  B、常规性文件操作会用到的类有五个:File,InputStream,OutputStream,FileInoutStream,FileOutputStream,均包含在java.io下面。注意,在使用前必须对类文件进行导入,方法为import java.io.File(实现时需要分号结尾)。

  C、创建InputStream类和OutputStream类的对象时,new关键字后边的类分别是FileInputStream和FileOutputStream(而不是其自身),如InputStream fin = new FileInputStream(File objectFile)。可以看出构造参数是File类型对象,其创建方式为File file = new File(String fileName)。

  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()。

  加密算法

  MD5:以512位分组来处理输入的信息,且每一分组又被划分为16个32位子分组,经过了一系列的处理后,输出由四个32位分组组成,将这四个32位分组级联后将生成一个128位散列值。

  SHA:接收一段明文,然后以一种不可逆的方式将它转换成一段(通常更小)密文,也可以简单的理解为取一串输入码(称为预映射或信息),并把它们转化为长度较短、位数固定的输出序列即散列值(也称为信息摘要或信息认证代码)的过程。

  DES:把64位的明文输入块变为64位的密文输出块,它所使用的密钥也是64位,主要分为两步:

    (1)初始置换,把输入的64位数据块按位重新组合,并把输出分为L0、R0两部分,每部分各长32位,其置换规则为将输入的第58位换到第一位,第50位换到第2位......依此类推,最后一位是原来的第7位。L0、R0则是换位输出后的两部分,L0是输出的左32位,R0是右32位。

    (2)逆置换,经过16次迭代运算后,得到L16、R16,将此作为输入,进行逆置换,逆置换正好是初始置换的逆运算,由此即得到密文输出。

  3-DES:使用3条56位的密钥对数据进行三次加密,是DES向AES过渡的加密算法(1999年,NIST将3-DES指定为过渡的加密标准)。

  AES:使用128、192、和256位密钥,并且用128位分组加密和解密数据。

  异或:与其说这是一种加密算法,倒不如称其为文件信息的简单变换,将每一个数据与某给定数据进行异或操作即可完成加密或解密,如dataEncrypt = dataSource^dataSecret。

  OK,是时候回到文件加密与解密的具体实现这个主题上来了。后续的举例均采用图片(包括GIF动画)类型,而其他类型资源的实现原理相同,就不一一给出了。首先来看对一幅JPG类型图片进行异或加密的Java实现,由于是第一次给出代码,所以贴上了Java文件“FileEncAndDec.java”的所有内容。

 import java.io.File;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream; public class FileEncAndDec {
private static final int numOfEncAndDec = 0x99; //加密解密秘钥
private static int dataOfFile = 0; //文件字节内容
public static void main(String[] args) { File srcFile = new File("桌面.jpg"); //初始文件
File encFile = new File("encFile.tif"); //加密文件
File decFile = new File("decFile.bmp"); //解密文件 try {
EncFile(srcFile, encFile); //加密操作
} catch (Exception e) {
e.printStackTrace();
}
} private static void EncFile(File srcFile, File encFile) throws Exception {
if(!srcFile.exists()){
System.out.println("source file not exixt");
return;
} if(!encFile.exists()){
System.out.println("encrypt file created");
encFile.createNewFile();
}
InputStream fis = new FileInputStream(srcFile);
OutputStream fos = new FileOutputStream(encFile); while ((dataOfFile = fis.read()) > -1) {
fos.write(dataOfFile^numOfEncAndDec);
} fis.close();
fos.flush();
fos.close();
}
}

  从代码可以看出,给定的加密秘钥(异或数据,可以在合法范围内随便定义)为十六进制数0x99。图片资源为以中文命名的“桌面.jpg”,加密文件为“encFile.png”,还有值为“decFile.bmp”的String类对象作为解密文件名称。

  相对应地,解密的实现几乎和加密相同,只是输入与输出文件不同,看下面代码。

 private static void DecFile(File encFile, File decFile) throws Exception {
  if(!encFile.exists()){
    System.out.println("encrypt file not exixt");
    return;
  }   if(!decFile.exists()){
    System.out.println("decrypt file created");
    decFile.createNewFile();
  }   InputStream fis = new FileInputStream(encFile);
  OutputStream fos = new FileOutputStream(decFile);   while ((dataOfFile = fis.read()) > -1) {
    fos.write(dataOfFile^numOfEncAndDec);
  }   fis.close();
  fos.flush();
  fos.close();
}

  由于加密后的图片文件(保存为PNG类型)是不能直接在图片查看器中打开的,因为其内容已经改变,所以其缩略图标会显示为两朵不同颜色的花。对于其他类型的加密或损坏文件的缩略图标:JPG为山水画,BMP和TIF为画刷涂鸦,GIF为三个不同颜色的几何图形。当然,这些默认的图标应该会因系统而异。

  下面给出初始、加密及解密后的图标截图:

  和预想的一致,经测试发现以上方法对GIF动画(不是GIF图片,而是可以播放的动画资源)的加密与解密同样适用,代码和截图也就没有区别了,不过还是贴上来:

 File srcFile = new File("srcFile.gif"); //初始文件
File encFile = new File("encFile.gif"); //加密文件
File decFile = new File("decFile.gif"); //解密文件

  有两点需要注意:

  1、在调用加密与解密方法时,必须加上异常处理块(try{...}catch{...},否则编译不通过)。

  2、对用来加密或解密的源文件进行打开(读取)操作之前,最好判断其是否存在,免得造成意想不到的错误和时间的浪费。因为若文件不存在,后续的操作都是没有意义的。

  今天就先写到这,总结一下吧。文件加密简单地说就是对数据进行变换,虽然一千种方法可能会有一千种一种结果,但是思想是通用的。关键是加密所采用的算法的难易,有时间会对文中提到的算法用Java进行实现。

Java实现文件的加密与解密的更多相关文章

  1. IOS, Android, Java Web Rest : RSA 加密和解密问题

    IOS, Android, Java Web Rest :  RSA 加密和解密问题 一对公钥私钥可以使用 OpenSSL创建, 通常 1024位长度够了. 注意: 1. 公钥私钥是BASE64编码的 ...

  2. JAVA实现AES的加密和解密算法

    原文 JAVA实现AES的加密和解密算法 import javax.crypto.Cipher; import javax.crypto.spec.IvParameterSpec; import ja ...

  3. JAVA中AES对称加密和解密以及与Python兼容

    引言:本文主要解决Java中用AES加密及解密,同时可通过Python脚本对Java加密后的字符进行解密的操作. 由于近期工作中用到需要使用Java对一串密钥进行加密,并且后台通过Python语言读取 ...

  4. JavaScript前端和Java后端的AES加密和解密

    在实际开发项目中,有些数据在前后端的传输过程中需要进行加密,那就需要保证前端和后端的加解密需要统一.这里给大家简单演示AES在JavaScript前端和Java后端是如何实现加密和解密的. 直接上代码 ...

  5. java的BASE64Encoder,BASE64Decoder加密与解密

    package com.app.common; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.Fi ...

  6. java对字符串进行加密和解密(以下是来自其他博主)

    背景:需要对读取数据库配置的文件进行加密,防止他人拿到数据,而对自己的代码,有要实现进行解密,网上给的加密方式,什么MD5,base64,还有等等,都太复杂,而且有些是单向的,只加密不解密,以下代码, ...

  7. JavaScript前端和Java后端的AES加密和解密(转)

    在实际开发项目中,有些数据在前后端的传输过程中需要进行加密,那就需要保证前端和后端的加解密需要统一.这里给大家简单演示AES在JavaScript前端和Java后端是如何实现加密和解密的. java端 ...

  8. 【Java】通过DES加密和解密工具,对字符串进行加密和解密操作

    分享一个非常不错的字符串加密和解密的程序. 可以指定不同的密钥对同一字符串进行不同的加密操作,增强加密性能. Java代码如下: package com.app; import java.securi ...

  9. java的AES对称加密和解密,有偏移量

    import java.math.BigDecimal; import javax.crypto.Cipher; import javax.crypto.spec.IvParameterSpec; i ...

随机推荐

  1. R语言中数据框的横向合并与纵向合并

    #横向合并ID<-c(1,2,3,4)name<-c("Jim","Tony","Lisa","Tom")s ...

  2. AngularJS模块加载

    配置块 在模块的加载阶段,AngularJS会在提供者注册和配置的过程中对模块进行配置.在整个AngularJS的工作流中,这个阶段是唯一能够在应用启动前进行修改的部分. angular.module ...

  3. ORA-01034: ORACLE not available如何解决

    一个小小的问题,让我折腾了一个上午,下午三点彻底解决了,分享一个给大家解决方法,尽管在测试服务器上,但是经验是值得总结和分享的. ERROR:ORA-01034: ORACLE not availab ...

  4. 循环队列+堆优化dijkstra最短路 BZOJ 4152: [AMPPZ2014]The Captain

    循环队列基础知识 1.循环队列需要几个参数来确定 循环队列需要2个参数,front和rear 2.循环队列各个参数的含义 (1)队列初始化时,front和rear值都为零: (2)当队列不为空时,fr ...

  5. 如何解决inline-block元素的空白间距

    早上在博客中有人提了这样一个问题:“li元素inline-block横向排列,出现了未知间隙”,我相信大家在写页面的时候都遇到过这样的情况吧. 我一般遇到这情况都会把li浮动起来,这样就没有间隙.但是 ...

  6. HDU 2602 Bone Collector --01背包

    这种01背包的裸题,本来是不想写解题报告的.但是鉴于还没写过背包的解题报告.于是来一发. 这个真的是裸的01背包. 代码: #include <iostream> #include < ...

  7. Linux环境安装Jenkins

    安装环境: CenOS 6.4 JDK_1.6.0_23 一.安装前检查环境 检查是否安装JDK: java --version 二.安装Jenkins 1. 添加Jenkins的源(reposito ...

  8. -bash: wget: command not found的两种解决方法

    今天给服务器安装新环境时,wget 时提示 -bash:wget command not found,很明显没有安装wget软件包.一般linux最小化安装时,wget不会默认被安装,这里是CentO ...

  9. [原创] NetBean开发c++程序指南1- 加入c++项目文件夹

    利用 NetBean开发c/c++程序,导入原有程序代码. 1. 在菜单栏的 "工具" -> 选项 -> c/c++开发 如果彩色就是激活的状态,否则选择激活. 2. ...

  10. Volley(一 )—— 框架简介

    一.引言 虽然网上已经有很多大神.高手都写过了类似的帖子,但作为新人,必须要走模仿的道路,再考虑超越,因此学习大神的笔记,记录自己的理解,是一个菜鸟走向成功的必经之路啊.如签名所言,记录自己摸爬滚打的 ...