refactor: Split Polynomial class into poly.rs file

This commit is contained in:
Alivecow 2024-11-22 15:28:00 +01:00
parent ad8326b51e
commit a5a3ea61fa
3 changed files with 825 additions and 798 deletions

View file

@ -1,3 +1,6 @@
use base64::prelude::*;
use std::{str::FromStr, u128, u8, usize};
use std::{
cmp::Ordering,
mem::discriminant,
@ -5,396 +8,14 @@ use std::{
};
use anyhow::{anyhow, Ok, Result};
use base64::prelude::*;
use serde_json::Value;
use crate::utils::poly::polynomial_2_block;
use super::poly::polynomial_2_block;
use super::{
math::{reverse_bits_in_bytevec, xor_bytes},
poly::gfmul,
};
#[derive(Debug, serde::Serialize)]
pub struct Polynomial {
polynomial: Vec<FieldElement>,
}
impl Polynomial {
pub const fn new(polynomial: Vec<FieldElement>) -> Self {
Self { polynomial }
}
pub fn from_c_array(array: &Value) -> Self {
let mut polynomial: Vec<FieldElement> = vec![];
let c_array: Vec<String> = array
.as_array()
.expect("Input is not an array")
.iter()
.map(|x| {
x.as_str()
.expect("Array element is not a string")
.to_string()
})
.collect();
eprintln!("{:?}", c_array);
for coefficient in c_array {
polynomial.push(FieldElement::new(
BASE64_STANDARD
.decode(coefficient)
.expect("Error on poly decode:"),
));
}
Self { polynomial }
}
pub fn to_c_array(self) -> Vec<String> {
let mut output: Vec<String> = vec![];
for coeff in self.polynomial {
output.push(BASE64_STANDARD.encode(coeff));
}
output
}
pub fn pow(&self, mut exponent: u128) -> Polynomial {
if exponent == 0 {
return Polynomial::new(vec![FieldElement::new(
polynomial_2_block(vec![0], "gcm").unwrap(),
)]);
}
let base = self.clone();
let mut result = base.clone();
exponent -= 1;
while exponent > 0 {
result = result * base.clone();
exponent -= 1;
}
result
}
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(),
)]);
if exponent == 1 {
eprintln!("special case 1: {:02X?}", self.clone().div(&modulus).1);
return self.div(&modulus).1;
}
if exponent == 0 {
let result = Polynomial::new(vec![FieldElement::new(
polynomial_2_block(vec![0], "gcm").unwrap(),
)]);
eprintln!("Returned value is: {:02X?}", result);
return result;
}
//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;
}
eprintln!("result in powmod before reduction: {:02X?}", result);
while !result.polynomial.is_empty()
&& result
.polynomial
.last()
.unwrap()
.as_ref()
.iter()
.all(|&x| x == 0)
{
result.polynomial.pop();
}
eprintln!("result in powmod after reduction: {:02X?}", result);
if result.is_empty() {
result = Polynomial::new(vec![FieldElement::new(vec![0; 16])]);
}
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
eprintln!("{:?}, {:?}", self.polynomial.len(), rhs.polynomial.len());
if self.polynomial.len() < rhs.polynomial.len() {
return (Polynomial::new(vec![FieldElement::new(vec![0; 16])]), self);
}
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,
);
}
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();
}
}
if remainder.is_empty() {
remainder = Polynomial::new(vec![FieldElement::new(vec![0; 16])]);
}
(Polynomial::new(quotient_coeffs), remainder)
}
fn is_zero(&self) -> bool {
for field_element in &self.polynomial {
if !field_element.is_zero() {
return false;
}
}
true
}
fn monic(mut self) -> Self {
let divident = self.polynomial.last().unwrap().clone();
for fieldelement in &mut self.polynomial.iter_mut() {
*fieldelement = fieldelement.clone() / divident.clone();
}
todo!();
}
}
impl Clone for Polynomial {
fn clone(&self) -> Self {
Polynomial {
polynomial: self.polynomial.clone(),
}
}
}
impl Mul for Polynomial {
type Output = Self;
fn mul(self, rhs: Self) -> Self::Output {
if self.is_zero() || rhs.is_zero() {
return Polynomial::new(vec![FieldElement::new(vec![0; 16])]);
}
let mut polynomial: Vec<FieldElement> =
vec![FieldElement::new(vec![0; 16]); self.polynomial.len() + rhs.polynomial.len() - 1];
for i in 0..self.polynomial.len() {
for j in 0..rhs.polynomial.len() {
polynomial[i + j] = &polynomial[i + j]
+ &(self.polynomial.get(i).unwrap() * rhs.polynomial.get(j).unwrap());
}
}
Polynomial::new(polynomial)
}
}
impl Mul for &Polynomial {
type Output = Polynomial;
fn mul(self, rhs: Self) -> Self::Output {
if self.is_zero() || rhs.is_zero() {
return Polynomial::new(vec![FieldElement::new(vec![0])]);
}
let mut polynomial: Vec<FieldElement> =
vec![FieldElement::new(vec![0; 16]); self.polynomial.len() + rhs.polynomial.len() - 1];
for i in 0..self.polynomial.len() {
for j in 0..rhs.polynomial.len() {
polynomial[i + j] = &polynomial[i + j]
+ &(self.polynomial.get(i).unwrap() * rhs.polynomial.get(j).unwrap());
}
}
Polynomial::new(polynomial)
}
}
impl Add for Polynomial {
type Output = Self;
fn add(self, rhs: Self) -> Self::Output {
let mut polynomial: Vec<FieldElement>;
if self.polynomial.len() > rhs.polynomial.len() {
polynomial = self.polynomial.clone();
for i in 0..rhs.polynomial.len() {
polynomial[i] = polynomial[i].clone() + rhs.polynomial[i].clone();
}
} else {
polynomial = rhs.polynomial.clone();
for i in 0..self.polynomial.len() {
polynomial[i] = polynomial[i].clone() + self.polynomial[i].clone();
}
}
while !polynomial.is_empty() && polynomial.last().unwrap().as_ref().iter().all(|&x| x == 0)
{
polynomial.pop();
}
if polynomial.is_empty() {
return Polynomial::new(vec![FieldElement::new(vec![0; 16])]);
}
Polynomial::new(polynomial)
}
}
impl Sub for &FieldElement {
type Output = FieldElement;
fn sub(self, rhs: Self) -> FieldElement {
self + rhs
}
}
trait IsEmpty {
fn is_empty(&self) -> bool;
}
impl IsEmpty for Polynomial {
fn is_empty(&self) -> bool {
self.polynomial.is_empty()
}
}
impl AsRef<[FieldElement]> for Polynomial {
fn as_ref(&self) -> &[FieldElement] {
&self.polynomial
}
}
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<Ordering> {
match other.polynomial.len().cmp(&self.polynomial.len()) {
Ordering::Equal => {
for (field_a, field_b) in
self.as_ref().iter().rev().zip(other.as_ref().iter().rev())
{
eprintln!(
"Poly partord: {:02X?} {:02X?} ",
self.clone().to_c_array(),
other.clone().to_c_array()
);
match field_a
.reverse_bits()
.partial_cmp(&field_b.reverse_bits())
.unwrap()
{
Ordering::Equal => continue,
other => return Some(other),
}
}
Some(Ordering::Equal)
}
other => Some(other.reverse()),
}
}
}
impl Eq for Polynomial {}
impl Ord for Polynomial {
fn cmp(&self, other: &Self) -> Ordering {
match other.polynomial.len().cmp(&self.polynomial.len()) {
Ordering::Equal => {
for (field_a, field_b) in
self.as_ref().iter().rev().zip(other.as_ref().iter().rev())
{
match field_a.reverse_bits().cmp(&field_b.reverse_bits()) {
Ordering::Equal => continue,
other => return other,
}
}
Ordering::Equal
}
other => other.reverse(),
}
}
}
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>,
@ -453,11 +74,11 @@ impl FieldElement {
FieldElement::new(inverse)
}
fn is_zero(&self) -> bool {
pub fn is_zero(&self) -> bool {
self.field_element.iter().all(|&x| x == 0x00)
}
fn reverse_bits(&self) -> Self {
pub fn reverse_bits(&self) -> Self {
FieldElement::new(reverse_bits_in_bytevec(self.field_element.clone()))
}
}
@ -817,415 +438,4 @@ mod tests {
assert_eq!(BASE64_STANDARD.encode(sum), "OZuIncPAGEp4tYouDownAA==");
}
#[test]
fn test_field_add_03() {
let json1 = json!([
"NeverGonnaGiveYouUpAAA==",
"NeverGonnaLetYouDownAA==",
"NeverGonnaRunAroundAAA==",
"AndDesertYouAAAAAAAAAA=="
]);
let json2 = json!(["KryptoanalyseAAAAAAAAA==", "DHBWMannheimAAAAAAAAAA=="]);
let element1: Polynomial = Polynomial::from_c_array(&json1);
let element2: Polynomial = Polynomial::from_c_array(&json2);
let sum = element2 + element1;
assert_eq!(
sum.to_c_array(),
vec![
"H1d3GuyA9/0OxeYouUpAAA==",
"OZuIncPAGEp4tYouDownAA==",
"NeverGonnaRunAroundAAA==",
"AndDesertYouAAAAAAAAAA=="
]
);
}
#[test]
fn test_field_add_multiple_zeros() {
let json1 = json!([
"AAAAAAAAAAAAAAAAAAAAAA==",
"AAAAAAAAAAAAAAAAAAAAAA==",
"AAAAAAAAAAAAAAAAAAAAAA==",
"AAAAAAAAAAAAAAAAAAAAAA=="
]);
let json2 = json!(["AAAAAAAAAAAAAAAAAAAAAA==", "AAAAAAAAAAAAAAAAAAAAAA=="]);
let element1: Polynomial = Polynomial::from_c_array(&json1);
let element2: Polynomial = Polynomial::from_c_array(&json2);
let sum = element2 + element1;
assert_eq!(sum.to_c_array(), vec!["AAAAAAAAAAAAAAAAAAAAAA==",]);
}
#[test]
fn test_field_add_same_element() {
let json1 = json!(["NeverGonnaGiveYouUpAAA=="]);
let json2 = json!(["NeverGonnaGiveYouUpAAA=="]);
let element1: Polynomial = Polynomial::from_c_array(&json1);
let element2: Polynomial = Polynomial::from_c_array(&json2);
let sum = element2 + element1;
assert_eq!(sum.to_c_array(), vec!["AAAAAAAAAAAAAAAAAAAAAA==",]);
}
#[test]
fn test_field_add_zero() {
let json1 = json!([
"NeverGonnaGiveYouUpAAA==",
"NeverGonnaLetYouDownAA==",
"NeverGonnaRunAroundAAA==",
"AndDesertYouAAAAAAAAAA=="
]);
let json2 = json!(["AAAAAAAAAAAAAAAAAAAAAA=="]);
let element1: Polynomial = Polynomial::from_c_array(&json1);
let element2: Polynomial = Polynomial::from_c_array(&json2);
let sum = element2 + element1;
assert_eq!(
sum.to_c_array(),
vec![
"NeverGonnaGiveYouUpAAA==",
"NeverGonnaLetYouDownAA==",
"NeverGonnaRunAroundAAA==",
"AndDesertYouAAAAAAAAAA=="
]
);
}
#[test]
fn test_field_add_zero_to_zero() {
let json1 = json!(["AAAAAAAAAAAAAAAAAAAAAA=="]);
let json2 = json!(["AAAAAAAAAAAAAAAAAAAAAA=="]);
let element1: Polynomial = Polynomial::from_c_array(&json1);
let element2: Polynomial = Polynomial::from_c_array(&json2);
let sum = element2 + element1;
assert_eq!(sum.to_c_array(), vec!["AAAAAAAAAAAAAAAAAAAAAA=="]);
}
#[test]
fn test_field_add_short_to_long() {
let json1 = json!(["AAAAAAAAAAAAAAAAAAAAAA=="]);
let json2 = json!([
"NeverGonnaGiveYouUpAAA==",
"NeverGonnaLetYouDownAA==",
"NeverGonnaRunAroundAAA==",
"AndDesertYouAAAAAAAAAA=="
]);
let element1: Polynomial = Polynomial::from_c_array(&json1);
let element2: Polynomial = Polynomial::from_c_array(&json2);
let sum = element2 + element1;
assert_eq!(
sum.to_c_array(),
vec![
"NeverGonnaGiveYouUpAAA==",
"NeverGonnaLetYouDownAA==",
"NeverGonnaRunAroundAAA==",
"AndDesertYouAAAAAAAAAA=="
]
);
}
#[test]
fn test_field_mul_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);
let result = element1 * element2;
assert_eq!(
result.to_c_array(),
vec![
"MoAAAAAAAAAAAAAAAAAAAA==",
"sUgAAAAAAAAAAAAAAAAAAA==",
"MbQAAAAAAAAAAAAAAAAAAA==",
"AAhAAAAAAAAAAAAAAAAAAA=="
]
);
//assert_eq!(BASE64_STANDARD.encode(product), "MoAAAAAAAAAAAAAAAAAAAA==");
}
#[test]
fn test_poly_mul_with_zero() {
let json1 = json!([
"JAAAAAAAAAAAAAAAAAAAAA==",
"wAAAAAAAAAAAAAAAAAAAAA==",
"ACAAAAAAAAAAAAAAAAAAAA=="
]);
let json2 = json!(["AAAAAAAAAAAAAAAAAAAAAA=="]);
let element1: Polynomial = Polynomial::from_c_array(&json1);
let element2: Polynomial = Polynomial::from_c_array(&json2);
//eprintln!("{:?}", element1);
let result = element1 * element2;
assert_eq!(result.to_c_array(), vec!["AAAAAAAAAAAAAAAAAAAAAA=="]);
//assert_eq!(BASE64_STANDARD.encode(product), "MoAAAAAAAAAAAAAAAAAAAA==");
}
#[test]
fn test_poly_pow_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_pow_with_zero() {
let json1 = json!([
"JAAAAAAAAAAAAAAAAAAAAA==",
"wAAAAAAAAAAAAAAAAAAAAA==",
"ACAAAAAAAAAAAAAAAAAAAA=="
]);
let element1: Polynomial = Polynomial::from_c_array(&json1);
let result = element1.pow(0);
assert_eq!(result.to_c_array(), vec!["gAAAAAAAAAAAAAAAAAAAAA=="]);
//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_field_pow_mod_with_zero() {
let json1 = json!([
"JAAAAAAAAAAAAAAAAAAAAA==",
"wAAAAAAAAAAAAAAAAAAAAA==",
"ACAAAAAAAAAAAAAAAAAAAA=="
]);
let element1: Polynomial = Polynomial::from_c_array(&json1);
let result = element1.pow(0);
assert_eq!(result.to_c_array(), vec!["gAAAAAAAAAAAAAAAAAAAAA=="]);
//assert_eq!(BASE64_STANDARD.encode(product), "MoAAAAAAAAAAAAAAAAAAAA==");
}
#[test]
fn test_poly_div_01() {
let element1 =
FieldElement::new(BASE64_STANDARD.decode("JAAAAAAAAAAAAAAAAAAAAA==").unwrap());
let element2 =
FieldElement::new(BASE64_STANDARD.decode("wAAAAAAAAAAAAAAAAAAAAA==").unwrap());
let result = element1 / element2;
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_div_larger_div() {
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) = element2.div(&element1);
assert_eq!(result.to_c_array(), vec!["AAAAAAAAAAAAAAAAAAAAAA=="]);
assert_eq!(
remainder.to_c_array(),
vec!["0AAAAAAAAAAAAAAAAAAAAA==", "IQAAAAAAAAAAAAAAAAAAAA=="]
);
//assert_eq!(BASE64_STANDARD.encode(product), "MoAAAAAAAAAAAAAAAAAAAA==");
}
#[test]
fn test_field_poly_div_eqdeg() {
let json1 = json!(["JAAAAAAAAAAAAAAAAAAAAA==", "wAAAAAAAAAAAAAAAAAAAAA==",]);
let json2 = json!(["0AAAAAAAAAAAAAAAAAAAAA==", "IQAAAAAAAAAAAAAAAAAAAA=="]);
let element1: Polynomial = Polynomial::from_c_array(&json1);
let element2: Polynomial = Polynomial::from_c_array(&json2);
let (result, remainder) = element2.div(&element1);
eprintln!("{:02X?}", (&result, &remainder));
assert!(!result.is_zero());
assert!(!remainder.is_zero());
//assert_eq!(BASE64_STANDARD.encode(product), "MoAAAAAAAAAAAAAAAAAAAA==");
}
#[test]
fn test_field_poly_div_eqdeg_02() {
let json1 = json!(["JAAAAAAAAAAAAAAAAAAAAA==", "wAAAAAAAAAAAAAAAAAAAAA==",]);
let json2 = json!(["KryptoanalyseAAAAAAAAA==", "DHBWMannheimAAAAAAAAAA=="]);
let element1: Polynomial = Polynomial::from_c_array(&json1);
let element2: Polynomial = Polynomial::from_c_array(&json2);
let (result, remainder) = element2.div(&element1);
eprintln!("{:02X?}", (&result, &remainder));
assert!(!result.is_zero());
assert!(!remainder.is_zero());
//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!["oNXl5P8xq2WpUTP92u25zg=="]);
}
#[test]
fn test_field_poly_powmod_k1() {
let json1 = json!(["JAAAAAAAAAAAAAAAAAAAAA==",]);
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(1, modulus);
eprintln!("Result is: {:02X?}", result);
assert_eq!(result.to_c_array(), vec!["JAAAAAAAAAAAAAAAAAAAAA=="]);
}
#[test]
fn test_field_poly_powmod_k0_special() {
let json1 = json!(["NeverGonnaGiveYouUpAAA=="]);
let json2 = json!(["NeverGonnaGiveYouUpAAA=="]);
let element1: Polynomial = Polynomial::from_c_array(&json1);
let modulus: Polynomial = Polynomial::from_c_array(&json2);
let result = element1.pow_mod(0, modulus);
eprintln!("Result is: {:02X?}", result);
assert_eq!(result.to_c_array(), vec!["gAAAAAAAAAAAAAAAAAAAAA=="]);
}
#[test]
fn test_field_poly_powmod_k0() {
let json1 = json!(["JAAAAAAAAAAAAAAAAAAAAA==",]);
let json2 = json!(["KryptoanalyseAAAAAAAAA=="]);
let element1: Polynomial = Polynomial::from_c_array(&json1);
let modulus: Polynomial = Polynomial::from_c_array(&json2);
let result = element1.pow_mod(0, modulus);
eprintln!("Result is: {:02X?}", result);
assert_eq!(result.to_c_array(), vec!["gAAAAAAAAAAAAAAAAAAAAA=="]);
}
#[test]
fn test_field_pow_mod_10mill() {
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(10000000, modulus);
assert!(!result.is_zero())
//assert_eq!(BASE64_STANDARD.encode(product), "MoAAAAAAAAAAAAAAAAAAAA==");
}
}

View file

@ -1,8 +1,391 @@
use crate::utils::field::ByteArray;
use anyhow::{anyhow, Result};
use base64::prelude::*;
use std::{str::FromStr, u128, u8, usize};
use std::{
cmp::Ordering,
mem::discriminant,
ops::{Add, BitXor, Div, Mul, Sub},
};
use anyhow::{anyhow, Ok, Result};
use serde_json::Value;
use super::field::FieldElement;
use super::math::{reverse_bits_in_bytevec, xor_bytes};
#[derive(Debug, serde::Serialize)]
pub struct Polynomial {
polynomial: Vec<FieldElement>,
}
impl Polynomial {
pub const fn new(polynomial: Vec<FieldElement>) -> Self {
Self { polynomial }
}
pub fn from_c_array(array: &Value) -> Self {
let mut polynomial: Vec<FieldElement> = vec![];
let c_array: Vec<String> = array
.as_array()
.expect("Input is not an array")
.iter()
.map(|x| {
x.as_str()
.expect("Array element is not a string")
.to_string()
})
.collect();
eprintln!("{:?}", c_array);
for coefficient in c_array {
polynomial.push(FieldElement::new(
BASE64_STANDARD
.decode(coefficient)
.expect("Error on poly decode:"),
));
}
Self { polynomial }
}
pub fn to_c_array(self) -> Vec<String> {
let mut output: Vec<String> = vec![];
for coeff in self.polynomial {
output.push(BASE64_STANDARD.encode(coeff));
}
output
}
pub fn pow(&self, mut exponent: u128) -> Polynomial {
if exponent == 0 {
return Polynomial::new(vec![FieldElement::new(
polynomial_2_block(vec![0], "gcm").unwrap(),
)]);
}
let base = self.clone();
let mut result = base.clone();
exponent -= 1;
while exponent > 0 {
result = result * base.clone();
exponent -= 1;
}
result
}
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(),
)]);
if exponent == 1 {
eprintln!("special case 1: {:02X?}", self.clone().div(&modulus).1);
return self.div(&modulus).1;
}
if exponent == 0 {
let result = Polynomial::new(vec![FieldElement::new(
polynomial_2_block(vec![0], "gcm").unwrap(),
)]);
eprintln!("Returned value is: {:02X?}", result);
return result;
}
//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;
}
eprintln!("result in powmod before reduction: {:02X?}", result);
while !result.polynomial.is_empty()
&& result
.polynomial
.last()
.unwrap()
.as_ref()
.iter()
.all(|&x| x == 0)
{
result.polynomial.pop();
}
eprintln!("result in powmod after reduction: {:02X?}", result);
if result.is_empty() {
result = Polynomial::new(vec![FieldElement::new(vec![0; 16])]);
}
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
eprintln!("{:?}, {:?}", self.polynomial.len(), rhs.polynomial.len());
if self.polynomial.len() < rhs.polynomial.len() {
return (Polynomial::new(vec![FieldElement::new(vec![0; 16])]), self);
}
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,
);
}
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();
}
}
if remainder.is_empty() {
remainder = Polynomial::new(vec![FieldElement::new(vec![0; 16])]);
}
(Polynomial::new(quotient_coeffs), remainder)
}
fn is_zero(&self) -> bool {
for field_element in &self.polynomial {
if !field_element.is_zero() {
return false;
}
}
true
}
fn monic(mut self) -> Self {
let divident = self.polynomial.last().unwrap().clone();
for fieldelement in &mut self.polynomial.iter_mut() {
*fieldelement = fieldelement.clone() / divident.clone();
}
self
}
}
impl Clone for Polynomial {
fn clone(&self) -> Self {
Polynomial {
polynomial: self.polynomial.clone(),
}
}
}
impl Mul for Polynomial {
type Output = Self;
fn mul(self, rhs: Self) -> Self::Output {
if self.is_zero() || rhs.is_zero() {
return Polynomial::new(vec![FieldElement::new(vec![0; 16])]);
}
let mut polynomial: Vec<FieldElement> =
vec![FieldElement::new(vec![0; 16]); self.polynomial.len() + rhs.polynomial.len() - 1];
for i in 0..self.polynomial.len() {
for j in 0..rhs.polynomial.len() {
polynomial[i + j] = &polynomial[i + j]
+ &(self.polynomial.get(i).unwrap() * rhs.polynomial.get(j).unwrap());
}
}
Polynomial::new(polynomial)
}
}
impl Mul for &Polynomial {
type Output = Polynomial;
fn mul(self, rhs: Self) -> Self::Output {
if self.is_zero() || rhs.is_zero() {
return Polynomial::new(vec![FieldElement::new(vec![0])]);
}
let mut polynomial: Vec<FieldElement> =
vec![FieldElement::new(vec![0; 16]); self.polynomial.len() + rhs.polynomial.len() - 1];
for i in 0..self.polynomial.len() {
for j in 0..rhs.polynomial.len() {
polynomial[i + j] = &polynomial[i + j]
+ &(self.polynomial.get(i).unwrap() * rhs.polynomial.get(j).unwrap());
}
}
Polynomial::new(polynomial)
}
}
impl Add for Polynomial {
type Output = Self;
fn add(self, rhs: Self) -> Self::Output {
let mut polynomial: Vec<FieldElement>;
if self.polynomial.len() > rhs.polynomial.len() {
polynomial = self.polynomial.clone();
for i in 0..rhs.polynomial.len() {
polynomial[i] = polynomial[i].clone() + rhs.polynomial[i].clone();
}
} else {
polynomial = rhs.polynomial.clone();
for i in 0..self.polynomial.len() {
polynomial[i] = polynomial[i].clone() + self.polynomial[i].clone();
}
}
while !polynomial.is_empty() && polynomial.last().unwrap().as_ref().iter().all(|&x| x == 0)
{
polynomial.pop();
}
if polynomial.is_empty() {
return Polynomial::new(vec![FieldElement::new(vec![0; 16])]);
}
Polynomial::new(polynomial)
}
}
trait IsEmpty {
fn is_empty(&self) -> bool;
}
impl IsEmpty for Polynomial {
fn is_empty(&self) -> bool {
self.polynomial.is_empty()
}
}
impl AsRef<[FieldElement]> for Polynomial {
fn as_ref(&self) -> &[FieldElement] {
&self.polynomial
}
}
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<Ordering> {
match other.polynomial.len().cmp(&self.polynomial.len()) {
Ordering::Equal => {
for (field_a, field_b) in
self.as_ref().iter().rev().zip(other.as_ref().iter().rev())
{
eprintln!(
"Poly partord: {:02X?} {:02X?} ",
self.clone().to_c_array(),
other.clone().to_c_array()
);
match field_a
.reverse_bits()
.partial_cmp(&field_b.reverse_bits())
.unwrap()
{
Ordering::Equal => continue,
other => return Some(other),
}
}
Some(Ordering::Equal)
}
other => Some(other.reverse()),
}
}
}
impl Eq for Polynomial {}
impl Ord for Polynomial {
fn cmp(&self, other: &Self) -> Ordering {
match other.polynomial.len().cmp(&self.polynomial.len()) {
Ordering::Equal => {
for (field_a, field_b) in
self.as_ref().iter().rev().zip(other.as_ref().iter().rev())
{
match field_a.reverse_bits().cmp(&field_b.reverse_bits()) {
Ordering::Equal => continue,
other => return other,
}
}
Ordering::Equal
}
other => other.reverse(),
}
}
}
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)
}
pub const RED_POLY: u128 = 0x87000000_00000000_00000000_00000000;
pub fn gfmul(poly_a: &Vec<u8>, poly_b: &Vec<u8>, semantic: &str) -> Result<Vec<u8>> {
@ -189,6 +572,7 @@ pub fn coefficient_to_binary(coefficients: Vec<u8>) -> u128 {
mod tests {
use crate::utils::poly::b64_2_num;
use anyhow::Result;
use serde_json::json;
// Note this useful idiom: importing names from outer (for mod tests) scope.
use super::*;
@ -256,4 +640,437 @@ mod tests {
Ok(())
}
#[test]
fn test_field_add_03() {
let json1 = json!([
"NeverGonnaGiveYouUpAAA==",
"NeverGonnaLetYouDownAA==",
"NeverGonnaRunAroundAAA==",
"AndDesertYouAAAAAAAAAA=="
]);
let json2 = json!(["KryptoanalyseAAAAAAAAA==", "DHBWMannheimAAAAAAAAAA=="]);
let element1: Polynomial = Polynomial::from_c_array(&json1);
let element2: Polynomial = Polynomial::from_c_array(&json2);
let sum = element2 + element1;
assert_eq!(
sum.to_c_array(),
vec![
"H1d3GuyA9/0OxeYouUpAAA==",
"OZuIncPAGEp4tYouDownAA==",
"NeverGonnaRunAroundAAA==",
"AndDesertYouAAAAAAAAAA=="
]
);
}
#[test]
fn test_field_add_multiple_zeros() {
let json1 = json!([
"AAAAAAAAAAAAAAAAAAAAAA==",
"AAAAAAAAAAAAAAAAAAAAAA==",
"AAAAAAAAAAAAAAAAAAAAAA==",
"AAAAAAAAAAAAAAAAAAAAAA=="
]);
let json2 = json!(["AAAAAAAAAAAAAAAAAAAAAA==", "AAAAAAAAAAAAAAAAAAAAAA=="]);
let element1: Polynomial = Polynomial::from_c_array(&json1);
let element2: Polynomial = Polynomial::from_c_array(&json2);
let sum = element2 + element1;
assert_eq!(sum.to_c_array(), vec!["AAAAAAAAAAAAAAAAAAAAAA==",]);
}
#[test]
fn test_field_add_same_element() {
let json1 = json!(["NeverGonnaGiveYouUpAAA=="]);
let json2 = json!(["NeverGonnaGiveYouUpAAA=="]);
let element1: Polynomial = Polynomial::from_c_array(&json1);
let element2: Polynomial = Polynomial::from_c_array(&json2);
let sum = element2 + element1;
assert_eq!(sum.to_c_array(), vec!["AAAAAAAAAAAAAAAAAAAAAA==",]);
}
#[test]
fn test_field_add_zero() {
let json1 = json!([
"NeverGonnaGiveYouUpAAA==",
"NeverGonnaLetYouDownAA==",
"NeverGonnaRunAroundAAA==",
"AndDesertYouAAAAAAAAAA=="
]);
let json2 = json!(["AAAAAAAAAAAAAAAAAAAAAA=="]);
let element1: Polynomial = Polynomial::from_c_array(&json1);
let element2: Polynomial = Polynomial::from_c_array(&json2);
let sum = element2 + element1;
assert_eq!(
sum.to_c_array(),
vec![
"NeverGonnaGiveYouUpAAA==",
"NeverGonnaLetYouDownAA==",
"NeverGonnaRunAroundAAA==",
"AndDesertYouAAAAAAAAAA=="
]
);
}
#[test]
fn test_field_add_zero_to_zero() {
let json1 = json!(["AAAAAAAAAAAAAAAAAAAAAA=="]);
let json2 = json!(["AAAAAAAAAAAAAAAAAAAAAA=="]);
let element1: Polynomial = Polynomial::from_c_array(&json1);
let element2: Polynomial = Polynomial::from_c_array(&json2);
let sum = element2 + element1;
assert_eq!(sum.to_c_array(), vec!["AAAAAAAAAAAAAAAAAAAAAA=="]);
}
#[test]
fn test_field_add_short_to_long() {
let json1 = json!(["AAAAAAAAAAAAAAAAAAAAAA=="]);
let json2 = json!([
"NeverGonnaGiveYouUpAAA==",
"NeverGonnaLetYouDownAA==",
"NeverGonnaRunAroundAAA==",
"AndDesertYouAAAAAAAAAA=="
]);
let element1: Polynomial = Polynomial::from_c_array(&json1);
let element2: Polynomial = Polynomial::from_c_array(&json2);
let sum = element2 + element1;
assert_eq!(
sum.to_c_array(),
vec![
"NeverGonnaGiveYouUpAAA==",
"NeverGonnaLetYouDownAA==",
"NeverGonnaRunAroundAAA==",
"AndDesertYouAAAAAAAAAA=="
]
);
}
#[test]
fn test_field_mul_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);
let result = element1 * element2;
assert_eq!(
result.to_c_array(),
vec![
"MoAAAAAAAAAAAAAAAAAAAA==",
"sUgAAAAAAAAAAAAAAAAAAA==",
"MbQAAAAAAAAAAAAAAAAAAA==",
"AAhAAAAAAAAAAAAAAAAAAA=="
]
);
//assert_eq!(BASE64_STANDARD.encode(product), "MoAAAAAAAAAAAAAAAAAAAA==");
}
#[test]
fn test_poly_mul_with_zero() {
let json1 = json!([
"JAAAAAAAAAAAAAAAAAAAAA==",
"wAAAAAAAAAAAAAAAAAAAAA==",
"ACAAAAAAAAAAAAAAAAAAAA=="
]);
let json2 = json!(["AAAAAAAAAAAAAAAAAAAAAA=="]);
let element1: Polynomial = Polynomial::from_c_array(&json1);
let element2: Polynomial = Polynomial::from_c_array(&json2);
//eprintln!("{:?}", element1);
let result = element1 * element2;
assert_eq!(result.to_c_array(), vec!["AAAAAAAAAAAAAAAAAAAAAA=="]);
//assert_eq!(BASE64_STANDARD.encode(product), "MoAAAAAAAAAAAAAAAAAAAA==");
}
#[test]
fn test_poly_pow_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_pow_with_zero() {
let json1 = json!([
"JAAAAAAAAAAAAAAAAAAAAA==",
"wAAAAAAAAAAAAAAAAAAAAA==",
"ACAAAAAAAAAAAAAAAAAAAA=="
]);
let element1: Polynomial = Polynomial::from_c_array(&json1);
let result = element1.pow(0);
assert_eq!(result.to_c_array(), vec!["gAAAAAAAAAAAAAAAAAAAAA=="]);
//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_field_pow_mod_with_zero() {
let json1 = json!([
"JAAAAAAAAAAAAAAAAAAAAA==",
"wAAAAAAAAAAAAAAAAAAAAA==",
"ACAAAAAAAAAAAAAAAAAAAA=="
]);
let element1: Polynomial = Polynomial::from_c_array(&json1);
let result = element1.pow(0);
assert_eq!(result.to_c_array(), vec!["gAAAAAAAAAAAAAAAAAAAAA=="]);
//assert_eq!(BASE64_STANDARD.encode(product), "MoAAAAAAAAAAAAAAAAAAAA==");
}
#[test]
fn test_poly_div_01() {
let element1 =
FieldElement::new(BASE64_STANDARD.decode("JAAAAAAAAAAAAAAAAAAAAA==").unwrap());
let element2 =
FieldElement::new(BASE64_STANDARD.decode("wAAAAAAAAAAAAAAAAAAAAA==").unwrap());
let result = element1 / element2;
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_div_larger_div() {
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) = element2.div(&element1);
assert_eq!(result.to_c_array(), vec!["AAAAAAAAAAAAAAAAAAAAAA=="]);
assert_eq!(
remainder.to_c_array(),
vec!["0AAAAAAAAAAAAAAAAAAAAA==", "IQAAAAAAAAAAAAAAAAAAAA=="]
);
//assert_eq!(BASE64_STANDARD.encode(product), "MoAAAAAAAAAAAAAAAAAAAA==");
}
#[test]
fn test_field_poly_div_eqdeg() {
let json1 = json!(["JAAAAAAAAAAAAAAAAAAAAA==", "wAAAAAAAAAAAAAAAAAAAAA==",]);
let json2 = json!(["0AAAAAAAAAAAAAAAAAAAAA==", "IQAAAAAAAAAAAAAAAAAAAA=="]);
let element1: Polynomial = Polynomial::from_c_array(&json1);
let element2: Polynomial = Polynomial::from_c_array(&json2);
let (result, remainder) = element2.div(&element1);
eprintln!("{:02X?}", (&result, &remainder));
assert!(!result.is_zero());
assert!(!remainder.is_zero());
//assert_eq!(BASE64_STANDARD.encode(product), "MoAAAAAAAAAAAAAAAAAAAA==");
}
#[test]
fn test_field_poly_div_eqdeg_02() {
let json1 = json!(["JAAAAAAAAAAAAAAAAAAAAA==", "wAAAAAAAAAAAAAAAAAAAAA==",]);
let json2 = json!(["KryptoanalyseAAAAAAAAA==", "DHBWMannheimAAAAAAAAAA=="]);
let element1: Polynomial = Polynomial::from_c_array(&json1);
let element2: Polynomial = Polynomial::from_c_array(&json2);
let (result, remainder) = element2.div(&element1);
eprintln!("{:02X?}", (&result, &remainder));
assert!(!result.is_zero());
assert!(!remainder.is_zero());
//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!["oNXl5P8xq2WpUTP92u25zg=="]);
}
#[test]
fn test_field_poly_powmod_k1() {
let json1 = json!(["JAAAAAAAAAAAAAAAAAAAAA==",]);
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(1, modulus);
eprintln!("Result is: {:02X?}", result);
assert_eq!(result.to_c_array(), vec!["JAAAAAAAAAAAAAAAAAAAAA=="]);
}
#[test]
fn test_field_poly_powmod_k0_special() {
let json1 = json!(["NeverGonnaGiveYouUpAAA=="]);
let json2 = json!(["NeverGonnaGiveYouUpAAA=="]);
let element1: Polynomial = Polynomial::from_c_array(&json1);
let modulus: Polynomial = Polynomial::from_c_array(&json2);
let result = element1.pow_mod(0, modulus);
eprintln!("Result is: {:02X?}", result);
assert_eq!(result.to_c_array(), vec!["gAAAAAAAAAAAAAAAAAAAAA=="]);
}
#[test]
fn test_field_poly_powmod_k0() {
let json1 = json!(["JAAAAAAAAAAAAAAAAAAAAA==",]);
let json2 = json!(["KryptoanalyseAAAAAAAAA=="]);
let element1: Polynomial = Polynomial::from_c_array(&json1);
let modulus: Polynomial = Polynomial::from_c_array(&json2);
let result = element1.pow_mod(0, modulus);
eprintln!("Result is: {:02X?}", result);
assert_eq!(result.to_c_array(), vec!["gAAAAAAAAAAAAAAAAAAAAA=="]);
}
#[test]
fn test_field_pow_mod_10mill() {
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(10000000, modulus);
assert!(!result.is_zero())
//assert_eq!(BASE64_STANDARD.encode(product), "MoAAAAAAAAAAAAAAAAAAAA==");
}
#[test]
fn test_poly_monic() {
let json1 = json!([
"NeverGonnaGiveYouUpAAA==",
"NeverGonnaLetYouDownAA==",
"NeverGonnaRunAroundAAA==",
"AndDesertYouAAAAAAAAAA=="
]);
let expected = json!([
"edY47onJ4MtCENDTHG/sZw==",
"oaXjCKnceBIxSavZ9eFT8w==",
"1Ial5rAJGOucIdUe3zh5bw==",
"gAAAAAAAAAAAAAAAAAAAAA=="
]);
let element1: Polynomial = Polynomial::from_c_array(&json1);
let result = element1.monic();
assert_eq!(json!(result.to_c_array()), expected);
//assert_eq!(BASE64_STANDARD.encode(product), "MoAAAAAAAAAAAAAAAAAAAA==");
}
}