Skip to content

Commit

Permalink
working aes implementation
Browse files Browse the repository at this point in the history
This patch adds a working AES256-GCM-SIV implementation, complete with one unit test. That test should be sufficient coverage, but in case it isn't, more tests can be added in the future.

Signed-off-by: Amy Parker <amy@amyip.net>
  • Loading branch information
amyipdev committed Feb 5, 2024
1 parent b5d16e4 commit 47e2267
Show file tree
Hide file tree
Showing 2 changed files with 52 additions and 6 deletions.
6 changes: 4 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ name = "libacc"
version = "0.1.0"
edition = "2021"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
aes-gcm-siv = "0.11.1"
rand = "0.8.5"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
52 changes: 48 additions & 4 deletions src/aes.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,57 @@
use std::io::{Error, ErrorKind};

use aes_gcm_siv::{
aead::{Aead, OsRng},
Aes256GcmSiv, KeyInit, Nonce,
};
use rand::RngCore;

/// Generates AES-encrypted packet from key.
/// Returns the encrypted packet with appended nonce,
/// which is really only the first 96 bits of the last 16 bytes.
fn encapsulate(pkt: &[u8], key: &[u8]) -> Vec<u8> {
unimplemented!()
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)
}

/// Attempts to decrypt AES with a given key.
/// If this fails, returns Err.
/// On success, returns Ok(Vec<u8>) containing the packet.
fn reveal(pkt: &[u8]) -> Result<Vec<u8>, std::io::Error> {
unimplemented!()
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)),
}
//unimplemented!()
}

#[cfg(test)]
mod tests {
use super::*;

#[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);
}
}

0 comments on commit 47e2267

Please sign in to comment.