Add polynomial sorting #16

Merged
0xalivecow merged 2 commits from dev into main 2024-11-20 18:52:16 +00:00
4 changed files with 220 additions and 33 deletions

View file

@ -8,10 +8,12 @@ use tasks01::{
gcm::{gcm_decrypt, gcm_encrypt}, gcm::{gcm_decrypt, gcm_encrypt},
gfmul::gfmul_task, gfmul::gfmul_task,
pad_oracle::padding_oracle, 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, poly2block::poly2block,
sea128::sea128, sea128::sea128,
xex::{fde_xex}, xex::fde_xex,
}; };
use anyhow::{anyhow, Result}; use anyhow::{anyhow, Result};
@ -118,6 +120,18 @@ pub fn task_deploy(testcase: &Testcase) -> Result<Value> {
Ok(json) Ok(json)
} }
"gfpoly_sort" => {
let sorted_array = gfpoly_sort(args)?;
let mut result: Vec<Vec<String>> = vec![];
for poly in sorted_array {
result.push(poly.to_c_array());
}
let json = json!({"sorted_polys" : json!(result)});
Ok(json)
}
_ => Err(anyhow!( _ => Err(anyhow!(
"Fatal. No compatible action found. Json data was {:?}. Arguments were; {:?}", "Fatal. No compatible action found. Json data was {:?}. Arguments were; {:?}",

View file

@ -2,7 +2,7 @@ use anyhow::Result;
use base64::{prelude::BASE64_STANDARD, Engine}; use base64::{prelude::BASE64_STANDARD, Engine};
use serde_json::Value; 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<Polynomial> { pub fn gfpoly_add(args: &Value) -> Result<Polynomial> {
let poly_a = Polynomial::from_c_array(&args["A"].clone()); let poly_a = Polynomial::from_c_array(&args["A"].clone());
@ -67,3 +67,75 @@ pub fn gfpoly_powmod(args: &Value) -> Result<Polynomial> {
Ok(result) Ok(result)
} }
pub fn gfpoly_sort(args: &Value) -> Result<Vec<Polynomial>> {
let poly_arrays: Vec<Value> = serde_json::from_value(args["polys"].clone())?;
let mut polys: Vec<Polynomial> = 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<String>> = vec![];
for poly in sorted_array {
result.push(poly.to_c_array());
}
assert_eq!(json!(result), expected);
//assert_eq!(BASE64_STANDARD.encode(product), "MoAAAAAAAAAAAAAAAAAAAA==");
}
}

View file

@ -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 anyhow::{anyhow, Ok, Result};
use base64::prelude::*; use base64::prelude::*;
@ -8,7 +11,7 @@ use crate::utils::poly::polynomial_2_block;
use super::{math::xor_bytes, poly::gfmul}; use super::{math::xor_bytes, poly::gfmul};
#[derive(Debug)] #[derive(Debug, serde::Serialize)]
pub struct Polynomial { pub struct Polynomial {
polynomial: Vec<FieldElement>, polynomial: Vec<FieldElement>,
} }
@ -284,17 +287,14 @@ impl Add for Polynomial {
} }
} }
// Helper implementation for subtraction
impl Sub for &FieldElement { impl Sub for &FieldElement {
type Output = FieldElement; type Output = FieldElement;
fn sub(self, rhs: Self) -> FieldElement { fn sub(self, rhs: Self) -> FieldElement {
// In a field of characteristic 2, addition and subtraction are the same operation (XOR)
self + rhs self + rhs
} }
} }
// Helper trait for checking emptiness
trait IsEmpty { trait IsEmpty {
fn is_empty(&self) -> bool; 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<std::cmp::Ordering> {
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<Polynomial>) -> Result<Vec<Polynomial>> {
// Algorithm to sort polynomials
// First sorting round
// Sorting by degree of polynomial
polys.sort();
Ok(polys)
}
#[derive(Debug, serde::Serialize)]
pub struct FieldElement { pub struct FieldElement {
field_element: Vec<u8>, field_element: Vec<u8>,
} }
@ -462,34 +521,39 @@ impl Div for &FieldElement {
} }
} }
/* impl PartialOrd for FieldElement {
impl Rem for FieldElement { fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
type Output = Self; for (byte_a, byte_b) in self.as_ref().iter().rev().zip(other.as_ref().iter().rev()) {
fn rem(self, rhs: Self) -> Self::Output { match byte_a.reverse_bits().cmp(&byte_b.reverse_bits()) {
let result: FieldElement = self.field_element; std::cmp::Ordering::Equal => continue,
other => return Some(other),
}
}
Some(Ordering::Equal)
}
}
while self.field_element[15] != 0x00 { impl PartialEq for FieldElement {
self.field_element fn eq(&self, other: &Self) -> bool {
} self.field_element == other.field_element
todo!();
} }
} }
*/
/*
impl BitXor for FieldElement {
fn bitxor(self, rhs: Self) -> Self::Output {
FieldElement
}
}
*/
/* impl Eq for FieldElement {
impl From<Vec<u8>> for FieldElement { // add code here
fn from(item: Vec<u8>) -> Self { }
FieldElement { bytes: item }
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)] #[derive(Debug)]
pub struct ByteArray(pub Vec<u8>); pub struct ByteArray(pub Vec<u8>);
@ -1110,8 +1174,16 @@ mod tests {
#[test] #[test]
fn test_field_poly_powmod_kn_eqdeg() { fn test_field_poly_powmod_kn_eqdeg() {
let json1 = json!(["JAAAAAAAAAAAAAAAAAAAAA==", "JAAAAAAAAAAAAAAAAAAAAA=="]); let json1 = json!([
let json2 = json!(["KryptoanalyseAAAAAAAAA==", "KryptoanalyseAAAAAAAAA=="]); "JAAAAAAAAAAAAAAAAAAAAA==",
"JAAAAAAAAAAAAAAAAAAAAA==",
"KryptoanalyseAAAAAAAAA=="
]);
let json2 = json!([
"KryptoanalyseAAAAAAAAA==",
"KryptoanalyseAAAAAAAAA==",
"JAAAAAAAAABBAAAAAAAAAA=="
]);
let element1: Polynomial = Polynomial::from_c_array(&json1); let element1: Polynomial = Polynomial::from_c_array(&json1);
let modulus: Polynomial = Polynomial::from_c_array(&json2); let modulus: Polynomial = Polynomial::from_c_array(&json2);

29
test_json/poly_algs.json Normal file
View file

@ -0,0 +1,29 @@
{
"testcases": {
"b856d760-023d-4b00-bad2-15d2b6da22fe": {
"action": "gfpoly_sort",
"arguments": {
"polys": [
[
"NeverGonnaGiveYouUpAAA==",
"NeverGonnaLetYouDownAA==",
"NeverGonnaRunAroundAAA==",
"AndDesertYouAAAAAAAAAA=="
],
[
"WereNoStrangersToLoveA==",
"YouKnowTheRulesAAAAAAA==",
"AndSoDoIAAAAAAAAAAAAAA=="
],
[
"NeverGonnaMakeYouCryAA==",
"NeverGonnaSayGoodbyeAA==",
"NeverGonnaTellALieAAAA==",
"AndHurtYouAAAAAAAAAAAA=="
]
]
}
}
}
}