use std::io::{Error, ErrorKind};
use aes_gcm_siv::{
aead::Aead,
Aes256GcmSiv, KeyInit, Nonce,
};
use rand::RngCore;
pub(crate) fn encapsulate(pkt: &[u8], key: &[u8]) -> Result<Vec<u8>, std::io::Error> {
if key.len() != 32 {
return Err(Error::from(ErrorKind::InvalidInput));
}
let mut rng: rand::rngs::ThreadRng = rand::thread_rng();
let mut nonce_raw: [u8; 12] = [0u8; 12];
rng.fill_bytes(&mut nonce_raw);
let cipher = Aes256GcmSiv::new(key.into());
let nonce = Nonce::from_slice(&nonce_raw);
let mut cpt: Vec<u8> = match cipher.encrypt(nonce, pkt) {
Ok(v) => v,
Err(_) => return Err(Error::from(ErrorKind::InvalidData)),
};
cpt.extend(&nonce_raw);
Ok(cpt)
}
pub(crate) fn reveal(pkt: &[u8], key: &[u8]) -> Result<Vec<u8>, std::io::Error> {
if key.len() != 32 {
return Err(Error::from(ErrorKind::InvalidInput));
}
let l0: usize = pkt.len();
let nonce = Nonce::from_slice(&pkt[l0 - 12..]);
let pkt = &pkt[..l0 - 12];
let cipher = Aes256GcmSiv::new(key.into());
match cipher.decrypt(nonce, pkt) {
Ok(v) => Ok(v),
Err(_) => Err(Error::from(ErrorKind::InvalidData)),
}
}
#[cfg(test)]
mod tests {
use super::*;
use aes_gcm_siv::aead::OsRng;
#[test]
fn enc_rev_pkts_aes256_single_rand() {
let key = Aes256GcmSiv::generate_key(OsRng);
let pkt = b"This is a sample packet for encryption with AES256-GCM-SIV!";
assert_eq!(reveal(&encapsulate(pkt, &key).unwrap(), &key).unwrap(), pkt);
}
}