java实现文件加解密方案

0、前序

上传加密:客户端上传文件,后台加密,将加密后的文件存储到文件服务器
下载解密:客户端请求文件,后台从文件服务器获取密文,解密返回客户端
 
注:对文件服务器上存储的文件需要做防篡改校验
 
效果预览:原文件,密文件,解密文件

1、客户端(html)

<form action="http://192.168.2.170:8080/api/v1/test/file/encryption" method="post" enctype="multipart/form-data">
    <p><input type="file" name="file"></p>
    <p><input type="text" name="clintMD5" value="e926b155ebf5f192bd71dbcec7dcb171"></p>
    <p><input type="submit" value="submit"></p>
</form>

2、客户端上传、请求文件

3、服务端(源码)

package com.huang.mydemo.encryption;

import org.apache.commons.codec.digest.DigestUtils;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;

@RestController
@RequestMapping(value = "api/v1/test")
public class FileUploadEncryptionController {
    //加密解密秘钥,不能超过一个字节,也就是8位(生产环境可针对每个文件随机生成秘钥,确保每个文件的秘钥都不一样)
    private static final int secretKey = 99;     //0x99 十六进制0-99,10进制0-255随机产生【异或】秘钥
    private static int dataByte = 0; //文件字节内容


    /**
     * 文件加密
     * @param file   上传的文件
     * @param request
     * @return
     */
    @PostMapping("file/encryption")
    public String encryption(@RequestParam("file") MultipartFile file, HttpServletRequest request) {
        try {
            //0、先检查文件是否被篡改:此操作<选加>
            String srcMd5 = DigestUtils.md5Hex(file.getInputStream());
            System.out.println("源文件MD5:"+srcMd5);

            String clintMD5 = request.getParameter("clintMD5");
            System.out.println("clintMD5:"+clintMD5);
            
            if(!clintMD5.equals(srcMd5))  return "上传文件被篡改";


            //2、创建加密文件:临时文件<异或加密:不改变文件大小和格式>
            File encFile = new File("F:\\Users\\admin\\Desktop\\enc_file.png");
            if(!encFile.exists()){
                encFile.createNewFile();//创建临时文件
            }


            //3、加密文件
            InputStream fis = file.getInputStream();
            OutputStream fos = new FileOutputStream(encFile);

            System.out.println("-------加密开始------");
            while ((dataByte = fis.read()) > -1) {
                fos.write(dataByte^secretKey);
            }

            fis.close();
            fos.flush();
            fos.close();
            System.out.println("-------加密完成------");

            //4、生成加密文件的MD5,防止文件服务器篡改<必加>
            String encMd5 = DigestUtils.md5Hex(new FileInputStream(encFile));
            System.out.println("密文件MD5:"+encMd5);

            //TODO 5、存储加密文件

            //TODO 6、删除临时文件:encFile

            return "ok";
        } catch (Exception e) {
            return e.getMessage();
        }
    }

    /**
     * 解密文件
     * @param response
     */
    @GetMapping("file/decryption")
    public void decryption(HttpServletResponse response) {
        File f = null;
        try {
            //TODO 1、从文件服务器获取加密文件(这里直接取上面加密后的临时文件,生产环境从oss或其他文件服务器获取)
            File encFile = new File("F:\\Users\\admin\\Desktop\\enc_file.png");
            //加密文件的MD5值,检查文件是否被篡改
            String encMd5 = DigestUtils.md5Hex(new FileInputStream(encFile));
            System.out.println("密文件MD5:"+encMd5);

            //TODO 2、encMd5与存储时的密码MD5进行比对(略),检查文件是否被篡改<必加>

            //3、创建解密文件:临时文件
            File decFile = new File("F:\\Users\\admin\\Desktop\\dec_file.jpeg");

            if(!decFile.exists()){
                decFile.createNewFile();//创建临时文件
            }

            //4、解密
            InputStream fis  = new FileInputStream(encFile);
            OutputStream fos = new FileOutputStream(decFile);

            System.out.println("--------------解密开始--------------");
            while ((dataByte = fis.read()) > -1) {
                fos.write(dataByte^secretKey);
            }
            fis.close();
            fos.close();
            fos.flush();

            System.out.println("--------------解密完成--------------");

            //TODO 5、响应数据添加MD5,防止响应文件数据被篡改<选加>

            //6、返回解密后的文件
            InputStream stream = new FileInputStream(decFile);
            ServletOutputStream out = response.getOutputStream();

            byte buff[] = new byte[1024];
            int length = 0;

            while ((length = stream.read(buff)) > 0) {
                out.write(buff,0,length);
            }
            stream.close();
            out.close();
            out.flush();

            //TODO 7、删除临时文件:decFile

        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

4、思路(复盘)

 

 

posted @ 2022-03-11 09:36  福尔摩狼  阅读(4190)  评论(0编辑  收藏  举报