cryptimitives/stream_cipher/
chacha20.rs1use chacha20::{
3    cipher::{KeyIvInit, StreamCipher as _},
4    ChaCha20,
5};
6use cryptraits::stream_cipher::StreamCipher as StreamCipherTrait;
7use zeroize::Zeroize;
8
9use crate::errors::StreamCipherError;
10
11#[derive(Zeroize)]
13pub struct StreamCipher(#[zeroize(skip)] ChaCha20);
14
15impl StreamCipherTrait for StreamCipher {
16    type E = StreamCipherError;
17
18    fn new_from_slices(key: &[u8], nonce: &[u8]) -> Result<Self, Self::E>
19    where
20        Self: Sized,
21    {
22        let cipher =
23            ChaCha20::new_from_slices(key, nonce).or(Err(StreamCipherError::InvalidLength))?;
24
25        Ok(Self(cipher))
26    }
27
28    fn apply_keystream(&mut self, data: &mut [u8]) -> Result<(), Self::E> {
29        self.0
30            .try_apply_keystream(data)
31            .or(Err(StreamCipherError::LoopError))
32    }
33}
34
35#[cfg(test)]
36mod tests {
37    use cryptraits::stream_cipher::StreamCipher as _;
38    use hex_literal::hex;
39
40    use crate::stream_cipher::chacha20::StreamCipher;
41
42    const KEY: [u8; 32] = hex!("000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f");
43
44    const IV: [u8; 12] = hex!("000000000000004a00000000");
45
46    const PLAINTEXT: [u8; 114] = hex!(
47        "
48        4c616469657320616e642047656e746c
49        656d656e206f662074686520636c6173
50        73206f66202739393a20496620492063
51        6f756c64206f6666657220796f75206f
52        6e6c79206f6e652074697020666f7220
53        746865206675747572652c2073756e73
54        637265656e20776f756c642062652069
55        742e
56        "
57    );
58
59    const KEYSTREAM: [u8; 114] = hex!(
60        "
61        224f51f3401bd9e12fde276fb8631ded8c131f823d2c06
62        e27e4fcaec9ef3cf788a3b0aa372600a92b57974cded2b
63        9334794cba40c63e34cdea212c4cf07d41b769a6749f3f
64        630f4122cafe28ec4dc47e26d4346d70b98c73f3e9c53a
65        c40c5945398b6eda1a832c89c167eacd901d7e2bf363
66        "
67    );
68
69    const CIPHERTEXT: [u8; 114] = hex!(
70        "
71        6e2e359a2568f98041ba0728dd0d6981
72        e97e7aec1d4360c20a27afccfd9fae0b
73        f91b65c5524733ab8f593dabcd62b357
74        1639d624e65152ab8f530c359f0861d8
75        07ca0dbf500d6a6156a38e088a22b65e
76        52bc514d16ccf806818ce91ab7793736
77        5af90bbf74a35be6b40b8eedf2785e42
78        874d
79        "
80    );
81
82    #[test]
83    fn test_keystream() {
84        let mut cipher = StreamCipher::new_from_slices(&KEY, &IV).unwrap();
85
86        let mut prefix = [0u8; 64];
88        cipher.apply_keystream(&mut prefix).unwrap();
89
90        let mut buf = [0u8; 114];
91        cipher.apply_keystream(&mut buf).unwrap();
92        assert_eq!(&buf[..], &KEYSTREAM[..]);
93    }
94
95    #[test]
96    fn test_encryption() {
97        let mut cipher = StreamCipher::new_from_slices(&KEY, &IV).unwrap();
98        let mut buf = PLAINTEXT.clone();
99
100        let mut prefix = [0u8; 64];
102        cipher.apply_keystream(&mut prefix).unwrap();
103
104        cipher.apply_keystream(&mut buf).unwrap();
105        assert_eq!(&buf[..], &CIPHERTEXT[..]);
106    }
107}