diff --git a/src/tasks/mod.rs b/src/tasks/mod.rs index 0fa72d6..f7475be 100644 --- a/src/tasks/mod.rs +++ b/src/tasks/mod.rs @@ -11,6 +11,7 @@ use tasks01::{ gcm::{gcm_decrypt, gcm_encrypt}, gfmul::gfmul_task, pad_oracle::padding_oracle, + pfmath::gfpoly_add, poly2block::poly2block, sea128::sea128, xex::{self, fde_xex}, @@ -83,6 +84,12 @@ pub fn task_deploy(testcase: &Testcase) -> Result { Ok(json) } + "gfpoly_add" => { + let result = gfpoly_add(args)?; + let json = json!({"plaintext" : result.to_c_array()}); + + Ok(json) + } _ => Err(anyhow!( "Fatal. No compatible action found. Json data was {:?}. Arguments were; {:?}", testcase, diff --git a/src/tasks/tasks01/mod.rs b/src/tasks/tasks01/mod.rs index 479fe47..8200de5 100644 --- a/src/tasks/tasks01/mod.rs +++ b/src/tasks/tasks01/mod.rs @@ -2,6 +2,7 @@ pub mod block2poly; pub mod gcm; pub mod gfmul; pub mod pad_oracle; +pub mod pfmath; pub mod poly2block; pub mod sea128; pub mod xex; diff --git a/src/tasks/tasks01/pfmath.rs b/src/tasks/tasks01/pfmath.rs new file mode 100644 index 0000000..b0c978e --- /dev/null +++ b/src/tasks/tasks01/pfmath.rs @@ -0,0 +1,15 @@ +use anyhow::Result; +use base64::{prelude::BASE64_STANDARD, Engine}; +use serde_json::Value; + +use crate::utils::field::Polynomial; + +pub fn gfpoly_add(args: &Value) -> Result { + let poly_a = Polynomial::from_c_array(&args["A"].clone()); + + let poly_b = Polynomial::from_c_array(&args["B"].clone()); + + let result = poly_a + poly_b; + + Ok(result) +} diff --git a/src/utils/field.rs b/src/utils/field.rs index c8de249..59ffc18 100644 --- a/src/utils/field.rs +++ b/src/utils/field.rs @@ -58,14 +58,12 @@ impl Polynomial { pub fn pow(&self, mut exponent: u128) -> Polynomial { if exponent == 0 { - // Return polynomial with coefficient 1 - return Polynomial::new(vec![FieldElement::new(vec![1])]); + return Polynomial::new(vec![FieldElement::new(vec![0])]); } let base = self.clone(); let mut result = base.clone(); - exponent -= 1; // Subtract 1 because we already set result to base - + exponent -= 1; while exponent > 0 { result = result * base.clone(); exponent -= 1; @@ -73,16 +71,90 @@ impl Polynomial { result } - /* - pub fn to_b64(&self) -> String { - let mut output: Vec = vec![]; - for coeff in self.polynomial { - output.push(BASE64_STANDARD.encode(coeff)); + + pub fn pow_mod(mut self, mut exponent: u128, modulus: Polynomial) -> Polynomial { + let mut result: Polynomial = Polynomial::new(vec![FieldElement::new( + polynomial_2_block(vec![0], "gcm").unwrap(), + )]); + + eprintln!("Initial result: {:?}", result); + while exponent > 0 { + eprintln!("Current exponent: {:02X}", exponent); + if exponent & 1 == 1 { + let temp = &self * &result; + eprintln!("After multiplication: {:?}", temp); + result = temp.div(&modulus).1; + eprintln!("After mod: {:?}", result); + } + let temp_square = &self * &self; + eprintln!("After squaring: {:?}", temp_square); + self = temp_square.div(&modulus).1; + eprintln!("After mod: {:?}", self); + exponent >>= 1; + } + result + } + + // Returns (quotient, remainder) + pub fn div(self, rhs: &Self) -> (Self, Self) { + // Div by zero check ommitted since data is guaranteed to be non 0 + + let mut remainder = self.clone(); + let divisor = rhs; + let dividend_deg = remainder.polynomial.len() - 1; + let divisor_deg = divisor.polynomial.len() - 1; + + if dividend_deg < divisor_deg { + return ( + Polynomial::new(vec![FieldElement::new( + polynomial_2_block(vec![0; 16], "gcm").unwrap(), + )]), + remainder, + ); } - output + let mut quotient_coeffs = + vec![ + FieldElement::new(polynomial_2_block(vec![0; 16], "gcm").unwrap()); + dividend_deg - divisor_deg + 1 + ]; + + while remainder.polynomial.len() >= divisor.polynomial.len() { + let deg_diff = remainder.polynomial.len() - divisor.polynomial.len(); + + let leading_dividend = remainder.polynomial.last().unwrap(); + let leading_divisor = divisor.polynomial.last().unwrap(); + let quot_coeff = leading_dividend / leading_divisor; + + quotient_coeffs[deg_diff] = quot_coeff.clone(); + + let mut subtrahend = + vec![FieldElement::new(polynomial_2_block(vec![0; 16], "gcm").unwrap()); deg_diff]; + subtrahend.extend( + divisor + .polynomial + .iter() + .map(|x| x.clone() * quot_coeff.clone()), + ); + let subtrahend_poly = Polynomial::new(subtrahend); + + remainder = remainder + subtrahend_poly; + + while !remainder.polynomial.is_empty() + && remainder + .polynomial + .last() + .unwrap() + .as_ref() + .iter() + .all(|&x| x == 0) + { + remainder.polynomial.pop(); + } + } + + (Polynomial::new(quotient_coeffs), remainder) } - */ } impl Clone for Polynomial { @@ -318,15 +390,20 @@ impl Div for &FieldElement { self.clone() * rhs_inv } } -/* -//TODO: Not yet ready - impl Rem for FieldElement { - fn rem(self, rhs: Self) -> Self::Output { +/* +impl Rem for FieldElement { + type Output = Self; + fn rem(self, rhs: Self) -> Self::Output { + let result: FieldElement = self.field_element; + + while self.field_element[15] != 0x00 { + self.field_element + } + todo!(); } } */ - /* impl BitXor for FieldElement { fn bitxor(self, rhs: Self) -> Self::Output { @@ -642,6 +719,32 @@ mod tests { //assert_eq!(BASE64_STANDARD.encode(product), "MoAAAAAAAAAAAAAAAAAAAA=="); } + #[test] + fn test_field_pow_mod_01() { + let json1 = json!([ + "JAAAAAAAAAAAAAAAAAAAAA==", + "wAAAAAAAAAAAAAAAAAAAAA==", + "ACAAAAAAAAAAAAAAAAAAAA==" + ]); + let element1: Polynomial = Polynomial::from_c_array(&json1); + + let result = element1.pow(3); + + assert_eq!( + result.to_c_array(), + vec![ + "AkkAAAAAAAAAAAAAAAAAAA==", + "DDAAAAAAAAAAAAAAAAAAAA==", + "LQIIAAAAAAAAAAAAAAAAAA==", + "8AAAAAAAAAAAAAAAAAAAAA==", + "ACgCQAAAAAAAAAAAAAAAAA==", + "AAAMAAAAAAAAAAAAAAAAAA==", + "AAAAAgAAAAAAAAAAAAAAAA==" + ] + ); + //assert_eq!(BASE64_STANDARD.encode(product), "MoAAAAAAAAAAAAAAAAAAAA=="); + } + #[test] fn test_poly_div_01() { let element1 = @@ -654,4 +757,45 @@ mod tests { assert_eq!(BASE64_STANDARD.encode(result), "OAAAAAAAAAAAAAAAAAAAAA=="); } + + #[test] + fn test_field_poly_div_01() { + let json1 = json!([ + "JAAAAAAAAAAAAAAAAAAAAA==", + "wAAAAAAAAAAAAAAAAAAAAA==", + "ACAAAAAAAAAAAAAAAAAAAA==" + ]); + let json2 = json!(["0AAAAAAAAAAAAAAAAAAAAA==", "IQAAAAAAAAAAAAAAAAAAAA=="]); + let element1: Polynomial = Polynomial::from_c_array(&json1); + let element2: Polynomial = Polynomial::from_c_array(&json2); + + //eprintln!("{:?}", element1); + + println!("Beginning the new division"); + let (result, remainder) = element1.div(&element2); + + assert_eq!( + result.to_c_array(), + vec!["nAIAgCAIAgCAIAgCAIAgCg==", "m85znOc5znOc5znOc5znOQ=="] + ); + assert_eq!(remainder.to_c_array(), vec!["lQNA0DQNA0DQNA0DQNA0Dg=="]); + //assert_eq!(BASE64_STANDARD.encode(product), "MoAAAAAAAAAAAAAAAAAAAA=="); + } + + #[test] + fn test_field_poly_powmod_01() { + let json1 = json!([ + "JAAAAAAAAAAAAAAAAAAAAA==", + "wAAAAAAAAAAAAAAAAAAAAA==", + "ACAAAAAAAAAAAAAAAAAAAA==" + ]); + let json2 = json!(["KryptoanalyseAAAAAAAAA==", "DHBWMannheimAAAAAAAAAA=="]); + let element1: Polynomial = Polynomial::from_c_array(&json1); + let modulus: Polynomial = Polynomial::from_c_array(&json2); + + let result = element1.pow_mod(1000, modulus); + + eprintln!("Result is: {:02X?}", result); + assert_eq!(result.to_c_array(), vec!["XrEhmKuat+Glt5zZWtMo6g=="]); + } }