使用密钥对文件进行加解密

package com.example.test.security;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
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;

public class FileSecurityUtils {

    public static void main(String[] args) {
        try {
            encryptFile("C:\\test.txt", "password");
            decryptFile("C:\\test.txt", "password");
        } catch (IOException | GeneralSecurityException e) {
            e.printStackTrace();
        }
    }

    /**
     * 任意选择8字节盐顺序
     */
    private static final byte[] salt =
        {(byte)0x43, (byte)0x76, (byte)0x95, (byte)0xc7, (byte)0x5b, (byte)0xd7, (byte)0x45, (byte)0x17};

    /**
     * 功能描述 : 制作密码
     *
     * @param pass
     *            密码
     * @param decryptMode
     *            加密或者解密
     * @return {@link Cipher}
     * @author Ziyear 2021-4-21 22:20
     */
    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);

        // 从盐和任意数量的迭代中创建参数:
        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;
    }

    /**
     * 功能描述 : 使用从密码短语派生的密钥将一个文件加密为第二个文件
     *
     * @param fileName
     *            文件名
     * @param pass
     *            密码
     * @author Ziyear 2021-4-21 22:27
     */
    public static void encryptFile(String fileName, String pass) throws IOException, GeneralSecurityException {
        byte[] decData;
        byte[] encData;
        File inFile = new File(fileName);
        // Generate the cipher using pass:
        Cipher cipher = FileSecurityUtils.makeCipher(pass, true);

        // Read in the file:
        FileInputStream inStream = new FileInputStream(inFile);

        int blockSize = 8;
        // Figure out how many bytes are padded
        int paddedCount = blockSize - ((int)inFile.length() % blockSize);

        // Figure out full size including padding
        int padded = (int)inFile.length() + paddedCount;

        decData = new byte[padded];

        inStream.read(decData);

        inStream.close();

        // Write out padding bytes as per PKCS5 algorithm
        for (int i = (int)inFile.length(); i < padded; ++i) {
            decData[i] = (byte)paddedCount;
        }

        // Encrypt the file data:
        encData = cipher.doFinal(decData);

        // Write the encrypted data to a new file:
        FileOutputStream outStream = new FileOutputStream(new File(fileName + ".encrypted"));
        outStream.write(encData);
        outStream.close();
    }

    /**
     * 功能描述 : 使用派生自密码短语的密钥将一个文件解密为第二个文件
     *
     * @param fileName
     *            文件名
     * @param pass
     *            密码
     * @author Ziyear 2021-4-21 22:28
     */
    public static void decryptFile(String fileName, String pass) throws GeneralSecurityException, IOException {
        String fileExt =
            fileName.substring(fileName.lastIndexOf(".") == -1 ? fileName.length() : fileName.lastIndexOf("."));

        byte[] encData;
        byte[] decData;
        File inFile = new File(fileName + ".encrypted");

        // Generate the cipher using pass:
        Cipher cipher = FileSecurityUtils.makeCipher(pass, false);

        // Read in the file:
        FileInputStream inStream = new FileInputStream(inFile);
        encData = new byte[(int)inFile.length()];
        inStream.read(encData);
        inStream.close();
        // Decrypt the file data:
        decData = cipher.doFinal(encData);

        // Figure out how much padding to remove

        int padCount = (int)decData[decData.length - 1];

        // Naive check, will fail if plaintext file actually contained
        // this at the end
        // For robust check, check that padCount bytes at the end have same value
        if (padCount >= 1 && padCount <= 8) {
            decData = Arrays.copyOfRange(decData, 0, decData.length - padCount);
        }

        // Write the decrypted data to a new file:
        FileOutputStream target = new FileOutputStream(new File(fileName + ".decrypted" + fileExt));
        target.write(decData);
        target.close();
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值