feat: Sorting of polynomial array with rust standard sort implemented

This commit is contained in:
Alivecow 2024-11-20 19:37:46 +01:00
parent bb5e762a1d
commit c3ea652c87
3 changed files with 185 additions and 33 deletions

View file

@ -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<Value> {
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; {:?}",

View file

@ -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<Polynomial> {
let poly_a = Polynomial::from_c_array(&args["A"].clone());
@ -67,3 +67,75 @@ pub fn gfpoly_powmod(args: &Value) -> Result<Polynomial> {
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 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<FieldElement>,
}
@ -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<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 {
field_element: Vec<u8>,
}
@ -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<Ordering> {
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<Vec<u8>> for FieldElement {
fn from(item: Vec<u8>) -> 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<u8>);
@ -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);