本文目录导读:

我来介绍几种Java文件加密的实现方法,从基础到进阶。
使用AES对称加密(推荐)
基础AES加密
import javax.crypto.*;
import javax.crypto.spec.*;
import java.io.*;
import java.security.*;
public class FileEncryptor {
// 生成密钥
public static SecretKey generateKey() throws Exception {
KeyGenerator keyGen = KeyGenerator.getInstance("AES");
keyGen.init(256); // 128, 192, 256
return keyGen.generateKey();
}
// 加密文件
public static void encryptFile(SecretKey key, File inputFile, File outputFile)
throws Exception {
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE, key);
// 获取IV(初始化向量)
byte[] iv = cipher.getIV();
try (FileInputStream inputStream = new FileInputStream(inputFile);
FileOutputStream outputStream = new FileOutputStream(outputFile)) {
// 先写入IV
outputStream.write(iv);
// 加密数据
CipherOutputStream cipherOutputStream =
new CipherOutputStream(outputStream, cipher);
byte[] buffer = new byte[8192];
int bytesRead;
while ((bytesRead = inputStream.read(buffer)) != -1) {
cipherOutputStream.write(buffer, 0, bytesRead);
}
cipherOutputStream.close();
}
}
// 解密文件
public static void decryptFile(SecretKey key, File inputFile, File outputFile)
throws Exception {
try (FileInputStream inputStream = new FileInputStream(inputFile)) {
// 读取IV
byte[] iv = new byte[16]; // AES的IV是16字节
inputStream.read(iv);
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
IvParameterSpec ivSpec = new IvParameterSpec(iv);
cipher.init(Cipher.DECRYPT_MODE, key, ivSpec);
try (CipherInputStream cipherInputStream =
new CipherInputStream(inputStream, cipher);
FileOutputStream outputStream = new FileOutputStream(outputFile)) {
byte[] buffer = new byte[8192];
int bytesRead;
while ((bytesRead = cipherInputStream.read(buffer)) != -1) {
outputStream.write(buffer, 0, bytesRead);
}
}
}
}
}
完整使用示例
public class FileEncryptionDemo {
public static void main(String[] args) {
try {
// 生成密钥
SecretKey key = FileEncryptor.generateKey();
// 保存密钥(实际应用中需要安全存储)
try (FileOutputStream fos = new FileOutputStream("secret.key")) {
fos.write(key.getEncoded());
}
// 加密文件
File inputFile = new File("original.txt");
File encryptedFile = new File("encrypted.aes");
FileDecryptor.encryptFile(key, inputFile, encryptedFile);
System.out.println("文件加密成功!");
// 解密文件
File decryptedFile = new File("decrypted.txt");
FileDecryptor.decryptFile(key, encryptedFile, decryptedFile);
System.out.println("文件解密成功!");
} catch (Exception e) {
e.printStackTrace();
}
}
}
使用密码保护(基于密码的加密)
import javax.crypto.*;
import javax.crypto.spec.*;
import java.security.*;
public class PasswordBasedFileEncryptor {
private static final int ITERATION_COUNT = 65536;
private static final int KEY_LENGTH = 256;
// 从密码生成密钥
public static SecretKey getKeyFromPassword(String password, byte[] salt)
throws Exception {
SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA256");
KeySpec spec = new PBEKeySpec(password.toCharArray(), salt,
ITERATION_COUNT, KEY_LENGTH);
SecretKey tmp = factory.generateSecret(spec);
return new SecretKeySpec(tmp.getEncoded(), "AES");
}
// 生成盐值
public static byte[] generateSalt() {
byte[] salt = new byte[16];
new SecureRandom().nextBytes(salt);
return salt;
}
// 使用密码加密文件
public static void encryptWithPassword(String password, File inputFile,
File outputFile) throws Exception {
byte[] salt = generateSalt();
SecretKey key = getKeyFromPassword(password, salt);
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE, key);
byte[] iv = cipher.getIV();
try (FileOutputStream outputStream = new FileOutputStream(outputFile)) {
// 写入盐值和IV
outputStream.write(salt);
outputStream.write(iv);
try (FileInputStream inputStream = new FileInputStream(inputFile);
CipherOutputStream cipherOutputStream =
new CipherOutputStream(outputStream, cipher)) {
byte[] buffer = new byte[8192];
int bytesRead;
while ((bytesRead = inputStream.read(buffer)) != -1) {
cipherOutputStream.write(buffer, 0, bytesRead);
}
}
}
}
// 使用密码解密文件
public static void decryptWithPassword(String password, File inputFile,
File outputFile) throws Exception {
try (FileInputStream inputStream = new FileInputStream(inputFile)) {
// 读取盐值和IV
byte[] salt = new byte[16];
inputStream.read(salt);
byte[] iv = new byte[16];
inputStream.read(iv);
SecretKey key = getKeyFromPassword(password, salt);
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
IvParameterSpec ivSpec = new IvParameterSpec(iv);
cipher.init(Cipher.DECRYPT_MODE, key, ivSpec);
try (CipherInputStream cipherInputStream =
new CipherInputStream(inputStream, cipher);
FileOutputStream outputStream = new FileOutputStream(outputFile)) {
byte[] buffer = new byte[8192];
int bytesRead;
while ((bytesRead = cipherInputStream.read(buffer)) != -1) {
outputStream.write(buffer, 0, bytesRead);
}
}
}
}
}
大文件分块加密(适合超大文件)
import javax.crypto.*;
import javax.crypto.spec.*;
import java.io.*;
import java.nio.channels.*;
public class LargeFileEncryptor {
private static final int BUFFER_SIZE = 8192;
public static void encryptLargeFile(SecretKey key, File inputFile,
File outputFile) throws Exception {
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE, key);
byte[] iv = cipher.getIV();
try (FileChannel inputChannel = new FileInputStream(inputFile).getChannel();
FileChannel outputChannel = new FileOutputStream(outputFile).getChannel()) {
// 写入IV
outputChannel.write(java.nio.ByteBuffer.wrap(iv));
// 分块处理
java.nio.ByteBuffer buffer = java.nio.ByteBuffer.allocate(BUFFER_SIZE);
while (inputChannel.read(buffer) > 0) {
buffer.flip();
byte[] data = new byte[buffer.limit()];
buffer.get(data);
byte[] encrypted = cipher.update(data);
if (encrypted != null) {
outputChannel.write(java.nio.ByteBuffer.wrap(encrypted));
}
buffer.clear();
}
// 处理最后一块
byte[] finalEncrypted = cipher.doFinal();
if (finalEncrypted != null) {
outputChannel.write(java.nio.ByteBuffer.wrap(finalEncrypted));
}
}
}
}
实用工具类(完整版)
import javax.crypto.*;
import javax.crypto.spec.*;
import java.io.*;
import java.security.*;
import java.util.Base64;
public class FileCryptoUtils {
// 加密文件并返回密钥(Base64编码)
public static String encryptFile(String inputPath, String outputPath)
throws Exception {
SecretKey key = generateKey();
encryptFile(key, new File(inputPath), new File(outputPath));
return Base64.getEncoder().encodeToString(key.getEncoded());
}
// 解密文件(使用Base64编码的密钥)
public static void decryptFile(String inputPath, String outputPath,
String base64Key) throws Exception {
byte[] decodedKey = Base64.getDecoder().decode(base64Key);
SecretKey key = new SecretKeySpec(decodedKey, 0, decodedKey.length, "AES");
decryptFile(key, new File(inputPath), new File(outputPath));
}
// 检查文件完整性
public static String getFileChecksum(File file) throws Exception {
MessageDigest md = MessageDigest.getInstance("SHA-256");
try (FileInputStream fis = new FileInputStream(file)) {
byte[] buffer = new byte[8192];
int bytesRead;
while ((bytesRead = fis.read(buffer)) != -1) {
md.update(buffer, 0, bytesRead);
}
}
return Base64.getEncoder().encodeToString(md.digest());
}
private static SecretKey generateKey() throws Exception {
KeyGenerator keyGen = KeyGenerator.getInstance("AES");
keyGen.init(256);
return keyGen.generateKey();
}
private static void encryptFile(SecretKey key, File inputFile,
File outputFile) throws Exception {
// 实现同前面的 encryptFile 方法
}
private static void decryptFile(SecretKey key, File inputFile,
File outputFile) throws Exception {
// 实现同前面的 decryptFile 方法
}
}
使用示例
public class Main {
public static void main(String[] args) {
try {
// 方法1:使用密码加密
PasswordBasedFileEncryptor.encryptWithPassword(
"mySecretPassword123",
new File("document.pdf"),
new File("document.encrypted")
);
System.out.println("密码加密完成!");
// 方法2:使用自动生成的密钥
String key = FileCryptoUtils.encryptFile(
"photo.jpg",
"photo.encrypted"
);
System.out.println("密钥: " + key);
// 解密
FileCryptoUtils.decryptFile(
"photo.encrypted",
"photo_decrypted.jpg",
key
);
System.out.println("解密完成!");
} catch (Exception e) {
e.printStackTrace();
}
}
}
注意事项
- 密钥管理:密钥需要安全存储,不要硬编码在代码中
- IV管理:每次加密都应使用不同的IV
- 性能考虑:大文件建议使用分块处理
- 错误处理:完善异常处理逻辑
- 安全性:使用强随机数生成器、适当迭代次数
这些实现适用于大多数文件加密场景,你可以根据具体需求选择合适的方案。