feat: gfmul and aes gcm working

This commit is contained in:
0xalivecow 2024-11-03 10:58:52 +01:00
parent 8db0bbaa63
commit e33a26adab
No known key found for this signature in database
4 changed files with 137 additions and 6 deletions

View file

@ -1,9 +1,9 @@
use std::io::BufRead; use std::{io::BufRead, process::Output};
use anyhow::Result; use anyhow::Result;
use openssl::symm::{Cipher, Crypter, Mode}; use openssl::symm::{Cipher, Crypter, Mode};
use crate::utils::field::ByteArray; use crate::utils::{field::ByteArray, math::reverse_bits_in_bytevec, poly::gfmul};
use super::math::xor_bytes; use super::math::xor_bytes;
@ -122,6 +122,92 @@ pub fn xex_decrypt(mut key: Vec<u8>, tweak: &Vec<u8>, input: &Vec<u8>) -> Result
Ok(output) Ok(output)
} }
pub fn gcm_encrypt_aes(
mut nonce: Vec<u8>,
key: Vec<u8>,
plaintext: Vec<u8>,
ad: Vec<u8>,
) -> Result<(Vec<u8>, Vec<u8>, Vec<u8>, Vec<u8>)> {
let mut ciphertext: Vec<u8> = vec![];
let mut counter: u32 = 1;
nonce.append(counter.to_be_bytes().to_vec().as_mut());
//nonce.append(0u8.to_le_bytes().to_vec().as_mut());
eprintln!("{:001X?}", nonce);
let auth_tag_xor = aes_128_encrypt(&key, &nonce)?;
let auth_key_h = aes_128_encrypt(&key, &0u128.to_be_bytes().to_vec())?;
let plaintext_chunks: Vec<Vec<u8>> = plaintext.chunks(16).map(|x| x.to_vec()).collect();
counter = 2;
for chunk in plaintext_chunks {
nonce.drain(12..);
nonce.append(counter.to_be_bytes().to_vec().as_mut());
eprintln!("{:001X?}", nonce);
let inter1 = aes_128_encrypt(&key, &nonce)?;
let mut inter2 = xor_bytes(&inter1, chunk.clone())?;
ciphertext.append(inter2.as_mut());
counter += 1;
}
let mut l_field: Vec<u8> = ((ad.len() * 8) as u64).to_be_bytes().to_vec();
let mut c_len: Vec<u8> = ((ciphertext.len() * 8) as u64).to_be_bytes().to_vec();
l_field.append(c_len.as_mut());
let auth_tag = xor_bytes(
&ghash(auth_key_h.clone(), ad, ciphertext.clone(), l_field.clone())?,
auth_tag_xor,
)?;
Ok((ciphertext, auth_tag, l_field, auth_key_h))
}
pub fn ghash(
auth_key_h: Vec<u8>,
mut ad: Vec<u8>,
mut ciphertext: Vec<u8>,
l_field: Vec<u8>,
) -> Result<Vec<u8>> {
let output: Vec<u8> = vec![0; 16];
eprintln!("{:?}", (ad.len() % 16) as u8);
eprintln!("{:001X?}", ad);
if ad.len() % 16 != 0 {
ad.append(vec![0u8; ad.len() % 16].as_mut());
}
if ciphertext.len() % 16 != 0 {
ciphertext.append(vec![0u8; ciphertext.len() % 16].as_mut());
}
eprintln!("{:001X?}", ad);
eprintln!("{:001X?}", ciphertext);
let inter1 = xor_bytes(&output, ad)?;
let mut inter_loop = gfmul(inter1, auth_key_h.clone(), "gcm")?;
inter_loop = inter_loop;
let cipher_chunks = ciphertext.chunks(16);
for chunk in cipher_chunks {
let inter3 = xor_bytes(&inter_loop, chunk.to_vec())?;
inter_loop = gfmul(inter3, auth_key_h.clone(), "gcm")?;
}
let inter4 = xor_bytes(&inter_loop, l_field)?;
inter_loop = gfmul(inter4, auth_key_h.clone(), "gcm")?;
Ok(inter_loop)
}
/* /*
* let mut bytes: [u8; 16] = [0u8; 16]; * let mut bytes: [u8; 16] = [0u8; 16];
bytes.copy_from_slice(&ciphertext); bytes.copy_from_slice(&ciphertext);
@ -180,4 +266,30 @@ mod tests {
Ok(()) Ok(())
} }
#[test]
fn test_gcm_encrypt_aes() -> Result<()> {
let nonce = BASE64_STANDARD.decode("4gF+BtR3ku/PUQci")?;
let key = BASE64_STANDARD.decode("Xjq/GkpTSWoe3ZH0F+tjrQ==")?;
let plaintext = BASE64_STANDARD.decode("RGFzIGlzdCBlaW4gVGVzdA==")?;
let ad = BASE64_STANDARD.decode("QUQtRGF0ZW4=")?;
let (ciphertext, auth_tag, l_field, auth_key_h) =
gcm_encrypt_aes(nonce, key, plaintext, ad)?;
eprintln!(
"Cipher: {:001X?} \n Tag: {:001X?} \n L_Field: {:001X?} \n H: {:001X?}",
BASE64_STANDARD.encode(&ciphertext),
BASE64_STANDARD.encode(&auth_tag),
BASE64_STANDARD.encode(&l_field),
BASE64_STANDARD.encode(&auth_key_h)
);
assert_eq!(BASE64_STANDARD.encode(ciphertext), "");
assert_eq!(BASE64_STANDARD.encode(auth_tag), "");
assert_eq!(BASE64_STANDARD.encode(l_field), "");
assert_eq!(BASE64_STANDARD.encode(auth_key_h), "");
Ok(())
}
} }

View file

@ -96,6 +96,10 @@ impl ByteArray {
} }
true true
} }
pub fn reverse_bits_in_bytevec(&mut self) {
self.0 = self.0.iter_mut().map(|byte| byte.reverse_bits()).collect();
}
} }
#[cfg(test)] #[cfg(test)]

View file

@ -10,3 +10,9 @@ pub fn xor_bytes(vec1: &Vec<u8>, mut vec2: Vec<u8>) -> Result<Vec<u8>> {
Ok(vec2) Ok(vec2)
} }
pub fn reverse_bits_in_bytevec(mut vec: Vec<u8>) -> Vec<u8> {
vec = vec.iter_mut().map(|byte| byte.reverse_bits()).collect();
vec
}

View file

@ -4,7 +4,7 @@ use base64::prelude::*;
use serde_json::Value; use serde_json::Value;
use std::{str::FromStr, u128, u8, usize}; use std::{str::FromStr, u128, u8, usize};
use super::field; use super::{field, math::reverse_bits_in_bytevec};
pub const RED_POLY: u128 = 0x87000000_00000000_00000000_00000000; pub const RED_POLY: u128 = 0x87000000_00000000_00000000_00000000;
pub fn gfmul(poly_a: Vec<u8>, poly_b: Vec<u8>, semantic: &str) -> Result<Vec<u8>> { pub fn gfmul(poly_a: Vec<u8>, poly_b: Vec<u8>, semantic: &str) -> Result<Vec<u8>> {
@ -17,15 +17,20 @@ pub fn gfmul(poly_a: Vec<u8>, poly_b: Vec<u8>, semantic: &str) -> Result<Vec<u8>
let mut poly2: ByteArray = ByteArray(poly_b); let mut poly2: ByteArray = ByteArray(poly_b);
poly2.0.push(0x00); poly2.0.push(0x00);
if semantic == "gcm" {
poly1.reverse_bits_in_bytevec();
poly2.reverse_bits_in_bytevec();
}
let mut result: ByteArray = ByteArray(vec![0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]); let mut result: ByteArray = ByteArray(vec![0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]);
if poly2.LSB_is_one() { if poly2.LSB_is_one() {
result.xor_byte_arrays(&poly1); result.xor_byte_arrays(&poly1);
} }
poly2.right_shift(semantic)?; poly2.right_shift("xex")?;
while !poly2.is_empty() { while !poly2.is_empty() {
poly1.left_shift(semantic)?; poly1.left_shift("xex")?;
if poly1.msb_is_one() { if poly1.msb_is_one() {
poly1.xor_byte_arrays(&red_poly_bytes); poly1.xor_byte_arrays(&red_poly_bytes);
@ -35,11 +40,15 @@ pub fn gfmul(poly_a: Vec<u8>, poly_b: Vec<u8>, semantic: &str) -> Result<Vec<u8>
result.xor_byte_arrays(&poly1); result.xor_byte_arrays(&poly1);
} }
poly2.right_shift(semantic)?; poly2.right_shift("xex")?;
} }
result.0.remove(16); result.0.remove(16);
if semantic == "gcm" {
result.reverse_bits_in_bytevec();
}
Ok(result.0) Ok(result.0)
} }