A keystream is a sequence of pseudorandom bytes used like a one-time masking stream: XOR it with plaintext to produce ciphertext, or with ciphertext to recover plaintext. Encryption preserves length, so no padding is required. section 4.5.3 section 4.5.2
A typical keystream-based encryption flow is:
- Provide a key, a unique nonce, and a counter to the construction. section 4.5.3 section 4.5.2
- Generate enough keystream, often by repeatedly encrypting nonce-and-counter values or calling an internal block function. section 4.5.3 section 4.5.2
- Truncate the stream to the plaintext length, then XOR corresponding bytes. section 4.5.3 section 4.5.2
The dangerous shortcut
Reusing a nonce under the same key recreates the same keystream. XORing the two resulting ciphertexts cancels that stream and reveals the XOR of the two plaintexts, creating a serious confidentiality failure. section 4.5.2 section 4.5.3
Figure 4.18 ChaCha20 works by taking a symmetric key and a unique nonce. It then generates a keystream that is XORed with the plaintext (or ciphertext) to produce the ciphertext (or plaintext). The encryption is length-preserving as the ciphertext and the plaintext are of the same length.
Trace how a symmetric key and unique nonce generate a keystream, and how XOR reversibly connects plaintext and ciphertext. section 4.5.3
Figure 4.19 ChaCha20’s keystream is created by calling an internal block function until enough bytes are produced. One block function call creates 64 bytes of random keystream.
Inspect how ChaCha20 builds a longer keystream from repeated 64-byte block-function outputs. section 4.5.3

