import java.io.*;
import java.security.GeneralSecurityException;
import java.util.Arrays;
import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.PBEKeySpec;
import javax.crypto.spec.PBEParameterSpec;
/**
* 文件加解密,返回对象为ByteArrayOutputStream
*/
public class FileEncryptor {
// 默认密码
private static final String KEY_ = "E!#%C$#@aOs%#@MyWeb001_";
//任意选择的8byte盐序列:
private static final byte[] salt = {
(byte) 0x43, (byte) 0x76, (byte) 0x95, (byte) 0xc7,
(byte) 0x5b, (byte) 0xd7, (byte) 0x45, (byte) 0x17
};
private static Cipher makeCipher(String pass, Boolean decryptMode) throws GeneralSecurityException {
//使用KeyFactory从密码短语中派生相应的密钥:
PBEKeySpec keySpec = new PBEKeySpec(pass.toCharArray());
SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("PBEWithMD5AndDES");
SecretKey key = keyFactory.generateSecret(keySpec);
//从salt创建参数和任意次数的迭代:
PBEParameterSpec pbeParamSpec = new PBEParameterSpec(salt, 42);
//设置密码:
Cipher cipher = Cipher.getInstance("PBEWithMD5AndDES");
//将密码模式设置为解密或加密:
if (decryptMode) {
cipher.init(Cipher.ENCRYPT_MODE, key, pbeParamSpec);
} else {
cipher.init(Cipher.DECRYPT_MODE, key, pbeParamSpec);
}
//返回密码;
return cipher;
}
/**
* 使用从密码短语派生的密钥将一个文件加密到第二个文件:
**/
public static ByteArrayOutputStream encryptFile(InputStream inStream) throws IOException, GeneralSecurityException {
return encryptFile(inStream, KEY_);
}
/**
* 使用从密码短语派生的密钥将一个文件加密到第二个文件:
**/
public static ByteArrayOutputStream encryptFile(InputStream inStream, String key) throws IOException, GeneralSecurityException {
byte[] decData;
byte[] encData;
//使用pass生成密码:
Cipher cipher = FileEncryptor.makeCipher(key, true);
//读入文件:
// FileInputStream inStream = new FileInputStream(file);
int blockSize = 8;
int fileLength = inStream.available();
//计算填充的byte数
int paddedCount = blockSize - (fileLength % blockSize);
//计算完整大小,包括填充
int padded = fileLength + paddedCount;
decData = new byte[padded];
inStream.read(decData);
inStream.close();
//根据PKCS5算法写出填充byte
for (int i = fileLength; i < padded; ++i) {
decData[i] = (byte) paddedCount;
}
//加密文件数据:
encData = cipher.doFinal(decData);
//将加密数据写入新文件:
// FileOutputStream outStream = new FileOutputStream(new File(fileName + ".encrypted"));
ByteArrayOutputStream outStream = new ByteArrayOutputStream();
outStream.write(encData);
outStream.close();
return outStream;
}
/**
* 使用从密码短语派生的密钥将一个文件解密到第二个文件:
**/
public static ByteArrayOutputStream decryptFile(InputStream inStream) throws GeneralSecurityException, IOException {
return decryptFile(inStream, KEY_);
}
/**
* 使用从密码短语派生的密钥将一个文件解密到第二个文件:
**/
public static ByteArrayOutputStream decryptFile(InputStream inStream, String key) throws GeneralSecurityException, IOException {
byte[] encData;
byte[] decData;
// File inFile = new File(fileName + ".encrypted");
//使用pass生成密码:
Cipher cipher = FileEncryptor.makeCipher(key, false);
//读入文件:
// FileInputStream inStream = new FileInputStream(file);
encData = new byte[(int) inStream.available()];
inStream.read(encData);
inStream.close();
//解密文件数据:
decData = cipher.doFinal(encData);
//计算要删除多少填充
int padCount = (int) decData[decData.length - 1];
//天真检查,如果明文文件实际包含
//这将在结束时失败
//为了进行健壮检查,检查末尾的padCountbyte是否具有相同的值
if (padCount >= 1 && padCount <= 8) {
decData = Arrays.copyOfRange(decData, 0, decData.length - padCount);
}
//将解密数据写入新文件:
// FileOutputStream target = new FileOutputStream(new File(fileName) + ".decrypted.txt");
ByteArrayOutputStream target = new ByteArrayOutputStream();
target.write(decData);
target.close();
return target;
}
// public static void main(String[] args) {
// try {
// File file = new File("D:\\源文件 - 副本.proc");
// FileInputStream inputStream = new FileInputStream(file);
// ByteArrayOutputStream encode = encryptFile(inputStream);
ByteArrayOutputStream encode = encryptFile(inputStream, "123");
// File file1 = new File("D:\\加密后.proc");
// FileOutputStream fos = new FileOutputStream(file1);
// fos.write(encode.toByteArray());
//
// FileInputStream decode = new FileInputStream(file1);
// ByteArrayOutputStream decrypt = decryptFile(decode);
ByteArrayOutputStream decrypt = decryptFile(decode, "123");
// File file2 = new File("D:\\解密后.proc");
// FileOutputStream fos1 = new FileOutputStream(file2);
// fos1.write(decrypt.toByteArray());
// } catch (IOException e) {
// // TODO自动生成的catch块
// e.printStackTrace();
// } catch (GeneralSecurityException e) {
// // TODO自动生成的catch块
// e.printStackTrace();
// }
// }
}
文件内容加密
于 2021-12-07 14:15:10 首次发布