The documentation is currently being reviewed, so you may see some inconsistencies between sections.
For the complete documentation index, see llms.txt. This page is also available as Markdown.

Stream and file encryption

Purpose

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.

This high-level API uses XChaCha20-Poly1305 internally whilst handling these issues for you. Plaintext chunks can have different sizes, there is no practical stream length limit, associated data is supported, and rekeying is possible midway through encrypting the stream.

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.

Usage

IncrementalXChaCha20Poly1305

Initializes 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(Span<byte> header, ReadOnlySpan<byte> key, bool encryption)

Exceptions

ArgumentOutOfRangeException

header has a length not equal to HeaderSize.

ArgumentOutOfRangeException

key has a length not equal to KeySize.

InvalidOperationException

Methods cannot be called from multiple threads simultaneously.

OutOfMemoryException

Allocating memory for the state failed.

CryptographicException

Error initializing stream encryption/decryption.

ChunkFlag

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.Message and ChunkFlag.Final are the only flags required. For online communication, ChunkFlag.Boundary and ChunkFlag.Rekey may also be useful.

EncryptChunk

Fills a span with the ciphertext chunk computed from a plaintext chunk and optional associated data. ChunkFlag.Final MUST be specified for the last plaintext chunk.

Exceptions

ArgumentOutOfRangeException

ciphertextChunk has a length not equal to plaintextChunk.Length + TagSize.

ArgumentOutOfRangeException

chunkFlag must be a value within the enum.

InvalidOperationException

Cannot encrypt on a decryption stream or after the final chunk without reinitializing.

InvalidOperationException

Methods cannot be called from multiple threads simultaneously.

ObjectDisposedException

The object has been disposed.

CryptographicException

Error encrypting plaintext chunk.

DecryptChunk

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.

To detect stream truncation, if you reach the end of the stream and ChunkFlag.Final was not returned, you MUST throw a CryptographicException.

Exceptions

ArgumentOutOfRangeException

ciphertextChunk has a length less than TagSize.

ArgumentOutOfRangeException

plaintextChunk has a length not equal to ciphertextChunk.Length - TagSize.

InvalidOperationException

Cannot decrypt on an encryption stream or after the final chunk without reinitializing.

InvalidOperationException

Methods cannot be called from multiple threads simultaneously.

ObjectDisposedException

The object has been disposed.

CryptographicException

Invalid chunk authentication tag for the given inputs.

Rekey

Explicitly rekeys without storing the ChunkFlag.Rekey flag. For decryption, this function MUST be called at the same stream location to avoid an exception when decrypting the following chunk.

Exceptions

InvalidOperationException

Cannot rekey after the final chunk without reinitializing.

InvalidOperationException

Methods cannot be called from multiple threads simultaneously.

ObjectDisposedException

The object has been disposed.

Reinitialize

Reinitializes stream encryption or decryption using a key and header. This avoids creating another using statement. 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.

Exceptions

ArgumentOutOfRangeException

header has a length not equal to HeaderSize.

ArgumentOutOfRangeException

key has a length not equal to KeySize.

InvalidOperationException

Methods cannot be called from multiple threads simultaneously.

ObjectDisposedException

The object has been disposed.

OutOfMemoryException

Allocating memory for the state failed.

CryptographicException

Error initializing stream encryption/decryption.

Constants

These are used for validation and/or save you defining your own constants.

Notes

Last updated