JAVA文件内容加密(异或^方式)

JAVA加密文件内容(异或^方式)

<dependency>
    <groupId>cn.hutool</groupId>
    <artifactId>hutool-all</artifactId>
    <version>***</version>
</dependency>
package pub;

import cn.hutool.core.io.FileUtil;
import cn.hutool.core.lang.Console;

import java.io.File;
import java.io.RandomAccessFile;
import java.util.List;
import java.util.Scanner;

public class AppMain {

    // 最小支持文件大小10K
    public static final long MINIMUM_FILE_SIZE = 10240L;

    //加密密钥,可写成读取配置文件
    public static final int KEY = ******;

    // 解密标志
    public static String DEC_MARK = "DEC0000000000000";
    // 加密标志
    public static String ENC_MARK = "ENC1111111111111";

	/**
     * 文件内容加密
     *
     * @param file 要加密的文件
     * @param key  加密密钥
     */
    public static void encFile(File file, int key) {
        long start = System.currentTimeMillis();

        try (RandomAccessFile raf = new RandomAccessFile(file, "rw")) {

            //   ---------------------------------------------------- 先读取文件末尾16个长度,判断加密,还是解密。 加解密标识无实际意义,仅作日志打印使用
            raf.seek(raf.length() - 16);
            byte[] endBytes = new byte[16];
            raf.read(endBytes, 0, endBytes.length);

            String mark;
            int markIndex = 2; // 0=使用工具解密状态,1=使用工具加密状态,2=未使用过工具(默认)
            if (ENC_MARK.equals(new String(endBytes))) {
                // 使用工具加密过
                markIndex = 1;
                mark = DEC_MARK;
                Console.log("文件=[{}]为加密状态,现操作解密:", file);
            } else if (DEC_MARK.equals(new String(endBytes))) {
                // 使用工具解密过
                markIndex = 0;
                Console.log("文件=[{}]为解密状态,现操作加密:", file);
                mark = ENC_MARK;
            } else {
                mark = ENC_MARK;
                Console.log("文件=[{}]为初始状态,现操作加密:", file);
            }

            //  ---------------------------------------------------- 每 MINIMUM_FILE_SIZE = 10K 数据,读取前1KB(1024)进行加密
            raf.seek(0);
            for (int i = 0; i < raf.length() / MINIMUM_FILE_SIZE; i++) {
                byte[] bytes = new byte[1024];
                raf.seek(MINIMUM_FILE_SIZE * i);
                // 读取前1KB(1024)进行加密
                raf.read(bytes, 0, bytes.length);
                byte[] newBytes = new byte[1024];
                for (int j = 0; j < bytes.length; j++) {
                    newBytes[j] = (byte) (bytes[j] ^ key);
                }
                raf.seek(MINIMUM_FILE_SIZE * i);
                raf.write(newBytes, 0, newBytes.length);
            }

            // ---------------------------------------------------对文件头前1024字节 与 key 异或加密
           /* raf.seek(0);
            byte[] bytes = new byte[1024];
            raf.read(bytes, 0, bytes.length);
            byte[] newBytes = new byte[1024];
            for (int i = 0; i < bytes.length; i++) {
                newBytes[i] = (byte) (bytes[i] ^ key);
            }
            raf.seek(0);
            raf.write(newBytes, 0, newBytes.length);*/

            // ----------------------------------------------------文件末尾写16位加解密标志
            if (markIndex == 2) {
                // 未使用为加密工具. 使用工具操作加/解密后文件多出16位加解密标识,不影响文件正常使用
                raf.seek(raf.length());
            } else {
                raf.seek(raf.length() - 16);
            }
            byte[] tempBytes = mark.getBytes();
            raf.write(tempBytes, 0, tempBytes.length);

            raf.close();

            long end = System.currentTimeMillis();
            Console.log("文件=[{}]=>{}成功,耗时=[{}]ms", file, markIndex == 1 ? "解密" : "加密", (end - start));
        } catch (Exception e) {
            Console.error("文件=[{}]加/解密失败,错误原因:[{}]", file, e.getMessage());
            e.printStackTrace();
        }
    }

    public static void main(String[] args) {
        try (Scanner scanner = new Scanner(System.in)) {
            System.out.println("请输入密码:");
            String keyStr = scanner.nextLine();
            if (!String.valueOf(KEY).equals(keyStr)) {
                Console.error("密钥不正确,退出!\n");
                return;
            }
            System.out.println("请输入加/解密文件夹路径:");
            String encPath = scanner.nextLine();
            if (!FileUtil.isDirectory(encPath)) {
                Console.error("输入的文件夹路径=[{}]不正确,退出!");
                return;
            }
            // 过滤掉.jar本执行程序
            List<File> files = FileUtil.loopFiles(encPath, pathname -> !pathname.getName().toLowerCase().endsWith(".jar"));
            for (File file : files) {
                if (!file.exists() || file.isDirectory()) {
                    Console.error("文件=[{}]无法访问,无法加密,continue.", file);
                    continue;
                }
                if (file.length() < MINIMUM_FILE_SIZE) {
                    Console.error("文件=[{}] length=[{}]<[{}] 无法加密,continue.", file, file.length(), MINIMUM_FILE_SIZE);
                    continue;
                }
                if (!file.canWrite()) {
                    Console.error("文件=[{}]不可写,无法加密,continue.", file, MINIMUM_FILE_SIZE);
                    continue;
                }
                encFile(file, KEY);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

    }

}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值