Merge Monic functionality #19
4 changed files with 865 additions and 802 deletions
|
|
@ -3,7 +3,6 @@ use base64::prelude::*;
|
||||||
use serde_json::Value;
|
use serde_json::Value;
|
||||||
use std::io::prelude::*;
|
use std::io::prelude::*;
|
||||||
use std::net::TcpStream;
|
use std::net::TcpStream;
|
||||||
use std::time::Instant;
|
|
||||||
use std::usize;
|
use std::usize;
|
||||||
|
|
||||||
pub fn padding_oracle(args: &Value) -> Result<Vec<u8>> {
|
pub fn padding_oracle(args: &Value) -> Result<Vec<u8>> {
|
||||||
|
|
|
||||||
|
|
@ -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::{sort_polynomial_array, FieldElement, Polynomial};
|
use crate::utils::{field::FieldElement, poly::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());
|
||||||
|
|
|
||||||
|
|
@ -1,400 +1,19 @@
|
||||||
|
use base64::prelude::*;
|
||||||
|
use std::{u128, u8, usize};
|
||||||
|
|
||||||
use std::{
|
use std::{
|
||||||
cmp::Ordering,
|
cmp::Ordering,
|
||||||
mem::discriminant,
|
ops::{Add, BitXor, Div, Mul},
|
||||||
ops::{Add, BitXor, Div, Mul, Sub},
|
|
||||||
};
|
};
|
||||||
|
|
||||||
use anyhow::{anyhow, Ok, Result};
|
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::{
|
use super::{
|
||||||
math::{reverse_bits_in_bytevec, xor_bytes},
|
math::{reverse_bits_in_bytevec, xor_bytes},
|
||||||
poly::gfmul,
|
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)]
|
#[derive(Debug, serde::Serialize)]
|
||||||
pub struct FieldElement {
|
pub struct FieldElement {
|
||||||
field_element: Vec<u8>,
|
field_element: Vec<u8>,
|
||||||
|
|
@ -453,11 +72,11 @@ impl FieldElement {
|
||||||
FieldElement::new(inverse)
|
FieldElement::new(inverse)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn is_zero(&self) -> bool {
|
pub fn is_zero(&self) -> bool {
|
||||||
self.field_element.iter().all(|&x| x == 0x00)
|
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()))
|
FieldElement::new(reverse_bits_in_bytevec(self.field_element.clone()))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -817,415 +436,4 @@ mod tests {
|
||||||
|
|
||||||
assert_eq!(BASE64_STANDARD.encode(sum), "OZuIncPAGEp4tYouDownAA==");
|
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==");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,405 @@
|
||||||
use crate::utils::field::ByteArray;
|
use crate::utils::field::ByteArray;
|
||||||
use anyhow::{anyhow, Result};
|
|
||||||
use base64::prelude::*;
|
use base64::prelude::*;
|
||||||
use std::{str::FromStr, u128, u8, usize};
|
use std::{str::FromStr, u128, u8, usize};
|
||||||
|
|
||||||
|
use std::{
|
||||||
|
cmp::Ordering,
|
||||||
|
ops::{Add, Div, Mul},
|
||||||
|
};
|
||||||
|
|
||||||
|
use anyhow::{anyhow, Ok, Result};
|
||||||
|
use serde_json::Value;
|
||||||
|
|
||||||
|
use super::field::FieldElement;
|
||||||
|
|
||||||
|
#[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();
|
||||||
|
}
|
||||||
|
|
||||||
|
while !self.polynomial.is_empty()
|
||||||
|
&& self
|
||||||
|
.polynomial
|
||||||
|
.last()
|
||||||
|
.unwrap()
|
||||||
|
.as_ref()
|
||||||
|
.iter()
|
||||||
|
.all(|&x| x == 0)
|
||||||
|
{
|
||||||
|
self.polynomial.pop();
|
||||||
|
}
|
||||||
|
|
||||||
|
if self.is_empty() {
|
||||||
|
self = Polynomial::new(vec![FieldElement::new(vec![0; 16])]);
|
||||||
|
}
|
||||||
|
|
||||||
|
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 const RED_POLY: u128 = 0x87000000_00000000_00000000_00000000;
|
||||||
|
|
||||||
pub fn gfmul(poly_a: &Vec<u8>, poly_b: &Vec<u8>, semantic: &str) -> Result<Vec<u8>> {
|
pub fn gfmul(poly_a: &Vec<u8>, poly_b: &Vec<u8>, semantic: &str) -> Result<Vec<u8>> {
|
||||||
|
|
@ -189,6 +586,7 @@ pub fn coefficient_to_binary(coefficients: Vec<u8>) -> u128 {
|
||||||
mod tests {
|
mod tests {
|
||||||
use crate::utils::poly::b64_2_num;
|
use crate::utils::poly::b64_2_num;
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
|
use serde_json::json;
|
||||||
// Note this useful idiom: importing names from outer (for mod tests) scope.
|
// Note this useful idiom: importing names from outer (for mod tests) scope.
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
|
|
@ -256,4 +654,462 @@ mod tests {
|
||||||
|
|
||||||
Ok(())
|
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())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[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);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_poly_monic_poly_zero() {
|
||||||
|
let json1 = json!(["AAAAAAAAAAAAAAAAAAAAAA=="]);
|
||||||
|
let expected = json!(["AAAAAAAAAAAAAAAAAAAAAA=="]);
|
||||||
|
let element1: Polynomial = Polynomial::from_c_array(&json1);
|
||||||
|
|
||||||
|
let result = element1.monic();
|
||||||
|
|
||||||
|
assert_eq!(json!(result.to_c_array()), expected);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_poly_monic_poly_multiple_zero() {
|
||||||
|
let json1 = json!([
|
||||||
|
"AAAAAAAAAAAAAAAAAAAAAA==",
|
||||||
|
"AAAAAAAAAAAAAAAAAAAAAA==",
|
||||||
|
"AAAAAAAAAAAAAAAAAAAAAA==",
|
||||||
|
"AAAAAAAAAAAAAAAAAAAAAA=="
|
||||||
|
]);
|
||||||
|
let expected = json!(["AAAAAAAAAAAAAAAAAAAAAA=="]);
|
||||||
|
let element1: Polynomial = Polynomial::from_c_array(&json1);
|
||||||
|
|
||||||
|
let result = element1.monic();
|
||||||
|
|
||||||
|
assert_eq!(json!(result.to_c_array()), expected);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue