Java案例怎么实现文件加密?

wen java案例 11

本文目录导读:

Java案例怎么实现文件加密?

  1. 使用AES对称加密(推荐)
  2. 使用密码保护(基于密码的加密)
  3. 大文件分块加密(适合超大文件)
  4. 实用工具类(完整版)
  5. 使用示例
  6. 注意事项

我来介绍几种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();
        }
    }
}

注意事项

  1. 密钥管理:密钥需要安全存储,不要硬编码在代码中
  2. IV管理:每次加密都应使用不同的IV
  3. 性能考虑:大文件建议使用分块处理
  4. 错误处理:完善异常处理逻辑
  5. 安全性:使用强随机数生成器、适当迭代次数

这些实现适用于大多数文件加密场景,你可以根据具体需求选择合适的方案。

抱歉,评论功能暂时关闭!