feat: add gcm semantic to b2p and p2b #5

Merged
0xalivecow merged 1 commit from dev into main 2024-11-01 20:22:56 +00:00
9 changed files with 299 additions and 206 deletions

View file

@ -27,7 +27,7 @@ pub fn task_deploy(testcase: &Testcase) -> Result<Value> {
match testcase.action.as_str() { match testcase.action.as_str() {
"poly2block" => { "poly2block" => {
let result = poly2block(args); let result = BASE64_STANDARD.encode(poly2block(args)?);
let json = json!({"block" : result}); let json = json!({"block" : result});
Ok(json) Ok(json)
} }

View file

@ -1,15 +1,17 @@
use crate::utils::poly::{b64_2_num, get_coefficients}; use crate::utils::poly::{b64_2_num, block_2_polynomial, get_coefficients};
use anyhow::Result; use anyhow::Result;
use base64::prelude::*;
use serde_json::Value; use serde_json::Value;
pub fn block2poly(val: &Value) -> Result<Vec<u8>> { pub fn block2poly(val: &Value) -> Result<Vec<u8>> {
// Convert JSON data in to a u128 // Convert JSON data in to a u128
// TODO: Transfer decoding into own function? // TODO: Transfer decoding into own function?
let string: String = serde_json::from_value(val["block"].clone())?; let string: String = serde_json::from_value(val["block"].clone())?;
let block = BASE64_STANDARD.decode(string)?;
let number = b64_2_num(&string)?; let semantic: String = serde_json::from_value(val["semantic"].clone())?;
let coefficients: Vec<u8> = get_coefficients(number); let coefficients: Vec<u8> = block_2_polynomial(block, &semantic)?; //get_coefficients(number);
Ok(coefficients) Ok(coefficients)
} }
@ -24,7 +26,7 @@ mod tests {
#[test] #[test]
fn block2poly_task01() -> Result<()> { fn block2poly_task01() -> Result<()> {
let block: Value = json!({"block" : "ARIAAAAAAAAAAAAAAAAAgA=="}); let block: Value = json!({"block" : "ARIAAAAAAAAAAAAAAAAAgA==", "semantic" : "xex"});
let coefficients: Vec<u8> = vec![0, 9, 12, 127]; let coefficients: Vec<u8> = vec![0, 9, 12, 127];
assert_eq!( assert_eq!(
block2poly(&block)?, block2poly(&block)?,
@ -35,4 +37,18 @@ mod tests {
Ok(()) Ok(())
} }
#[test]
fn block2poly_task02() -> Result<()> {
let block: Value = json!({"block" : "ARIAAAAAAAAAAAAAAAAAgA==", "semantic" : "gcm"});
let coefficients: Vec<u8> = vec![7, 11, 14, 120];
assert_eq!(
block2poly(&block)?,
coefficients,
"Coefficients were: {:?}",
block2poly(&block)?
);
Ok(())
}
} }

View file

@ -1,5 +1,5 @@
use crate::utils::{ use crate::utils::{
math::ByteArray, field::ByteArray,
poly::{b64_2_num, coefficient_to_binary, gfmul}, poly::{b64_2_num, coefficient_to_binary, gfmul},
}; };

View file

@ -1,8 +1,9 @@
use crate::utils::poly::{self}; use crate::utils::poly::{self, polynomial_2_block};
use anyhow::{Ok, Result};
use base64::prelude::*; use base64::prelude::*;
use serde_json::Value; use serde_json::Value;
pub fn poly2block(args: &Value) -> String { pub fn poly2block(args: &Value) -> Result<Vec<u8>> {
let coefficients: Vec<u8> = args["coefficients"] let coefficients: Vec<u8> = args["coefficients"]
.as_array() .as_array()
.unwrap() .unwrap()
@ -10,5 +11,9 @@ pub fn poly2block(args: &Value) -> String {
.map(|x| x.as_u64().unwrap() as u8) .map(|x| x.as_u64().unwrap() as u8)
.collect(); .collect();
BASE64_STANDARD.encode(poly::coefficient_to_binary(coefficients).to_ne_bytes()) let semantic: String = serde_json::from_value(args["semantic"].clone())?;
let result = polynomial_2_block(coefficients, &semantic).unwrap();
Ok(result)
} }

View file

@ -3,7 +3,7 @@ use std::io::BufRead;
use anyhow::Result; use anyhow::Result;
use openssl::symm::{Cipher, Crypter, Mode}; use openssl::symm::{Cipher, Crypter, Mode};
use crate::utils::math::ByteArray; use crate::utils::field::ByteArray;
use super::math::xor_bytes; use super::math::xor_bytes;

198
src/utils/field.rs Normal file
View file

@ -0,0 +1,198 @@
use anyhow::{anyhow, Ok, Result};
use base64::Engine;
use super::poly::gfmul;
#[derive(Debug)]
pub struct ByteArray(pub Vec<u8>);
impl ByteArray {
pub fn left_shift(&mut self, semantic: &str) -> Result<u8> {
match semantic {
"xex" => {
let mut carry = 0u8;
for byte in self.0.iter_mut() {
let new_carry = *byte >> 7;
*byte = (*byte << 1) | carry;
carry = new_carry;
}
Ok(carry)
}
"gcm" => {
let mut carry = 0u8;
for byte in self.0.iter_mut() {
let new_carry = *byte & 1;
*byte = (*byte >> 1) | (carry << 7);
carry = new_carry;
}
Ok(carry)
}
_ => Err(anyhow!("Failure in lsh. No compatible action found")),
}
}
pub fn left_shift_reduce(&mut self, semantic: &str) {
match semantic {
"xex" => {
let alpha_poly: Vec<u8> = base64::prelude::BASE64_STANDARD
.decode("AgAAAAAAAAAAAAAAAAAAAA==")
.expect("Decode failed");
self.0 = gfmul(self.0.clone(), alpha_poly, "xex").unwrap();
}
"gcm" => {
let alpha_poly: Vec<u8> = base64::prelude::BASE64_STANDARD
.decode("AgAAAAAAAAAAAAAAAAAAAA==")
.expect("Decode failed");
self.0 = gfmul(self.0.clone(), alpha_poly, "gcm").unwrap();
}
_ => {}
}
}
pub fn right_shift(&mut self, semantic: &str) -> Result<u8> {
match semantic {
"xex" => {
let mut carry = 0u8;
for byte in self.0.iter_mut().rev() {
let new_carry = *byte & 1;
*byte = (*byte >> 1) | (carry << 7);
carry = new_carry;
}
Ok(carry)
}
"gcm" => {
let mut carry = 0u8;
for byte in self.0.iter_mut().rev() {
let new_carry = *byte & 1;
*byte = (*byte << 1) | carry;
carry = new_carry;
}
Ok(carry)
}
_ => Err(anyhow!("Failure in rsh. No valid semantic found")),
}
}
pub fn xor_byte_arrays(&mut self, vec2: &ByteArray) {
self.0
.iter_mut()
.zip(vec2.0.iter())
.for_each(|(x1, x2)| *x1 ^= *x2);
}
pub fn LSB_is_one(&self) -> bool {
(self.0.first().unwrap() & 1) == 1
}
pub fn msb_is_one(&self) -> bool {
(self.0.last().unwrap() & 1) == 1
}
pub fn is_empty(&self) -> bool {
for i in self.0.iter() {
if *i != 0 {
return false;
}
}
true
}
}
#[cfg(test)]
mod tests {
use super::*;
use std::fs;
#[test]
fn test_byte_array_shift1() {
let mut byte_array: ByteArray = ByteArray(vec![0x00, 0x01]);
let shifted_array: ByteArray = ByteArray(vec![0x00, 0x02]);
byte_array.left_shift("xex");
assert_eq!(byte_array.0, shifted_array.0);
}
#[test]
fn test_byte_array_shift2() {
let mut byte_array: ByteArray = ByteArray(vec![0xFF, 0x00]);
let shifted_array: ByteArray = ByteArray(vec![0xFE, 0x01]);
byte_array.left_shift("xex");
assert_eq!(
byte_array.0, shifted_array.0,
"Failure: Shifted array was: {:?}",
byte_array.0
);
}
#[test]
fn test_byte_array_shift1_gcm() {
let mut byte_array: ByteArray = ByteArray(vec![0xFF, 0x00]);
let shifted_array: ByteArray = ByteArray(vec![0x7F, 0x80]);
byte_array.left_shift("gcm");
assert_eq!(
byte_array.0, shifted_array.0,
"Failure: Shifted array was: {:02X?}",
byte_array.0
);
}
#[test]
fn test_byte_array_shift1_right_gcm() {
let mut byte_array: ByteArray = ByteArray(vec![0xFF, 0x00]);
let shifted_array: ByteArray = ByteArray(vec![0xFE, 0x00]);
byte_array.right_shift("gcm");
assert_eq!(
byte_array.0, shifted_array.0,
"Failure: Shifted array was: {:02X?}",
byte_array.0
);
}
#[test]
fn test_byte_array_shift_right() {
let mut byte_array: ByteArray = ByteArray(vec![0x02]);
let shifted_array: ByteArray = ByteArray(vec![0x01]);
byte_array.right_shift("xex");
assert_eq!(
byte_array.0, shifted_array.0,
"Failure: Shifted array was: {:?}",
byte_array.0
);
}
#[test]
fn test_lsb_one() {
let byte_array: ByteArray = ByteArray(vec![0x00, 0xFF]);
assert!(!byte_array.LSB_is_one());
let byte_array2: ByteArray = ByteArray(vec![0x02, 0xFF]);
assert!(!byte_array2.LSB_is_one());
let byte_array3: ByteArray = ByteArray(vec![0xFF, 0x00]);
assert!(byte_array3.LSB_is_one());
}
#[test]
fn test_byte_xor() {
let mut byte_array: ByteArray = ByteArray(vec![0x25, 0x25]);
let byte_array2: ByteArray = ByteArray(vec![0x55, 0x55]);
byte_array.xor_byte_arrays(&byte_array2);
assert_eq!(byte_array.0, vec![0x70, 0x70]);
}
#[test]
fn test_byte_xor2() {
let mut byte_array: ByteArray = ByteArray(vec![0x00, 0x00]);
let byte_array2: ByteArray = ByteArray(vec![0x55, 0x55]);
byte_array.xor_byte_arrays(&byte_array2);
assert_eq!(byte_array.0, vec![0x55, 0x55]);
}
}

View file

@ -10,197 +10,3 @@ pub fn xor_bytes(vec1: &Vec<u8>, mut vec2: Vec<u8>) -> Result<Vec<u8>> {
Ok(vec2) Ok(vec2)
} }
#[derive(Debug)]
pub struct ByteArray(pub Vec<u8>);
impl ByteArray {
pub fn left_shift(&mut self, semantic: &str) -> Result<u8> {
match semantic {
"xex" => {
let mut carry = 0u8;
for byte in self.0.iter_mut() {
let new_carry = *byte >> 7;
*byte = (*byte << 1) | carry;
carry = new_carry;
}
Ok(carry)
}
"gcm" => {
let mut carry = 0u8;
for byte in self.0.iter_mut() {
let new_carry = *byte & 1;
*byte = (*byte >> 1) | (carry << 7);
carry = new_carry;
}
Ok(carry)
}
_ => Err(anyhow!("Failure in lsh. No compatible action found")),
}
}
pub fn left_shift_reduce(&mut self, semantic: &str) {
match semantic {
"xex" => {
let alpha_poly: Vec<u8> = base64::prelude::BASE64_STANDARD
.decode("AgAAAAAAAAAAAAAAAAAAAA==")
.expect("Decode failed");
self.0 = gfmul(self.0.clone(), alpha_poly, "xex").unwrap();
}
"gcm" => {
let alpha_poly: Vec<u8> = base64::prelude::BASE64_STANDARD
.decode("AgAAAAAAAAAAAAAAAAAAAA==")
.expect("Decode failed");
self.0 = gfmul(self.0.clone(), alpha_poly, "gcm").unwrap();
}
_ => {}
}
}
pub fn right_shift(&mut self, semantic: &str) -> Result<u8> {
match semantic {
"xex" => {
let mut carry = 0u8;
for byte in self.0.iter_mut().rev() {
let new_carry = *byte & 1;
*byte = (*byte >> 1) | (carry << 7);
carry = new_carry;
}
Ok(carry)
}
"gcm" => {
let mut carry = 0u8;
for byte in self.0.iter_mut().rev() {
let new_carry = *byte & 1;
*byte = (*byte << 1) | carry;
carry = new_carry;
}
Ok(carry)
}
_ => Err(anyhow!("Failure in rsh. No valid semantic found")),
}
}
pub fn xor_byte_arrays(&mut self, vec2: &ByteArray) {
self.0
.iter_mut()
.zip(vec2.0.iter())
.for_each(|(x1, x2)| *x1 ^= *x2);
}
pub fn LSB_is_one(&self) -> bool {
(self.0.first().unwrap() & 1) == 1
}
pub fn msb_is_one(&self) -> bool {
(self.0.last().unwrap() & 1) == 1
}
pub fn is_empty(&self) -> bool {
for i in self.0.iter() {
if *i != 0 {
return false;
}
}
true
}
}
#[cfg(test)]
mod tests {
use super::*;
use std::fs;
#[test]
fn test_byte_array_shift1() {
let mut byte_array: ByteArray = ByteArray(vec![0x00, 0x01]);
let shifted_array: ByteArray = ByteArray(vec![0x00, 0x02]);
byte_array.left_shift("xex");
assert_eq!(byte_array.0, shifted_array.0);
}
#[test]
fn test_byte_array_shift2() {
let mut byte_array: ByteArray = ByteArray(vec![0xFF, 0x00]);
let shifted_array: ByteArray = ByteArray(vec![0xFE, 0x01]);
byte_array.left_shift("xex");
assert_eq!(
byte_array.0, shifted_array.0,
"Failure: Shifted array was: {:?}",
byte_array.0
);
}
#[test]
fn test_byte_array_shift1_gcm() {
let mut byte_array: ByteArray = ByteArray(vec![0xFF, 0x00]);
let shifted_array: ByteArray = ByteArray(vec![0x7F, 0x80]);
byte_array.left_shift("gcm");
assert_eq!(
byte_array.0, shifted_array.0,
"Failure: Shifted array was: {:02X?}",
byte_array.0
);
}
#[test]
fn test_byte_array_shift1_right_gcm() {
let mut byte_array: ByteArray = ByteArray(vec![0xFF, 0x00]);
let shifted_array: ByteArray = ByteArray(vec![0xFE, 0x00]);
byte_array.right_shift("gcm");
assert_eq!(
byte_array.0, shifted_array.0,
"Failure: Shifted array was: {:02X?}",
byte_array.0
);
}
#[test]
fn test_byte_array_shift_right() {
let mut byte_array: ByteArray = ByteArray(vec![0x02]);
let shifted_array: ByteArray = ByteArray(vec![0x01]);
byte_array.right_shift("xex");
assert_eq!(
byte_array.0, shifted_array.0,
"Failure: Shifted array was: {:?}",
byte_array.0
);
}
#[test]
fn test_lsb_one() {
let byte_array: ByteArray = ByteArray(vec![0x00, 0xFF]);
assert!(!byte_array.LSB_is_one());
let byte_array2: ByteArray = ByteArray(vec![0x02, 0xFF]);
assert!(!byte_array2.LSB_is_one());
let byte_array3: ByteArray = ByteArray(vec![0xFF, 0x00]);
assert!(byte_array3.LSB_is_one());
}
#[test]
fn test_byte_xor() {
let mut byte_array: ByteArray = ByteArray(vec![0x25, 0x25]);
let byte_array2: ByteArray = ByteArray(vec![0x55, 0x55]);
byte_array.xor_byte_arrays(&byte_array2);
assert_eq!(byte_array.0, vec![0x70, 0x70]);
}
#[test]
fn test_byte_xor2() {
let mut byte_array: ByteArray = ByteArray(vec![0x00, 0x00]);
let byte_array2: ByteArray = ByteArray(vec![0x55, 0x55]);
byte_array.xor_byte_arrays(&byte_array2);
assert_eq!(byte_array.0, vec![0x55, 0x55]);
}
}

View file

@ -1,4 +1,5 @@
pub mod ciphers; pub mod ciphers;
pub mod field;
pub mod math; pub mod math;
pub mod parse; pub mod parse;
pub mod poly; pub mod poly;

View file

@ -1,8 +1,10 @@
use crate::utils::math::ByteArray; use crate::utils::field::ByteArray;
use anyhow::Result; use anyhow::{anyhow, Result};
use base64::prelude::*; use base64::prelude::*;
use serde_json::Value; use serde_json::Value;
use std::{str::FromStr, u128, u8, usize}; use std::{str::FromStr, u128, u8, usize};
use super::field;
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>> {
@ -41,6 +43,15 @@ pub fn gfmul(poly_a: Vec<u8>, poly_b: Vec<u8>, semantic: &str) -> Result<Vec<u8>
Ok(result.0) Ok(result.0)
} }
pub fn convert_gcm_to_xex(gcm_poly: Vec<u8>) -> Result<Vec<u8>> {
let xex_poly = gcm_poly
.into_iter()
.map(|block| block.reverse_bits())
.collect();
Ok(xex_poly)
}
pub fn get_alpha_rep(num: u128) -> String { pub fn get_alpha_rep(num: u128) -> String {
let powers: Vec<u8> = get_coefficients(num); let powers: Vec<u8> = get_coefficients(num);
@ -92,6 +103,62 @@ pub fn get_bit_indices_from_byte(byte: u8) -> Vec<u8> {
coefficients coefficients
} }
pub fn block_2_polynomial(block: Vec<u8>, semantic: &str) -> Result<Vec<u8>> {
let mut output: Vec<u8> = vec![];
match semantic {
"xex" => {
for i in 0u8..=15 {
for j in 0u8..=7 {
if (block[i as usize] >> j) & 1 == 1 {
output.push(8 * i + j);
}
}
}
output.sort();
Ok(output)
}
"gcm" => {
for i in 0u8..=15 {
for j in 0u8..=7 {
if (block[i as usize] >> j) & 1 == 1 {
output.push(8 * i + 7 - j);
}
}
}
output.sort();
Ok(output)
}
_ => Err(anyhow!("Error in b2p")),
}
}
pub fn polynomial_2_block(coefficients: Vec<u8>, semantic: &str) -> Result<Vec<u8>> {
let mut output: Vec<u8> = Vec::with_capacity(16);
output.resize(16, 0);
match semantic {
"xex" => {
for coefficient in coefficients {
let byte_position = coefficient / 8;
let bit_position = coefficient % 8;
output[byte_position as usize] ^= 1 << bit_position;
}
Ok(output)
}
"gcm" => {
for coefficient in coefficients {
let byte_position = coefficient / 8;
let bit_position = coefficient % 8;
output[byte_position as usize] ^= 1 << 7 - bit_position;
}
Ok(output)
}
_ => Err(anyhow!("Error in b2p")),
}
}
pub fn coefficients_to_byte_arr_xex(coeffs: Vec<u8>) -> Vec<u8> { pub fn coefficients_to_byte_arr_xex(coeffs: Vec<u8>) -> Vec<u8> {
let mut byte_array: Vec<u8> = vec![0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]; let mut byte_array: Vec<u8> = vec![0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
for coeff in coeffs { for coeff in coeffs {