1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
//! Streaming / file encryption.
//!
//! Chunked AEAD with a [STREAM-construction] frame format. Lets you
//! encrypt data that doesn't fit in memory, transport it in pieces,
//! and decrypt back to the original with the same authentication
//! guarantees as the single-shot [`crate::Crypt`] surface — plus
//! detection of chunk truncation, reordering, and duplication.
//!
//! [STREAM-construction]: https://eprint.iacr.org/2015/189.pdf
//!
//! # Quick API tour
//!
//! - [`StreamEncryptor`] — buffer plaintext, emit chunks of `chunk_size`
//! ciphertext + 16 bytes of authentication tag.
//! - [`StreamDecryptor`] — feed encrypted bytes, get plaintext as
//! complete chunks decrypt.
//! - [`encrypt_file`] / [`decrypt_file`] *(requires `std`)* — the
//! common "encrypt this file into that file" workflow.
//!
//! # Wire format
//!
//! See [`frame`] for the on-the-wire layout: 24-byte header, then
//! N-1 non-final chunks of `chunk_size + 16` bytes each, then 1
//! final chunk of strictly less than `chunk_size + 16` bytes. The
//! final chunk is always emitted (even if it carries zero plaintext)
//! so the decoder can detect end-of-stream unambiguously.
//!
//! # Security properties
//!
//! - **Tampering** in any chunk → `Error::AuthenticationFailed` on
//! that chunk's decrypt.
//! - **Truncation** (cutting bytes off the end of the stream) →
//! `Error::AuthenticationFailed` when the buffered "almost-final"
//! chunk fails to verify under the `last_flag = 1` nonce.
//! - **Reordering or duplicating chunks** → each chunk's nonce
//! includes a 32-bit counter; swapping or repeating produces a
//! counter mismatch and an authentication failure.
//! - **Header tampering** (flipping the algorithm byte, the chunk
//! size, or the nonce prefix) → the header bytes are bound into
//! every chunk's AAD; tampering shows up as authentication failure
//! on the first chunk.
//! - **Wrong key** → authentication failure on the first chunk.
//!
//! # Example
//!
//! ```
//! # #[cfg(all(feature = "stream", feature = "aead-chacha20"))] {
//! use crypt_io::Algorithm;
//! use crypt_io::stream::{StreamEncryptor, StreamDecryptor};
//!
//! let key = [0u8; 32];
//! let plaintext = b"the quick brown fox jumps over the lazy dog".repeat(1000);
//!
//! // Encrypt
//! let (mut enc, header) = StreamEncryptor::new(&key, Algorithm::ChaCha20Poly1305)?;
//! let mut wire = header.to_vec();
//! wire.extend(enc.update(&plaintext)?);
//! wire.extend(enc.finalize()?);
//!
//! // Decrypt
//! let mut dec = StreamDecryptor::new(&key, &wire[..24])?;
//! let mut recovered = dec.update(&wire[24..])?;
//! recovered.extend(dec.finalize()?);
//!
//! assert_eq!(recovered, plaintext);
//! # }
//! # Ok::<(), crypt_io::Error>(())
//! ```
// Crypto-style: pass fixed-size keys/nonces/prefixes by reference for
// caller clarity, even when clippy thinks small arrays should be
// pass-by-value. Matches the convention of every RustCrypto crate.
pub use StreamDecryptor;
pub use StreamEncryptor;
pub use ;
// Re-export the bits of the frame format that callers may want to
// reason about. Keep the rest of `frame` crate-private — it's
// implementation detail of the wire format.
pub use ;