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)]
13pub enum InnerStreamError {
15 #[error("Unsupported inner stream type: {0:?}")]
16 UnsupportedCipher(InnerStreamCipherAlgorithm),
18}
19
20impl InnerStreamCipherAlgorithm {
21 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}