问题描述
摘要:我正在寻找一些 PGP 加密的 InputStream 实现,而不是 BouncyCastle 的 OutputStream 实现。
我目前正在重构文件上传 servlet 的一些代码,该代码对上传的数据进行 PGP 加密并将其转发到 REST 服务进行存储。我尝试以流式方式执行此操作,而无需在内存或磁盘中缓冲整个文件。
在对数据进行加密的 servlet 中,我在 org.apache.commons.fileupload.servlet.ServletFileUpload
的帮助下读取数据,它提供对作为 InputStream 的数据的访问。 IE。我的 servlet 必须主动从浏览器读取数据(“拉”它)。
要访问 REST 接口,我使用 org.apache.http.client.methods.HttpPost
。在这里,我也必须以 InputStream 的形式提供数据,远程 REST 服务负责从我的 servlet 中“拉取”数据。
问题:BouncyCastle 使用 PGPEncryptedDataGenerator
创建一个加密的 OutputStream,它需要我的 servlet write
数据(线程“推送”数据)。要将两端的 OutputStream 与 InputStreams 连接,我需要 InputStream.transferTo(OutputStream)
将来自 Servlet 上传的数据复制到加密输出流中(为此我需要一个额外的线程),以及附加的 PipedStream 操作以从中复制加密数据再次将 OutputStream 转换为 InputStream。
现在这真的很复杂,如果我可以使用加密的 InputStream 来代替它会容易得多。有了这个,我可以从 servlet 包装 InputStream 并将它传递给 REST 接口处的 HttpPost,消除对额外线程的需要,因为来自消费 REST 服务的“拉”操作将通过我的 servlet 代码直接连接到提供原始数据的浏览器上的“拉”。
我的问题:有人知道/有一些 BouncyCastle 的 EncryptingInputStream 实现吗?
这是我基于使用加密输出流的工作代码示例。要运行它,您必须在类路径上有一个“keyBox”格式的公钥环,并在 CLI 上提供密钥 userId。
public class Main {
public static void main(String...args) throws NoSuchAlgorithmException,NoSuchProviderException,InvalidAlgorithmParameterException,PGPException,IOException,ExecutionException,InterruptedException {
Security.addProvider(new BouncyCastleProvider());
final PGPPublicKey publicKey = readPublicKeyRing(args[0]);
ByteArrayOutputStream output = new ByteArrayOutputStream(); // Simulates the REST-service as data sink.
// Setup encryption
final JcePGPDataEncryptorBuilder encryptorBuilder = new JcePGPDataEncryptorBuilder(SymmetricKeyAlgorithmTags.AES_256)
.setWithIntegrityPacket(true)
.setSecureRandom(new SecureRandom()).setProvider("BC");
final JcePublicKeyKeyEncryptionMethodGenerator methodGenerator = new JcePublicKeyKeyEncryptionMethodGenerator(publicKey)
.setProvider("BC");
final PGPEncryptedDataGenerator encGen = new PGPEncryptedDataGenerator(encryptorBuilder);
encGen.addMethod(methodGenerator);
PGPLiteralDataGenerator dataGenerator = new PGPLiteralDataGenerator();
// Setup the streams.
try (PipedInputStream recEncInput = new PipedInputStream()) {
// The thread to process the encrypted data has to be started first.
final CompletableFuture<Void> receiveData = CompletableFuture.runAsync(() -> {
System.out.println("Pulling encrypted data from PipedInputStream");
try {
recEncInput.transferTo(output);
System.out.println("Finished receiving encrypted data from pipe");
} catch (IOException e) {
e.printstacktrace();
}
});
try (PipedOutputStream pipedOutput = new PipedOutputStream(recEncInput);
OutputStream encOut = encGen.open(pipedOutput,new byte[4096]);
OutputStream effectiveOut = dataGenerator.open(encOut,PGPLiteralData.BINARY,"Message",new Date(),new byte[4096]))
{
// copy the data from servlet input stream to encrypting output stream.
try (InputStream inputStream = new ByteArrayInputStream(Strings.toByteArray("Hello,world!"))) { // Simulates the servlet input stream with uploaded data.
inputStream.transferTo(effectiveOut);
System.out.println("Finished transfering data to encrypting OutputStream");
} catch (IOException e) {
e.printstacktrace();
}
}
receiveData.get(); // wait until copy thread has finished (after the encrypting streams are closed!)
}
byte[] encData = output.toByteArray();
Files.write(Paths.get("pgp-encrypted-string.pgp"),encData);
}
/**
* Read the public key for given userId from "pubring.kbx" on classpath.
* @param userId
*/
static PGPPublicKey readPublicKeyRing(String userId) throws IOException,NoSuchAlgorithmException,NoSuchProviderException {
try (final InputStream pubringString = Main.class.getClassLoader().getResourceAsstream("pubring.kbx")) {
final JcaKeyBox keyBox = new JcaKeyBoxBuilder().build(pubringString);
final List<KeyBlob> blobs = keyBox.getKeyBlobs();
final Optional<KeyBlob> keyBlob = blobs.stream().filter(blob -> {
boolean matches = blob.getUserIds().stream()
.map(uid -> uid.getUserIDAsstring())
.anyMatch(uidStr -> uidStr.toLowerCase(Locale.ROOT).contains(userId.toLowerCase(Locale.ROOT)));
return matches;
}).findAny();
if (keyBlob.isPresent()) {
PublicKeyRingBlob pgkr = (PublicKeyRingBlob)keyBlob.get();
PGPPublicKeyRing ring = pgkr.getPGPPublicKeyRing();
return ring.getPublicKey();
} else {
return null;
}
}
}
}
解决方法
暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!
如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。
小编邮箱:dio#foxmail.com (将#修改为@)