diff --git a/.github/workflows/stream-cipher.yml b/.github/workflows/stream-cipher.yml index 5c101b93..c6d9a535 100644 --- a/.github/workflows/stream-cipher.yml +++ b/.github/workflows/stream-cipher.yml @@ -51,6 +51,7 @@ jobs: toolchain: ${{ matrix.rust }} - run: cargo check --all-features - run: cargo test --release + - run: cargo test --features block-cipher - run: cargo test --features dev --release - run: cargo test --features std --release - run: cargo test --all-features --release diff --git a/Cargo.lock b/Cargo.lock index 9a1ddc3f..44f861d9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -248,6 +248,7 @@ name = "stream-cipher" version = "0.4.0-pre" dependencies = [ "blobby", + "block-cipher", "generic-array 0.14.1", ] diff --git a/stream-cipher/Cargo.toml b/stream-cipher/Cargo.toml index f127c9a0..b45cc1a8 100644 --- a/stream-cipher/Cargo.toml +++ b/stream-cipher/Cargo.toml @@ -15,9 +15,15 @@ categories = ["cryptography", "no-std"] generic-array = "0.14" blobby = { version = "0.1", optional = true } +[dependencies.block-cipher] +version = "= 0.7.0-pre" +optional = true +path = "../block-cipher" + [features] std = [] dev = ["blobby"] [package.metadata.docs.rs] -features = [ "std" ] +all-features = true +rustdoc-args = ["--cfg", "docsrs"] diff --git a/stream-cipher/src/dev.rs b/stream-cipher/src/dev.rs index 56e80ca6..cd5e080e 100644 --- a/stream-cipher/src/dev.rs +++ b/stream-cipher/src/dev.rs @@ -4,6 +4,7 @@ pub use blobby; /// Test core functionality of synchronous stream cipher #[macro_export] +#[cfg_attr(docsrs, doc(cfg(feature = "dev")))] macro_rules! new_sync_test { ($name:ident, $cipher:ty, $test_name:expr) => { #[test] @@ -43,6 +44,7 @@ macro_rules! new_sync_test { /// Test stream synchronous stream cipher seeking capabilities #[macro_export] +#[cfg_attr(docsrs, doc(cfg(feature = "dev")))] macro_rules! new_seek_test { ($name:ident, $cipher:ty, $test_name:expr) => { #[test] @@ -85,6 +87,7 @@ macro_rules! new_seek_test { /// Test core functionality of asynchronous stream cipher #[macro_export] +#[cfg_attr(docsrs, doc(cfg(feature = "dev")))] macro_rules! new_async_test { ($name:ident, $test_name:expr, $cipher:ty) => { #[test] @@ -149,6 +152,7 @@ macro_rules! new_async_test { /// Create synchronous stream cipher benchmarks #[macro_export] +#[cfg_attr(docsrs, doc(cfg(feature = "dev")))] macro_rules! bench_sync { ($name:ident, $cipher:path, $data_len:expr) => { #[bench] @@ -187,6 +191,7 @@ macro_rules! bench_sync { /// Create synchronous stream cipher benchmarks #[macro_export] +#[cfg_attr(docsrs, doc(cfg(feature = "dev")))] macro_rules! bench_async { ($enc_name:ident, $dec_name:ident, $cipher:path, $data_len:expr) => { #[bench] diff --git a/stream-cipher/src/lib.rs b/stream-cipher/src/lib.rs index 8a236690..1a056c83 100644 --- a/stream-cipher/src/lib.rs +++ b/stream-cipher/src/lib.rs @@ -5,6 +5,7 @@ //! for ciphers implementation. #![no_std] +#![cfg_attr(docsrs, feature(doc_cfg))] #![doc(html_logo_url = "https://raw.githubusercontent.com/RustCrypto/meta/master/logo_small.png")] #![forbid(unsafe_code)] #![warn(missing_docs, rust_2018_idioms)] @@ -13,6 +14,7 @@ extern crate std; #[cfg(feature = "dev")] +#[cfg_attr(docsrs, doc(cfg(feature = "dev")))] pub mod dev; mod errors; @@ -23,6 +25,9 @@ pub use generic_array::{self, typenum::consts}; use generic_array::typenum::Unsigned; use generic_array::{ArrayLength, GenericArray}; +#[cfg(feature = "block-cipher")] +use block_cipher::{BlockCipher, NewBlockCipher}; + /// Stream cipher creation trait. /// /// It can be used for creation of synchronous and asynchronous ciphers. @@ -112,3 +117,34 @@ impl StreamCipher for C { SyncStreamCipher::apply_keystream(self, data); } } + +/// Trait for initializing a stream cipher from a block cipher +#[cfg(feature = "block-cipher")] +#[cfg_attr(docsrs, doc(cfg(feature = "block-cipher")))] +pub trait FromBlockCipher { + /// Block cipher + type BlockCipher: BlockCipher + NewBlockCipher; + + /// Instantiate a stream cipher from a block cipher + // TODO(tarcieri): add associated type for NonceSize? + fn from_block_cipher( + cipher: Self::BlockCipher, + nonce: &block_cipher::Block, + ) -> Self; +} + +#[cfg(feature = "block-cipher")] +impl NewStreamCipher for C +where + C: FromBlockCipher, +{ + type KeySize = <::BlockCipher as NewBlockCipher>::KeySize; + type NonceSize = <::BlockCipher as BlockCipher>::BlockSize; + + fn new(key: &GenericArray, nonce: &GenericArray) -> C { + C::from_block_cipher( + <::BlockCipher as NewBlockCipher>::new(key), + nonce, + ) + } +}