Description
Describe the bug:
The reader returned by calling NewDecryptingReader(in)
on the result of streamingaead.New(handle)
keeps the entire contents of in
in-memory until the reader is garbage collected.
This happens because the ciphertext stream is tee'd to a buffer here, and that's what's passed to the primitive's real NewDecryptionReader
implementation:
https://github.com/google/tink/blob/645c17cbd121b9db7c6c336521c2c37717003332/go/streamingaead/decrypt_reader.go#L67-L71
That buffer makes it possible to rewind the stream and try another key if the first one fails, but the buffer isn't just used while finding the correct key. It's still referenced by the io.TeeReader
implementation, so reading a 1GiB stream will allocate more than 1GiB of memory.
Going around streamingaead.New(handle)
by turning the primary primitive into a tink.StreamingAEAD
and calling NewDecryptingReader(...)
on that works around the problem and the process consumes megabytes of memory instead of gigabytes on large streams.
What was the expected behavior?
Streaming AEAD memory usage during decryption should not increase linearly with the stream length.
One fix is to implement a reader that replaces the tee+buffer with a buffer that can be deactivated once the matching key is found.
How can we reproduce the bug?
Example of the problem and the workaround that shows ideal/expected memory usage:
https://gist.github.com/vonhollen/64d51c56bd9d2294428da57a552ed457
Do you have any debugging information?
When running the example above, you'll see the tee'd buffer in the heap summary near the end:
Top in-use heap objects:
#1 size=1023.05MiB objects=1
bytes.makeSlice buffer.go:229
bytes.(*Buffer).grow buffer.go:142
bytes.(*Buffer).Write buffer.go:172
io.(*teeReader).Read io.go:574
io.ReadAtLeast io.go:331
io.ReadFull io.go:350
tink/go/streamingaead/subtle/noncebased/noncebased.(*Reader).Read tink/go/streamingaead/subtle/noncebased/noncebased.go:280
tink/go/streamingaead/streamingaead.(*decryptReader).Read tink/go/streamingaead/decrypt_reader.go:46
main.main streammemoryusage.go:70
Provide your version information:
- Language: Go
- Version:
- Environment: Debian