diff --git a/src/utils/field.rs b/src/utils/field.rs index dd2e982..9b9876b 100644 --- a/src/utils/field.rs +++ b/src/utils/field.rs @@ -8,6 +8,8 @@ use std::{ use anyhow::{anyhow, Ok, Result}; +use crate::utils::poly::bgfmul; + use super::poly::polynomial_2_block; use super::{ math::{reverse_bits_in_bytevec, xor_bytes}, @@ -21,7 +23,7 @@ pub struct FieldElement { impl FieldElement { pub const IRREDUCIBLE_POLYNOMIAL: [u8; 17] = [ - 87, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 01, + 0x87, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 0x01, ]; pub fn rand() -> Self { @@ -29,10 +31,14 @@ impl FieldElement { FieldElement::new(rand_field.to_vec()) } - pub fn zero(self) -> Self { + pub fn zero() -> Self { FieldElement::new(vec![0]) } + pub fn one() -> Self { + FieldElement::new(vec![0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]) + } + pub const fn new(field_element: Vec) -> Self { Self { field_element } } @@ -46,8 +52,7 @@ impl FieldElement { } pub fn pow(mut self, mut exponent: u128) -> FieldElement { - let mut result: FieldElement = - FieldElement::new(polynomial_2_block(vec![0], "gcm").unwrap()); + let mut result: FieldElement = FieldElement::one(); if exponent == 1 { eprintln!("special case 1: {:02X?}", self.clone()); @@ -56,7 +61,7 @@ impl FieldElement { } if exponent == 0 { - let result = FieldElement::new(polynomial_2_block(vec![0], "gcm").unwrap()); + let result = FieldElement::one(); eprintln!("Returned value is: {:02X?}", result); return result; @@ -89,8 +94,10 @@ impl FieldElement { } pub fn inv(mut self) -> Self { - let mut inverser: u128 = 0xfffffffffffffffffffffffffffffffe; - let mut inverse: Vec = polynomial_2_block(vec![0], "gcm").unwrap(); + const INVERSER_START: u128 = 0xfffffffffffffffffffffffffffffffe; + + let mut inverser = INVERSER_START; + let mut inverse: Vec = vec![0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]; //eprintln!("Inverse start {:02X?}", inverse); while inverser > 0 { @@ -186,7 +193,7 @@ impl Div for FieldElement { type Output = Self; fn div(self, rhs: Self) -> Self::Output { let inverse = rhs.inv(); - self.clone() * inverse + self * inverse } } @@ -194,10 +201,7 @@ 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 + self.clone() * rhs.clone().inv() } } diff --git a/src/utils/poly.rs b/src/utils/poly.rs index f42f1c5..68edb82 100644 --- a/src/utils/poly.rs +++ b/src/utils/poly.rs @@ -1,6 +1,9 @@ use crate::utils::field::ByteArray; use base64::prelude::*; -use num::{BigUint, One, Zero}; + +use num::traits::FromBytes; +use num::{BigInt, BigUint, One, Zero}; + use std::{str::FromStr, u128, u8, usize}; use std::{ @@ -12,6 +15,7 @@ use anyhow::{anyhow, Ok, Result}; use serde_json::Value; use super::field::FieldElement; +use super::math::reverse_bits_in_bytevec; #[derive(Debug, serde::Serialize, serde::Deserialize)] pub struct Polynomial { @@ -290,10 +294,7 @@ impl Polynomial { } let mut quotient_coeffs = - vec![ - FieldElement::new(polynomial_2_block(vec![0; 16], "gcm").unwrap()); - dividend_deg - divisor_deg + 1 - ]; + vec![FieldElement::new(vec![0; 16]); dividend_deg - divisor_deg + 1]; while remainder.polynomial.len() >= divisor.polynomial.len() { let deg_diff = remainder.polynomial.len() - divisor.polynomial.len(); @@ -304,8 +305,7 @@ impl Polynomial { quotient_coeffs[deg_diff] = quot_coeff.clone(); - let mut subtrahend = - vec![FieldElement::new(polynomial_2_block(vec![0; 16], "gcm").unwrap()); deg_diff]; + let mut subtrahend = vec![FieldElement::new(vec![0; 16]); deg_diff]; subtrahend.extend( divisor .polynomial @@ -614,20 +614,20 @@ pub const RED_POLY: u128 = 0x87000000_00000000_00000000_00000000; 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); + //red_poly_bytes.0.push(0x01); let mut poly1: ByteArray = ByteArray(poly_a.to_owned()); - poly1.0.push(0x00); + //poly1.0.push(0x00); let mut poly2: ByteArray = ByteArray(poly_b.to_owned()); - poly2.0.push(0x00); + //poly2.0.push(0x00); if semantic == "gcm" { poly1.reverse_bits_in_bytevec(); poly2.reverse_bits_in_bytevec(); } - let mut result: ByteArray = ByteArray(vec![0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]); + let mut result: ByteArray = ByteArray(vec![0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]); if poly2.LSB_is_one() { result.xor_byte_arrays(&poly1); @@ -635,9 +635,9 @@ pub fn gfmul(poly_a: &Vec, poly_b: &Vec, semantic: &str) -> Result, poly_b: &Vec, semantic: &str) -> Result, poly_b: &Vec, semantic: &str) -> Result, poly_b: &Vec, semantic: &str) -> Result> { + //TODO: Implement gfmul with bigint + let red_poly_bytes: BigUint = BigUint::from_slice(&[ + 0x87, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 0x01, + ]); + + let mut poly1: BigUint = BigUint::from_le_bytes(&reverse_bits_in_bytevec(poly_a.to_owned())); + + let mut poly2: BigUint = BigUint::from_le_bytes(&reverse_bits_in_bytevec(poly_b.to_owned())); + + /* + if semantic == "gcm" { + poly1.re; + poly2.reverse_bits_in_bytevec(); + } + */ + + let mut result: BigUint = BigUint::zero(); + + if (&poly2 & (BigUint::one() << 127)) == BigUint::one() { + result = &result ^ &poly1; + } + poly2 = &poly2 >> 1; + + while &poly2 != &BigUint::zero() { + poly1 = &poly1 << 1; + + if (&poly1 & (BigUint::one() << 127)) == BigUint::one() { + poly1 = &poly1 ^ &red_poly_bytes; + } + + if &poly2 & BigUint::one() == BigUint::one() { + result = &result ^ &poly1; + } + + poly2 = &poly2 >> 1; + } + + /* + if semantic == "gcm" { + result.reverse_bits_in_bytevec(); + } + */ + + Ok(reverse_bits_in_bytevec(result.to_bytes_le())) +} + pub fn convert_gcm_to_xex(gcm_poly: Vec) -> Result> { let xex_poly = gcm_poly .into_iter() @@ -794,7 +841,7 @@ pub fn coefficient_to_binary(coefficients: Vec) -> u128 { #[cfg(test)] mod tests { - use crate::utils::poly::b64_2_num; + use crate::utils::poly::{b64_2_num, gcd}; use anyhow::Result; use serde_json::json; // Note this useful idiom: importing names from outer (for mod tests) scope. @@ -1428,4 +1475,17 @@ mod tests { assert_eq!(json!(result.to_c_array()), expected); } + + #[test] + fn test_poly_gcd_stress() { + eprintln!("{:?}", Polynomial::one()); + + let poly1 = Polynomial::rand(&(500 as usize)); + let poly2 = Polynomial::rand(&(500 as usize)); + + let result = gcd(&poly1.monic(), &poly2.monic()); + + eprintln!("{:02X?}", result.to_c_array()); + assert!(true); + } }