1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89
use crate::util::generate_key; use openssl::symm; use rand::distributions::Standard; use rand::{thread_rng, Rng}; pub struct Cipher { pub cipher: symm::Cipher, pub key: Vec<u8>, pub iv: Vec<u8>, pub iv_len: usize, pub enc: Option<symm::Crypter>, pub dec: Option<symm::Crypter>, } impl Cipher { pub fn new(method: &str, password: &str) -> Cipher { let cipher = match method { "aes-256-cfb" => symm::Cipher::aes_256_cfb128(), "aes-128-cfb" => symm::Cipher::aes_128_cfb128(), "aes-128-cfb1" => symm::Cipher::aes_128_cfb1(), "aes-128-cfb8" => symm::Cipher::aes_128_cfb8(), "rc4-md5" => symm::Cipher::rc4(), _ => panic!("method not supported"), }; let key = generate_key(password.as_bytes(), cipher.key_len()); Cipher { cipher, key: Vec::from(&key[..]), iv: vec![], iv_len: cipher.iv_len().unwrap_or_default(), enc: None, dec: None, } } pub fn init_encrypt(&mut self) { if self.iv.is_empty() { let rng = thread_rng(); self.iv = rng.sample_iter(&Standard).take(self.iv_len).collect(); } self.enc = Some( symm::Crypter::new(self.cipher, symm::Mode::Encrypt, &self.key, Some(&self.iv)) .expect("init enc error"), ); } pub fn init_decrypt(&mut self, iv: &[u8]) { self.dec = Some( symm::Crypter::new(self.cipher, symm::Mode::Decrypt, &self.key, Some(iv)) .expect("init enc error"), ); } pub fn encrypt(&mut self, input: &[u8]) -> Option<Vec<u8>> { let reserve_len = input.len() + self.cipher.block_size(); let mut out = vec![0u8; reserve_len]; if let Some(ref mut enc) = self.enc { if enc.update(input, &mut out).is_ok() { return Some(out); } } None } pub fn decrypt(&mut self, input: &[u8]) -> Option<Vec<u8>> { let reserve_len = input.len() + self.cipher.block_size(); let mut out = vec![0u8; reserve_len]; if let Some(ref mut dec) = self.dec { if dec.update(input, &mut out).is_ok() { return Some(out); } } None } pub fn reset(&self) -> Cipher { Cipher { cipher: self.cipher, key: self.key.clone(), iv: vec![], iv_len: self.iv_len, enc: None, dec: None, } } }