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 90 91
use std::cmp; use ring::aead::{Algorithm, LessSafeKey, Nonce, UnboundKey, Aad}; use ring::aead::{AES_128_GCM, AES_256_GCM, CHACHA20_POLY1305}; use ring::digest; use ring::error; #[derive(Debug, Clone)] pub enum Method { Aes128Gcm, Aes256Gcm, ChaCha20Poly1305 } impl Method { fn algorithm(&self) -> &'static Algorithm { match self { Method::Aes128Gcm => &AES_128_GCM, Method::Aes256Gcm => &AES_256_GCM, Method::ChaCha20Poly1305 => &CHACHA20_POLY1305 } } } impl Default for Method { fn default() -> Self { Method::Aes256Gcm } } #[derive(Debug)] pub struct Aead { aead: LessSafeKey, nonce: Vec<u8> } impl Aead { pub fn new(method: &Method, key: &[u8]) -> Aead { let algorithm = method.algorithm(); let key_len = algorithm.key_len(); let key = digest::digest(&digest::SHA256, key).as_ref().to_vec(); let key = UnboundKey::new(algorithm, &key[0..key_len]).expect("Fails if key_bytes.len() != algorithm.key_len()`."); let aead = LessSafeKey::new(key); let nonce_len = algorithm.nonce_len(); let mut nonce = vec![0u8; nonce_len]; nonce[..5].clone_from_slice(&[113, 117, 101, 101, 110]); Aead { aead, nonce } } pub fn set_nonce(&mut self, nonce: &[u8]) { let min = cmp::min(self.nonce.len(), nonce.len()); self.nonce[..min].clone_from_slice(&nonce[..min]) } pub fn encrypt(&mut self, in_out: &mut Vec<u8>) -> Result<(), error::Unspecified> { let nonce = Nonce::try_assume_unique_for_key(&self.nonce).unwrap(); let tag = self.aead.seal_in_place_separate_tag(nonce, Aad::empty(), &mut in_out[4..])?; in_out.extend_from_slice(tag.as_ref()); let len = (in_out.len() as i32).to_le_bytes(); in_out[..4].clone_from_slice(&len); Ok(()) } pub fn decrypt(&mut self, in_out: &mut Vec<u8>) -> Result<(), error::Unspecified> { let nonce = Nonce::try_assume_unique_for_key(&self.nonce).unwrap(); self.aead.open_in_place(nonce, Aad::empty(), &mut in_out[4..]).map(|_| {})?; unsafe { in_out.set_len(in_out.len() - self.aead.algorithm().tag_len()); } let len = (in_out.len() as i32).to_le_bytes(); in_out[..4].clone_from_slice(&len); Ok(()) } }