1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
pub use blobby;
#[macro_export]
#[cfg_attr(docsrs, doc(cfg(feature = "dev")))]
macro_rules! new_test {
($name:ident, $test_name:expr, $cipher:ty) => {
#[test]
fn $name() {
use block_cipher::dev::blobby::Blob3Iterator;
use block_cipher::generic_array::typenum::Unsigned;
use block_cipher::generic_array::GenericArray;
use block_cipher::{BlockCipher, NewBlockCipher};
fn run_test(key: &[u8], pt: &[u8], ct: &[u8]) -> bool {
let state = <$cipher as NewBlockCipher>::new_varkey(key).unwrap();
let mut block = GenericArray::clone_from_slice(pt);
state.encrypt_block(&mut block);
if ct != block.as_slice() {
return false;
}
state.decrypt_block(&mut block);
if pt != block.as_slice() {
return false;
}
true
}
fn run_par_test(key: &[u8], pt: &[u8]) -> bool {
type ParBlocks = <$cipher as BlockCipher>::ParBlocks;
type BlockSize = <$cipher as BlockCipher>::BlockSize;
type Block = GenericArray<u8, BlockSize>;
type ParBlock = GenericArray<Block, ParBlocks>;
let state = <$cipher as NewBlockCipher>::new_varkey(key).unwrap();
let block = Block::clone_from_slice(pt);
let mut blocks1 = ParBlock::default();
for (i, b) in blocks1.iter_mut().enumerate() {
*b = block;
b[0] = b[0].wrapping_add(i as u8);
}
let mut blocks2 = blocks1.clone();
state.encrypt_blocks(&mut blocks1);
for b in blocks2.iter_mut() {
state.encrypt_block(b);
}
if blocks1 != blocks2 {
return false;
}
state.decrypt_blocks(&mut blocks1);
for b in blocks2.iter_mut() {
state.decrypt_block(b);
}
if blocks1 != blocks2 {
return false;
}
true
}
let pb = <$cipher as BlockCipher>::ParBlocks::to_usize();
let data = include_bytes!(concat!("data/", $test_name, ".blb"));
for (i, row) in Blob3Iterator::new(data).unwrap().enumerate() {
let [key, pt, ct] = row.unwrap();
if !run_test(key, pt, ct) {
panic!(
"\n\
Failed test №{}\n\
key:\t{:?}\n\
plaintext:\t{:?}\n\
ciphertext:\t{:?}\n",
i, key, pt, ct,
);
}
if pb != 1 {
if !run_par_test(key, pt) {
panic!(
"\n\
Failed parallel test №{}\n\
key:\t{:?}\n\
plaintext:\t{:?}\n\
ciphertext:\t{:?}\n",
i, key, pt, ct,
);
}
}
}
let key = Default::default();
let _ = <$cipher as NewBlockCipher>::new(&key).clone();
}
};
}
#[macro_export]
#[cfg_attr(docsrs, doc(cfg(feature = "dev")))]
macro_rules! bench {
($cipher:path, $key_len:expr) => {
extern crate test;
use block_cipher::{BlockCipher, NewBlockCipher};
use test::Bencher;
#[bench]
pub fn encrypt(bh: &mut Bencher) {
let state = <$cipher>::new_varkey(&[1u8; $key_len]).unwrap();
let mut block = Default::default();
bh.iter(|| {
state.encrypt_block(&mut block);
test::black_box(&block);
});
bh.bytes = block.len() as u64;
}
#[bench]
pub fn decrypt(bh: &mut Bencher) {
let state = <$cipher>::new_varkey(&[1u8; $key_len]).unwrap();
let mut block = Default::default();
bh.iter(|| {
state.decrypt_block(&mut block);
test::black_box(&block);
});
bh.bytes = block.len() as u64;
}
};
}