[][src]Module orion::aead::streaming

Streaming AEAD based on XChaCha20Poly1305.

Use case:

This can be used to encrypt and authenticate a stream of data. It prevents the modification, reordering, dropping or duplication of messages. Nonce management is handled automatically.

An example of this could be the encryption of files that are too large to encrypt in one piece.


This implementation is based on and compatible with the "secretstream" API of libsodium.


  • secret_key: The secret key.
  • nonce: The nonce value.
  • plaintext: The data to be encrypted.
  • ciphertext: The encrypted data with a Poly1305 tag and a StreamTag indicating its function.
  • tag: Indicates the type of message. The tag is a part of the output when encrypting. It is encrypted and authenticated.


An error will be returned if:

  • secret_key is not 32 bytes.
  • The length of ciphertext is not at least ABYTES.
  • The received mac does not match the calculated mac when decrypting. This can indicate a dropped or reordered message within the stream.
  • More than 2^32-3 * 64 bytes of data are processed when encrypting/decrypting a single chunk.
  • ABYTES + plaintext.len() overflows when encrypting.


A panic will occur if:

  • 64 + (ciphertext.len() - ABYTES) overflows when decrypting.
  • Failure to generate random bytes securely.


  • It is critical for security that a given nonce is not re-used with a given key.
  • To securely generate a strong key, use SecretKey::generate().
  • The length of the messages is leaked.
  • It is recommended to use StreamTag::FINISH as tag for the last message. This allows the decrypting side to detect if messages at the end of the stream are lost.


use orion::aead::streaming::*;
use orion::aead::SecretKey;

let key = SecretKey::default();
let (mut sealer, nonce) = StreamSealer::new(&key)?;
let mut opener = StreamOpener::new(&key, &nonce)?;

// Message 1
let plaintext1 = "Secret message 1".as_bytes().to_vec();
let cipher1 = sealer.seal_chunk(&plaintext1, StreamTag::MESSAGE)?;
let (dec1, tag1) = opener.open_chunk(&cipher1)?;
assert_eq!(plaintext1, dec1);
assert_eq!(tag1, StreamTag::MESSAGE);

// Message 2
let plaintext2 = "Secret message 2".as_bytes().to_vec();
let cipher2 = sealer.seal_chunk(&plaintext2, StreamTag::MESSAGE)?;
let (dec2, tag2) = opener.open_chunk(&cipher2)?;
assert_eq!(plaintext2, dec2);
assert_eq!(tag2, StreamTag::MESSAGE);

// Message 3 (Last message of this stream, using the FINISH tag)
let plaintext3 = "Secret message 3".as_bytes().to_vec();
let cipher3 = sealer.seal_chunk(&plaintext3, StreamTag::FINISH)?;
let (dec3, tag3) = opener.open_chunk(&cipher3)?;
assert_eq!(plaintext3, dec3);
assert_eq!(tag3, StreamTag::FINISH);


pub use crate::hazardous::aead::streaming::Nonce;
pub use crate::hazardous::aead::streaming::StreamTag;



Streaming authenticated decryption.


Streaming authenticated encryption.