项目实战:Java实现超大文件分片加密和解密(附完整源码)

一,项目需求

今天在工作中遇到这样一个问题,系统中,文件上传的过程中需要进行加密,下载时再进行对应的解密。当文件不是太大时没有问题,但是当文件过大时,比如有个几百M或者几个G时就出问题了。这么大文件进行一次性加密解密,时间太长以至于出现系统超时,甚至出现内存溢出的情况。如何解决?经过研究,我们在进行文件加密时其实没有必要加密整个文件,只加密其中的一部分(比如加密1M文件),然后和另外一部分不加密的文件拼接在一起,生成最终的加密文件。虽然只加密了其中一部分,但是因为加密其中的一部分,对整个文件的格式其实是有破坏的,所以最终生成的文件其实也是一个加密的状态,用户用对应的软件是打不开的,这样就起到了文件加密的作用。下面讲解实现方法和过程。

二,实现思路

我们假定只加密文件的前1M,将这个文件分为前1M和剩余文件两个部分,前1M加密,后面剩余的部分不加密,如图1:
在这里插入图片描述
图2即为加密后的文件结构,下面详述加密解密的步骤
**加粗样式**在这里插入图片描述

  • 第一步。我们取出文件前1M并进行加密,经测试,加密后的文件会增大一点,但不会太多,基本是几十个字节。
  • 第二步。将前1M加密后的文件和分隔符进行拼接,这里分隔符的作用是在解密时依据分隔符找到加密的文件内容。
  • 第三步。增加无用的填充的数据和第二步生成的文件拼接,保证大小为2M。这里填充到2M的目的也是为了解密时的方便,即解密时我们固定取加密文件的前2M来进行解密。
  • 第四步。将第三步生成的2M文件和后面剩余未加密的文件进行拼接,生成最终的密文。至此加密工作完成。底下介绍解密过程。
  • 第五步。解密,我们固定取密文的前2M文件,然后依据分隔符找到前1M的加密文件,然后进行解密,然后和剩余未加密的文件进行拼接,最终生成解密后的完成文件。

三,源码分析

主要的核心代码即为加密和解密的方法,源码如下:

   
   private static String SEPARATOR = "******file_encode_separator******";//文件分段加密分隔符

    private static int EN_LIMIT_SIZE = 1024 * 1024;//加密文件临界大小,1M.

    private static int DE_LIMIT_SIZE = 2 * 1024 * 1024;//解密文件临界大小,2M.

   /**
     * 加密文件
     *
     * @return
     * @throws Exception
     */
    public static byte[] encryptFile(byte[] data) throws Exception {
        if (data.length > EN_LIMIT_SIZE) {//大于1M
            /**
             * 取前1M并且加密
             */
            byte[] data_1m = Arrays.copyOf(data, EN_LIMIT_SIZE);
            byte[] data_1m_en = SM2Util.encrypt(SM2Util.PUBLIC_KEY, data_1m);
            /**
             * 读取剩余的文件
             */
            byte[] data_left = Arrays.copyOfRange(data, EN_LIMIT_SIZE, data.length);
            /**
             * 合并加密的1M文件和分隔符
             */
            byte[] data_1m_en_separator = ArrayUtils.byteMerger(data_1m_en, SEPARATOR.getBytes());
            /**
             * 填充至2M
             */
            byte[] data_padding = new byte[DE_LIMIT_SIZE - data_1m_en_separator.length];
            Arrays.fill(data_padding, (byte) 1);
            byte[] data_2m = ArrayUtils.byteMerger(data_1m_en_separator, data_padding);
            /**
             *生成最终加密文件
             */
            return ArrayUtils.byteMerger(data_2m, data_left);
        } else {//小于等于1M,全部加密
            return SM2Util.encrypt(SM2Util.PUBLIC_KEY, data);
        }
    }

    /**
     * 解密文件
     *
     * @return
     */
    public static byte[] decryptFile(byte[] data) throws Exception {
        if (data.length > DE_LIMIT_SIZE) {//大于2M
            /**
             * 取前2M并且解密
             */
            byte[] data_2m = Arrays.copyOf(data, DE_LIMIT_SIZE);
            int index_separator = ArrayUtils.searchInByteArray(data_2m, SEPARATOR.getBytes());
            if (index_separator > 0) {//存在分隔符
                byte[] data_pre_en = Arrays.copyOf(data_2m, index_separator);
                byte[] data_pre = SM2Util.decrypt(SM2Util.PRIVATE_KEY, data_pre_en);
                byte[] data_left = Arrays.copyOfRange(data, DE_LIMIT_SIZE, data.length);//取2M后的剩余部分文件
                return ArrayUtils.byteMerger(data_pre, data_left);//生成最终解密文件
            } else {
                return SM2Util.decrypt(SM2Util.PRIVATE_KEY, data);
            }
        } else {//文件小于2M,采用全部解密
            return SM2Util.decrypt(SM2Util.PRIVATE_KEY, data);
        }
    }

编写测试main方法进行测试:

String resource = "E:\\source.doc";

String file_en = "E:\\source_en.doc";

String file_de = "E:\\source_de.doc";

writeFile(file_en, encryptFile(readFile(resource)));

writeFile(file_de, decryptFile(readFile(file_en)));

四,最后总结

好了,至此项目中碰到大文件加密解密的处理技巧介绍完毕。今天分享给大家,希望对大家有用,欢迎留言,一起讨论。关注以下公众号,回复 “文件” 即可获得完整源代码。
在这里插入图片描述

Java中对文本文件进行加密解密的操作可以使用加密算法和解密算法来实现。常用的加密算法有DES、AES、RSA等,解密算法则是对应的解密算法。下面是一个简单的示例,使用DES算法对文本文件进行加密解密加密操作: ```java import javax.crypto.Cipher; import javax.crypto.SecretKey; import javax.crypto.SecretKeyFactory; import javax.crypto.spec.DESKeySpec; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.security.SecureRandom; public class FileEncryptor { public static void encrypt(String key, File inputFile, File outputFile) throws Exception { FileInputStream inputStream = new FileInputStream(inputFile); FileOutputStream outputStream = new FileOutputStream(outputFile); byte[] buffer = new byte[1024]; SecureRandom secureRandom = new SecureRandom(key.getBytes()); DESKeySpec desKeySpec = new DESKeySpec(key.getBytes()); SecretKeyFactory secretKeyFactory = SecretKeyFactory.getInstance("DES"); SecretKey secretKey = secretKeyFactory.generateSecret(desKeySpec); Cipher cipher = Cipher.getInstance("DES"); cipher.init(Cipher.ENCRYPT_MODE, secretKey, secureRandom); int length; while ((length = inputStream.read(buffer)) != -1) { byte[] output = cipher.update(buffer, 0, length); if (output != null) { outputStream.write(output); } } byte[] output = cipher.doFinal(); if (output != null) { outputStream.write(output); } inputStream.close(); outputStream.flush(); outputStream.close(); } } ``` 解密操作: ```java import javax.crypto.Cipher; import javax.crypto.SecretKey; import javax.crypto.SecretKeyFactory; import javax.crypto.spec.DESKeySpec; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.security.SecureRandom; public class FileDecryptor { public static void decrypt(String key, File inputFile, File outputFile) throws Exception { FileInputStream inputStream = new FileInputStream(inputFile); FileOutputStream outputStream = new FileOutputStream(outputFile); byte[] buffer = new byte[1024]; SecureRandom secureRandom = new SecureRandom(key.getBytes()); DESKeySpec desKeySpec = new DESKeySpec(key.getBytes()); SecretKeyFactory secretKeyFactory = SecretKeyFactory.getInstance("DES"); SecretKey secretKey = secretKeyFactory.generateSecret(desKeySpec); Cipher cipher = Cipher.getInstance("DES"); cipher.init(Cipher.DECRYPT_MODE, secretKey, secureRandom); int length; while ((length = inputStream.read(buffer)) != -1) { byte[] output = cipher.update(buffer, 0, length); if (output != null) { outputStream.write(output); } } byte[] output = cipher.doFinal(); if (output != null) { outputStream.write(output); } inputStream.close(); outputStream.flush(); outputStream.close(); } } ``` 示例中使用的是DES算法,可以根据需要替换为其他算法。对于密钥,建议使用安全的方式存储,例如通过密码学哈希函数对其进行散列,以保证安全性。
评论 11
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值