From c3ea652c87bc271a373d10ec7ff30459368b0cce Mon Sep 17 00:00:00 2001 From: Alivecow Date: Wed, 20 Nov 2024 19:37:46 +0100 Subject: [PATCH] feat: Sorting of polynomial array with rust standard sort implemented --- src/tasks/mod.rs | 12 +++- src/tasks/tasks01/pfmath.rs | 74 +++++++++++++++++++- src/utils/field.rs | 132 ++++++++++++++++++++++++++++-------- 3 files changed, 185 insertions(+), 33 deletions(-) diff --git a/src/tasks/mod.rs b/src/tasks/mod.rs index bdb2fb0..a4751e4 100644 --- a/src/tasks/mod.rs +++ b/src/tasks/mod.rs @@ -8,10 +8,12 @@ use tasks01::{ gcm::{gcm_decrypt, gcm_encrypt}, gfmul::gfmul_task, pad_oracle::padding_oracle, - pfmath::{gfdiv, gfpoly_add, gfpoly_divmod, gfpoly_mul, gfpoly_pow, gfpoly_powmod}, + pfmath::{ + gfdiv, gfpoly_add, gfpoly_divmod, gfpoly_mul, gfpoly_pow, gfpoly_powmod, gfpoly_sort, + }, poly2block::poly2block, sea128::sea128, - xex::{fde_xex}, + xex::fde_xex, }; use anyhow::{anyhow, Result}; @@ -118,6 +120,12 @@ pub fn task_deploy(testcase: &Testcase) -> Result { Ok(json) } + "gfpoly_sort" => { + let result = gfpoly_sort(args)?; + let json = json!({"sorted_polys" : json!(result)}); + + Ok(json) + } _ => Err(anyhow!( "Fatal. No compatible action found. Json data was {:?}. Arguments were; {:?}", diff --git a/src/tasks/tasks01/pfmath.rs b/src/tasks/tasks01/pfmath.rs index 4ad3ac7..9742be8 100644 --- a/src/tasks/tasks01/pfmath.rs +++ b/src/tasks/tasks01/pfmath.rs @@ -2,7 +2,7 @@ use anyhow::Result; use base64::{prelude::BASE64_STANDARD, Engine}; use serde_json::Value; -use crate::utils::field::{FieldElement, Polynomial}; +use crate::utils::field::{sort_polynomial_array, FieldElement, Polynomial}; pub fn gfpoly_add(args: &Value) -> Result { let poly_a = Polynomial::from_c_array(&args["A"].clone()); @@ -67,3 +67,75 @@ pub fn gfpoly_powmod(args: &Value) -> Result { Ok(result) } + +pub fn gfpoly_sort(args: &Value) -> Result> { + let poly_arrays: Vec = serde_json::from_value(args["polys"].clone())?; + let mut polys: Vec = vec![]; + + for array in poly_arrays { + polys.push(Polynomial::from_c_array(&array)); + } + + polys.sort(); + //polys.sort(); + Ok(polys) +} + +#[cfg(test)] +mod tests { + use super::*; + use serde_json::json; + + #[test] + fn test_poly_sorting() { + let json1 = json!( + {"polys": [ + [ + "NeverGonnaGiveYouUpAAA==", + "NeverGonnaLetYouDownAA==", + "NeverGonnaRunAroundAAA==", + "AndDesertYouAAAAAAAAAA==" + ], + [ + "WereNoStrangersToLoveA==", + "YouKnowTheRulesAAAAAAA==", + "AndSoDoIAAAAAAAAAAAAAA==" + ], + [ + "NeverGonnaMakeYouCryAA==", + "NeverGonnaSayGoodbyeAA==", + "NeverGonnaTellALieAAAA==", + "AndHurtYouAAAAAAAAAAAA==" + ] + ]}); + + let expected = json!([ + [ + "WereNoStrangersToLoveA==", + "YouKnowTheRulesAAAAAAA==", + "AndSoDoIAAAAAAAAAAAAAA==" + ], + [ + "NeverGonnaMakeYouCryAA==", + "NeverGonnaSayGoodbyeAA==", + "NeverGonnaTellALieAAAA==", + "AndHurtYouAAAAAAAAAAAA==" + ], + [ + "NeverGonnaGiveYouUpAAA==", + "NeverGonnaLetYouDownAA==", + "NeverGonnaRunAroundAAA==", + "AndDesertYouAAAAAAAAAA==" + ] + ]); + + let sorted_array = gfpoly_sort(&json1).unwrap(); + let mut result: Vec> = vec![]; + for poly in sorted_array { + result.push(poly.to_c_array()); + } + + assert_eq!(json!(result), expected); + //assert_eq!(BASE64_STANDARD.encode(product), "MoAAAAAAAAAAAAAAAAAAAA=="); + } +} diff --git a/src/utils/field.rs b/src/utils/field.rs index e4fff9c..a682eff 100644 --- a/src/utils/field.rs +++ b/src/utils/field.rs @@ -1,4 +1,7 @@ -use std::ops::{Add, BitXor, Div, Mul, Sub}; +use std::{ + cmp::Ordering, + ops::{Add, BitXor, Div, Mul, Sub}, +}; use anyhow::{anyhow, Ok, Result}; use base64::prelude::*; @@ -8,7 +11,7 @@ use crate::utils::poly::polynomial_2_block; use super::{math::xor_bytes, poly::gfmul}; -#[derive(Debug)] +#[derive(Debug, serde::Serialize)] pub struct Polynomial { polynomial: Vec, } @@ -284,17 +287,14 @@ 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; } @@ -310,7 +310,66 @@ impl AsRef<[FieldElement]> for Polynomial { } } -#[derive(Debug)] +impl PartialEq for Polynomial { + fn eq(&self, other: &Self) -> bool { + if self.polynomial.len() != other.polynomial.len() { + return false; + } + // Compare each coefficient + self.polynomial + .iter() + .zip(other.polynomial.iter()) + .all(|(a, b)| a == b) + } +} + +impl PartialOrd for Polynomial { + fn partial_cmp(&self, other: &Self) -> Option { + if self.polynomial.len() != other.polynomial.len() { + return Some(self.polynomial.len().cmp(&other.polynomial.len())); + } else { + for (field_a, field_b) in self.as_ref().iter().rev().zip(other.as_ref().iter().rev()) { + match field_a.cmp(field_b) { + std::cmp::Ordering::Equal => continue, + other => return Some(other.reverse()), + } + } + Some(Ordering::Equal) + } + } +} + +impl Eq for Polynomial {} + +impl Ord for Polynomial { + fn cmp(&self, other: &Self) -> Ordering { + match self.polynomial.len().cmp(&other.polynomial.len()) { + Ordering::Equal => { + for (field_a, field_b) in + self.as_ref().iter().rev().zip(other.as_ref().iter().rev()) + { + match field_a.cmp(field_b) { + std::cmp::Ordering::Equal => continue, + other => return other.reverse(), + } + } + Ordering::Equal + } + other => other, + } + } +} + +pub fn sort_polynomial_array(mut polys: Vec) -> Result> { + // Algorithm to sort polynomials + // First sorting round + // Sorting by degree of polynomial + polys.sort(); + + Ok(polys) +} + +#[derive(Debug, serde::Serialize)] pub struct FieldElement { field_element: Vec, } @@ -462,34 +521,39 @@ impl Div for &FieldElement { } } -/* -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 +impl PartialOrd for FieldElement { + fn partial_cmp(&self, other: &Self) -> Option { + for (byte_a, byte_b) in self.as_ref().iter().rev().zip(other.as_ref().iter().rev()) { + match byte_a.reverse_bits().cmp(&byte_b.reverse_bits()) { + std::cmp::Ordering::Equal => continue, + other => return Some(other), + } } - todo!(); + Some(Ordering::Equal) } } -*/ -/* -impl BitXor for FieldElement { - fn bitxor(self, rhs: Self) -> Self::Output { - FieldElement - } -} -*/ -/* -impl From> for FieldElement { - fn from(item: Vec) -> Self { - FieldElement { bytes: item } +impl PartialEq for FieldElement { + fn eq(&self, other: &Self) -> bool { + self.field_element == other.field_element + } +} + +impl Eq for FieldElement { + // add code here +} + +impl Ord for FieldElement { + fn cmp(&self, other: &Self) -> Ordering { + for (byte_a, byte_b) in self.as_ref().iter().zip(other.as_ref().iter()) { + match byte_a.reverse_bits().cmp(&byte_b.reverse_bits()) { + std::cmp::Ordering::Equal => continue, + other => return other, + } + } + Ordering::Equal } } -*/ #[derive(Debug)] pub struct ByteArray(pub Vec); @@ -1110,8 +1174,16 @@ mod tests { #[test] fn test_field_poly_powmod_kn_eqdeg() { - let json1 = json!(["JAAAAAAAAAAAAAAAAAAAAA==", "JAAAAAAAAAAAAAAAAAAAAA=="]); - let json2 = json!(["KryptoanalyseAAAAAAAAA==", "KryptoanalyseAAAAAAAAA=="]); + let json1 = json!([ + "JAAAAAAAAAAAAAAAAAAAAA==", + "JAAAAAAAAAAAAAAAAAAAAA==", + "KryptoanalyseAAAAAAAAA==" + ]); + let json2 = json!([ + "KryptoanalyseAAAAAAAAA==", + "KryptoanalyseAAAAAAAAA==", + "JAAAAAAAAABBAAAAAAAAAA==" + ]); let element1: Polynomial = Polynomial::from_c_array(&json1); let modulus: Polynomial = Polynomial::from_c_array(&json2);