diff --git a/chacha20/README.md b/chacha20/README.md
index 78a479aa..11359ffb 100644
--- a/chacha20/README.md
+++ b/chacha20/README.md
@@ -8,37 +8,18 @@
[![Project Chat][chat-image]][chat-link]
[![HAZMAT][hazmat-image]][hazmat-link]
-Pure Rust implementation of the [ChaCha20 Stream Cipher][1].
+Implementation of the [ChaCha] family of stream ciphers.
-
+ChaCha improves upon the previous [Salsa] family of stream ciphers
+with increased per-round diffusion at no cost to performance.
-## About
+This crate also contains an implementation of the [XChaCha] family of stream ciphers
+with an extended 192-bit (24-byte) nonce, gated under the `xchacha` Cargo feature,
+and "legacy" (a.k.a "djb") variant with 64-bit nonce, gated under the `legacy` crate feature.
-[ChaCha20][1] is a [stream cipher][2] which is designed to support
-high-performance software implementations.
-
-It improves upon the previous [Salsa20][3] stream cipher with increased
-per-round diffusion at no cost to performance.
-
-This crate also contains an implementation of [XChaCha20][4]: a variant
-of ChaCha20 with an extended 192-bit (24-byte) nonce, gated under the
-`chacha20` Cargo feature (on-by-default).
-
-## Implementations
-
-This crate contains the following implementations of ChaCha20, all of which
-work on stable Rust with the following `RUSTFLAGS`:
-
-- `x86` / `x86_64`
- - `avx2`: (~1.4cpb) `-Ctarget-cpu=haswell -Ctarget-feature=+avx2`
- - `sse2`: (~1.6cpb) `-Ctarget-feature=+sse2` (on by default on x86 CPUs)
- - `avx512`: `-Ctarget-feature=+avx512f,+avx512vl --cfg chacha20_avx512` requires Rust 1.89+
-- `aarch64`
- - `neon` (~2-3x faster than `soft`) requires the `neon` feature enabled
-- Portable
- - `soft`: (~5 cpb on x86/x86_64)
-
-NOTE: cpb = cycles per byte (smaller is better)
+**WARNING:** This implementation internally uses 32-bit counter,
+while the original "legacy" variant implementation uses 64-bit counter.
+In other words, it does not allow encryption of more than 256 GiB of data.
## Security
@@ -48,19 +29,80 @@ This crate does not ensure ciphertexts are authentic (i.e. by using a MAC to
verify ciphertext integrity), which can lead to serious vulnerabilities
if used incorrectly!
-To avoid this, use an [AEAD][5] mode based on ChaCha20, i.e. [ChaCha20Poly1305][6].
-See the [RustCrypto/AEADs][7] repository for more information.
+To avoid this, use an [AEAD] mode based on ChaCha20, e.g. [`chacha20poly1305`].
+See the [RustCrypto/AEADs] repository for more information.
USE AT YOUR OWN RISK!
### Notes
-This crate has received one [security audit by NCC Group][8], with no significant
-findings. We would like to thank [MobileCoin][9] for funding the audit.
+This crate has received one [security audit by NCC Group][NCC-AUDIT], with no significant
+findings. We would like to thank [MobileCoin] for funding the audit.
All implementations contained in the crate (along with the underlying ChaCha20
stream cipher itself) are designed to execute in constant time.
+## Examples
+
+```rust
+// This example requires `cipher` crate feature
+#[cfg(feature = "cipher")] {
+
+use chacha20::ChaCha20;
+use chacha20::cipher::{KeyIvInit, StreamCipher, StreamCipherSeek};
+use hex_literal::hex;
+
+let key = [0x42; 32];
+let nonce = [0x24; 12];
+let plaintext = hex!("00010203 04050607 08090A0B 0C0D0E0F");
+let ciphertext = hex!("e405626e 4f1236b3 670ee428 332ea20e");
+
+// Key and IV must be references to the `Array` type.
+// Here we use the `Into` trait to convert arrays into it.
+let mut cipher = ChaCha20::new(&key.into(), &nonce.into());
+
+let mut buffer = plaintext;
+
+// apply keystream (encrypt)
+cipher.apply_keystream(&mut buffer);
+assert_eq!(buffer, ciphertext);
+
+let ciphertext = buffer;
+
+// ChaCha ciphers support seeking
+cipher.seek(0u32);
+
+// decrypt ciphertext by applying keystream again
+cipher.apply_keystream(&mut buffer);
+assert_eq!(buffer, plaintext);
+
+// stream ciphers can be used with streaming messages
+cipher.seek(0u32);
+for chunk in buffer.chunks_mut(3) {
+ cipher.apply_keystream(chunk);
+}
+assert_eq!(buffer, ciphertext);
+}
+```
+
+## Configuration Flags
+
+You can modify crate using the following configuration flags:
+
+- `chacha20_backend="avx2"`: force AVX2 backend on x86/x86_64 targets.
+ Requires enabled AVX2 target feature. Ignored on non-x86(_64) targets.
+- `chacha20_backend="avx512"`: force AVX-512 backend on x86/x86_64 targets.
+ Requires enabled AVX-512 target feature (MSRV 1.89). Ignored on non-x86(_64) targets.
+- `chacha20_backend="soft"`: force software backend.
+- `chacha20_backend="sse2"`: force SSE2 backend on x86/x86_64 targets.
+ Requires enabled SSE2 target feature. Ignored on non-x86(-64) targets.
+
+To use the MSRV 1.89 AVX-512 support with autodetection, you must enable it using
+`chacha20_avx512` configuration flag.
+
+The flags can be enabled using `RUSTFLAGS` environmental variable
+(e.g. `RUSTFLAGS='--cfg chacha20_backend="avx2"'`) or by modifying `.cargo/config.toml`.
+
## License
Licensed under either of:
@@ -93,12 +135,11 @@ dual licensed as above, without any additional terms or conditions.
[//]: # (footnotes)
-[1]: https://en.wikipedia.org/wiki/Salsa20#ChaCha_variant
-[2]: https://en.wikipedia.org/wiki/Stream_cipher
-[3]: https://en.wikipedia.org/wiki/Salsa20
-[4]: https://tools.ietf.org/html/draft-arciszewski-xchacha-02
-[5]: https://en.wikipedia.org/wiki/Authenticated_encryption
-[6]: https://github.com/RustCrypto/AEADs/tree/master/chacha20poly1305
-[7]: https://github.com/RustCrypto/AEADs
-[8]: https://web.archive.org/web/20240108154854/https://research.nccgroup.com/wp-content/uploads/2020/02/NCC_Group_MobileCoin_RustCrypto_AESGCM_ChaCha20Poly1305_Implementation_Review_2020-02-12_v1.0.pdf
-[9]: https://www.mobilecoin.com/
+[ChaCha]: https://en.wikipedia.org/wiki/Salsa20#ChaCha_variant
+[Salsa]: https://en.wikipedia.org/wiki/Salsa20
+[XChaCha]: https://tools.ietf.org/html/draft-arciszewski-xchacha-02
+[AEAD]: https://en.wikipedia.org/wiki/Authenticated_encryption
+[`chacha20poly1305`]: https://docs.rs/chacha20poly1305
+[RustCrypto/AEADs]: https://github.com/RustCrypto/AEADs
+[NCC-AUDIT]: https://web.archive.org/web/20240108154854/https://research.nccgroup.com/wp-content/uploads/2020/02/NCC_Group_MobileCoin_RustCrypto_AESGCM_ChaCha20Poly1305_Implementation_Review_2020-02-12_v1.0.pdf
+[MobileCoin]: https://www.mobilecoin.com/
diff --git a/chacha20/src/lib.rs b/chacha20/src/lib.rs
index f3e47ae0..bb867e5f 100644
--- a/chacha20/src/lib.rs
+++ b/chacha20/src/lib.rs
@@ -1,96 +1,10 @@
#![no_std]
-#![cfg_attr(docsrs, feature(doc_cfg))]
#![doc = include_str!("../README.md")]
#![doc(
html_logo_url = "https://raw.githubusercontent.com/RustCrypto/media/8f1a9894/logo.svg",
html_favicon_url = "https://raw.githubusercontent.com/RustCrypto/media/8f1a9894/logo.svg"
)]
-
-//! # Usage
-//!
-//! Cipher functionality is accessed using traits from re-exported [`cipher`] crate, or as a set
-//! of random number generator types ending in `*Rng` which implement traits from the [`rand_core`]
-//! crate.
-//!
-//! This crate contains the following variants of the ChaCha20 core algorithm:
-//!
-//! - [`ChaCha20`]: standard IETF variant with 96-bit nonce
-//! - [`ChaCha8`] / [`ChaCha12`]: reduced round variants of ChaCha20
-//! - [`XChaCha20`]: 192-bit extended nonce variant
-//! - [`XChaCha8`] / [`XChaCha12`]: reduced round variants of XChaCha20
-//! - [`ChaCha20Legacy`]: "djb" variant with 64-bit nonce.
-//! **WARNING:** This implementation internally uses 32-bit counter,
-//! while the original implementation uses 64-bit counter. In other words,
-//! it does not allow encryption of more than 256 GiB of data.
-//!
-//! ## Example
-#![cfg_attr(feature = "cipher", doc = " ```")]
-#![cfg_attr(not(feature = "cipher"), doc = " ```ignore")]
-//! use chacha20::ChaCha20;
-//! // Import relevant traits
-//! use chacha20::cipher::{KeyIvInit, StreamCipher, StreamCipherSeek};
-//! use hex_literal::hex;
-//!
-//! let key = [0x42; 32];
-//! let nonce = [0x24; 12];
-//! let plaintext = hex!("00010203 04050607 08090A0B 0C0D0E0F");
-//! let ciphertext = hex!("e405626e 4f1236b3 670ee428 332ea20e");
-//!
-//! // Key and IV must be references to the `Array` type.
-//! // Here we use the `Into` trait to convert arrays into it.
-//! let mut cipher = ChaCha20::new(&key.into(), &nonce.into());
-//!
-//! let mut buffer = plaintext;
-//!
-//! // apply keystream (encrypt)
-//! cipher.apply_keystream(&mut buffer);
-//! assert_eq!(buffer, ciphertext);
-//!
-//! let ciphertext = buffer;
-//!
-//! // ChaCha ciphers support seeking
-//! cipher.seek(0u32);
-//!
-//! // decrypt ciphertext by applying keystream again
-//! cipher.apply_keystream(&mut buffer);
-//! assert_eq!(buffer, plaintext);
-//!
-//! // stream ciphers can be used with streaming messages
-//! cipher.seek(0u32);
-//! for chunk in buffer.chunks_mut(3) {
-//! cipher.apply_keystream(chunk);
-//! }
-//! assert_eq!(buffer, ciphertext);
-//! ```
-//!
-//! # Configuration Flags
-//!
-//! You can modify crate using the following configuration flags:
-//!
-//! - `chacha20_backend="avx2"`: force AVX2 backend on x86/x86_64 targets.
-//! Requires enabled AVX2 target feature. Ignored on non-x86(_64) targets.
-//! - `chacha20_backend="avx512": force AVX-512 backend on x86/x86_64 targets.
-//! Requires enabled AVX-512 target feature (MSRV 1.89). Ignored on non-x86(_64) targets.
-//! - `chacha20_backend="soft"`: force software backend.
-//! - `chacha20_backend="sse2"`: force SSE2 backend on x86/x86_64 targets.
-//! Requires enabled SSE2 target feature. Ignored on non-x86(-64) targets.
-//!
-//! The flags can be enabled using `RUSTFLAGS` environmental variable
-//! (e.g. `RUSTFLAGS='--cfg chacha20_backend="avx2"'`) or by modifying `.cargo/config.toml`:
-//!
-//! ```toml
-//! # In .cargo/config.toml
-//! [build]
-//! rustflags = ['--cfg', 'chacha20_backend="avx2"']
-//! ```
-//!
-//! ## AVX-512 support
-//!
-//! To use the MSRV 1.89 AVX-512 support, you must enable it using: `--cfg chacha20_avx512`.
-//!
-//! [ChaCha]: https://tools.ietf.org/html/rfc8439
-//! [Salsa]: https://en.wikipedia.org/wiki/Salsa20
-//! [`chacha20poly1305`]: https://docs.rs/chacha20poly1305
+#![cfg_attr(docsrs, feature(doc_cfg))]
pub mod variants;
diff --git a/hc-256/README.md b/hc-256/README.md
index 290c451c..046f13c5 100644
--- a/hc-256/README.md
+++ b/hc-256/README.md
@@ -8,7 +8,7 @@
[![Project Chat][chat-image]][chat-link]
[![HAZMAT][hazmat-image]][hazmat-link]
-Pure Rust implementation of the [HC-256 Stream Cipher][1].
+Implementation of the [HC-256] stream cipher.
## ⚠️ Security Warning: [Hazmat!][hazmat-link]
@@ -22,6 +22,43 @@ architectures.
USE AT YOUR OWN RISK!
+# Examples
+
+```rust
+use hc_256::Hc256;
+use hc_256::cipher::{KeyIvInit, StreamCipher};
+use hex_literal::hex;
+
+let key = [0x42; 32];
+let nonce = [0x24; 32];
+let plaintext = hex!("00010203 04050607 08090A0B 0C0D0E0F");
+let ciphertext = hex!("ca982177 325cd40e bc208045 066c420f");
+
+// Key and IV must be references to the `Array` type.
+// Here we use the `Into` trait to convert arrays into it.
+let mut cipher = Hc256::new(&key.into(), &nonce.into());
+
+let mut buffer = plaintext;
+
+// apply keystream (encrypt)
+cipher.apply_keystream(&mut buffer);
+assert_eq!(buffer, ciphertext);
+
+let ciphertext = buffer;
+
+// decrypt ciphertext by applying keystream again
+let mut cipher = Hc256::new(&key.into(), &nonce.into());
+cipher.apply_keystream(&mut buffer);
+assert_eq!(buffer, plaintext);
+
+// stream ciphers can be used with streaming messages
+let mut cipher = Hc256::new(&key.into(), &nonce.into());
+for chunk in buffer.chunks_mut(3) {
+ cipher.apply_keystream(chunk);
+}
+assert_eq!(buffer, ciphertext);
+```
+
## License
Licensed under either of:
@@ -54,4 +91,4 @@ dual licensed as above, without any additional terms or conditions.
[//]: # (footnotes)
-[1]: https://en.wikipedia.org/wiki/HC-256
+[HC-256]: https://en.wikipedia.org/wiki/HC-256
diff --git a/hc-256/src/lib.rs b/hc-256/src/lib.rs
index 2365a90e..3cf09c20 100644
--- a/hc-256/src/lib.rs
+++ b/hc-256/src/lib.rs
@@ -1,59 +1,10 @@
-//! Implementation of the [HC-256] stream cipher.
-//!
-//! Cipher functionality is accessed using traits from re-exported [`cipher`] crate.
-//!
-//! # ⚠️ Security Warning: Hazmat!
-//!
-//! This crate does not ensure ciphertexts are authentic! Thus ciphertext integrity
-//! is not verified, which can lead to serious vulnerabilities!
-//!
-//! USE AT YOUR OWN RISK!
-//!
-//! # Example
-//! ```
-//! use hc_256::Hc256;
-//! // Import relevant traits
-//! use hc_256::cipher::{KeyIvInit, StreamCipher};
-//! use hex_literal::hex;
-//!
-//! let key = [0x42; 32];
-//! let nonce = [0x24; 32];
-//! let plaintext = hex!("00010203 04050607 08090A0B 0C0D0E0F");
-//! let ciphertext = hex!("ca982177 325cd40e bc208045 066c420f");
-//!
-//! // Key and IV must be references to the `Array` type.
-//! // Here we use the `Into` trait to convert arrays into it.
-//! let mut cipher = Hc256::new(&key.into(), &nonce.into());
-//!
-//! let mut buffer = plaintext;
-//!
-//! // apply keystream (encrypt)
-//! cipher.apply_keystream(&mut buffer);
-//! assert_eq!(buffer, ciphertext);
-//!
-//! let ciphertext = buffer;
-//!
-//! // decrypt ciphertext by applying keystream again
-//! let mut cipher = Hc256::new(&key.into(), &nonce.into());
-//! cipher.apply_keystream(&mut buffer);
-//! assert_eq!(buffer, plaintext);
-//!
-//! // stream ciphers can be used with streaming messages
-//! let mut cipher = Hc256::new(&key.into(), &nonce.into());
-//! for chunk in buffer.chunks_mut(3) {
-//! cipher.apply_keystream(chunk);
-//! }
-//! assert_eq!(buffer, ciphertext);
-//! ```
-//!
-//! [HC-256]: https://en.wikipedia.org/wiki/HC-256
-
#![no_std]
-#![cfg_attr(docsrs, feature(doc_cfg))]
+#![doc = include_str!("../README.md")]
#![doc(
html_logo_url = "https://raw.githubusercontent.com/RustCrypto/media/8f1a9894/logo.svg",
html_favicon_url = "https://raw.githubusercontent.com/RustCrypto/media/8f1a9894/logo.svg"
)]
+#![cfg_attr(docsrs, feature(doc_cfg))]
#![forbid(unsafe_code)]
#![warn(missing_docs, rust_2018_idioms)]
diff --git a/rabbit/README.md b/rabbit/README.md
index 27a2c906..205776cf 100644
--- a/rabbit/README.md
+++ b/rabbit/README.md
@@ -8,7 +8,7 @@
[![Project Chat][chat-image]][chat-link]
[![HAZMAT][hazmat-image]][hazmat-link]
-Rust implementation of the [Rabbit Stream Cipher Algorithm (RFC 4503)][1].
+Implementation of the [Rabbit] stream cipher ([RFC 4503]).
## ⚠️ Security Warning: [Hazmat!][hazmat-link]
@@ -22,6 +22,44 @@ architectures.
**USE AT YOUR OWN RISK!**
+
+## Examples
+
+```rust
+use rabbit::Rabbit;
+use rabbit::cipher::{KeyIvInit, StreamCipher};
+use hex_literal::hex;
+
+let key = [0x42; 16];
+let nonce = [0x24; 8];
+let plaintext = hex!("00010203 04050607 08090A0B 0C0D0E0F");
+let ciphertext = hex!("10298496 ceda18ee 0e257cbb 1ab43bcc");
+
+// Key and IV must be references to the `Array` type.
+// Here we use the `Into` trait to convert arrays into it.
+let mut cipher = Rabbit::new(&key.into(), &nonce.into());
+
+let mut buffer = plaintext;
+
+// apply keystream (encrypt)
+cipher.apply_keystream(&mut buffer);
+assert_eq!(buffer, ciphertext);
+
+let ciphertext = buffer;
+
+// decrypt ciphertext by applying keystream again
+let mut cipher = Rabbit::new(&key.into(), &nonce.into());
+cipher.apply_keystream(&mut buffer);
+assert_eq!(buffer, plaintext);
+
+// stream ciphers can be used with streaming messages
+let mut cipher = Rabbit::new(&key.into(), &nonce.into());
+for chunk in buffer.chunks_mut(3) {
+ cipher.apply_keystream(chunk);
+}
+assert_eq!(buffer, ciphertext);
+```
+
## License
Licensed under either of:
@@ -54,4 +92,5 @@ dual licensed as above, without any additional terms or conditions.
[//]: # (footnotes)
-[1]: https://tools.ietf.org/html/rfc4503
+[Rabbit]: https://en.wikipedia.org/wiki/Rabbit_(cipher)
+[RFC 4503]: https://tools.ietf.org/html/rfc4503
diff --git a/rabbit/src/lib.rs b/rabbit/src/lib.rs
index c92fe04b..5614ee6c 100644
--- a/rabbit/src/lib.rs
+++ b/rabbit/src/lib.rs
@@ -1,59 +1,10 @@
-//! Implementation of the [Rabbit] stream cipher.
-//!
-//! Cipher functionality is accessed using traits from re-exported [`cipher`] crate.
-//!
-//! # ⚠️ Security Warning: Hazmat!
-//!
-//! This crate does not ensure ciphertexts are authentic! Thus ciphertext integrity
-//! is not verified, which can lead to serious vulnerabilities!
-//!
-//! USE AT YOUR OWN RISK!
-//!
-//! # Example
-//! ```
-//! use rabbit::Rabbit;
-//! // Import relevant traits
-//! use rabbit::cipher::{KeyIvInit, StreamCipher};
-//! use hex_literal::hex;
-//!
-//! let key = [0x42; 16];
-//! let nonce = [0x24; 8];
-//! let plaintext = hex!("00010203 04050607 08090A0B 0C0D0E0F");
-//! let ciphertext = hex!("10298496 ceda18ee 0e257cbb 1ab43bcc");
-//!
-//! // Key and IV must be references to the `Array` type.
-//! // Here we use the `Into` trait to convert arrays into it.
-//! let mut cipher = Rabbit::new(&key.into(), &nonce.into());
-//!
-//! let mut buffer = plaintext;
-//!
-//! // apply keystream (encrypt)
-//! cipher.apply_keystream(&mut buffer);
-//! assert_eq!(buffer, ciphertext);
-//!
-//! let ciphertext = buffer;
-//!
-//! // decrypt ciphertext by applying keystream again
-//! let mut cipher = Rabbit::new(&key.into(), &nonce.into());
-//! cipher.apply_keystream(&mut buffer);
-//! assert_eq!(buffer, plaintext);
-//!
-//! // stream ciphers can be used with streaming messages
-//! let mut cipher = Rabbit::new(&key.into(), &nonce.into());
-//! for chunk in buffer.chunks_mut(3) {
-//! cipher.apply_keystream(chunk);
-//! }
-//! assert_eq!(buffer, ciphertext);
-//! ```
-//!
-//! [Rabbit]: https://tools.ietf.org/html/rfc4503#section-2.3
-
#![no_std]
-#![cfg_attr(docsrs, feature(doc_cfg))]
+#![doc = include_str!("../README.md")]
#![doc(
html_logo_url = "https://raw.githubusercontent.com/RustCrypto/media/8f1a9894/logo.svg",
html_favicon_url = "https://raw.githubusercontent.com/RustCrypto/media/8f1a9894/logo.svg"
)]
+#![cfg_attr(docsrs, feature(doc_cfg))]
#![deny(unsafe_code)]
#![warn(missing_docs, rust_2018_idioms)]
diff --git a/rc4/README.md b/rc4/README.md
index 26af2e47..8b138d20 100644
--- a/rc4/README.md
+++ b/rc4/README.md
@@ -24,6 +24,33 @@ relied on for security/confidentiality.
**USE AT YOUR OWN RISK!**
+## Examples
+
+```rust
+use hex_literal::hex;
+use rc4::{consts::*, KeyInit, StreamCipher};
+use rc4::{Key, Rc4};
+
+let mut rc4 = Rc4::::new(b"Key".into());
+let mut data = b"Plaintext".to_vec();
+rc4.apply_keystream(&mut data);
+assert_eq!(data, [0xBB, 0xF3, 0x16, 0xE8, 0xD9, 0x40, 0xAF, 0x0A, 0xD3]);
+
+let mut rc4 = Rc4::::new(b"Wiki".into());
+let mut data = b"pedia".to_vec();
+rc4.apply_keystream(&mut data);
+assert_eq!(data, [0x10, 0x21, 0xBF, 0x04, 0x20]);
+
+let key = Key::::from_slice(b"Secret");
+let mut rc4 = Rc4::<_>::new(key);
+let mut data = b"Attack at dawn".to_vec();
+rc4.apply_keystream(&mut data);
+assert_eq!(
+ data,
+ [0x45, 0xA0, 0x1F, 0x64, 0x5F, 0xC3, 0x5B, 0x38, 0x35, 0x52, 0x54, 0x4B, 0x9B, 0xF5]
+);
+```
+
## License
Licensed under either of:
diff --git a/rc4/src/lib.rs b/rc4/src/lib.rs
index f18bde85..bc79125e 100644
--- a/rc4/src/lib.rs
+++ b/rc4/src/lib.rs
@@ -1,40 +1,13 @@
#![no_std]
-#![cfg_attr(docsrs, feature(doc_cfg))]
#![doc = include_str!("../README.md")]
#![doc(
html_logo_url = "https://raw.githubusercontent.com/RustCrypto/media/8f1a9894/logo.svg",
html_favicon_url = "https://raw.githubusercontent.com/RustCrypto/media/8f1a9894/logo.svg"
)]
+#![cfg_attr(docsrs, feature(doc_cfg))]
#![forbid(unsafe_code)]
#![warn(missing_docs, rust_2018_idioms)]
-//! # Usage
-//!
-//! ```rust
-//! use hex_literal::hex;
-//! use rc4::{consts::*, KeyInit, StreamCipher};
-//! use rc4::{Key, Rc4};
-//!
-//! let mut rc4 = Rc4::::new(b"Key".into());
-//! let mut data = b"Plaintext".to_vec();
-//! rc4.apply_keystream(&mut data);
-//! assert_eq!(data, [0xBB, 0xF3, 0x16, 0xE8, 0xD9, 0x40, 0xAF, 0x0A, 0xD3]);
-//!
-//! let mut rc4 = Rc4::::new(b"Wiki".into());
-//! let mut data = b"pedia".to_vec();
-//! rc4.apply_keystream(&mut data);
-//! assert_eq!(data, [0x10, 0x21, 0xBF, 0x04, 0x20]);
-//!
-//! let key = Key::::from_slice(b"Secret");
-//! let mut rc4 = Rc4::<_>::new(key);
-//! let mut data = b"Attack at dawn".to_vec();
-//! rc4.apply_keystream(&mut data);
-//! assert_eq!(
-//! data,
-//! [0x45, 0xA0, 0x1F, 0x64, 0x5F, 0xC3, 0x5B, 0x38, 0x35, 0x52, 0x54, 0x4B, 0x9B, 0xF5]
-//! );
-//! ```
-
pub use cipher::{self, KeyInit, StreamCipher, consts};
use cipher::{
diff --git a/salsa20/README.md b/salsa20/README.md
index a4ae28c3..ebbf5b17 100644
--- a/salsa20/README.md
+++ b/salsa20/README.md
@@ -8,18 +8,8 @@
[![Project Chat][chat-image]][chat-link]
[![HAZMAT][hazmat-image]][hazmat-link]
-Pure Rust implementation of the [Salsa20 Stream Cipher][1].
-
-
-
-## About
-
-[Salsa20][1] is a [stream cipher][2] which is designed to support
-high-performance software implementations.
-
-This crate also contains an implementation of [XSalsa20][3]: a variant
-of Salsa20 with an extended 192-bit (24-byte) nonce, gated under the
-`xsalsa20` Cargo feature (on-by-default).
+Implementation of the [Salsa] family of stream ciphers, including the [XSalsa] variants with
+an extended 192-bit (24-byte) nonce.
## ⚠️ Security Warning: [Hazmat!][hazmat-link]
@@ -33,6 +23,45 @@ architectures.
USE AT YOUR OWN RISK!
+# Examples
+
+```rust
+use salsa20::Salsa20;
+use salsa20::cipher::{KeyIvInit, StreamCipher, StreamCipherSeek};
+use hex_literal::hex;
+
+let key = [0x42; 32];
+let nonce = [0x24; 8];
+let plaintext = hex!("00010203 04050607 08090A0B 0C0D0E0F");
+let ciphertext = hex!("85843cc5 d58cce7b 5dd3dd04 fa005ded");
+
+// Key and IV must be references to the `Array` type.
+// Here we use the `Into` trait to convert arrays into it.
+let mut cipher = Salsa20::new(&key.into(), &nonce.into());
+
+let mut buffer = plaintext;
+
+// apply keystream (encrypt)
+cipher.apply_keystream(&mut buffer);
+assert_eq!(buffer, ciphertext);
+
+let ciphertext = buffer;
+
+// Salsa ciphers support seeking
+cipher.seek(0u32);
+
+// decrypt ciphertext by applying keystream again
+cipher.apply_keystream(&mut buffer);
+assert_eq!(buffer, plaintext);
+
+// stream ciphers can be used with streaming messages
+cipher.seek(0u32);
+for chunk in buffer.chunks_mut(3) {
+ cipher.apply_keystream(chunk);
+}
+assert_eq!(buffer, ciphertext);
+```
+
## License
Licensed under either of:
@@ -65,7 +94,5 @@ dual licensed as above, without any additional terms or conditions.
[//]: # (footnotes)
-[1]: https://en.wikipedia.org/wiki/Salsa20
-[2]: https://en.wikipedia.org/wiki/Stream_cipher
-[3]: https://cr.yp.to/snuffle/xsalsa-20081128.pdf
-[4]: https://github.com/RustCrypto/AEADs/tree/master/xsalsa20poly1305
+[Salsa]: https://en.wikipedia.org/wiki/Salsa20
+[XSalsa]: https://cr.yp.to/snuffle/xsalsa-20081128.pdf
diff --git a/salsa20/src/lib.rs b/salsa20/src/lib.rs
index 856afc82..e794b593 100644
--- a/salsa20/src/lib.rs
+++ b/salsa20/src/lib.rs
@@ -1,78 +1,12 @@
-//! Implementation of the [Salsa] family of stream ciphers.
-//!
-//! Cipher functionality is accessed using traits from re-exported [`cipher`] crate.
-//!
-//! # ⚠️ Security Warning: Hazmat!
-//!
-//! This crate does not ensure ciphertexts are authentic! Thus ciphertext integrity
-//! is not verified, which can lead to serious vulnerabilities!
-//!
-//! USE AT YOUR OWN RISK!
-//!
-//! # Diagram
-//!
-//! This diagram illustrates the Salsa quarter round function.
-//! Each round consists of four quarter-rounds:
-//!
-//!
-//!
-//! Legend:
-//!
-//! - ⊞ add
-//! - ‹‹‹ rotate
-//! - ⊕ xor
-//!
-//! # Example
-//! ```
-//! use salsa20::Salsa20;
-//! // Import relevant traits
-//! use salsa20::cipher::{KeyIvInit, StreamCipher, StreamCipherSeek};
-//! use hex_literal::hex;
-//!
-//! let key = [0x42; 32];
-//! let nonce = [0x24; 8];
-//! let plaintext = hex!("00010203 04050607 08090A0B 0C0D0E0F");
-//! let ciphertext = hex!("85843cc5 d58cce7b 5dd3dd04 fa005ded");
-//!
-//! // Key and IV must be references to the `Array` type.
-//! // Here we use the `Into` trait to convert arrays into it.
-//! let mut cipher = Salsa20::new(&key.into(), &nonce.into());
-//!
-//! let mut buffer = plaintext;
-//!
-//! // apply keystream (encrypt)
-//! cipher.apply_keystream(&mut buffer);
-//! assert_eq!(buffer, ciphertext);
-//!
-//! let ciphertext = buffer;
-//!
-//! // Salsa ciphers support seeking
-//! cipher.seek(0u32);
-//!
-//! // decrypt ciphertext by applying keystream again
-//! cipher.apply_keystream(&mut buffer);
-//! assert_eq!(buffer, plaintext);
-//!
-//! // stream ciphers can be used with streaming messages
-//! cipher.seek(0u32);
-//! for chunk in buffer.chunks_mut(3) {
-//! cipher.apply_keystream(chunk);
-//! }
-//! assert_eq!(buffer, ciphertext);
-//! ```
-//!
-//! Salsa20 will run the SSE2 backend in x86(-64) targets for Salsa20/20 variant.
-//! Other variants will fallback to the software backend.
-//!
-//! [Salsa]: https://en.wikipedia.org/wiki/Salsa20
-
#![no_std]
-#![cfg_attr(docsrs, feature(doc_cfg))]
+#![doc = include_str!("../README.md")]
#![doc(
html_logo_url = "https://raw.githubusercontent.com/RustCrypto/media/8f1a9894/logo.svg",
html_favicon_url = "https://raw.githubusercontent.com/RustCrypto/media/8f1a9894/logo.svg"
)]
+#![cfg_attr(docsrs, feature(doc_cfg))]
#![warn(missing_docs, rust_2018_idioms, trivial_casts, unused_qualifications)]
+
pub use cipher;
use cipher::{