AES对文件加解密
package com.zbwt.archives.util.encrypteDecryption;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.util.Arrays;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.KeyGenerator;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
public class AESTwo {
private static KeyGenerator kgen;
private static SecureRandom secureRandom;
private static SecretKeySpec key;
private static Cipher cipher;
/**
* AES加密算法
*/
public AESTwo() {
}
private static void init(String keyWord){
try {
kgen = KeyGenerator.getInstance("AES");
secureRandom = SecureRandom.getInstance("SHA1PRNG" );
secureRandom.setSeed(keyWord.getBytes());
kgen.init(128,secureRandom);
SecretKey secretKey = kgen.generateKey();
byte[] enCodeFormat = secretKey.getEncoded();
key = new SecretKeySpec(enCodeFormat, "AES");
cipher = Cipher.getInstance("AES");// 创建密码器
} catch (NoSuchAlgorithmException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (NoSuchPaddingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
/********************************对文件进行加密解密*********************************************************/
/**
* @param fileName 加密的文件路径
* @param fileNameEncrypt 加密后的文件路径 当fileNameEncrypt为null时加密文件代替原文件
* @param keyWord 加密密钥
*
*/
public static void encryptFile(String fileName,String fileNameEncrypt, String keyWord){
try {
boolean replace = false;
if(fileNameEncrypt==null || fileNameEncrypt.equals("")){
fileNameEncrypt = fileName+".tem";
replace = true;
}
init(keyWord);
cipher.init(Cipher.ENCRYPT_MODE, key);// 初始化
File file = new File(fileNameEncrypt);
if (!file.exists())
file.createNewFile();
FileInputStream fileinputstream=new FileInputStream(fileName);
FileOutputStream out = new FileOutputStream(file);
byte bytes[] = new byte[131072]; //因在断点下载时用到,不能修改 除非 断点下载处修改
byte enbytes[] = null;
int line = 0;
while ((line = fileinputstream.read(bytes)) != -1) {
enbytes = cipher.doFinal(Arrays.copyOfRange(bytes, 0, line));
out.write(enbytes, 0, enbytes.length);
}
out.close();
fileinputstream.close();
if(replace){
File oldFile = new File(fileName);
oldFile.delete();
File newFile = new File(fileNameEncrypt);
newFile.renameTo(oldFile);
}
} catch (InvalidKeyException e) {
e.printStackTrace();
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (IllegalBlockSizeException e) {
e.printStackTrace();
} catch (BadPaddingException e) {
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
/**解密
* @param content 待解密内容
* @param keyWord 解密密钥
* @return byte[]
*/
public static void decryptFile(String encryptFileName,String decryptFileName, String keyWord) {
try {
boolean replace = false;
if(decryptFileName==null || decryptFileName.equals("")){
decryptFileName = encryptFileName+".tem";
replace = true;
}
init(keyWord);
cipher.init(Cipher.DECRYPT_MODE, key);// 初始化
File file = new File(decryptFileName); //解密后的文件
if (!file.exists())
file.createNewFile();
FileInputStream fileinputstream=new FileInputStream(encryptFileName); //要解密的文件
FileOutputStream out = new FileOutputStream(file);
byte bytes[] = new byte[131080]; //因在断点下载时用到,不能修改 除非 断点下载处修改
byte enbytes[] = null;
int line = 0;
while ((line = fileinputstream.read(bytes)) != -1) {
enbytes = cipher.doFinal(Arrays.copyOfRange(bytes, 0, line));
out.write(enbytes, 0, enbytes.length);
}
out.close();
fileinputstream.close();
if(replace){
File oldFile = new File(encryptFileName);
oldFile.delete();
File newFile = new File(decryptFileName);
newFile.renameTo(oldFile);
}
} catch (InvalidKeyException e) {
e.printStackTrace();
} catch (IllegalBlockSizeException e) {
e.printStackTrace();
} catch (BadPaddingException e) {
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
/********************************对文件进行加密解密结束*****************************************************/
/**将二进制转换成16进制
* @param buf
* @return String
*/
public static String parseByte2HexStr(byte buf[]) {
StringBuffer sb = new StringBuffer();
for (int i = 0; i < buf.length; i++) {
String hex = Integer.toHexString(buf[i] & 0xFF);
if (hex.length() == 1) {
hex = '0' + hex;
}
sb.append(hex.toUpperCase());
}
return sb.toString();
}
/**将16进制转换为二进制
* @param hexStr
* @return byte[]
*/
public static byte[] parseHexStr2Byte(String hexStr) {
if (hexStr.length() < 1)
return null;
byte[] result = new byte[hexStr.length()/2];
for (int i = 0;i< hexStr.length()/2; i++) {
int high = Integer.parseInt(hexStr.substring(i*2, i*2+1), 16);
int low = Integer.parseInt(hexStr.substring(i*2+1, i*2+2), 16);
result[i] = (byte) (high * 16 + low);
}
return result;
}
public static void main(String[] args) {
AESTwo.encryptFile("D:\\tcas4home\\certificateKey\\jingoal.rar", "D:\\tcas4home\\certificateKey\\复件 (2) jingoal.rar", "ABCDEFGHABCDEFGH");
AESTwo.decryptFile("D:\\tcas4home\\certificateKey\\复件 (2) jingoal.rar", "D:\\tcas4home\\certificateKey\\复件 jingoal.rar", "ABCDEFGHABCDEFGH");
}
}
报异常:
javax.crypto.IllegalBlockSizeException: Input length must be multiple of 16 when decrypting with padded cipher
at com.sun.crypto.provider.SunJCE_f.b(DashoA13*..)
at com.sun.crypto.provider.SunJCE_f.b(DashoA13*..)
at com.sun.crypto.provider.AESCipher.engineDoFinal(DashoA13*..)
at javax.crypto.Cipher.doFinal(DashoA13*..)
在网上搜的错误原因说是
这主要是因为加密后的byte数组是不能强制转换成字符串的,换言之:字符串和byte数组在这种情况下不是互逆的;可是没看出上述程序有什么逆转啊
还有我现在解密时读的字节流是 byte bytes[] = new byte[131080]; 如果把 131080改成 131088就不报错了 可是因为项目中这个 131080因为在文件下载时需要支持断点下载 所以给写死了 无法修改。纠结啊。。
还有一种情况不报错,就是 在上述程序中 文件小于 128kb时加解密都没问题
高分求牛人 解决。。。。。。。。。。。。。。。。。。。。。。。。。。