1use crate::{errors::InvalidLength, BlockCipher, NewBlockCipher};
2use generic_array::{typenum::Unsigned, ArrayLength, GenericArray};
3
4pub type CipherKey<C> = GenericArray<u8, <C as NewCipher>::KeySize>;
6
7pub type Nonce<C> = GenericArray<u8, <C as NewCipher>::NonceSize>;
9
10pub trait NewCipher: Sized {
14 type KeySize: ArrayLength<u8>;
16
17 type NonceSize: ArrayLength<u8>;
19
20 fn new(key: &CipherKey<Self>, nonce: &Nonce<Self>) -> Self;
22
23 #[inline]
26 fn new_from_slices(key: &[u8], nonce: &[u8]) -> Result<Self, InvalidLength> {
27 let kl = Self::KeySize::to_usize();
28 let nl = Self::NonceSize::to_usize();
29 if key.len() != kl || nonce.len() != nl {
30 Err(InvalidLength)
31 } else {
32 let key = GenericArray::from_slice(key);
33 let nonce = GenericArray::from_slice(nonce);
34 Ok(Self::new(key, nonce))
35 }
36 }
37}
38
39pub trait FromBlockCipher {
41 type BlockCipher: BlockCipher;
43 type NonceSize: ArrayLength<u8>;
45
46 fn from_block_cipher(
48 cipher: Self::BlockCipher,
49 nonce: &GenericArray<u8, Self::NonceSize>,
50 ) -> Self;
51}
52
53impl<C> NewCipher for C
54where
55 C: FromBlockCipher,
56 C::BlockCipher: NewBlockCipher,
57{
58 type KeySize = <<Self as FromBlockCipher>::BlockCipher as NewBlockCipher>::KeySize;
59 type NonceSize = <Self as FromBlockCipher>::NonceSize;
60
61 fn new(key: &CipherKey<Self>, nonce: &Nonce<Self>) -> C {
62 C::from_block_cipher(
63 <<Self as FromBlockCipher>::BlockCipher as NewBlockCipher>::new(key),
64 nonce,
65 )
66 }
67
68 fn new_from_slices(key: &[u8], nonce: &[u8]) -> Result<Self, InvalidLength> {
69 if nonce.len() != Self::NonceSize::USIZE {
70 Err(InvalidLength)
71 } else {
72 C::BlockCipher::new_from_slice(key)
73 .map_err(|_| InvalidLength)
74 .map(|cipher| {
75 let nonce = GenericArray::from_slice(nonce);
76 Self::from_block_cipher(cipher, nonce)
77 })
78 }
79 }
80}