diff --git a/src/tasks/tasks01/gfmul.rs b/src/tasks/tasks01/gfmul.rs index c4acefe..2c1d6b8 100644 --- a/src/tasks/tasks01/gfmul.rs +++ b/src/tasks/tasks01/gfmul.rs @@ -16,7 +16,7 @@ pub fn gfmul_task(args: &Value) -> Result> { let semantic: String = serde_json::from_value(args["semantic"].clone())?; - let result = gfmul(poly_a, poly_b, &semantic)?; + let result = gfmul(&poly_a, &poly_b, &semantic)?; Ok(result) } @@ -39,7 +39,7 @@ mod tests { let poly2_text: String = serde_json::from_value(args["b"].clone())?; let poly_b = BASE64_STANDARD.decode(poly2_text)?; - let result = BASE64_STANDARD.encode(gfmul(poly_a, poly_b, "xex")?); + let result = BASE64_STANDARD.encode(gfmul(&poly_a, &poly_b, "xex")?); assert_eq!( result, "hSQAAAAAAAAAAAAAAAAAAA==", @@ -59,7 +59,7 @@ mod tests { let poly2_text: String = serde_json::from_value(args["b"].clone())?; let poly_b = BASE64_STANDARD.decode(poly2_text)?; - let result = BASE64_STANDARD.encode(gfmul(poly_a, poly_b, "xex")?); + let result = BASE64_STANDARD.encode(gfmul(&poly_a, &poly_b, "xex")?); assert_eq!( result, "QKgUAAAAAAAAAAAAAAAAAA==", @@ -79,7 +79,7 @@ mod tests { let poly2_text: String = serde_json::from_value(args["b"].clone())?; let poly_b = BASE64_STANDARD.decode(poly2_text)?; - let result = BASE64_STANDARD.encode(gfmul(poly_a, poly_b, "xex")?); + let result = BASE64_STANDARD.encode(gfmul(&poly_a, &poly_b, "xex")?); assert_eq!( result, "UIAUAAAAAAAAAAAAAAAAAA==", @@ -99,7 +99,7 @@ mod tests { let poly2_text: String = serde_json::from_value(args["b"].clone())?; let poly_b = BASE64_STANDARD.decode(poly2_text)?; - let result = BASE64_STANDARD.encode(gfmul(poly_a, poly_b, "xex")?); + let result = BASE64_STANDARD.encode(gfmul(&poly_a, &poly_b, "xex")?); assert_eq!( result, "hSQAAAAAAAAAAAAAAAAAAA==", diff --git a/src/utils/ciphers.rs b/src/utils/ciphers.rs index 917a1c7..333ec13 100644 --- a/src/utils/ciphers.rs +++ b/src/utils/ciphers.rs @@ -340,25 +340,25 @@ pub fn ghash( eprintln!("Ad chunks before first next {:001X?}", ad_chunks); let inter1 = xor_bytes(&output, ad_chunks.next().unwrap().to_vec())?; - let mut inter_loop = gfmul(inter1, auth_key_h.clone(), "gcm")?; + let mut inter_loop = gfmul(&inter1, &auth_key_h, "gcm")?; eprintln!("Ad chunks after first next {:001X?}", ad_chunks); for chunk in ad_chunks { eprintln!("Inside ad chunk loop"); eprintln!("Ad chunk in loop {:001X?}", chunk); let inter2 = xor_bytes(&inter_loop, chunk.to_vec())?; - inter_loop = gfmul(inter2, auth_key_h.clone(), "gcm")?; + inter_loop = gfmul(&inter2, &auth_key_h, "gcm")?; } 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")?; + inter_loop = gfmul(&inter3, &auth_key_h, "gcm")?; } let inter4 = xor_bytes(&inter_loop, l_field)?; - inter_loop = gfmul(inter4, auth_key_h.clone(), "gcm")?; + inter_loop = gfmul(&inter4, &auth_key_h, "gcm")?; eprintln!("GHASH auth tag: {:001X?}", inter_loop); diff --git a/src/utils/field.rs b/src/utils/field.rs index 25088cf..c8de249 100644 --- a/src/utils/field.rs +++ b/src/utils/field.rs @@ -1,12 +1,15 @@ use std::{ env::args, - ops::{Add, BitXor, Mul}, + ops::{Add, BitXor, Div, Mul, Rem, Sub}, + result, }; use anyhow::{anyhow, Ok, Result}; use base64::prelude::*; use serde_json::Value; +use crate::{tasks::tasks01::poly2block::poly2block, utils::poly::polynomial_2_block}; + use super::{math::xor_bytes, poly::gfmul}; #[derive(Debug)] @@ -142,36 +145,32 @@ impl Add for Polynomial { } } +// Helper implementation for subtraction +impl Sub for &FieldElement { + type Output = FieldElement; + + fn sub(self, rhs: Self) -> FieldElement { + // In a field of characteristic 2, addition and subtraction are the same operation (XOR) + self + rhs + } +} + +// Helper trait for checking emptiness +trait IsEmpty { + fn is_empty(&self) -> bool; +} + +impl IsEmpty for Polynomial { + fn is_empty(&self) -> bool { + self.polynomial.is_empty() + } +} impl AsRef<[FieldElement]> for Polynomial { fn as_ref(&self) -> &[FieldElement] { &self.polynomial } } -/* -impl AsRef<[u8]> for Polynomial { - fn as_ref(&self) -> &[u8] { - &self.polynomial - } -} -*/ -/* -impl Add for Polynomial { - type Output = Self; - fn add(self, rhs: Self) -> Self::Output { - FieldElement::new( - xor_bytes(&self.field_element, rhs.field_element).expect("Error in poly add"), - ) - } -} - -impl AsRef<[u8]> for Polynomial { - fn as_ref(&self) -> &[u8] { - &self.field_element.as_ref() - } -} -*/ - #[derive(Debug)] pub struct FieldElement { field_element: Vec, @@ -187,12 +186,48 @@ impl FieldElement { } pub fn mul(&self, poly_a: Vec, poly_b: Vec) -> Result> { - gfmul(poly_a, poly_b, "gcm") + gfmul(&poly_a, &poly_b, "gcm") } pub fn to_b64(&self) -> String { BASE64_STANDARD.encode(&self.field_element) } + + pub fn pow(&self, mut exponent: u128) -> FieldElement { + if exponent == 0 { + // Return polynomial with coefficient 1 + return FieldElement::new(vec![1]); + } + + let base = self.clone(); + let mut result = base.clone(); + exponent -= 1; // Subtract 1 because we already set result to base + + while exponent > 0 { + result = result * base.clone(); + exponent -= 1; + } + + result + } + + pub fn inv(mut self) -> Self { + let mut inverser: u128 = 0xfffffffffffffffffffffffffffffffe; + let mut inverse: Vec = polynomial_2_block(vec![0], "gcm").unwrap(); + eprintln!("Inverse start {:02X?}", inverse); + + while inverser > 0 { + //eprintln!("{:02X}", inverser); + if inverser & 1 == 1 { + inverse = gfmul(&self.field_element, &inverse, "gcm").unwrap(); + } + inverser >>= 1; + self.field_element = gfmul(&self.field_element, &self.field_element, "gcm") + .expect("Error in sqrmul sqr"); + } + eprintln!("Inverse rhs {:?}", inverse); + FieldElement::new(inverse) + } } impl Mul for FieldElement { @@ -200,7 +235,7 @@ impl Mul for FieldElement { fn mul(self, rhs: Self) -> Self::Output { FieldElement::new( - gfmul(self.field_element, rhs.field_element, "gcm") + gfmul(&self.field_element, &rhs.field_element, "gcm") .expect("Error during multiplication"), ) } @@ -211,7 +246,7 @@ impl Mul for &FieldElement { fn mul(self, rhs: &FieldElement) -> FieldElement { FieldElement::new( - gfmul(self.field_element.clone(), rhs.field_element.clone(), "gcm") + gfmul(&self.field_element, &rhs.field_element, "gcm") .expect("Error during multiplication"), ) } @@ -262,6 +297,36 @@ impl BitXor for FieldElement { } } +impl Div for FieldElement { + type Output = Self; + fn div(self, rhs: Self) -> Self::Output { + eprintln!("RHS in div{:02X?}", &rhs); + + let inverse = rhs.inv(); + eprintln!("Inverse in div{:02X?}", inverse); + self.clone() * inverse + } +} + +impl Div for &FieldElement { + type Output = FieldElement; + + fn div(self, rhs: Self) -> Self::Output { + // First clone and invert the divisor (rhs) + let rhs_inv = rhs.clone().inv(); + // Multiply original number by the inverse + self.clone() * rhs_inv + } +} +/* +//TODO: Not yet ready + impl Rem for FieldElement { + fn rem(self, rhs: Self) -> Self::Output { + + } +} +*/ + /* impl BitXor for FieldElement { fn bitxor(self, rhs: Self) -> Self::Output { @@ -312,13 +377,13 @@ impl ByteArray { let alpha_poly: Vec = base64::prelude::BASE64_STANDARD .decode("AgAAAAAAAAAAAAAAAAAAAA==") .expect("Decode failed"); - self.0 = gfmul(self.0.clone(), alpha_poly, "xex").unwrap(); + self.0 = gfmul(&self.0, &alpha_poly, "xex").unwrap(); } "gcm" => { let alpha_poly: Vec = base64::prelude::BASE64_STANDARD .decode("AgAAAAAAAAAAAAAAAAAAAA==") .expect("Decode failed"); - self.0 = gfmul(self.0.clone(), alpha_poly, "gcm").unwrap(); + self.0 = gfmul(&self.0, &alpha_poly, "gcm").unwrap(); } _ => {} } @@ -576,4 +641,17 @@ mod tests { ); //assert_eq!(BASE64_STANDARD.encode(product), "MoAAAAAAAAAAAAAAAAAAAA=="); } + + #[test] + fn test_poly_div_01() { + let element1 = + FieldElement::new(BASE64_STANDARD.decode("JAAAAAAAAAAAAAAAAAAAAA==").unwrap()); + + let element2 = + FieldElement::new(BASE64_STANDARD.decode("wAAAAAAAAAAAAAAAAAAAAA==").unwrap()); + + let result = element1 / element2; + + assert_eq!(BASE64_STANDARD.encode(result), "OAAAAAAAAAAAAAAAAAAAAA=="); + } } diff --git a/src/utils/poly.rs b/src/utils/poly.rs index 78889c8..6425577 100644 --- a/src/utils/poly.rs +++ b/src/utils/poly.rs @@ -7,14 +7,14 @@ use std::{str::FromStr, u128, u8, usize}; use super::{field, math::reverse_bits_in_bytevec}; pub const RED_POLY: u128 = 0x87000000_00000000_00000000_00000000; -pub fn gfmul(poly_a: Vec, poly_b: Vec, semantic: &str) -> Result> { +pub fn gfmul(poly_a: &Vec, poly_b: &Vec, semantic: &str) -> Result> { let mut red_poly_bytes: ByteArray = ByteArray(RED_POLY.to_be_bytes().to_vec()); red_poly_bytes.0.push(0x01); - let mut poly1: ByteArray = ByteArray(poly_a); + let mut poly1: ByteArray = ByteArray(poly_a.to_owned()); poly1.0.push(0x00); - let mut poly2: ByteArray = ByteArray(poly_b); + let mut poly2: ByteArray = ByteArray(poly_b.to_owned()); poly2.0.push(0x00); if semantic == "gcm" {