1

我正在尝试使用 Google Tink 加密文件(txt、pdf、doc) - 流式 AEAD 加密,下面是我尝试执行的 Java 代码。但我得到的只是 1 KB 的输出加密文件,没有错误。所有输入文件,无论是 2 MB 还是超过 10 MB,输出文件将始终为 1 KB。我无法弄清楚可能出了什么问题,有人可以帮忙。

      TinkConfig.register();

      final int chunkSize = 256;

      KeysetHandle keysetHandle = KeysetHandle.generateNew(               
      StreamingAeadKeyTemplates.AES128_CTR_HMAC_SHA256_4KB);

    // 2. Get the primitive.
    StreamingAead streamingAead = keysetHandle.getPrimitive(StreamingAead.class);
    // 3. Use the primitive to encrypt some data and write the ciphertext to a file,
    FileChannel ciphertextDestination =
            new FileOutputStream("encyptedOutput.txt").getChannel();
    String associatedData = "Tinks34";
    WritableByteChannel encryptingChannel =
            streamingAead.newEncryptingChannel(ciphertextDestination, associatedData.getBytes());

    ByteBuffer buffer = ByteBuffer.allocate(chunkSize);
    InputStream in = new FileInputStream("FileToEncrypt.txt");

    while (in.available() > 0) {
        in.read(buffer.array());
        System.out.println(in);
        encryptingChannel.write(buffer);
    }
    encryptingChannel.close();
    in.close();
    System.out.println("completed");
4

1 回答 1

1

这一切都与理解ByteBuffer及其运作方式有关。让我解释。

in.read(buffer.array());

这会将数据写入底层数组,但由于数组与原始缓冲区的状态解耦,因此缓冲区的位置不会提前。这不好,作为下一个调用:

encryptingChannel.write(buffer);

现在会认为位置是 0。限制也没有改变,因此仍然设置为容量:256。这意味着写操作的结果是写入 256 个字节并将位置设置为限制(位置)。

现在读取操作仍然在底层字节数组上运行,它的大小仍然是 256 字节。因此,所有下一个读取操作都会完美地进行。但是,所有的写操作都将假定没有要写入的字节,因为位置保持在 256。

要使用ByteBuffer,您可以使用FileBuffer.read. 然后你需要flip在写入读取数据之前缓存。最后,在写入之后,您需要clear缓冲区的位置(和限制,但仅在最后一次读取时更改)为下一次读取操作准备缓冲区。所以顺序通常是读取、翻转、写入、清除的实例Buffer

不要混用Channels 和 I/O 流,这会让你的生活变得不必要的复杂,而且学习如何使用ByteBuffer本身就已经够难了。

于 2020-02-03T13:59:27.090 回答