in src/main/java/software/amazon/encryption/s3/internal/BufferedCipherSubscriber.java [63:98]
public void onNext(ByteBuffer byteBuffer) {
int amountToReadFromByteBuffer = getAmountToReadFromByteBuffer(byteBuffer);
if (amountToReadFromByteBuffer > 0) {
byte[] buf = BinaryUtils.copyBytesFrom(byteBuffer, amountToReadFromByteBuffer);
try {
outputBuffer = cipher.update(buf, 0, amountToReadFromByteBuffer);
} catch (final IllegalStateException exception) {
// This happens when the stream is reset and the cipher is reused with the
// same key/IV. It's actually fine here, because the data is the same, but any
// sane implementation will throw an exception.
// Request a new cipher using the same materials to avoid reinit issues
cipher = CipherProvider.createAndInitCipher(materials, iv);
}
if (outputBuffer == null && amountToReadFromByteBuffer < cipher.getBlockSize()) {
// The underlying data is too short to fill in the block cipher
// This is true at the end of the file, so complete to get the final
// bytes
this.onComplete();
}
// Enqueue the buffer until all data is read
buffers.add(ByteBuffer.wrap(outputBuffer));
// Sometimes, onComplete won't be called, so we check if all
// data is read to avoid hanging indefinitely
if (contentRead.get() == contentLength) {
this.onComplete();
}
// This avoids the subscriber waiting indefinitely for more data
// without actually releasing any plaintext before it can be authenticated
wrappedSubscriber.onNext(ByteBuffer.allocate(0));
}
}