cipher/
common.rs

1use crate::{errors::InvalidLength, BlockCipher, NewBlockCipher};
2use generic_array::{typenum::Unsigned, ArrayLength, GenericArray};
3
4/// Key for an algorithm that implements [`NewCipher`].
5pub type CipherKey<C> = GenericArray<u8, <C as NewCipher>::KeySize>;
6
7/// Nonce for an algorithm that implements [`NewCipher`].
8pub type Nonce<C> = GenericArray<u8, <C as NewCipher>::NonceSize>;
9
10/// Cipher creation trait.
11///
12/// It can be used for creation of block modes, synchronous and asynchronous stream ciphers.
13pub trait NewCipher: Sized {
14    /// Key size in bytes
15    type KeySize: ArrayLength<u8>;
16
17    /// Nonce size in bytes
18    type NonceSize: ArrayLength<u8>;
19
20    /// Create new stream cipher instance from key and nonce arrays.
21    fn new(key: &CipherKey<Self>, nonce: &Nonce<Self>) -> Self;
22
23    /// Create new stream cipher instance from variable length key and nonce
24    /// given as byte slices.
25    #[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
39/// Trait for types which can be initialized from a block cipher and nonce.
40pub trait FromBlockCipher {
41    /// Block cipher
42    type BlockCipher: BlockCipher;
43    /// Nonce size in bytes
44    type NonceSize: ArrayLength<u8>;
45
46    /// Instantiate a stream cipher from a block cipher
47    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}