Skip to content

Commit

Permalink
cipher: v0.3 changes (#435)
Browse files Browse the repository at this point in the history
- remove `SeekNum` impls for signed integers
- fix block mode compilation bug
- change `SeekNum` impls to fit with the new `BlockBuffer`
- return `SeenNum` impl for `i32`
- re-export `blobby` from root
- reorganize modules

Co-authored-by: Артём Павлов [Artyom Pavlov] <newpavlov@gmail.com>
  • Loading branch information
tarcieri and newpavlov committed Dec 30, 2020
1 parent fb84fc2 commit d5d137d
Show file tree
Hide file tree
Showing 9 changed files with 136 additions and 158 deletions.
16 changes: 6 additions & 10 deletions cipher/src/block.rs
Expand Up @@ -9,21 +9,17 @@
//! [1]: https://en.wikipedia.org/wiki/Block_cipher
//! [2]: https://en.wikipedia.org/wiki/Symmetric-key_algorithm

#[cfg(feature = "dev")]
#[cfg_attr(docsrs, doc(cfg(feature = "dev")))]
pub mod dev;

use crate::errors::InvalidLength;
use core::convert::TryInto;
use generic_array::{typenum::Unsigned, ArrayLength, GenericArray};

/// Key for an algorithm that implements [`NewBlockCipher`].
pub type Key<B> = GenericArray<u8, <B as NewBlockCipher>::KeySize>;
pub type BlockCipherKey<B> = GenericArray<u8, <B as NewBlockCipher>::KeySize>;

/// Block on which a [`BlockCipher`] operates.
pub type Block<B> = GenericArray<u8, <B as BlockCipher>::BlockSize>;

/// Blocks being acted over in parallel.
/// Block on which a [`BlockCipher`] operates in parallel.
pub type ParBlocks<B> = GenericArray<Block<B>, <B as BlockCipher>::ParBlocks>;

/// Instantiate a [`BlockCipher`] algorithm.
Expand All @@ -32,13 +28,13 @@ pub trait NewBlockCipher: Sized {
type KeySize: ArrayLength<u8>;

/// Create new block cipher instance from key with fixed size.
fn new(key: &Key<Self>) -> Self;
fn new(key: &BlockCipherKey<Self>) -> Self;

/// Create new block cipher instance from key with variable size.
///
/// Default implementation will accept only keys with length equal to
/// `KeySize`, but some ciphers can accept range of key lengths.
fn new_varkey(key: &[u8]) -> Result<Self, InvalidLength> {
fn new_var(key: &[u8]) -> Result<Self, InvalidLength> {
if key.len() != Self::KeySize::to_usize() {
Err(InvalidLength)
} else {
Expand All @@ -57,7 +53,7 @@ pub trait BlockCipher {
type ParBlocks: ArrayLength<Block<Self>>;
}

/// Encrypt-only functionality for block ciphers
/// Encrypt-only functionality for block ciphers.
pub trait BlockEncrypt: BlockCipher {
/// Encrypt block in-place
fn encrypt_block(&self, block: &mut Block<Self>);
Expand Down Expand Up @@ -94,7 +90,7 @@ pub trait BlockEncrypt: BlockCipher {
}
}

/// Decrypt-only functionality for block ciphers
/// Decrypt-only functionality for block ciphers.
pub trait BlockDecrypt: BlockCipher {
/// Decrypt block in-place
fn decrypt_block(&self, block: &mut Block<Self>);
Expand Down
79 changes: 79 additions & 0 deletions cipher/src/common.rs
@@ -0,0 +1,79 @@
use crate::{errors::InvalidLength, BlockCipher, NewBlockCipher};
use generic_array::{typenum::Unsigned, ArrayLength, GenericArray};

/// Key for an algorithm that implements [`NewCipher`].
pub type CipherKey<C> = GenericArray<u8, <C as NewCipher>::KeySize>;

/// Nonce for an algorithm that implements [`NewCipher`].
pub type Nonce<C> = GenericArray<u8, <C as NewCipher>::NonceSize>;

/// Cipher creation trait.
///
/// It can be used for creation of block modes, synchronous and asynchronous stream ciphers.
pub trait NewCipher: Sized {
/// Key size in bytes
type KeySize: ArrayLength<u8>;

/// Nonce size in bytes
type NonceSize: ArrayLength<u8>;

/// Create new stream cipher instance from variable length key and nonce.
fn new(key: &CipherKey<Self>, nonce: &Nonce<Self>) -> Self;

/// Create new stream cipher instance from variable length key and nonce.
#[inline]
fn new_var(key: &[u8], nonce: &[u8]) -> Result<Self, InvalidLength> {
let kl = Self::KeySize::to_usize();
let nl = Self::NonceSize::to_usize();
if key.len() != kl || nonce.len() != nl {
Err(InvalidLength)
} else {
let key = GenericArray::from_slice(key);
let nonce = GenericArray::from_slice(nonce);
Ok(Self::new(key, nonce))
}
}
}

/// Trait for types which can be initialized from a block cipher and nonce.
pub trait FromBlockCipher {
/// Block cipher
type BlockCipher: BlockCipher;
/// Nonce size in bytes
type NonceSize: ArrayLength<u8>;

/// Instantiate a stream cipher from a block cipher
fn from_block_cipher(
cipher: Self::BlockCipher,
nonce: &GenericArray<u8, Self::NonceSize>,
) -> Self;
}

impl<C> NewCipher for C
where
C: FromBlockCipher,
C::BlockCipher: NewBlockCipher,
{
type KeySize = <<Self as FromBlockCipher>::BlockCipher as NewBlockCipher>::KeySize;
type NonceSize = <Self as FromBlockCipher>::NonceSize;

fn new(key: &CipherKey<Self>, nonce: &Nonce<Self>) -> C {
C::from_block_cipher(
<<Self as FromBlockCipher>::BlockCipher as NewBlockCipher>::new(key),
nonce,
)
}

fn new_var(key: &[u8], nonce: &[u8]) -> Result<Self, InvalidLength> {
if nonce.len() != Self::NonceSize::USIZE {
Err(InvalidLength)
} else {
C::BlockCipher::new_var(key)
.map_err(|_| InvalidLength)
.map(|cipher| {
let nonce = GenericArray::from_slice(nonce);
Self::from_block_cipher(cipher, nonce)
})
}
}
}
2 changes: 2 additions & 0 deletions cipher/src/dev.rs
@@ -0,0 +1,2 @@
mod block;
mod stream;
16 changes: 8 additions & 8 deletions cipher/src/block/dev.rs → cipher/src/dev/block.rs
Expand Up @@ -9,13 +9,13 @@ macro_rules! block_cipher_test {
($name:ident, $test_name:expr, $cipher:ty) => {
#[test]
fn $name() {
use cipher::block::{
dev::blobby::Blob3Iterator, BlockCipher, BlockDecrypt, BlockEncrypt, NewBlockCipher,
};
use cipher::generic_array::{typenum::Unsigned, GenericArray};
use cipher::{
blobby::Blob3Iterator, BlockCipher, BlockDecrypt, BlockEncrypt, NewBlockCipher,
};

fn run_test(key: &[u8], pt: &[u8], ct: &[u8]) -> bool {
let state = <$cipher as NewBlockCipher>::new_varkey(key).unwrap();
let state = <$cipher as NewBlockCipher>::new_var(key).unwrap();

let mut block = GenericArray::clone_from_slice(pt);
state.encrypt_block(&mut block);
Expand All @@ -37,7 +37,7 @@ macro_rules! block_cipher_test {
type Block = GenericArray<u8, BlockSize>;
type ParBlock = GenericArray<Block, ParBlocks>;

let state = <$cipher as NewBlockCipher>::new_varkey(key).unwrap();
let state = <$cipher as NewBlockCipher>::new_var(key).unwrap();

let block = Block::clone_from_slice(pt);
let mut blocks1 = ParBlock::default();
Expand Down Expand Up @@ -113,12 +113,12 @@ macro_rules! block_cipher_bench {
($cipher:path, $key_len:expr) => {
extern crate test;

use cipher::block::{BlockCipher, BlockDecrypt, BlockEncrypt, NewBlockCipher};
use cipher::{BlockCipher, BlockDecrypt, BlockEncrypt, NewBlockCipher};
use test::Bencher;

#[bench]
pub fn encrypt(bh: &mut Bencher) {
let state = <$cipher>::new_varkey(&[1u8; $key_len]).unwrap();
let state = <$cipher>::new_var(&[1u8; $key_len]).unwrap();
let mut block = Default::default();

bh.iter(|| {
Expand All @@ -130,7 +130,7 @@ macro_rules! block_cipher_bench {

#[bench]
pub fn decrypt(bh: &mut Bencher) {
let state = <$cipher>::new_varkey(&[1u8; $key_len]).unwrap();
let state = <$cipher>::new_var(&[1u8; $key_len]).unwrap();
let mut block = Default::default();

bh.iter(|| {
Expand Down
14 changes: 6 additions & 8 deletions cipher/src/stream/dev.rs → cipher/src/dev/stream.rs
Expand Up @@ -3,12 +3,12 @@
/// Test core functionality of synchronous stream cipher
#[macro_export]
#[cfg_attr(docsrs, doc(cfg(feature = "dev")))]
macro_rules! stream_cipher_sync_test {
macro_rules! stream_cipher_test {
($name:ident, $cipher:ty, $test_name:expr) => {
#[test]
fn $name() {
use cipher::generic_array::GenericArray;
use cipher::stream::{blobby::Blob4Iterator, NewStreamCipher, SyncStreamCipher};
use cipher::{blobby::Blob4Iterator, NewCipher, StreamCipher};

let data = include_bytes!(concat!("data/", $test_name, ".blb"));
for (i, row) in Blob4Iterator::new(data).unwrap().enumerate() {
Expand Down Expand Up @@ -44,7 +44,7 @@ macro_rules! stream_cipher_seek_test {
#[test]
fn $name() {
use cipher::generic_array::GenericArray;
use cipher::stream::{NewStreamCipher, SyncStreamCipher, SyncStreamCipherSeek};
use cipher::{NewCipher, StreamCipher, StreamCipherSeek};

fn get_cipher() -> $cipher {
<$cipher>::new(&Default::default(), &Default::default())
Expand Down Expand Up @@ -97,7 +97,7 @@ macro_rules! stream_cipher_async_test {
#[test]
fn $name() {
use cipher::generic_array::GenericArray;
use cipher::stream::{blobby::Blob4Iterator, NewStreamCipher, StreamCipher};
use cipher::{blobby::Blob4Iterator, AsyncStreamCipher, NewCipher};

fn run_test(
key: &[u8],
Expand Down Expand Up @@ -172,8 +172,7 @@ macro_rules! stream_cipher_sync_bench {
($cipher:path) => {
extern crate test;

use cipher::generic_array::GenericArray;
use cipher::stream::{NewStreamCipher, SyncStreamCipher};
use cipher::{generic_array::GenericArray, NewCipher, StreamCipher};
use test::Bencher;

#[inline(never)]
Expand Down Expand Up @@ -225,8 +224,7 @@ macro_rules! stream_cipher_async_bench {
($cipher:path) => {
extern crate test;

use cipher::generic_array::GenericArray;
use cipher::stream::{NewStreamCipher, StreamCipher};
use cipher::{generic_array::GenericArray, AsyncStreamCipher, NewCipher};
use test::Bencher;

#[inline(never)]
Expand Down
2 changes: 1 addition & 1 deletion cipher/src/errors.rs
@@ -1,4 +1,4 @@
//! Error types
//! Error types.

use core::fmt;

Expand Down
17 changes: 9 additions & 8 deletions cipher/src/lib.rs
Expand Up @@ -16,14 +16,15 @@
#[cfg(feature = "std")]
extern crate std;

pub mod block;
#[cfg(feature = "dev")]
pub use blobby;

mod block;
mod common;
#[cfg(feature = "dev")]
mod dev;
pub mod errors;
pub mod stream;
mod stream;

pub use crate::{
block::{
BlockCipher, BlockDecrypt, BlockDecryptMut, BlockEncrypt, BlockEncryptMut, NewBlockCipher,
},
stream::{NewStreamCipher, StreamCipher, SyncStreamCipher, SyncStreamCipherSeek},
};
pub use crate::{block::*, common::*, stream::*};
pub use generic_array::{self, typenum::consts};

0 comments on commit d5d137d

Please sign in to comment.