接到一个奇怪的业务:
先使用公钥对已经加密过的上传文件进行解密,再使用另一个密钥对解密好的文件进行加密,然后保存到内网:
https://blog.csdn.net/ylcacsdn/article/details/73866091 感谢这位博主的文章,给我提供了非常大的帮助!
直接上代码Demo:
Controller 类:
@RestController @RequestMapping("/file") @Slf4j /** * 笔录文件保存类 */ public class FileController { @Autowired private ProjectUrl projectUrl; /** * 文件公钥解密后加密保存 * @param file 文件本体 * @return */ @PostMapping("/decryptFile") public ResultVO decryptFile(@RequestParam("file") MultipartFile file) { if (file.isEmpty()) { log.error("【保存失败!文件出错,file={}】", file); return ResultVoUtil.error(ResultEnum.FILE_ERROR); } // 文件名加上文件后缀名 String originalName = file.getOriginalFilename(); String suffixName = originalName.substring(originalName.lastIndexOf(".")); String filename = UUID.randomUUID()+ String.valueOf(new Random().nextInt(1000)) + suffixName; // 解密文件后保存 UpLoadFileUtil.saveAndEditFile(file, projectUrl.getFilePath(), filename, AESTypeEnum.DECRYPT.getCode()); return ResultVoUtil.success(); } }
UpLoadFileUtil 对文件加密的工具类:
public class UpLoadFileUtil { /** * * @param file 上传源文件 * @param filePath 保存路径 * @param fileName 保存文件名 * @param type 密文类型 */ public static void saveAndEditFile(MultipartFile file, String filePath, String fileName, Integer type) { // 公共密钥 String cKey = "123"; // 开始加密文件 // 临时解密文件 File tempFile = new File(filePath + "_" + fileName); // 再加密的目标文件 File goalFile = new File(filePath + fileName); if (!tempFile.getParentFile().exists()) { tempFile.getParentFile().mkdirs(); } if (tempFile.isFile() && tempFile.exists()) { tempFile.delete(); } if (type == AESTypeEnum.ENCRYPT.getCode()) { // 文件加密 tempFile = AESUtil.encryptFile(file, tempFile, cKey); }else if (type == AESTypeEnum.DECRYPT.getCode()) { // 文件解密 tempFile = AESUtil.decryptFile(file, tempFile, cKey); // 使用密钥2加密 String sKey2 = "456"; goalFile = AESUtil.encryptFile(tempFile, goalFile, sKey2); if (tempFile.exists()) tempFile.delete(); }else if (type == AESTypeEnum.NONE.getCode()) { try { file.transferTo(tempFile); } catch (IOException e) { e.printStackTrace(); } } } }
AESTypeEnum 枚举类:
@Getter public enum AESTypeEnum { ENCRYPT(0, "AES加密"), DECRYPT(1, "AES解密"), NONE(2, "不加密") ; private Integer code; private String msg; AESTypeEnum(Integer code, String msg) { this.code = code; this.msg = msg; } }
AESUtil 类:(用于AES流的初始化的工具类)
public class AESUtil { // AES 加密初始化 public static Cipher initAESCipher(String sKey, int cipherMode) { // 创建Key gen KeyGenerator generator = null; Cipher cipher = null; try { generator = KeyGenerator.getInstance("AES"); generator.init(128, new SecureRandom(sKey.getBytes())); SecretKey secretKey = generator.generateKey(); byte[] codeFormat = secretKey.getEncoded(); SecretKeySpec keySpec = new SecretKeySpec(codeFormat, "AES"); cipher = Cipher.getInstance("AES"); // 初始化 cipher.init(cipherMode, keySpec); } catch (NoSuchAlgorithmException e) { e.printStackTrace(); } catch (InvalidKeyException e) { e.printStackTrace(); } catch (NoSuchPaddingException e) { e.printStackTrace(); } return cipher; } /** * 文件格式化 * @param sourceFile1 上传文件 * @param sourceFile2 本地文件 * @param encrypFile 加密后的文件 * @param sKey 密钥 * @param type 加密类型 * @return */ public static File enOrDeFile(MultipartFile sourceFile1, File sourceFile2, File encrypFile, String sKey, int type) { InputStream inputStream = null; OutputStream outputStream = null; try { if (sourceFile1 != null) inputStream = sourceFile1.getInputStream(); if (sourceFile2 != null) inputStream = new FileInputStream(sourceFile2); outputStream = new FileOutputStream(encrypFile); Cipher cipher = initAESCipher(sKey, type); CipherInputStream cipherInputStream = null; CipherOutputStream cipherOutputStream = null; if (Cipher.ENCRYPT_MODE == type) { // 创建加密流 cipherInputStream = new CipherInputStream(inputStream, cipher); }else if (Cipher.DECRYPT_MODE == type) { // 创建解密流 cipherOutputStream = new CipherOutputStream(outputStream, cipher); } byte [] cache = new byte[1024]; int isread = 0; if (Cipher.ENCRYPT_MODE == type) { // 加密流写入文件 while ((isread = cipherInputStream.read(cache, 0, cache.length)) != -1) { outputStream.write(cache, 0, isread); } }else if (Cipher.DECRYPT_MODE == type) { // 解密流开始写入文件 while ((isread = inputStream.read(cache, 0, cache.length)) != -1) { cipherOutputStream.write(cache, 0, isread); } } if (cipherInputStream != null) cipherInputStream.close(); if (cipherOutputStream != null) cipherOutputStream.close(); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } finally { try { if (inputStream != null) inputStream.close(); if (outputStream != null) outputStream.close(); } catch (IOException e) { e.printStackTrace(); } } return encrypFile; } // 文件加密 public static File encryptFile(MultipartFile sourceFile, File encrypFile, String sKey) { File file = enOrDeFile(sourceFile, null, encrypFile,sKey, Cipher.ENCRYPT_MODE); return file; } /** * 文件解密 * @param sourceFile http通讯文件 * @param encrypFile 目标文件 * @param sKey 密钥 * @return */ public static File decryptFile(MultipartFile sourceFile, File encrypFile, String sKey) { File file = enOrDeFile(sourceFile, null, encrypFile,sKey, Cipher.DECRYPT_MODE); return file; } /** * 加密文件 * @param sourceFile 源文件 * @param encrypFile 目标文件 * @param sKey 密钥 * @return */ public static File encryptFile(File sourceFile, File encrypFile, String sKey) { File file = enOrDeFile(null, sourceFile, encrypFile, sKey, Cipher.ENCRYPT_MODE); return file; } }
文件上传测试:
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width,initial-scale=1.0,user-scalable=no"> <title></title> </head> <body> <div class="content"> <h3>文件解密</h3> <input id="fileupload" type="file" name="file" data-url="/file/decryptFile"> </div> <script type="text/javascript" src="/js/jquery-1.8.3.min.js"></script> <script type="text/javascript" src="/js/jquery.ui.widget.js"></script> <script type="text/javascript" src="/js/jquery.iframe-transport.js"></script> <script type="text/javascript" src="/js/jquery.fileupload.js"></script> <script> $(function(){ }) $('#fileupload').fileupload({ dataType: 'json', url: "/file/decryptFile",//文件的后台接受地址 //设置进度条 progressall: function (e, data) { var progress = parseInt(data.loaded / data.total * 100); $('#progress .bar').css( 'width', progress + '%' ); }, //上传完成之后的操作,显示在img里面 done: function (e, data){ $("#uploadimg").attr({src: data.result.pic_url}); $("#uploadimg").css({width: "400px", height: "400px"}); } }); </script> </body> </html>
现在开始上传一份使用公钥“123”加密过的文件:
后台打断点调试:
可以看到,tempFile文件的解密内容了:

}
}