【问题标题】:Encrypting large streams to be sent via Amazon S3加密要通过 Amazon S3 发送的大型流
【发布时间】:2018-12-09 14:06:07
【问题描述】:

我想加密流,然后使用 Amazon S3 发送它。我正在使用遗留代码并有两个重要参数:未加密的InputStream 及其长度。这很重要,因为 AmazonS3Client 想在上传流之前知道流的长度。

加密流并不是很困难的任务:

        InputStream in = new FileInputStream("path-to-file");
        KeyGenerator keygen = KeyGenerator.getInstance("AES");
        Key key = keygen.generateKey();

        Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding");
        cipher.init(Cipher.ENCRYPT_MODE, key);

        OutputStream encryptedStream = new ByteArrayOutputStream();
        CipherOutputStream out = new CipherOutputStream(encryptedStream, cipher);
        out.write(in.read());
        out.flush();

        byte[] bytes = ((ByteArrayOutputStream) encryptedStream).toByteArray();
        InputStream encryptedInput = new ByteArrayInputStream(bytes);

但是,这种方法只能用于小文件,因为它们被写入内存中的字节数组。问题是我想加密大文件(> 1TB)。我该怎么做呢?更具体地说,我得到 InputStream,我的工作是返回将由 Amazon S3 使用的加密 InputStream。

【问题讨论】:

  • 所以,总结一下:你想从未加密文件的大小知道加密文件的大小..
  • 现在,我想加密输入流并最终加密输入流。

标签: java encryption amazon-s3


【解决方案1】:

不要使用ByteArrayOutputStream

    InputStream in = new FileInputStream("path-to-file");
    KeyGenerator keygen = KeyGenerator.getInstance("AES");
    Key key = keygen.generateKey();

    Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding");
    cipher.init(Cipher.ENCRYPT_MODE, key);

    try(CipherOutputStream out = new CipherOutputStream(
            new FileOutputStream(new File("path to enc file")), cipher))
    {
        byte[] buffer = new byte[8192];
        int count;
        while ((count = in.read(buffer)) > 0)
        {
            out.write(buffer, 0, count);
        }
    }

    return new FileInputStream(new File("path to enc file"));

管道流的另一个答案。

    InputStream in = new FileInputStream("path-to-file");
    KeyGenerator keygen = KeyGenerator.getInstance("AES");
    Key key = keygen.generateKey();

    Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding");
    cipher.init(Cipher.ENCRYPT_MODE, key);

    PipedOutputStream pout = new PipedOutputStream();
    //write data in a separate thread.
    new Thread(() -> {
        try(CipherOutputStream out = new CipherOutputStream(
                pout, cipher))
        {
            byte[] buffer = new byte[8192];
            int count;
            while ((count = in.read(buffer)) > 0)
            {
                out.write(buffer, 0, count);
            }
        } catch (IOException  e)
        {
            e.printStackTrace();
        }
    }).start();

    return new PipedInputStream(pout);

【讨论】:

  • 谢谢。但是,结果应该是 InputStream,在您的解决方案中我有 OutputStream。
  • 再次打开enc文件。理想情况下,输入流不应成为此方法的一部分。它应该由负责关闭它的方法创建。
  • 又添加了一个答案。这次使用管道流。在一个线程中写入输出流的内容将通过管道传输到输入流。
  • 就是这样。谢谢!
  • 此代码使大于 4GB 的文件的线程挂起(我假设它的管道流错误)。是否可以使用缓冲流来编写它?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-02-27
  • 1970-01-01
  • 2013-01-12
  • 2019-08-15
  • 2014-08-07
相关资源
最近更新 更多