需求描述
对原本代码生成的明文报表文件直接上传到目标服务器的流程,增加在上传到目标服务器之前将报表加密进行加密后上传的环节
代码参考
开发流程
1. 工具包使用
- 导入工具包
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcpg-jdk15on</artifactId>
<version>1.64</version>
</dependency>
- 使用工具类
加密的几个核心对象
PGPPublicKeyRingCollection
- 数据加密构造器,指定数据加密的方式
PGPDataEncryptorBuilder
addMethod方法添加公钥,
open方法
PGPEncryptedDataGenerator
//压缩
PGPCompressedDataGenerator
- 参考上述示例,了解加密流程
参考代码
//outputFileName 输出文件名,不带任何路径信息,默认输出在当前项目路径下,所以后续对加密后文件的操作,也可以使用这个outputFileName这个引入操作
//inputFileName 读取的文件路径:对哪个路径上的什么文件进行加密
//publicKeyStr 加密公钥的字符串
//armor 为true代表非二进制加密,false代表二进制加密
//withIntegrityCheck 暂时不知道
public static void encryptFile(String outputFileName, String inputFileName, String publicKeyStr, boolean armor,
boolean withIntegrityCheck) throws Exception {
Security.addProvider(new BouncyCastleProvider());
InputStream publicKeyInputStream = new ByteArrayInputStream(publicKeyStr.getBytes());
PGPPublicKey pgpPublicKey = GPGUtils.readPublicKey(publicKeyInputStream);
OutputStream out = null;
try {
out = new BufferedOutputStream(new FileOutputStream(outputFileName));
encryptFile(out, inputFileName, pgpPublicKey, armor, withIntegrityCheck);
} finally {
closeStream(out);
}
}
private static void encryptFile(OutputStream out, String fileName, PGPPublicKey encKey, boolean armor, boolean withIntegrityCheck) throws Exception {
OutputStream cOut = null;
try {
if (armor) {
out = new ArmoredOutputStream(out);
}
byte[] bytes = compressFile(fileName, CompressionAlgorithmTags.ZIP);
PGPEncryptedDataGenerator encGen = new PGPEncryptedDataGenerator(new JcePGPDataEncryptorBuilder(PGPEncryptedData.CAST5)
.setWithIntegrityPacket(withIntegrityCheck).setSecureRandom(new SecureRandom()).setProvider(new BouncyCastleProvider()));
encGen.addMethod(new JcePublicKeyKeyEncryptionMethodGenerator(encKey).setProvider(new BouncyCastleProvider()));
cOut = encGen.open(out, bytes.length);
cOut.write(bytes);
} finally {
closeStream(cOut);
if (armor) {
closeStream(out);
}
}
}
static byte[] compressFile(String fileName, int algorithm) throws IOException {
ByteArrayOutputStream bOut = new ByteArrayOutputStream();
PGPCompressedDataGenerator comData = new PGPCompressedDataGenerator(algorithm);
PGPUtil.writeFileToLiteralData(comData.open(bOut), PGPLiteralData.BINARY, new File(fileName));
comData.close();
return bOut.toByteArray();
}
文件前置处理
- 一般加密之前文件都是压缩后的,例如原始文件是csv格式的,先压缩为csv.gz,再加密后就是csv.gz.gpg
针对读取指定路径下的原始格式文件,转换成输出流或者字节码文件方便操作
import java.io.*;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
public class FileToOutputStreamExample {
public static void main(String[] args) {
String filePath = "/your/absolute/file/path/sample.txt"; // 指定文件的绝对路径
// 检查文件是否存在
File file = new File(filePath);
if (!file.exists() || !file.isFile()) {
System.out.println("指定文件不存在或不是一个文件。");
return;
}
// 创建输出流
try {
OutputStream outputStream = new FileOutputStream("output.txt"); // 这里使用示例输出流,你可以替换为其他输出流
// 使用文件路径创建输入流并读取文件内容
Path path = Paths.get(filePath);
Files.copy(path, outputStream);
// 关闭输出流
outputStream.close();
System.out.println("文件内容已经写入输出流。");
} catch (IOException e) {
e.printStackTrace();
}
}
}
import java.io.*;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
public class FileToByteArrayExample {
public static void main(String[] args) {
String filePath = "/your/absolute/file/path/sample.txt"; // 指定文件的绝对路径
// 检查文件是否存在
File file = new File(filePath);
if (!file.exists() || !file.isFile()) {
System.out.println("指定文件不存在或不是一个文件。");
return;
}
try {
// 使用文件路径创建输入流并读取文件内容到字节数组
Path path = Paths.get(filePath);
byte[] fileBytes = Files.readAllBytes(path);
// 现在,fileBytes 包含了文件的内容
// 你可以在这里对字节数组进行处理,例如写入其他地方或进行其他操作
System.out.println("文件内容已经读取到字节数组。");
} catch (IOException e) {
e.printStackTrace();
}
}
}
@PostMapping("/test01")
public void test01(@PathVariable("organizationId") Long tenantId, @RequestBody Map<String, String> map) throws Exception {
//String fileAbsolutePath = "D:\\Code\\Coding\\OneCode\\OMS\\pnmo-financial-management\\saleshistory_20231030_193121_445.csv";
String date = "20231031";
String fileAbsolutePath = "D:\\Code\\Coding\\hello.csv";
String fileName = map.get("fileName");
Path path = Paths.get(fileAbsolutePath);
byte[] fileBytes = Files.readAllBytes(path);
//GzipUtil.compress(fileBytes);
File encryptBeforeFile = new File(fileName);
try (FileOutputStream fos = new FileOutputStream(encryptBeforeFile)) {
fos.write(Objects.requireNonNull(GzipUtil.compress(fileBytes)));
}
RedisTransferConf transferConf = foundationClient.getTransferConf(tenantId, "PFIN.SALE_HISTORY_TO_DATA_PF");
String gpgFileName = fileName + FinancialConstants.FileTypeSuffix.GPG;
GPGFileHelper.encryptFile(gpgFileName, encryptBeforeFile.getAbsolutePath(), transferConf.getPrivateKey(), true, true);
File encryptAfterFile = new File(gpgFileName);
byte[] bytes = FileReader.create(encryptAfterFile).readBytes();
Map<String, String> metaMap = new HashMap<>();
Map<String, Object> metadata = new HashMap<>(5);
metadata.put("opeDate", date);
metadata.put("gbuCd", Collections.singletonList(map.get("gbuCd")));
metadata.put("brndCd", Collections.singletonList(map.get("brndCd")));
metadata.put("dataBuCd", Collections.singletonList(map.get("dataBuCd")));
metadata.put("cntryCd", Collections.singletonList(map.get("cntryCd")));
metaMap.put("if-meta-info", JsonHelper.objectToString(metadata));
BaseUtil.upload(transferConf, gpgFileName, FileConstants.FileContentType.GZIP, bytes, metaMap);
}