java实现文件加解密方案
0、前序
上传加密:客户端上传文件,后台加密,将加密后的文件存储到文件服务器
下载解密:客户端请求文件,后台从文件服务器获取密文,解密返回客户端
注:对文件服务器上存储的文件需要做防篡改校验
效果预览:原文件,密文件,解密文件
![](https://img2022.cnblogs.com/blog/803841/202203/803841-20220311091537155-1176019246.png)
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、思路(复盘)