Java实现文件加密只读保护工具类

9/27/2022 excel

# 需求前景

项目中需要导出一份Excel 以及 Word ,并且需要用户自定义文件密码。于是便写了一个适用于WordExcel的加密保护工具类

# FileReadonlyProtectionUtil

/**
 * @version 1.0.0
 * @className: FileReadonlyProtectionUtil
 * @description: 文件只读密码保护
 * @author: LiJunYi
 */
@Slf4j
public class FileReadonlyProtectionUtil
{
    /**
     * word 执行只读保护
     *
     * @param filePath 文件路径
     * @param password 文件解除保护密码,为 null则随机密码
     * @throws IOException ioexception
     */
    public static void enforceReadonlyProtectionWord(String filePath,String password) throws IOException
    {
        log.info("------ word执行只读保护开始 ------");
        // try-with-resources 自动关闭文件流
        Path path = Paths.get(filePath);
        try(InputStream in = Files.newInputStream(path))
        {
            XWPFDocument document = new XWPFDocument(in);
            if (StrUtil.isEmpty(password))
            {
                //  填写窗口模式,密码随机
                document.enforceReadonlyProtection(RandomUtil.randomString(10), HashAlgorithm.sha512);
                // 其他几种形式
                // document.isEnforcedReadonlyProtection();不行
                // document.enforceReadonlyProtection("123", HashAlgorithm.md5);wps无效
                // document.enforceReadonlyProtection("123", HashAlgorithm.sha512);可以,但是依然可以复制
                // document.enforceTrackedChangesProtection("123", HashAlgorithm.sha512);修订
                // document.enforceCommentsProtection("123", HashAlgorithm.sha512);//批注
            }else
            {
                //  填写窗口模式,指定密码
                document.enforceReadonlyProtection(password, HashAlgorithm.sha512);
            }
            OutputStream oaf = Files.newOutputStream(path);
            document.write(oaf);
            oaf.flush();
            oaf.close();
            document.close();
            log.info("------ word执行只读保护结束 ------");
        }
    }

    /**
     * excel 执行加密保护
     *
     * @param filePath 文件路径
     * @param password 密码
     * @throws Exception 异常
     */
    public static void enforceEncryptProtectionExcel(String filePath,String password) throws Exception
    {
        File fileSource = new File(filePath);
        // 文件加密
        POIFSFileSystem fs = new POIFSFileSystem();
        EncryptionInfo info = new EncryptionInfo(EncryptionMode.agile);
        Encryptor enc = info.getEncryptor();
        enc.confirmPassword(password);
        OPCPackage opc = OPCPackage.open(fileSource, PackageAccess.READ_WRITE);
        OutputStream os = enc.getDataStream(fs);
        opc.save(os);
        opc.close();
        // 导出之前一定要先关闭加密文件流,不然导出文件会损坏而无法打开
        os.close();
        // 导出
        FileOutputStream fos = new FileOutputStream(fileSource);
        fs.writeFilesystem(fos);
        fos.close();
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75

# 文件内容加密工具类

/**
 *  文件内容加密工具类
 * @author LiJunYi
 */
public class FileEncryptUtil {

    private Key key;

    private FileEncryptUtil(String str){
        //生成秘钥
        getKey(str);
    }

    /**
     * 根据参数生成KEY
     */
    private void getKey(String strKey){
        try {
            KeyGenerator generator = KeyGenerator.getInstance("AES");
            generator.init(new SecureRandom(strKey.getBytes()));
            this.key = generator.generateKey();
            generator = null;
        }catch (Exception e){
            System.out.println(e.getMessage());
        }
    }

    /**
     * 对文件进行加密并保存目标文件destFile中
     *
     * @param file   要加密的文件
     * @param destFile 加密后存放的文件名
     */
    private void encrypt(String file,String destFile) throws Exception{
        Cipher cipher = Cipher.getInstance("AES");
        cipher.init(Cipher.ENCRYPT_MODE,this.key);
        InputStream is = new FileInputStream(file);
        OutputStream out = new FileOutputStream(destFile);
        CipherInputStream cis = new CipherInputStream(is,cipher);
        byte[] buffer = new byte[1024];
        int r;
        while ((r = cis.read(buffer)) > 0){
            out.write(buffer,0,r);
        }
        cis.close();
        is.close();
        out.close();
    }

    /**
     * 解密文件
     * @param file 已加密的文件 
     * @param dest 解密后存放的文件名
     */
    private void decrypt(String file, String dest) throws Exception {
        Cipher cipher = Cipher.getInstance("AES");
        cipher.init(Cipher.DECRYPT_MODE,this.key);
        InputStream is = new FileInputStream(file);
        OutputStream out = new FileOutputStream(dest);
        CipherOutputStream cos = new CipherOutputStream(out,cipher);
        byte[] buffer = new byte[1024];
        int r;
        while ((r = is.read(buffer)) >= 0){
            System.out.println();
            cos.write(buffer,0,r);
        }
        cos.close();
        out.close();
        is.close();
    }

    public static void main(String[] args) throws Exception {
        FileEncryptUtil td = new FileEncryptUtil("aaa");
        //加密
        td.encrypt("G:/file.docx", "G:/file加密.docx");
        //解密
        td.decrypt("G:/file加密.docx", "G:/file.docx");
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79