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、思路(复盘)