转载于:http://blog.csdn.net/w18756901575
临时起意写一片关于文件加密的代码,我觉得所谓加密不过是将原来的信息通过一定的形式转化另一种难以阅读理解的方式.加密的方式又分为两种,一种是对称加密,一种是非对称加密. 所谓对称加密,即是加密和解密都使用同意个key,而非对称加密,即将key分为两个,一个是私钥一个是公钥,如果是用私钥进行加密那么只能用对应的公钥进行解密,如果是用公钥进行加密,那么只能用对应的私钥进行解密 下面关于文件的加密,和解密使用的是3des加密,属于对称加密,在进行文件加密的第一步就是要获取一个key,下面直接上代码
import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.DESedeKeySpec;
import java.io.*;
/**
* Created by wkk on 2017/6/20/020.
*/
public class Utils {
private static String keyPath = "C:\\key.key"; //key文件存放的位置
/**
* 数据加密
*
* @param bs
* @return
*/
public static byte[] encrypt3DES(byte[] bs) {
try {
SecretKey generateSecret = get3DESKey();
// 加密
Cipher cipher = Cipher.getInstance("DESede/ECB/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE, generateSecret);
byte[] result = cipher.doFinal(bs);
return result;
} catch (Exception e) {
System.out.println("加密出错:" + e.getMessage());
}
return null;
}
/**
* 数据解密3DES
*/
public static byte[] decoder3DES(byte[] str) {
SecretKey generateSecret = get3DESKey();
try {
Cipher cipher = Cipher.getInstance("DESede/ECB/PKCS5Padding");//
cipher.init(Cipher.DECRYPT_MODE, generateSecret);
byte[] result = cipher.doFinal(str);
return result;
} catch (Exception e) {
e.printStackTrace();
Log.d(e.toString());
System.out.println("解密出错:" + e.getMessage());
}
return null;
}
/**
* 获取key
*
* @return
*/
private static SecretKey get3DESKey() {
try {
SecretKey key = getKey();
if (key != null) {
return key;
}
// 生成key
KeyGenerator keyGenerator = KeyGenerator.getInstance("DESede");
keyGenerator.init(168);// can 168 or 112/new SecureRandom()
SecretKey secretKey = keyGenerator.generateKey();
byte[] bytesKey = secretKey.getEncoded();
// 转化key
DESedeKeySpec deSedeKeySpec = new DESedeKeySpec(bytesKey);
SecretKeyFactory factory = SecretKeyFactory.getInstance("DESede");
SecretKey generateSecret = factory.generateSecret(deSedeKeySpec);
//保存key
saveKey(generateSecret);
return generateSecret;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
/**
* 保存key
*
* @param object
*/
private static void saveKey(Object object) {
try {
ObjectOutputStream objectOutputStream = new ObjectOutputStream(new FileOutputStream(new File(keyPath)));
objectOutputStream.writeObject(object);
objectOutputStream.flush();
objectOutputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* 读取key
*
* @return
*/
private static SecretKey getKey() {
File file = new File(keyPath);
if (!file.exists()) {
return null;
}
try {
ObjectInputStream objectInputStream = new ObjectInputStream(new FileInputStream(new File(keyPath)));
SecretKey key = (SecretKey) objectInputStream.readObject();
objectInputStream.close();
return key;
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
return null;
}
}
以上就是工具类部分,关于key我是直接放在本地的,因为只是一个demo,所以如果你要正式使用上面的代码,请根据自己的需要做出修改. 上面只是工具类,但是有了工具类并不是说你立马就能对文件进行加密,还有文件加密的代码需要封装.
看上面的代码,乍一看好像没有问题,读取,加密,写入—>读取,解密,还原,所有的流程都是对的,但是在实际的运行过程中确保了一个错误* 解密文件 * * @param fromPath * @param toPath */ public static void decoderFile(String fromPath, String toPath) { File file = new File(toPath); File file1 = new File(fromPath); try { FileInputStream fileInputStream = new FileInputStream(file1); if (!file1.exists()) { file1.createNewFile(); } FileOutputStream fileOutputStream = new FileOutputStream(file); byte bs[] = new byte[1024]; int l = 0; while ((l = fileInputStream.read(bs)) != -1) { fileOutputStream.write(Utils.decoder3DES(bs)); } fileOutputStream.flush(); fileOutputStream.close(); fileInputStream.close(); file1.delete(); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } /** * 加密文件 */ public static void encryptFile(String fromPath, String toPath) { File file = new File(fromPath); try { FileInputStream fileInputStream = new FileInputStream(file); File file1 = new File(toPath); if (!file1.exists()) { file1.createNewFile(); } FileOutputStream fileOutputStream = new FileOutputStream(file1); byte bs[] = new byte[1024]; int l = 0; while ((l = fileInputStream.read(bs)) != -1) { byte[] bytes = Utils.encrypt3DES(bs); fileOutputStream.write(bytes); } fileOutputStream.flush(); fileOutputStream.close(); fileInputStream.close(); file.delete(); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } }
这个问题困扰了我一个下午的时间,我去百度,有的说是key的问题,有的说是加密填充的问题,但是我照着改了很多仍旧没有解决,我就先去试了试加密解密普通字符串,结果一切正常,就是搞不懂为什么放在文件上就不行了呢?当天我并没有解决这个问题,然后就等到第二天,我想是不是加密的时候文件的完整性被破环了?然后我就在加密之前调用了base64对要加密的内容进行了编码,然后解密的时候还是报错,我十分纳闷,心想是不是base64的编码有问题,然后就log了一下base64编码过后的内容
突然想到,数据加密后和数据加密之前的长度是不一样的,我去加密1024个字节如果加密后变成了2000个字节,然而我解密读取的时候还是读取1024个字节,这样就会造成数据的不完整.解密当然会出错,所以应该log看一下1024字节进行加密后的大小,然后解密的时候读取对应的长度就能解决问题了,修改后的代码如下:
加密文件的代码没有问题,只需要修改解密文件时读取的字节长度就可以了,这个是我log出来看后的长度,如果你用的时候使用不同的加密算法,或者不同长度的密钥,应该做出对应的修改 写以上的代码只是出于我的个人兴趣,假如有一天你项目交不出来,作业或者论文没写,又或者其他的情况你可以调用代码,假装自己的电脑中病毒了ヽ(´ー`)ノ遍历文件夹的代码: http://blog.csdn.net/w18756901575/article/details/70238234* 解密文件 * * @param fromPath * @param toPath */ public static void decoderFile(String fromPath, String toPath) { File file = new File(toPath); File file1 = new File(fromPath); try { FileInputStream fileInputStream = new FileInputStream(file1); if (!file1.exists()) { file1.createNewFile(); } FileOutputStream fileOutputStream = new FileOutputStream(file); byte bs[] = new byte[1032]; int l = 0; while ((l = fileInputStream.read(bs)) != -1) { fileOutputStream.write(Utils.decoder3DES(bs)); } fileOutputStream.flush(); fileOutputStream.close(); fileInputStream.close(); file1.delete(); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } }