blob: 0496345d46d0e83ac3d63d5ec7d505afd12800c4 [file] [log] [blame]
//! Development-related functionality
/// Test core functionality of synchronous stream cipher
#[macro_export]
#[cfg_attr(docsrs, doc(cfg(feature = "dev")))]
macro_rules! stream_cipher_test {
($name:ident, $test_name:expr, $cipher:ty $(,)?) => {
#[test]
fn $name() {
use cipher::generic_array::GenericArray;
use cipher::{blobby::Blob4Iterator, KeyIvInit, StreamCipher};
let data = include_bytes!(concat!("data/", $test_name, ".blb"));
for (i, row) in Blob4Iterator::new(data).unwrap().enumerate() {
let [key, iv, pt, ct] = row.unwrap();
for chunk_n in 1..256 {
let mut mode = <$cipher>::new_from_slices(key, iv).unwrap();
let mut pt = pt.to_vec();
for chunk in pt.chunks_mut(chunk_n) {
mode.apply_keystream(chunk);
}
if pt != &ct[..] {
panic!(
"Failed main test №{}, chunk size: {}\n\
key:\t{:?}\n\
iv:\t{:?}\n\
plaintext:\t{:?}\n\
ciphertext:\t{:?}\n",
i, chunk_n, key, iv, pt, ct,
);
}
}
}
}
};
}
/// Test stream synchronous stream cipher seeking capabilities
#[macro_export]
#[cfg_attr(docsrs, doc(cfg(feature = "dev")))]
macro_rules! stream_cipher_seek_test {
($name:ident, $cipher:ty) => {
#[test]
fn $name() {
use cipher::generic_array::GenericArray;
use cipher::{KeyIvInit, StreamCipher, StreamCipherSeek};
fn get_cipher() -> $cipher {
<$cipher>::new(&Default::default(), &Default::default())
}
const MAX_SEEK: usize = 512;
let mut ct = [0u8; MAX_SEEK];
get_cipher().apply_keystream(&mut ct[..]);
for n in 0..MAX_SEEK {
let mut cipher = get_cipher();
assert_eq!(cipher.current_pos::<usize>(), 0);
cipher.seek(n);
assert_eq!(cipher.current_pos::<usize>(), n);
let mut buf = [0u8; MAX_SEEK];
cipher.apply_keystream(&mut buf[n..]);
assert_eq!(cipher.current_pos::<usize>(), MAX_SEEK);
assert_eq!(&buf[n..], &ct[n..]);
}
const MAX_CHUNK: usize = 128;
const MAX_LEN: usize = 1024;
let mut buf = [0u8; MAX_CHUNK];
let mut cipher = get_cipher();
assert_eq!(cipher.current_pos::<usize>(), 0);
cipher.apply_keystream(&mut []);
assert_eq!(cipher.current_pos::<usize>(), 0);
for n in 1..MAX_CHUNK {
assert_eq!(cipher.current_pos::<usize>(), 0);
for m in 1.. {
cipher.apply_keystream(&mut buf[..n]);
assert_eq!(cipher.current_pos::<usize>(), n * m);
if n * m > MAX_LEN {
break;
}
}
cipher.seek(0);
}
}
};
}
/// Create stream cipher benchmarks
#[macro_export]
#[cfg_attr(docsrs, doc(cfg(feature = "dev")))]
macro_rules! stream_cipher_bench {
(
$cipher:ty;
$($name:ident $bs:expr;)*
) => {
$crate::stream_cipher_bench!(
Init: {
use $crate::KeyIvInit;
let key = test::black_box(Default::default());
let iv = test::black_box(Default::default());
<$cipher>::new(&key, &iv)
};
$($name $bs;)*
);
};
(
Key: $cipher:ty;
$($name:ident $bs:expr;)*
) => {
$crate::stream_cipher_bench!(
Init: {
use $crate::KeyInit;
let key = test::black_box(Default::default());
let iv = test::black_box(Default::default());
<$cipher>::new(&key, &iv)
};
$($name $bs;)*
);
};
(
Init: $init:expr;
$($name:ident $bs:expr;)*
) => {
$(
#[bench]
fn $name(b: &mut test::Bencher) {
use $crate::StreamCipher;
let mut cipher = $init;
let mut buf = vec![0; $bs];
b.iter(|| {
cipher.apply_keystream(&mut buf);
test::black_box(&buf);
});
b.bytes = $bs;
}
)*
};
}