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
use crate::{errors::InvalidLength, BlockCipher, NewBlockCipher};
use generic_array::{typenum::Unsigned, ArrayLength, GenericArray};
pub type CipherKey<C> = GenericArray<u8, <C as NewCipher>::KeySize>;
pub type Nonce<C> = GenericArray<u8, <C as NewCipher>::NonceSize>;
pub trait NewCipher: Sized {
    type KeySize: ArrayLength<u8>;
    type NonceSize: ArrayLength<u8>;
    fn new(key: &CipherKey<Self>, nonce: &Nonce<Self>) -> Self;
    #[inline]
    fn new_from_slices(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))
        }
    }
}
pub trait FromBlockCipher {
    type BlockCipher: BlockCipher;
    type NonceSize: ArrayLength<u8>;
    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_from_slices(key: &[u8], nonce: &[u8]) -> Result<Self, InvalidLength> {
        if nonce.len() != Self::NonceSize::USIZE {
            Err(InvalidLength)
        } else {
            C::BlockCipher::new_from_slice(key)
                .map_err(|_| InvalidLength)
                .map(|cipher| {
                    let nonce = GenericArray::from_slice(nonce);
                    Self::from_block_cipher(cipher, nonce)
                })
        }
    }
}