Comment on page
Stream and file encryption
Encrypting streams and files should be done in chunks. This keeps memory usage low and detects corrupted chunks early. However, this is more complicated than one would expect because you need to prevent chunks from being removed, truncated, duplicated, and reordered.
The optional associated data is useful for authenticating file headers, version numbers, timestamps, counters, and so on. It can be used to prevent confused deputy attacks and replay attacks. It is not encrypted nor part of the ciphertext. It must be reproduceable or stored somewhere for decryption to be possible.
For file encryption, optimal chunk sizes include 16 KiB, 32 KiB, and 64 KiB. Pick one and use it for everything but the last chunk, which will likely be smaller.
Initialises stream encryption or decryption using a key and header. For encryption, the header is filled with a random nonce. It MUST be sent/stored before the sequence of ciphertext messages because it is required to decrypt the stream.
using var secretstream = new IncrementalXChaCha20Poly1305(bool decryption, Span<byte> header, ReadOnlySpan<byte> key);
headerhas a length not equal to
keyhas a length not equal to
Before encryption, a flag is attached to each chunk to provide information about that chunk:
ChunkFlag.Message: an ordinary plaintext chunk.
ChunkFlag.Boundary: the end of a set of messages but not the end of the stream.
ChunkFlag.Rekey: derive a new key after this chunk.
ChunkFlag.Final: the last plaintext chunk, marking the end of the stream.
For file encryption,
ChunkFlag.Finalare the only flags required. For online communication,
ChunkFlag.Rekeymay also be useful.
Fills a span with the ciphertext chunk computed from a plaintext chunk and optional associated data.
ChunkFlag.FinalMUST be specified for the last plaintext chunk.
secretstream.Push(Span<byte> ciphertextChunk, ReadOnlySpan<byte> plaintextChunk, ReadOnlySpan<byte> associatedData = default, ChunkFlag chunkFlag = ChunkFlag.Message)
ciphertextChunkhas a length not equal to
plaintextChunk.Length + TagSize.
Cannot push into a decryption stream or push after
Verifies that the tag appended to the ciphertext chunk is correct for the given inputs. If verification fails, an exception is thrown. Otherwise, it fills a span with the decrypted ciphertext and returns the decrypted flag for that chunk.
var chunkFlag = secretstream.Pull(Span<byte> plaintextChunk, ReadOnlySpan<byte> ciphertextChunk, ReadOnlySpan<byte> associatedData = default)
plaintextChunkhas a length not equal to
ciphertextChunk.Length - TagSize.
Cannot pull from an encryption stream or pull after
Invalid authentication tag for the given inputs.
Explicitly rekeys without storing the
ChunkFlag.Rekeyflag. For decryption, this function MUST be called at the same stream location to avoid an exception when decrypting the following chunk.
Cannot rekey after
These are used for validation and/or save you defining your own constants.
public const int KeySize = 32;
public const int HeaderSize = 24;
public const int TagSize = 17;