kdbx_rs/stream/
random.rs

1use chacha20::ChaCha20;
2use cipher::KeyIvInit;
3use cipher::StreamCipher;
4use salsa20::Salsa20;
5use sha2::{Digest, Sha256, Sha512};
6use thiserror::Error;
7
8use crate::binary::InnerStreamCipherAlgorithm;
9
10pub const SALSA20_IV: [u8; 8] = [0xe8, 0x30, 0x09, 0x4b, 0x97, 0x20, 0x5d, 0x2a];
11
12#[derive(Debug, Error)]
13/// Errors creating inner stream used to decrypt protected values
14pub enum InnerStreamError {
15    #[error("Unsupported inner stream type: {0:?}")]
16    /// The cipher type is not supported by this library
17    UnsupportedCipher(InnerStreamCipherAlgorithm),
18}
19
20impl InnerStreamCipherAlgorithm {
21    /// Create a stream cipher instance for this algorithm
22    pub fn stream_cipher(self, key: &[u8]) -> Result<Box<dyn StreamCipher>, InnerStreamError> {
23        match self {
24            InnerStreamCipherAlgorithm::ChaCha20 => {
25                let iv = Sha512::digest(key);
26                Ok(Box::new(
27                    ChaCha20::new_from_slices(&iv[0..32], &iv[32..44]).unwrap(),
28                ))
29            }
30            InnerStreamCipherAlgorithm::Salsa20 => {
31                let iv = Sha256::digest(key);
32                Ok(Box::new(
33                    Salsa20::new_from_slices(&iv[0..32], &SALSA20_IV).unwrap(),
34                ))
35            }
36            _ => Err(InnerStreamError::UnsupportedCipher(self)),
37        }
38    }
39}