Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/392.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
PGP使用BouncyCastle/Java加密输入流_Java_Encryption_Bouncycastle_Pgp - Fatal编程技术网

PGP使用BouncyCastle/Java加密输入流

PGP使用BouncyCastle/Java加密输入流,java,encryption,bouncycastle,pgp,Java,Encryption,Bouncycastle,Pgp,摘要:我正在寻找一些PGP加密InputStream实现,而不是BouncyCastle的OutputStream实现 我目前正在为一个文件上传servlet重构一些代码,PGP对上传的数据进行加密,并将其转发给REST服务进行存储。我尝试以流式方式来实现这一点,而无需在内存或磁盘中缓冲整个文件 在加密数据的servlet中,我通过org.apache.commons.fileupload.servlet.ServletFileUpload读取数据,它提供了对数据的InputStream访问。也

摘要:我正在寻找一些PGP加密InputStream实现,而不是BouncyCastle的OutputStream实现

我目前正在为一个文件上传servlet重构一些代码,PGP对上传的数据进行加密,并将其转发给REST服务进行存储。我尝试以流式方式来实现这一点,而无需在内存或磁盘中缓冲整个文件

在加密数据的servlet中,我通过
org.apache.commons.fileupload.servlet.ServletFileUpload
读取数据,它提供了对数据的InputStream访问。也就是说,我的servlet必须主动地从浏览器中读取数据(“拉”它)

要访问REST接口,我使用
org.apache.http.client.methods.HttpPost
。在这里,我还必须以InputStream的形式提供数据,远程REST服务负责从我的servlet中“提取”数据

问题:BouncyCastle使用
PGPEncryptedDataGenerator
创建加密输出流,这需要我的servlet
写入数据(线程“推送”数据)。要将两端的输出流与输入流连接起来,我需要
InputStream.transferTo(OutputStream)
将Servlet上传的数据复制到加密输出流(我需要一个额外的线程),并需要额外的管道流操作将加密数据从输出流再次复制到输入流

现在这真的很复杂,如果我可以用加密输入流来代替,那就容易多了。这样,我就可以从servlet包装InputStream并将其传递到REST接口处的HttpPost,这样就不需要额外的线程,因为来自消费REST服务的“pull”操作将通过我的servlet代码直接连接到提供原始数据的浏览器上的“pull”

我的问题:是否有人知道/拥有一些用于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;
        }
    }
}
}
公共类主{
publicstaticvoidmain(String…args)抛出NoSuchAlgorithmException、NoSuchProviderException、invalidalgorithParameterException、pgpeException、IOException、ExecutionException、interruptedeException{
addProvider(新的BouncyCastleProvider());
最终PGPPublicKey=readPublicKeyRing(参数[0]);
ByteArrayOutputStream output=new ByteArrayOutputStream();//将REST服务模拟为数据接收器。
//设置加密
最终JcePGPDataEncryptorBuilder encryptorBuilder=新的JcePGPDataEncryptorBuilder(SymmetricKeyAlgorithmTags.AES_256)
.SetWithIntegrityPack(真)
.setSecurerRandom(new SecureRandom()).setProvider(“BC”);
最终JCEPubliceKeyEncryptionMethodGenerator=新的JCEPubliceKeyEncryptionMethodGenerator(公钥)
.setProvider(“BC”);
最终PGPEncryptedDataGenerator encGen=新的PGPEncryptedDataGenerator(encryptorBuilder);
encGen.addMethod(methodGenerator);
PGPLiteralDataGenerator dataGenerator=新的PGPLiteralDataGenerator();
//设置流。
try(PipedInputStream recEncInput=new PipedInputStream()){
//必须首先启动处理加密数据的线程。
final CompletableFuture receiveData=CompletableFuture.runAsync(()->{
System.out.println(“从PipedInputStream中提取加密数据”);
试一试{
接收输入。传输到(输出);
System.out.println(“已完成从管道接收加密数据”);
}捕获(IOE异常){
e、 printStackTrace();
}
});
try(PipedOutputStream pipedOutput=新的PipedOutputStream(recEncInput);
OutputStream encOut=encGen.open(pipedOutput,新字节[4096]);
OutputStream effectiveOut=dataGenerator.open(encOut,PGPLiteralData.BINARY,“Message”,new Date(),new byte[4096]))
{
//将数据从servlet输入流复制到加密输出流。
try(InputStream InputStream=newbytearrayinputstream(Strings.toByteArray(“Hello,world!”)){//用上传的数据模拟servlet输入流。
inputStream.transferTo(有效输出);
System.out.println(“已完成将数据传输到加密输出流”);
}捕获(IOE异常){
e、 printStackTrace();
}
}
receiveData.get();//等待复制线程完成(在加密流关闭之后!)
}
字节[]encData=output.toByteArray();
file.write(path.get(“pgp encrypted string.pgp”)、encData;
}
/**
*从类路径上的“pubring.kbx”中读取给定userId的公钥。
*@param userId
*/
静态PGPPublicKey readPublicKeyRing(字符串用户ID)引发IOException、NoSuchAlgorithmException、NoSuchProviderException{
try(final InputStream pubringString=Main.class.getClassLoader().getResourceAsStream(“pubring.kbx”)){
final JcaKeyBox keyBox=new JcaKeyBoxBuilder().build(pubringString);
最终列表blobs=keyBox.getKeyBlobs();
最终可选的keyBlob=blobs.stream().filter(blob->{
布尔匹配=blob.getUserId().stream()
.map(uid->uid.getUserIDAsString())
.anyMatch(uidStr->uidStr.toLowerCase(Locale.ROOT).contains(userId.toLowerCase(Locale.ROOT));
返回比赛;
}).findAny();
if(keyBlob.isPresent()){
PublicKeyRingBlob pgkr=(PublicKeyRingBlob)keyBlob.get();
PGPPubliceRing环=pgkr.getPGPPubliceRing();
返回环。getPublicKey();
}否则{
返回null;
}
}
}
}