接到一个奇怪的业务:
先使用公钥对已经加密过的上传文件进行解密,再使用另一个密钥对解密好的文件进行加密,然后保存到内网:
感谢这位博主的文章,给我提供了非常大的帮助!
直接上代码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 枚举类:
@Getterpublic 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; }}
文件上传测试:
文件解密
现在开始上传一份使用公钥“123”加密过的文件:
后台打断点调试:
可以看到,tempFile文件的解密内容了:
} }