Compare commits

..

No commits in common. "main" and "feat_field_element" have entirely different histories.

22 changed files with 635 additions and 2121 deletions

View file

@ -10,17 +10,9 @@ base64 = "0.22"
openssl = "0.10" openssl = "0.10"
serde = { version = "1.0", features = ["derive"] } serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0" serde_json = "1.0"
num = "0.4"
rand = "0.8"
threadpool = "1.8"
num_cpus = "1.16.0"
[source.crates-io] [source.crates-io]
replace-with = "vendored-sources" replace-with = "vendored-sources"
[source.vendored-sources] [source.vendored-sources]
directory = "vendor" directory = "vendor"
[profile.profiling]
inherits = "release"
debug = true

View file

@ -1,10 +1,8 @@
use std::{ use std::{
env::{self}, env::{self, args},
fs, fs,
}; };
// TESTING 2
use anyhow::Result; use anyhow::Result;
fn main() -> Result<()> { fn main() -> Result<()> {
@ -14,7 +12,7 @@ fn main() -> Result<()> {
let json = fs::read_to_string(path_to_workload).unwrap(); let json = fs::read_to_string(path_to_workload).unwrap();
let workload = kauma::utils::parse::parse_json(json)?; let workload = kauma::utils::parse::parse_json(json)?;
let response = kauma::tasks::task_distribute(&workload)?; let response = kauma::tasks::task_distrubute(&workload)?;
println!("{}", serde_json::to_string(&response)?); println!("{}", serde_json::to_string(&response)?);
Ok(()) Ok(())

View file

@ -1,22 +1,20 @@
use base64::prelude::*; use base64::prelude::*;
use std::collections::HashMap; use std::{collections::HashMap, env::args};
use crate::utils::parse::{Responses, Testcase, Testcases}; use crate::utils::{
ciphers::gcm_encrypt_aes,
parse::{Responses, Testcase, Testcases},
};
use tasks01::{ use tasks01::{
block2poly::block2poly, block2poly::block2poly,
gcm::{gcm_decrypt, gcm_encrypt}, gcm::{gcm_decrypt, gcm_encrypt},
gcm_crack::gcm_crack,
gfmul::gfmul_task, gfmul::gfmul_task,
pad_oracle::padding_oracle, pad_oracle::padding_oracle,
pfmath::{ pfmath::{gfdiv, gfpoly_add, gfpoly_divmod, gfpoly_mul, gfpoly_pow, gfpoly_powmod},
gfdiv, gfpoly_add, gfpoly_diff, gfpoly_divmod, gfpoly_factor_ddf, gfpoly_factor_edf,
gfpoly_factor_sff, gfpoly_gcd, gfpoly_make_monic, gfpoly_mul, gfpoly_pow, gfpoly_powmod,
gfpoly_sort, gfpoly_sqrt,
},
poly2block::poly2block, poly2block::poly2block,
sea128::sea128, sea128::sea128,
xex::fde_xex, xex::{self, fde_xex},
}; };
use anyhow::{anyhow, Result}; use anyhow::{anyhow, Result};
@ -106,7 +104,7 @@ pub fn task_deploy(testcase: &Testcase) -> Result<Value> {
} }
"gfdiv" => { "gfdiv" => {
let result = gfdiv(args)?; let result = gfdiv(args)?;
let out = result.to_b64(); let out = BASE64_STANDARD.encode(result);
let json = json!({"q" : out}); let json = json!({"q" : out});
Ok(json) Ok(json)
@ -123,66 +121,6 @@ pub fn task_deploy(testcase: &Testcase) -> Result<Value> {
Ok(json) Ok(json)
} }
"gfpoly_sort" => {
let sorted_array = gfpoly_sort(args)?;
let mut result: Vec<Vec<String>> = vec![];
for poly in sorted_array {
result.push(poly.to_c_array());
}
let json = json!({"sorted_polys" : json!(result)});
Ok(json)
}
"gfpoly_make_monic" => {
let result = gfpoly_make_monic(args)?;
let json = json!({"A*" : result.to_c_array()});
Ok(json)
}
"gfpoly_sqrt" => {
let result = gfpoly_sqrt(args)?;
let json = json!({"S" : result.to_c_array()});
Ok(json)
}
"gfpoly_diff" => {
let result = gfpoly_diff(args)?;
let json = json!({"F'" : result.to_c_array()});
Ok(json)
}
"gfpoly_gcd" => {
let result = gfpoly_gcd(args)?;
let json = json!({"G" : result.to_c_array()});
Ok(json)
}
"gfpoly_factor_sff" => {
let result = gfpoly_factor_sff(args)?;
let json = json!({"factors" : result});
Ok(json)
}
"gfpoly_factor_ddf" => {
let result = gfpoly_factor_ddf(args)?;
let json = json!({"factors" : result});
Ok(json)
}
"gfpoly_factor_edf" => {
let result = gfpoly_factor_edf(args)?;
let json = json!({"factors" : result});
Ok(json)
}
"gcm_crack" => {
let result = gcm_crack(args)?;
let json = json!(result);
Ok(json)
}
_ => Err(anyhow!( _ => Err(anyhow!(
"Fatal. No compatible action found. Json data was {:?}. Arguments were; {:?}", "Fatal. No compatible action found. Json data was {:?}. Arguments were; {:?}",
@ -192,60 +130,16 @@ pub fn task_deploy(testcase: &Testcase) -> Result<Value> {
} }
} }
fn task_distribute_mt(testcases: &Testcases) -> Result<Responses> { pub fn task_distrubute(testcases: &Testcases) -> Result<Responses> {
eprintln!("USING MULTITHREADED");
let mut responses: HashMap<String, Value> = HashMap::new();
let pool = threadpool::ThreadPool::default();
let (tx, rx) = std::sync::mpsc::channel();
for (key, testcase) in testcases.testcases.clone() {
let tx = tx.clone();
let testcase = testcase.clone();
pool.execute(move || {
tx.send((key, task_deploy(&testcase)))
.expect("could not send return value of thread to main thread")
});
}
for _ in 0..testcases.testcases.len() {
let result = match rx.recv_timeout(std::time::Duration::from_secs(60 * 5)) {
Ok(r) => r,
Err(e) => {
eprintln!("! Job timed out: {e}");
return Err(e.into());
}
};
match result.1 {
Ok(v) => {
let _ = responses.insert(result.0, v);
}
Err(e) => {
eprintln!("! failed to solve a challenge: {e:#}");
continue;
}
}
}
Ok(Responses { responses })
}
pub fn task_distribute_st(testcases: &Testcases) -> Result<Responses> {
//eprintln!("USING SINGLETHREADED");
let mut responses: HashMap<String, Value> = HashMap::new(); let mut responses: HashMap<String, Value> = HashMap::new();
for (id, testcase) in &testcases.testcases { for (id, testcase) in &testcases.testcases {
responses.insert(id.to_owned(), task_deploy(testcase).unwrap()); responses.insert(id.to_owned(), task_deploy(testcase).unwrap());
} }
Ok(Responses { responses }) Ok(Responses {
} responses: responses,
})
pub fn task_distribute(testcases: &Testcases) -> Result<Responses> {
let cpus = num_cpus::get();
if cpus > 1 {
task_distribute_mt(testcases)
} else {
task_distribute_st(testcases)
}
} }
#[cfg(test)] #[cfg(test)]
@ -278,7 +172,7 @@ mod tests {
let expected = json!({ "responses": { "b856d760-023d-4b00-bad2-15d2b6da22fe": {"block": "ARIAAAAAAAAAAAAAAAAAgA=="}}}); let expected = json!({ "responses": { "b856d760-023d-4b00-bad2-15d2b6da22fe": {"block": "ARIAAAAAAAAAAAAAAAAAgA=="}}});
assert_eq!( assert_eq!(
serde_json::to_value(task_distribute(&parsed)?).unwrap(), serde_json::to_value(task_distrubute(&parsed)?).unwrap(),
serde_json::to_value(expected).unwrap() serde_json::to_value(expected).unwrap()
); );
@ -302,7 +196,7 @@ mod tests {
}); });
assert_eq!( assert_eq!(
serde_json::to_value(task_distribute(&parsed)?).unwrap(), serde_json::to_value(task_distrubute(&parsed)?).unwrap(),
serde_json::to_value(expected).unwrap() serde_json::to_value(expected).unwrap()
); );
@ -317,7 +211,7 @@ mod tests {
let expected = json!({ "responses": { "b856d760-023d-4b00-bad2-15d2b6da22fe": {"product": "hSQAAAAAAAAAAAAAAAAAAA=="}}}); let expected = json!({ "responses": { "b856d760-023d-4b00-bad2-15d2b6da22fe": {"product": "hSQAAAAAAAAAAAAAAAAAAA=="}}});
assert_eq!( assert_eq!(
serde_json::to_value(task_distribute(&parsed)?).unwrap(), serde_json::to_value(task_distrubute(&parsed)?).unwrap(),
serde_json::to_value(expected).unwrap() serde_json::to_value(expected).unwrap()
); );
@ -335,7 +229,7 @@ mod tests {
}}); }});
assert_eq!( assert_eq!(
serde_json::to_value(task_distribute(&parsed)?).unwrap(), serde_json::to_value(task_distrubute(&parsed)?).unwrap(),
serde_json::to_value(expected).unwrap() serde_json::to_value(expected).unwrap()
); );
@ -355,7 +249,7 @@ mod tests {
}}}); }}});
assert_eq!( assert_eq!(
serde_json::to_value(task_distribute(&parsed)?).unwrap(), serde_json::to_value(task_distrubute(&parsed)?).unwrap(),
serde_json::to_value(expected).unwrap() serde_json::to_value(expected).unwrap()
); );
@ -375,7 +269,7 @@ mod tests {
}}}); }}});
assert_eq!( assert_eq!(
serde_json::to_value(task_distribute(&parsed)?).unwrap(), serde_json::to_value(task_distrubute(&parsed)?).unwrap(),
serde_json::to_value(expected).unwrap() serde_json::to_value(expected).unwrap()
); );
@ -393,7 +287,7 @@ mod tests {
}}}); }}});
assert_eq!( assert_eq!(
serde_json::to_value(task_distribute(&parsed)?).unwrap(), serde_json::to_value(task_distrubute(&parsed)?).unwrap(),
serde_json::to_value(expected).unwrap() serde_json::to_value(expected).unwrap()
); );
@ -411,7 +305,7 @@ mod tests {
}}}); }}});
assert_eq!( assert_eq!(
serde_json::to_value(task_distribute(&parsed)?).unwrap(), serde_json::to_value(task_distrubute(&parsed)?).unwrap(),
serde_json::to_value(expected).unwrap() serde_json::to_value(expected).unwrap()
); );
@ -429,7 +323,7 @@ mod tests {
}}}); }}});
assert_eq!( assert_eq!(
serde_json::to_value(task_distribute(&parsed)?).unwrap(), serde_json::to_value(task_distrubute(&parsed)?).unwrap(),
serde_json::to_value(expected).unwrap() serde_json::to_value(expected).unwrap()
); );

View file

@ -1,4 +1,4 @@
use crate::utils::poly::block_2_polynomial; use crate::utils::poly::{b64_2_num, block_2_polynomial, get_coefficients};
use anyhow::Result; use anyhow::Result;
use base64::prelude::*; use base64::prelude::*;
use serde_json::Value; use serde_json::Value;
@ -19,6 +19,7 @@ pub fn block2poly(val: &Value) -> Result<Vec<u8>> {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use serde_json::json; use serde_json::json;
use std::str::FromStr;
// 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::*;

View file

@ -1,174 +0,0 @@
use anyhow::{Ok, Result};
use base64::{prelude::BASE64_STANDARD, Engine};
use serde::{Deserialize, Serialize};
use serde_json::Value;
use crate::utils::{
ciphers::ghash,
dff::ddf,
edf::edf,
field::FieldElement,
math::{reverse_bits_in_bytevec, xor_bytes},
poly::Polynomial,
sff::sff,
};
#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct CrackAnswer {
tag: String,
H: String,
mask: String,
}
#[derive(Debug, Serialize, Deserialize, Clone)]
struct Message {
ciphertext: Vec<u8>,
ad: Vec<u8>,
tag: Vec<u8>,
l_field: Vec<u8>,
}
fn parse_message(val: &Value) -> Result<(Message, Polynomial)> {
let ciphertext_text: String = serde_json::from_value(val["ciphertext"].clone())?;
let mut ciphertext_bytes: Vec<u8> = BASE64_STANDARD.decode(ciphertext_text)?;
let mut c_len: Vec<u8> = ((ciphertext_bytes.len() * 8) as u64).to_be_bytes().to_vec();
if ciphertext_bytes.len() % 16 != 0 {
ciphertext_bytes.append(vec![0u8; 16 - (ciphertext_bytes.len() % 16)].as_mut());
}
let ciphertext_chunks: Vec<FieldElement> = ciphertext_bytes
.chunks(16)
.into_iter()
.map(|chunk| FieldElement::new(chunk.to_vec()))
.collect();
let ad_text: String = serde_json::from_value(val["associated_data"].clone())?;
let mut ad_bytes: Vec<u8> = BASE64_STANDARD.decode(ad_text)?;
let mut l_field: Vec<u8> = ((ad_bytes.len() * 8) as u64).to_be_bytes().to_vec();
if ad_bytes.len() % 16 != 0 || ad_bytes.is_empty() {
ad_bytes.append(vec![0u8; 16 - (ad_bytes.len() % 16)].as_mut());
}
let ad_chunks: Vec<FieldElement> = ad_bytes
.chunks(16)
.into_iter()
.map(|chunk| FieldElement::new(chunk.to_vec()))
.collect();
let tag_text: String = serde_json::from_value(val["tag"].clone()).unwrap_or("".to_string());
let tag_bytes: Vec<u8> = BASE64_STANDARD.decode(tag_text)?;
let tag_field: FieldElement = FieldElement::new(tag_bytes.clone());
l_field.append(c_len.as_mut());
// Combine all data
let mut combined: Vec<FieldElement> =
Vec::with_capacity(ad_chunks.len() + ciphertext_chunks.len() + 1);
combined.extend(ad_chunks);
combined.extend(ciphertext_chunks.clone());
combined.push(FieldElement::new(l_field.clone()));
combined.push(tag_field);
combined.reverse();
let h_poly: Polynomial = Polynomial::new(combined);
Ok((
Message {
ciphertext: ciphertext_bytes,
ad: ad_bytes,
tag: tag_bytes,
l_field,
},
h_poly,
))
}
pub fn gcm_crack(args: &Value) -> Result<CrackAnswer> {
// Prepare first equation
let (m1_data, m1_h_poly) = parse_message(&args["m1"])?;
let (_, m2_h_poly) = parse_message(&args["m2"])?;
let (m3_data, _) = parse_message(&args["m3"])?;
let combine_poly = m1_h_poly + m2_h_poly;
let combine_sff = sff(combine_poly.monic());
let mut combine_ddf: Vec<(Polynomial, u128)> = vec![];
for (factor, _) in combine_sff {
combine_ddf.extend(ddf(factor));
}
let mut combine_edf: Vec<Polynomial> = vec![];
for (factor, degree) in combine_ddf {
if degree == 1 {
combine_edf.extend(edf(factor, degree as u32));
}
}
let mut m3_auth_tag: Vec<u8> = vec![];
let mut h_candidate: FieldElement = FieldElement::zero();
let mut eky0: Vec<u8> = vec![];
for candidate in combine_edf {
if candidate.degree() == 1 {
h_candidate = candidate.extract_component(0);
let m1_ghash = ghash(
reverse_bits_in_bytevec(h_candidate.to_vec()),
m1_data.ad.clone(),
m1_data.ciphertext.clone(),
m1_data.l_field.clone(),
)
.unwrap();
eky0 = xor_bytes(&m1_data.tag, m1_ghash).unwrap();
eprintln!("eky0: {:?}", BASE64_STANDARD.encode(eky0.clone()));
let m3_ghash = ghash(
reverse_bits_in_bytevec(h_candidate.to_vec()),
m3_data.ad.clone(),
m3_data.ciphertext.clone(),
m3_data.l_field.clone(),
)
.unwrap();
m3_auth_tag = xor_bytes(&eky0, m3_ghash).unwrap();
eprintln!(
"M3 auth tag: {:02X?}",
BASE64_STANDARD.encode(m3_auth_tag.clone())
);
if m3_auth_tag == m3_data.tag {
break;
} else {
eprintln!("H candidate not valid");
}
}
}
let (forgery_data, _) = parse_message(&args["forgery"])?;
let forgery_ghash = ghash(
reverse_bits_in_bytevec(h_candidate.to_vec()),
forgery_data.ad.clone(),
forgery_data.ciphertext.clone(),
forgery_data.l_field.clone(),
)
.unwrap();
let forgery_auth_tag = xor_bytes(&eky0, forgery_ghash).unwrap();
if eky0.is_empty() {
eky0 = vec![0; 16];
}
Ok(CrackAnswer {
tag: BASE64_STANDARD.encode(forgery_auth_tag),
H: h_candidate.to_b64(),
mask: BASE64_STANDARD.encode(eky0),
})
}

View file

@ -1,4 +1,7 @@
use crate::utils::poly::gfmul; use crate::utils::{
field::ByteArray,
poly::{b64_2_num, coefficient_to_binary, gfmul},
};
use anyhow::Result; use anyhow::Result;
use base64::prelude::*; use base64::prelude::*;
@ -21,6 +24,7 @@ pub fn gfmul_task(args: &Value) -> Result<Vec<u8>> {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use serde_json::json; use serde_json::json;
use std::str::FromStr;
// 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::*;

View file

@ -1,6 +1,5 @@
pub mod block2poly; pub mod block2poly;
pub mod gcm; pub mod gcm;
pub mod gcm_crack;
pub mod gfmul; pub mod gfmul;
pub mod pad_oracle; pub mod pad_oracle;
pub mod pfmath; pub mod pfmath;

View file

@ -3,7 +3,8 @@ 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::usize; use std::time::{Duration, Instant};
use std::{thread, usize};
pub fn padding_oracle(args: &Value) -> Result<Vec<u8>> { pub fn padding_oracle(args: &Value) -> Result<Vec<u8>> {
let hostname: String = serde_json::from_value(args["hostname"].clone())?; let hostname: String = serde_json::from_value(args["hostname"].clone())?;
@ -28,8 +29,9 @@ pub fn padding_oracle(args: &Value) -> Result<Vec<u8>> {
let mut chunk_counter = 0; let mut chunk_counter = 0;
for chunk in &cipher_chunks { for chunk in &cipher_chunks {
let start = Instant::now();
let mut stream = TcpStream::connect(format!("{}:{}", hostname, port))?; let mut stream = TcpStream::connect(format!("{}:{}", hostname, port))?;
stream.set_nodelay(true).expect("Error on no delay");
stream.set_nonblocking(false)?; stream.set_nonblocking(false)?;
// Track value sent to server // Track value sent to server
@ -40,6 +42,7 @@ pub fn padding_oracle(args: &Value) -> Result<Vec<u8>> {
let q_block_count: u16 = 256; let q_block_count: u16 = 256;
//Send the first ciphertext chunk //Send the first ciphertext chunk
//eprintln!("Sending Ciphertext chunk: {:002X?}", chunk);
stream.flush()?; stream.flush()?;
stream.write_all(&chunk)?; stream.write_all(&chunk)?;
stream.flush()?; stream.flush()?;
@ -49,16 +52,24 @@ pub fn padding_oracle(args: &Value) -> Result<Vec<u8>> {
// FIXME: Assignment is redundant for now // FIXME: Assignment is redundant for now
// TODO: Goal is to maybe add speed increase in the future // TODO: Goal is to maybe add speed increase in the future
let l_msg: [u8; 2] = q_block_count.to_le_bytes(); let l_msg: [u8; 2] = q_block_count.to_le_bytes();
//eprintln!("Sending l_msg: {:02X?}", l_msg);
//stream.write_all(&l_msg)?;
//stream.flush()?;
//eprintln!("L_msg sent");
// Generate attack blocks // Generate attack blocks
// TODO: Collect all and send in one // TODO: Collect all and send in one
let mut payload: Vec<u8> = Vec::with_capacity(2 + 16 * 265); let mut payload: Vec<u8> = l_msg.to_vec();
payload.extend(l_msg.to_vec()); for j in 0..q_block_count {
for _j in 0..q_block_count {
// Next byte // Next byte
//eprintln!("Sending attack block: {:02X?}", attack_counter);
//thread::sleep(Duration::from_millis(1000));
payload.extend(&attack_counter); payload.extend(&attack_counter);
//eprintln!("I in q builder {}", i);
attack_counter[i as usize] += 1; attack_counter[i as usize] += 1;
} }
//eprintln!("Time for qblocks: {:?}", start.elapsed());
stream.write_all(&payload)?; stream.write_all(&payload)?;
stream.flush()?; stream.flush()?;
@ -66,6 +77,7 @@ pub fn padding_oracle(args: &Value) -> Result<Vec<u8>> {
// Read server response // Read server response
let mut server_q_resp = [0u8; 256]; let mut server_q_resp = [0u8; 256];
stream.read_exact(&mut server_q_resp)?; stream.read_exact(&mut server_q_resp)?;
//eprintln!("{:02X?}", buf);
// extract valid position // extract valid position
let valid_val = server_q_resp let valid_val = server_q_resp
@ -75,6 +87,7 @@ pub fn padding_oracle(args: &Value) -> Result<Vec<u8>> {
if valid_val == 0x00 { if valid_val == 0x00 {
eprintln!("No valid found in main loop"); eprintln!("No valid found in main loop");
} }
//eprintln!("Valid value found: {:02X?}", valid_val);
// Craft next attack vector padding; 0x01, 0x02, ... // Craft next attack vector padding; 0x01, 0x02, ...
attack_counter[i as usize] = valid_val; attack_counter[i as usize] = valid_val;
@ -88,35 +101,57 @@ pub fn padding_oracle(args: &Value) -> Result<Vec<u8>> {
l_msg_check.extend(check_q_block.as_slice()); l_msg_check.extend(check_q_block.as_slice());
stream.write_all(&l_msg_check)?; stream.write_all(&l_msg_check)?;
//stream.write_all(&check_q_block)?;
let mut buf = [0u8; 0x01]; let mut buf = [0u8; 0x01];
stream.read(&mut buf)?; stream.read(&mut buf)?;
//eprintln!("I = {}", i);
//eprintln!("Buffer from pad check: {:02X?}", buf);
if buf == [0x01] { if buf == [0x01] {
//eprintln!("Valid padding");
} else { } else {
//eprintln!("Invalid padding");
// Search for second hit // Search for second hit
let valid_val = 255 let valid_val = (255
- server_q_resp - server_q_resp
.iter() .iter()
.rev() .rev()
.position(|&r| r == 0x01) .position(|&r| r == 0x01)
.unwrap_or(0x00) as u8; .unwrap_or(0x00) as u8);
if valid_val == 0x00 { if valid_val == 0x00 {
eprintln!("No valid found"); eprintln!("No valid found");
} }
//eprintln!("Valid value found: {:02X?}", valid_val);
// Craft next attack vector padding; 0x01, 0x02, ... // Craft next attack vector padding; 0x01, 0x02, ...
attack_counter[i as usize] = valid_val; attack_counter[i as usize] = valid_val;
} }
} }
if chunk_counter + 1 < cipher_chunks.len() { if chunk_counter + 1 < cipher_chunks.len() {
//eprintln!("XOR Next Ciph block");
plaintext.push( plaintext.push(
cipher_chunks[chunk_counter + 1][i] cipher_chunks[chunk_counter + 1][i]
^ (attack_counter[i as usize] ^ (15 - i as u8 + 1)), ^ (attack_counter[i as usize] ^ (15 - i as u8 + 1)),
); );
} else { } else {
//seprintln!("XOR IV");
plaintext.push(iv[i] ^ (attack_counter[i as usize] ^ (15 - i as u8 + 1))); plaintext.push(iv[i] ^ (attack_counter[i as usize] ^ (15 - i as u8 + 1)));
} }
//eprintln!("Attack counter after set: {:02X?}", attack_counter);
let range = i; let range = i;
for pos in range..=15 { for pos in range..=15 {
//eprintln!("i is: {:02X?}", i);
//eprintln!("i + 1 is: {:02X?}", ((16 - i) as u8).to_le());
/*
eprintln!(
"attack_counter[pos as usize]: {:02X?}",
attack_counter[pos as usize]
);
eprintln!(
"attack_counter[pos as usize] ^ 0x02 {:02X?}",
attack_counter[pos as usize] ^ (15 - i as u8 + 1)
);
*/
let intermediate = attack_counter[pos as usize] ^ (15 - i as u8 + 1); let intermediate = attack_counter[pos as usize] ^ (15 - i as u8 + 1);
attack_counter[pos as usize] = intermediate ^ ((15 - i as u8 + 1) + 1); attack_counter[pos as usize] = intermediate ^ ((15 - i as u8 + 1) + 1);
@ -125,10 +160,13 @@ pub fn padding_oracle(args: &Value) -> Result<Vec<u8>> {
stream.flush()?; stream.flush()?;
// Write plaintext // Write plaintext
//eprintln!("{:02X?}", plaintext);
} }
chunk_counter += 1; chunk_counter += 1;
stream.flush()?; stream.flush()?;
// break;
drop(stream); drop(stream);
//eprintln!("Time rest of calc: {:?}", start.elapsed());
} }
plaintext.reverse(); plaintext.reverse();
@ -140,6 +178,7 @@ pub fn padding_oracle(args: &Value) -> Result<Vec<u8>> {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::*; use super::*;
use serde_json::json;
#[test] #[test]
fn test_connection() -> Result<()> { fn test_connection() -> Result<()> {

View file

@ -1,16 +1,8 @@
use anyhow::Result; 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::{ use crate::utils::field::{FieldElement, Polynomial};
self,
dff::ddf,
edf::edf,
field::FieldElement,
poly::{gcd, Polynomial},
sff::{sff, Factors},
};
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());
@ -75,208 +67,3 @@ pub fn gfpoly_powmod(args: &Value) -> Result<Polynomial> {
Ok(result) Ok(result)
} }
pub fn gfpoly_sort(args: &Value) -> Result<Vec<Polynomial>> {
let poly_arrays: Vec<Value> = serde_json::from_value(args["polys"].clone())?;
let mut polys: Vec<Polynomial> = vec![];
for array in poly_arrays {
polys.push(Polynomial::from_c_array(&array));
}
polys.sort();
//polys.sort();
Ok(polys)
}
pub fn gfpoly_make_monic(args: &Value) -> Result<Polynomial> {
let poly_a = Polynomial::from_c_array(&args["A"].clone());
let result = poly_a.monic();
Ok(result)
}
pub fn gfpoly_sqrt(args: &Value) -> Result<Polynomial> {
let poly_a = Polynomial::from_c_array(&args["Q"].clone());
let result = poly_a.sqrt();
Ok(result)
}
pub fn gfpoly_diff(args: &Value) -> Result<Polynomial> {
let poly_f = Polynomial::from_c_array(&args["F"].clone());
let result = poly_f.diff();
Ok(result)
}
pub fn gfpoly_gcd(args: &Value) -> Result<Polynomial> {
let poly_a = Polynomial::from_c_array(&args["A"].clone());
let poly_b = Polynomial::from_c_array(&args["B"].clone());
let result = gcd(&poly_a.monic(), &poly_b.monic());
Ok(result)
}
pub fn gfpoly_factor_sff(arsg: &Value) -> Result<Vec<Factors>> {
let poly_f = Polynomial::from_c_array(&arsg["F"].clone());
let mut factors = sff(poly_f);
factors.sort();
let mut result: Vec<Factors> = vec![];
for (factor, exponent) in factors {
result.push(Factors {
factor: factor.to_c_array(),
exponent,
});
}
Ok(result)
}
pub fn gfpoly_factor_ddf(arsg: &Value) -> Result<Vec<utils::dff::Factors>> {
let poly_f = Polynomial::from_c_array(&arsg["F"].clone());
let mut factors = ddf(poly_f);
factors.sort();
let mut result: Vec<utils::dff::Factors> = vec![];
for (factor, degree) in factors {
result.push(utils::dff::Factors {
factor: factor.to_c_array(),
degree: degree as u32,
});
}
Ok(result)
}
pub fn gfpoly_factor_edf(arsg: &Value) -> Result<Vec<Vec<String>>> {
let poly_f = Polynomial::from_c_array(&arsg["F"].clone());
let d: u32 = serde_json::from_value(arsg["d"].clone())?;
let mut factors = edf(poly_f, d);
factors.sort();
let mut result: Vec<Vec<String>> = vec![];
for factor in factors {
result.push(factor.to_c_array())
}
Ok(result)
}
#[cfg(test)]
mod tests {
use super::*;
use serde_json::json;
#[test]
fn test_poly_sorting() {
let json1 = json!(
{"polys": [
[
"NeverGonnaGiveYouUpAAA==",
"NeverGonnaLetYouDownAA==",
"NeverGonnaRunAroundAAA==",
"AndDesertYouAAAAAAAAAA=="
],
[
"WereNoStrangersToLoveA==",
"YouKnowTheRulesAAAAAAA==",
"AndSoDoIAAAAAAAAAAAAAA=="
],
[
"NeverGonnaMakeYouCryAA==",
"NeverGonnaSayGoodbyeAA==",
"NeverGonnaTellALieAAAA==",
"AndHurtYouAAAAAAAAAAAA=="
]
]});
let expected = json!([
[
"WereNoStrangersToLoveA==",
"YouKnowTheRulesAAAAAAA==",
"AndSoDoIAAAAAAAAAAAAAA=="
],
[
"NeverGonnaMakeYouCryAA==",
"NeverGonnaSayGoodbyeAA==",
"NeverGonnaTellALieAAAA==",
"AndHurtYouAAAAAAAAAAAA=="
],
[
"NeverGonnaGiveYouUpAAA==",
"NeverGonnaLetYouDownAA==",
"NeverGonnaRunAroundAAA==",
"AndDesertYouAAAAAAAAAA=="
]
]);
let sorted_array = gfpoly_sort(&json1).unwrap();
let mut result: Vec<Vec<String>> = vec![];
for poly in sorted_array {
result.push(poly.to_c_array());
}
assert_eq!(json!(result), expected);
//assert_eq!(BASE64_STANDARD.encode(product), "MoAAAAAAAAAAAAAAAAAAAA==");
}
#[test]
fn test_poly_sorting_02() {
let json1 = json!(
{"polys": [
[
"AQAAAAAAAAAAAAAAAAAAAA==", // 0x01
"AgAAAAAAAAAAAAAAAAAAAA==", // 0x02
"AwAAAAAAAAAAAAAAAAAAAA==" // 0x03
],
[
"AQAAAAAAAAAAAAAAAAAAAA==", // 0x01
"AgAAAAAAAAAAAAAAAAAAAA==", // 0x02
"BAAAAAAAAAAAAAAAAAAAAA==" // 0x04
],
[
"AQAAAAAAAAAAAAAAAAAAAA==", // 0x01
"AgAAAAAAAAAAAAAAAAAAAA==" // 0x02
],
[
"AQAAAAAAAAAAAAAAAAAAAA==", // 0x01
"AwAAAAAAAAAAAAAAAAAAAA==" // 0x03
]
],});
let expected = json!([
["AQAAAAAAAAAAAAAAAAAAAA==", "AgAAAAAAAAAAAAAAAAAAAA=="],
["AQAAAAAAAAAAAAAAAAAAAA==", "AwAAAAAAAAAAAAAAAAAAAA=="],
[
"AQAAAAAAAAAAAAAAAAAAAA==",
"AgAAAAAAAAAAAAAAAAAAAA==",
"BAAAAAAAAAAAAAAAAAAAAA=="
],
[
"AQAAAAAAAAAAAAAAAAAAAA==",
"AgAAAAAAAAAAAAAAAAAAAA==",
"AwAAAAAAAAAAAAAAAAAAAA=="
]
]);
let sorted_array = gfpoly_sort(&json1).unwrap();
let mut result: Vec<Vec<String>> = vec![];
for poly in sorted_array {
result.push(poly.to_c_array());
}
assert_eq!(json!(result), expected);
//assert_eq!(BASE64_STANDARD.encode(product), "MoAAAAAAAAAAAAAAAAAAAA==");
}
}

View file

@ -1,5 +1,6 @@
use crate::utils::poly::polynomial_2_block; use crate::utils::poly::{self, polynomial_2_block};
use anyhow::{Ok, Result}; use anyhow::{Ok, Result};
use base64::prelude::*;
use serde_json::Value; use serde_json::Value;
pub fn poly2block(args: &Value) -> Result<Vec<u8>> { pub fn poly2block(args: &Value) -> Result<Vec<u8>> {

View file

@ -6,13 +6,19 @@ use crate::utils::ciphers::{sea_128_decrypt, sea_128_encrypt};
pub fn sea128(args: &Value) -> Result<String> { pub fn sea128(args: &Value) -> Result<String> {
let key_string: String = serde_json::from_value(args["key"].clone())?; let key_string: String = serde_json::from_value(args["key"].clone())?;
//let key: &[u8] = b64_2_num(key_string)?.to_ne_bytes();
let key = BASE64_STANDARD.decode(key_string)?; let key = BASE64_STANDARD.decode(key_string)?;
//eprintln!("{:?}", key);
let input_string: String = serde_json::from_value(args["input"].clone())?; let input_string: String = serde_json::from_value(args["input"].clone())?;
//let plaintexts: &[u8] = &b64_2_num(plaintexts_string)?.to_ne_bytes();
let input = BASE64_STANDARD.decode(input_string)?; let input = BASE64_STANDARD.decode(input_string)?;
let xor_val: u128 = 0xc0ffeec0ffeec0ffeec0ffeec0ffee11;
let mode: String = serde_json::from_value(args["mode"].clone())?; let mode: String = serde_json::from_value(args["mode"].clone())?;
match mode.as_str() { match mode.as_str() {
"encrypt" => { "encrypt" => {
//eprintln!("{:?}", plaintexts);
let output = BASE64_STANDARD.encode(sea_128_encrypt(&key, &input)?); let output = BASE64_STANDARD.encode(sea_128_encrypt(&key, &input)?);
Ok(output) Ok(output)
@ -28,6 +34,7 @@ pub fn sea128(args: &Value) -> Result<String> {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use std::fs;
use anyhow::Result; use anyhow::Result;
use serde_json::json; use serde_json::json;

View file

@ -1,5 +1,8 @@
use crate::utils::{field::ByteArray, poly::gfmul}; use std::{io::BufRead, process::Output};
use crate::utils::{field::ByteArray, math::reverse_bits_in_bytevec, poly::gfmul};
use anyhow::Result; use anyhow::Result;
use base64::prelude::*;
use openssl::symm::{Cipher, Crypter, Mode}; use openssl::symm::{Cipher, Crypter, Mode};
use super::math::xor_bytes; use super::math::xor_bytes;
@ -37,6 +40,7 @@ pub fn aes_128_decrypt(key: &Vec<u8>, input: &Vec<u8>) -> Result<Vec<u8>> {
let mut bytes: [u8; 16] = [0u8; 16]; let mut bytes: [u8; 16] = [0u8; 16];
bytes.copy_from_slice(&plaintext); bytes.copy_from_slice(&plaintext);
let number: u128 = <u128>::from_be_bytes(bytes);
Ok(plaintext) Ok(plaintext)
} }
@ -118,8 +122,10 @@ pub fn gcm_encrypt_aes(
let mut counter: u32 = 1; let mut counter: u32 = 1;
nonce.append(counter.to_be_bytes().to_vec().as_mut()); nonce.append(counter.to_be_bytes().to_vec().as_mut());
//nonce.append(0u8.to_le_bytes().to_vec().as_mut()); //nonce.append(0u8.to_le_bytes().to_vec().as_mut());
eprintln!("{:001X?}", nonce);
let auth_tag_xor = aes_128_encrypt(&key, &nonce)?; let auth_tag_xor = aes_128_encrypt(&key, &nonce)?;
eprintln!("Y0 {:001X?}", auth_tag_xor);
let auth_key_h = aes_128_encrypt(&key, &0u128.to_be_bytes().to_vec())?; let auth_key_h = aes_128_encrypt(&key, &0u128.to_be_bytes().to_vec())?;
@ -130,6 +136,8 @@ pub fn gcm_encrypt_aes(
nonce.drain(12..); nonce.drain(12..);
nonce.append(counter.to_be_bytes().to_vec().as_mut()); nonce.append(counter.to_be_bytes().to_vec().as_mut());
eprintln!("{:001X?}", nonce);
let inter1 = aes_128_encrypt(&key, &nonce)?; let inter1 = aes_128_encrypt(&key, &nonce)?;
let mut inter2 = xor_bytes(&inter1, chunk.clone())?; let mut inter2 = xor_bytes(&inter1, chunk.clone())?;
@ -146,6 +154,7 @@ pub fn gcm_encrypt_aes(
&ghash(auth_key_h.clone(), ad, ciphertext.clone(), l_field.clone())?, &ghash(auth_key_h.clone(), ad, ciphertext.clone(), l_field.clone())?,
auth_tag_xor, auth_tag_xor,
)?; )?;
eprintln!("aes auth tag: {:001X?}", &auth_tag);
Ok((ciphertext, auth_tag, l_field, auth_key_h)) Ok((ciphertext, auth_tag, l_field, auth_key_h))
} }
@ -161,6 +170,8 @@ pub fn gcm_decrypt_aes(
let mut counter: u32 = 1; let mut counter: u32 = 1;
nonce.append(counter.to_be_bytes().to_vec().as_mut()); nonce.append(counter.to_be_bytes().to_vec().as_mut());
//nonce.append(0u8.to_le_bytes().to_vec().as_mut());
eprintln!("{:001X?}", nonce);
let auth_tag_xor = aes_128_encrypt(&key, &nonce)?; let auth_tag_xor = aes_128_encrypt(&key, &nonce)?;
@ -173,6 +184,8 @@ pub fn gcm_decrypt_aes(
nonce.drain(12..); nonce.drain(12..);
nonce.append(counter.to_be_bytes().to_vec().as_mut()); nonce.append(counter.to_be_bytes().to_vec().as_mut());
eprintln!("{:001X?}", nonce);
let inter1 = aes_128_encrypt(&key, &nonce)?; let inter1 = aes_128_encrypt(&key, &nonce)?;
let mut inter2 = xor_bytes(&inter1, chunk.clone())?; let mut inter2 = xor_bytes(&inter1, chunk.clone())?;
@ -191,6 +204,7 @@ pub fn gcm_decrypt_aes(
)?; )?;
let valid = auth_tag == tag; let valid = auth_tag == tag;
eprintln!("aes auth tag: {:001X?}", auth_tag);
Ok((plaintext, valid)) Ok((plaintext, valid))
} }
@ -206,6 +220,7 @@ pub fn gcm_encrypt_sea(
let mut counter: u32 = 1; let mut counter: u32 = 1;
nonce.append(counter.to_be_bytes().to_vec().as_mut()); nonce.append(counter.to_be_bytes().to_vec().as_mut());
//nonce.append(0u8.to_le_bytes().to_vec().as_mut()); //nonce.append(0u8.to_le_bytes().to_vec().as_mut());
eprintln!("{:001X?}", nonce);
let auth_tag_xor = sea_128_encrypt(&key, &nonce)?; let auth_tag_xor = sea_128_encrypt(&key, &nonce)?;
@ -218,6 +233,8 @@ pub fn gcm_encrypt_sea(
nonce.drain(12..); nonce.drain(12..);
nonce.append(counter.to_be_bytes().to_vec().as_mut()); nonce.append(counter.to_be_bytes().to_vec().as_mut());
eprintln!("{:001X?}", nonce);
let inter1 = sea_128_encrypt(&key, &nonce)?; let inter1 = sea_128_encrypt(&key, &nonce)?;
let mut inter2 = xor_bytes(&inter1, chunk.clone())?; let mut inter2 = xor_bytes(&inter1, chunk.clone())?;
@ -249,6 +266,8 @@ pub fn gcm_decrypt_sea(
let mut counter: u32 = 1; let mut counter: u32 = 1;
nonce.append(counter.to_be_bytes().to_vec().as_mut()); nonce.append(counter.to_be_bytes().to_vec().as_mut());
//nonce.append(0u8.to_le_bytes().to_vec().as_mut());
eprintln!("Nonce 1: {:001X?}", nonce);
let auth_tag_xor = sea_128_encrypt(&key, &nonce)?; let auth_tag_xor = sea_128_encrypt(&key, &nonce)?;
@ -256,11 +275,17 @@ pub fn gcm_decrypt_sea(
let plaintext_chunks: Vec<Vec<u8>> = ciphertext.chunks(16).map(|x| x.to_vec()).collect(); let plaintext_chunks: Vec<Vec<u8>> = ciphertext.chunks(16).map(|x| x.to_vec()).collect();
eprintln!("{:?}", plaintext_chunks);
counter = 2; counter = 2;
for chunk in plaintext_chunks { for chunk in plaintext_chunks {
eprintln!("Inside loop");
nonce.drain(12..); nonce.drain(12..);
nonce.append(counter.to_be_bytes().to_vec().as_mut()); nonce.append(counter.to_be_bytes().to_vec().as_mut());
eprintln!("Nonce 2: {:001X?}", nonce);
let inter1 = sea_128_encrypt(&key, &nonce)?; let inter1 = sea_128_encrypt(&key, &nonce)?;
let mut inter2 = xor_bytes(&inter1, chunk.clone())?; let mut inter2 = xor_bytes(&inter1, chunk.clone())?;
@ -273,11 +298,15 @@ pub fn gcm_decrypt_sea(
let mut c_len: Vec<u8> = ((plaintext.len() * 8) as u64).to_be_bytes().to_vec(); let mut c_len: Vec<u8> = ((plaintext.len() * 8) as u64).to_be_bytes().to_vec();
l_field.append(c_len.as_mut()); l_field.append(c_len.as_mut());
eprintln!("Ciphertext: {}", BASE64_STANDARD.encode(&ciphertext));
let auth_tag = xor_bytes( let auth_tag = xor_bytes(
&ghash(auth_key_h.clone(), ad, ciphertext.clone(), l_field.clone())?, &ghash(auth_key_h.clone(), ad, ciphertext.clone(), l_field.clone())?,
auth_tag_xor, auth_tag_xor,
)?; )?;
eprintln!("sea dec auth tag: {}", BASE64_STANDARD.encode(&auth_tag));
let valid = auth_tag == tag; let valid = auth_tag == tag;
Ok((plaintext, valid)) Ok((plaintext, valid))
@ -291,6 +320,10 @@ pub fn ghash(
) -> Result<Vec<u8>> { ) -> Result<Vec<u8>> {
let output: Vec<u8> = vec![0; 16]; let output: Vec<u8> = vec![0; 16];
eprintln!("{:?}", ad.len() as u8);
eprintln!("{:?}", (ad.len() % 16) as u8);
eprintln!("{:001X?}", ad);
if ad.len() % 16 != 0 || ad.is_empty() { if ad.len() % 16 != 0 || ad.is_empty() {
ad.append(vec![0u8; 16 - (ad.len() % 16)].as_mut()); ad.append(vec![0u8; 16 - (ad.len() % 16)].as_mut());
} }
@ -299,12 +332,20 @@ pub fn ghash(
ciphertext.append(vec![0u8; 16 - (ciphertext.len() % 16)].as_mut()); ciphertext.append(vec![0u8; 16 - (ciphertext.len() % 16)].as_mut());
} }
eprintln!("{:001X?}", ad);
eprintln!("{:001X?}", ciphertext);
let mut ad_chunks = ad.chunks(16); let mut ad_chunks = ad.chunks(16);
eprintln!("Ad chunks before first next {:001X?}", ad_chunks);
let inter1 = xor_bytes(&output, ad_chunks.next().unwrap().to_vec())?; let inter1 = xor_bytes(&output, ad_chunks.next().unwrap().to_vec())?;
let mut inter_loop = gfmul(&inter1, &auth_key_h, "gcm")?; let mut inter_loop = gfmul(&inter1, &auth_key_h, "gcm")?;
eprintln!("Ad chunks after first next {:001X?}", ad_chunks);
for chunk in ad_chunks { for chunk in ad_chunks {
eprintln!("Inside ad chunk loop");
eprintln!("Ad chunk in loop {:001X?}", chunk);
let inter2 = xor_bytes(&inter_loop, chunk.to_vec())?; let inter2 = xor_bytes(&inter_loop, chunk.to_vec())?;
inter_loop = gfmul(&inter2, &auth_key_h, "gcm")?; inter_loop = gfmul(&inter2, &auth_key_h, "gcm")?;
} }
@ -319,9 +360,18 @@ pub fn ghash(
let inter4 = xor_bytes(&inter_loop, l_field)?; let inter4 = xor_bytes(&inter_loop, l_field)?;
inter_loop = gfmul(&inter4, &auth_key_h, "gcm")?; inter_loop = gfmul(&inter4, &auth_key_h, "gcm")?;
eprintln!("GHASH auth tag: {:001X?}", inter_loop);
Ok(inter_loop) Ok(inter_loop)
} }
/*
* let mut bytes: [u8; 16] = [0u8; 16];
bytes.copy_from_slice(&ciphertext);
let number: u128 = <u128>::from_be_bytes(bytes);
* */
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::*; use super::*;

View file

@ -1,81 +0,0 @@
use std::usize;
use num::{pow::Pow, BigUint, FromPrimitive};
use serde::{Deserialize, Serialize};
use super::poly::{gcd, Polynomial};
#[derive(Debug, Serialize, Deserialize)]
pub struct Factors {
pub factor: Vec<String>,
pub degree: u32,
}
pub fn ddf(f: Polynomial) -> Vec<(Polynomial, u128)> {
let q = BigUint::pow(&BigUint::from_u8(2).unwrap(), 128);
let mut z: Vec<(Polynomial, u128)> = vec![];
let mut d: u128 = 1;
let mut f_star = f.clone();
let one_cmp = Polynomial::one();
while f_star.degree() as u128 >= (2 * d) {
let h = Polynomial::x().bpow_mod(q.clone().pow(d), &f_star.clone()) + Polynomial::x();
let g = gcd(&h, &f_star);
if g != one_cmp {
z.push((g.clone(), d));
f_star = f_star.div(&g).0;
}
d += 1;
}
if f_star != one_cmp {
z.push((f_star.clone(), f_star.degree() as u128));
} else if z.len() == 0 {
z.push((f.clone(), 1));
}
z
}
#[cfg(test)]
mod tests {
use serde_json::json;
// Note this useful idiom: importing names from outer (for mod tests) scope.
use super::*;
#[test]
fn test_dff_sheet() {
let json_f = json!([
"tpkgAAAAAAAAAAAAAAAAAA==",
"m6MQAAAAAAAAAAAAAAAAAA==",
"8roAAAAAAAAAAAAAAAAAAA==",
"3dUAAAAAAAAAAAAAAAAAAA==",
"FwAAAAAAAAAAAAAAAAAAAA==",
"/kAAAAAAAAAAAAAAAAAAAA==",
"a4AAAAAAAAAAAAAAAAAAAA==",
"gAAAAAAAAAAAAAAAAAAAAA=="
]);
let poly_f = Polynomial::from_c_array(&json_f);
let mut factors = ddf(poly_f);
factors.sort();
let mut result: Vec<Factors> = vec![];
for (factor, degree) in factors {
result.push(Factors {
factor: factor.to_c_array(),
degree: degree as u32,
});
}
println!("Result: {:?}", result);
let _bit_indices: Vec<u8> = vec![0];
assert!(false)
}
}

View file

@ -1,86 +0,0 @@
use num::{BigUint, FromPrimitive, One};
use rand::Rng;
use super::poly::{gcd, Polynomial};
pub fn edf(f: Polynomial, d: u32) -> Vec<Polynomial> {
let q = BigUint::pow(&BigUint::from_u8(2).unwrap(), 128);
let n: u32 = (f.degree() as u32) / (d);
let mut z: Vec<Polynomial> = vec![f.clone()];
let one_cmp = Polynomial::one();
while (z.len() as u32) < n {
let h = Polynomial::rand(&rand::thread_rng().gen_range(1..=f.degree()));
let exponent = (q.pow(d) - BigUint::one()) / BigUint::from_u8(3).unwrap();
let g = h.bpow_mod(exponent, &f) + Polynomial::one();
for i in (0..z.len()).rev() {
if z[i].degree() as u32 > d {
let j = gcd(&z[i], &g);
if j != one_cmp && j != z[i] {
let intemediate = z[i].div(&j).0;
z.remove(i);
z.push(j.clone());
z.push(intemediate);
}
}
}
}
z
}
#[cfg(test)]
mod tests {
use serde_json::json;
// Note this useful idiom: importing names from outer (for mod tests) scope.
use super::*;
#[test]
fn test_edf_sheet() {
let json_f = json!([
"mmAAAAAAAAAAAAAAAAAAAA==",
"AbAAAAAAAAAAAAAAAAAAAA==",
"zgAAAAAAAAAAAAAAAAAAAA==",
"FwAAAAAAAAAAAAAAAAAAAA==",
"AAAAAAAAAAAAAAAAAAAAAA==",
"wAAAAAAAAAAAAAAAAAAAAA==",
"gAAAAAAAAAAAAAAAAAAAAA=="
]);
let d = 3;
let poly_f = Polynomial::from_c_array(&json_f);
let mut factors = edf(poly_f, d);
factors.sort();
let mut result: Vec<Vec<String>> = vec![];
for factor in factors {
result.push(factor.to_c_array())
}
println!("Result: {:?}", result);
assert_eq!(
result,
vec![
[
"iwAAAAAAAAAAAAAAAAAAAA==",
"CAAAAAAAAAAAAAAAAAAAAA==",
"AAAAAAAAAAAAAAAAAAAAAA==",
"gAAAAAAAAAAAAAAAAAAAAA=="
],
[
"kAAAAAAAAAAAAAAAAAAAAA==",
"CAAAAAAAAAAAAAAAAAAAAA==",
"wAAAAAAAAAAAAAAAAAAAAA==",
"gAAAAAAAAAAAAAAAAAAAAA=="
]
]
)
}
}

View file

@ -1,52 +1,259 @@
use base64::prelude::*;
use std::{u128, u8, usize};
use std::{ use std::{
cmp::Ordering, env::args,
ops::{Add, BitXor, Div, Mul}, ops::{Add, BitXor, Div, Mul, Rem, Sub},
result,
}; };
use anyhow::{anyhow, Ok, Result}; use anyhow::{anyhow, Ok, Result};
use base64::prelude::*;
use serde_json::Value;
use super::{ use crate::{tasks::tasks01::poly2block::poly2block, utils::poly::polynomial_2_block};
math::{reverse_bits_in_bytevec, xor_bytes},
poly::gfmul,
};
#[derive(Debug, serde::Serialize, serde::Deserialize)] use super::{math::xor_bytes, poly::gfmul};
#[derive(Debug)]
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(vec![0])]);
}
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(),
)]);
//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;
}
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
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();
}
}
(Polynomial::new(quotient_coeffs), remainder)
}
}
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 {
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 {
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();
}
}
Polynomial::new(polynomial)
}
}
// Helper implementation for subtraction
impl Sub for &FieldElement {
type Output = FieldElement;
fn sub(self, rhs: Self) -> FieldElement {
// In a field of characteristic 2, addition and subtraction are the same operation (XOR)
self + rhs
}
}
// Helper trait for checking emptiness
trait IsEmpty {
fn is_empty(&self) -> bool;
}
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
}
}
#[derive(Debug)]
pub struct FieldElement { pub struct FieldElement {
field_element: Vec<u8>, field_element: Vec<u8>,
} }
impl FieldElement { impl FieldElement {
pub const IRREDUCIBLE_POLYNOMIAL: [u8; 17] = [ pub const IRREDUCIBLE_POLYNOMIAL: [u8; 17] = [
0x87, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 0x01, 87, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 01,
]; ];
pub fn rand() -> Self { pub const fn new(field_element: Vec<u8>) -> Self {
let rand_field: [u8; 16] = rand::random();
FieldElement::new_no_convert(rand_field.to_vec())
}
pub fn zero() -> Self {
FieldElement::new_no_convert(vec![0; 16])
}
pub fn one() -> Self {
FieldElement::new_no_convert(vec![0x01, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0])
}
pub fn to_vec(&self) -> Vec<u8> {
self.field_element.clone()
}
pub fn new(field_element: Vec<u8>) -> Self {
Self {
field_element: reverse_bits_in_bytevec(field_element),
}
}
pub fn new_no_convert(field_element: Vec<u8>) -> Self {
Self { field_element } Self { field_element }
} }
@ -55,60 +262,43 @@ impl FieldElement {
} }
pub fn to_b64(&self) -> String { pub fn to_b64(&self) -> String {
BASE64_STANDARD.encode(reverse_bits_in_bytevec(self.field_element.to_owned())) BASE64_STANDARD.encode(&self.field_element)
} }
pub fn pow(mut self, mut exponent: u128) -> FieldElement { pub fn pow(&self, mut exponent: u128) -> FieldElement {
let mut result: FieldElement = FieldElement::one();
if exponent == 1 {
return self;
}
if exponent == 0 { if exponent == 0 {
let result = FieldElement::one(); // Return polynomial with coefficient 1
return FieldElement::new(vec![1]);
return result;
} }
let base = self.clone();
let mut result = base.clone();
exponent -= 1; // Subtract 1 because we already set result to base
while exponent > 0 { while exponent > 0 {
if exponent & 1 == 1 { result = result * base.clone();
let temp = &self * &result; exponent -= 1;
result = temp
}
let temp_square = &self * &self;
self = temp_square;
exponent >>= 1;
} }
result result
} }
pub fn inv(mut self) -> Self { pub fn inv(mut self) -> Self {
const INVERSER_START: u128 = 0xfffffffffffffffffffffffffffffffe; let mut inverser: u128 = 0xfffffffffffffffffffffffffffffffe;
let mut inverse: Vec<u8> = polynomial_2_block(vec![0], "gcm").unwrap();
let mut inverser = INVERSER_START; //eprintln!("Inverse start {:02X?}", inverse);
let mut inverse: Vec<u8> = vec![0x01, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
while inverser > 0 { while inverser > 0 {
//eprintln!("{:02X}", inverser);
if inverser & 1 == 1 { if inverser & 1 == 1 {
inverse = gfmul(&self.field_element, &inverse, "xex").unwrap(); inverse = gfmul(&self.field_element, &inverse, "gcm").unwrap();
} }
inverser >>= 1; inverser >>= 1;
self.field_element = gfmul(&self.field_element, &self.field_element, "xex") self.field_element = gfmul(&self.field_element, &self.field_element, "gcm")
.expect("Error in sqrmul sqr"); .expect("Error in sqrmul sqr");
} }
FieldElement::new_no_convert(inverse) //eprintln!("Inverse rhs {:?}", inverse);
} FieldElement::new(inverse)
pub fn is_zero(&self) -> bool {
self.field_element.iter().all(|&x| x == 0x00)
}
pub fn reverse_bits(&self) -> Self {
FieldElement::new_no_convert(reverse_bits_in_bytevec(self.field_element.clone()))
} }
} }
@ -116,8 +306,8 @@ impl Mul for FieldElement {
type Output = Self; type Output = Self;
fn mul(self, rhs: Self) -> Self::Output { fn mul(self, rhs: Self) -> Self::Output {
FieldElement::new_no_convert( FieldElement::new(
gfmul(&self.field_element, &rhs.field_element, "xex") gfmul(&self.field_element, &rhs.field_element, "gcm")
.expect("Error during multiplication"), .expect("Error during multiplication"),
) )
} }
@ -127,8 +317,8 @@ impl Mul for &FieldElement {
type Output = FieldElement; type Output = FieldElement;
fn mul(self, rhs: &FieldElement) -> FieldElement { fn mul(self, rhs: &FieldElement) -> FieldElement {
FieldElement::new_no_convert( FieldElement::new(
gfmul(&self.field_element, &rhs.field_element, "xex") gfmul(&self.field_element, &rhs.field_element, "gcm")
.expect("Error during multiplication"), .expect("Error during multiplication"),
) )
} }
@ -137,7 +327,7 @@ impl Mul for &FieldElement {
impl Add for FieldElement { impl Add for FieldElement {
type Output = Self; type Output = Self;
fn add(self, rhs: Self) -> Self::Output { fn add(self, rhs: Self) -> Self::Output {
FieldElement::new_no_convert( FieldElement::new(
xor_bytes(&self.field_element, rhs.field_element).expect("Error in poly add"), xor_bytes(&self.field_element, rhs.field_element).expect("Error in poly add"),
) )
} }
@ -146,7 +336,7 @@ impl Add for FieldElement {
impl Add for &FieldElement { impl Add for &FieldElement {
type Output = FieldElement; type Output = FieldElement;
fn add(self, rhs: Self) -> Self::Output { fn add(self, rhs: Self) -> Self::Output {
FieldElement::new_no_convert( FieldElement::new(
xor_bytes(&self.field_element, rhs.field_element.clone()).expect("Error in poly add"), xor_bytes(&self.field_element, rhs.field_element.clone()).expect("Error in poly add"),
) )
} }
@ -175,15 +365,18 @@ impl BitXor for FieldElement {
.zip(rhs.field_element.iter()) .zip(rhs.field_element.iter())
.map(|(&x1, &x2)| x1 ^ x2) .map(|(&x1, &x2)| x1 ^ x2)
.collect(); .collect();
FieldElement::new_no_convert(result) FieldElement::new(result)
} }
} }
impl Div for FieldElement { impl Div for FieldElement {
type Output = Self; type Output = Self;
fn div(self, rhs: Self) -> Self::Output { fn div(self, rhs: Self) -> Self::Output {
eprintln!("RHS in div{:02X?}", &rhs);
let inverse = rhs.inv(); let inverse = rhs.inv();
self * inverse eprintln!("Inverse in div{:02X?}", inverse);
self.clone() * inverse
} }
} }
@ -191,49 +384,41 @@ impl Div for &FieldElement {
type Output = FieldElement; type Output = FieldElement;
fn div(self, rhs: Self) -> Self::Output { fn div(self, rhs: Self) -> Self::Output {
self.clone() * rhs.clone().inv() // First clone and invert the divisor (rhs)
let rhs_inv = rhs.clone().inv();
// Multiply original number by the inverse
self.clone() * rhs_inv
} }
} }
impl PartialOrd for FieldElement { /*
fn partial_cmp(&self, other: &Self) -> Option<Ordering> { impl Rem for FieldElement {
for (byte_a, byte_b) in self.as_ref().iter().rev().zip(other.as_ref().iter().rev()) { type Output = Self;
if byte_a > byte_b { fn rem(self, rhs: Self) -> Self::Output {
return Some(Ordering::Greater); let result: FieldElement = self.field_element;
} else if byte_a < byte_b {
return Some(Ordering::Less); while self.field_element[15] != 0x00 {
} else { self.field_element
continue;
}
} }
Some(Ordering::Equal) todo!();
} }
} }
*/
impl PartialEq for FieldElement { /*
fn eq(&self, other: &Self) -> bool { impl BitXor for FieldElement {
self.field_element == other.field_element fn bitxor(self, rhs: Self) -> Self::Output {
FieldElement
} }
} }
*/
impl Eq for FieldElement { /*
// add code here impl From<Vec<u8>> for FieldElement {
} fn from(item: Vec<u8>) -> Self {
FieldElement { bytes: item }
impl Ord for FieldElement {
fn cmp(&self, other: &Self) -> Ordering {
for (byte_a, byte_b) in self.as_ref().iter().rev().zip(other.as_ref().iter().rev()) {
if byte_a > byte_b {
return Ordering::Greater;
} else if byte_a < byte_b {
return Ordering::Less;
} else {
continue;
}
}
Ordering::Equal
} }
} }
*/
#[derive(Debug)] #[derive(Debug)]
pub struct ByteArray(pub Vec<u8>); pub struct ByteArray(pub Vec<u8>);
@ -337,12 +522,15 @@ impl ByteArray {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::*; use super::*;
use base64::prelude::*;
use serde_json::json;
use std::fs;
#[test] #[test]
fn test_byte_array_shift1() { fn test_byte_array_shift1() {
let mut byte_array: ByteArray = ByteArray(vec![0x00, 0x01]); let mut byte_array: ByteArray = ByteArray(vec![0x00, 0x01]);
let shifted_array: ByteArray = ByteArray(vec![0x00, 0x02]); let shifted_array: ByteArray = ByteArray(vec![0x00, 0x02]);
byte_array.left_shift("xex").unwrap(); byte_array.left_shift("xex");
assert_eq!(byte_array.0, shifted_array.0); assert_eq!(byte_array.0, shifted_array.0);
} }
@ -351,7 +539,7 @@ mod tests {
fn test_byte_array_shift2() { fn test_byte_array_shift2() {
let mut byte_array: ByteArray = ByteArray(vec![0xFF, 0x00]); let mut byte_array: ByteArray = ByteArray(vec![0xFF, 0x00]);
let shifted_array: ByteArray = ByteArray(vec![0xFE, 0x01]); let shifted_array: ByteArray = ByteArray(vec![0xFE, 0x01]);
byte_array.left_shift("xex").unwrap(); byte_array.left_shift("xex");
assert_eq!( assert_eq!(
byte_array.0, shifted_array.0, byte_array.0, shifted_array.0,
@ -364,7 +552,7 @@ mod tests {
fn test_byte_array_shift1_gcm() { fn test_byte_array_shift1_gcm() {
let mut byte_array: ByteArray = ByteArray(vec![0xFF, 0x00]); let mut byte_array: ByteArray = ByteArray(vec![0xFF, 0x00]);
let shifted_array: ByteArray = ByteArray(vec![0x7F, 0x80]); let shifted_array: ByteArray = ByteArray(vec![0x7F, 0x80]);
byte_array.left_shift("gcm").unwrap(); byte_array.left_shift("gcm");
assert_eq!( assert_eq!(
byte_array.0, shifted_array.0, byte_array.0, shifted_array.0,
@ -377,7 +565,7 @@ mod tests {
fn test_byte_array_shift1_right_gcm() { fn test_byte_array_shift1_right_gcm() {
let mut byte_array: ByteArray = ByteArray(vec![0xFF, 0x00]); let mut byte_array: ByteArray = ByteArray(vec![0xFF, 0x00]);
let shifted_array: ByteArray = ByteArray(vec![0xFE, 0x00]); let shifted_array: ByteArray = ByteArray(vec![0xFE, 0x00]);
byte_array.right_shift("gcm").unwrap(); byte_array.right_shift("gcm");
assert_eq!( assert_eq!(
byte_array.0, shifted_array.0, byte_array.0, shifted_array.0,
@ -390,7 +578,7 @@ mod tests {
fn test_byte_array_shift_right() { fn test_byte_array_shift_right() {
let mut byte_array: ByteArray = ByteArray(vec![0x02]); let mut byte_array: ByteArray = ByteArray(vec![0x02]);
let shifted_array: ByteArray = ByteArray(vec![0x01]); let shifted_array: ByteArray = ByteArray(vec![0x01]);
byte_array.right_shift("xex").unwrap(); byte_array.right_shift("xex");
assert_eq!( assert_eq!(
byte_array.0, shifted_array.0, byte_array.0, shifted_array.0,
@ -439,7 +627,7 @@ mod tests {
FieldElement::new(BASE64_STANDARD.decode("KryptoanalyseAAAAAAAAA==").unwrap()); FieldElement::new(BASE64_STANDARD.decode("KryptoanalyseAAAAAAAAA==").unwrap());
let sum = element2 + element1; let sum = element2 + element1;
assert_eq!(sum.to_b64(), "H1d3GuyA9/0OxeYouUpAAA=="); assert_eq!(BASE64_STANDARD.encode(sum), "H1d3GuyA9/0OxeYouUpAAA==");
} }
#[test] #[test]
@ -450,11 +638,115 @@ mod tests {
FieldElement::new(BASE64_STANDARD.decode("DHBWMannheimAAAAAAAAAA==").unwrap()); FieldElement::new(BASE64_STANDARD.decode("DHBWMannheimAAAAAAAAAA==").unwrap());
let sum = element2 + element1; let sum = element2 + element1;
assert_eq!(sum.to_b64(), "OZuIncPAGEp4tYouDownAA=="); assert_eq!(BASE64_STANDARD.encode(sum), "OZuIncPAGEp4tYouDownAA==");
} }
#[test] #[test]
fn test_field_div_01() { 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_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_field_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_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_poly_div_01() {
let element1 = let element1 =
FieldElement::new(BASE64_STANDARD.decode("JAAAAAAAAAAAAAAAAAAAAA==").unwrap()); FieldElement::new(BASE64_STANDARD.decode("JAAAAAAAAAAAAAAAAAAAAA==").unwrap());
@ -463,6 +755,47 @@ mod tests {
let result = element1 / element2; let result = element1 / element2;
assert_eq!(result.to_b64(), "OAAAAAAAAAAAAAAAAAAAAA=="); 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_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!["XrEhmKuat+Glt5zZWtMo6g=="]);
} }
} }

View file

@ -1,5 +1,7 @@
use anyhow::{Ok, Result}; use anyhow::{anyhow, Ok, Result};
use base64::Engine;
use super::poly::gfmul;
pub fn xor_bytes(vec1: &Vec<u8>, mut vec2: Vec<u8>) -> Result<Vec<u8>> { pub fn xor_bytes(vec1: &Vec<u8>, mut vec2: Vec<u8>) -> Result<Vec<u8>> {
for (byte1, byte2) in vec1.iter().zip(vec2.iter_mut()) { for (byte1, byte2) in vec1.iter().zip(vec2.iter_mut()) {

View file

@ -1,9 +1,6 @@
pub mod ciphers; pub mod ciphers;
pub mod dff;
pub mod edf;
pub mod field; pub mod field;
pub mod math; pub mod math;
pub mod net; pub mod net;
pub mod parse; pub mod parse;
pub mod poly; pub mod poly;
pub mod sff;

View file

@ -8,13 +8,13 @@ pub struct Testcases {
pub testcases: HashMap<String, Testcase>, pub testcases: HashMap<String, Testcase>,
} }
#[derive(Debug, Serialize, Deserialize, Clone)] #[derive(Debug, Serialize, Deserialize)]
pub struct Testcase { pub struct Testcase {
pub action: String, pub action: String,
pub arguments: Value, pub arguments: Value,
} }
#[derive(Debug, Serialize, Deserialize, Clone)] #[derive(Debug, Serialize, Deserialize)]
pub struct Responses { pub struct Responses {
pub responses: HashMap<String, Value>, pub responses: HashMap<String, Value>,
} }
@ -28,6 +28,8 @@ pub fn parse_json(json: String) -> Result<Testcases> {
mod tests { mod tests {
use std::fs; use std::fs;
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::*;

File diff suppressed because it is too large Load diff

View file

@ -1,92 +0,0 @@
use serde::{Deserialize, Serialize};
use crate::utils::{
field::FieldElement,
poly::{gcd, polynomial_2_block},
};
use super::poly::Polynomial;
#[derive(Debug, Serialize, Deserialize)]
pub struct Factors {
pub factor: Vec<String>,
pub exponent: u128,
}
pub fn sff(mut f: Polynomial) -> Vec<(Polynomial, u128)> {
let mut c = gcd(&f, &f.clone().diff());
f = f.div(&c).0;
let mut z: Vec<(Polynomial, u128)> = vec![];
let mut e: u128 = 1;
let one_element = Polynomial::new(vec![FieldElement::new(
polynomial_2_block(vec![0], "gcm").unwrap(),
)]);
while f != one_element {
let y = gcd(&f, &c);
if f != y {
z.push(((f.div(&y).0), e));
}
f = y.clone();
c = c.div(&y).0;
e += 1;
}
if c != one_element {
let r = sff(c.sqrt());
for (f_star, e_star) in r {
z.push((f_star, 2 * e_star));
}
}
z
}
#[cfg(test)]
mod tests {
use serde_json::json;
// Note this useful idiom: importing names from outer (for mod tests) scope.
use super::*;
#[test]
fn byte_indices_0x01() {
let json_f = json!([
"vL77UwAAAAAAAAAAAAAAAA==",
"mEHchYAAAAAAAAAAAAAAAA==",
"9WJa0MAAAAAAAAAAAAAAAA==",
"akHfwWAAAAAAAAAAAAAAAA==",
"E12o/QAAAAAAAAAAAAAAAA==",
"vKJ/FgAAAAAAAAAAAAAAAA==",
"yctWwAAAAAAAAAAAAAAAAA==",
"c1BXYAAAAAAAAAAAAAAAAA==",
"o0AtAAAAAAAAAAAAAAAAAA==",
"AbP2AAAAAAAAAAAAAAAAAA==",
"k2YAAAAAAAAAAAAAAAAAAA==",
"vBYAAAAAAAAAAAAAAAAAAA==",
"dSAAAAAAAAAAAAAAAAAAAA==",
"69gAAAAAAAAAAAAAAAAAAA==",
"VkAAAAAAAAAAAAAAAAAAAA==",
"a4AAAAAAAAAAAAAAAAAAAA==",
"gAAAAAAAAAAAAAAAAAAAAA=="
]);
let poly_f = Polynomial::from_c_array(&json_f);
let mut factors = sff(poly_f);
factors.sort();
let mut result: Vec<Factors> = vec![];
for (factor, exponent) in factors {
result.push(Factors {
factor: factor.to_c_array(),
exponent,
});
}
println!("{:?}", result);
let _bit_indices: Vec<u8> = vec![0];
assert!(false)
}
}

View file

@ -1,29 +0,0 @@
{
"testcases": {
"b856d760-023d-4b00-bad2-15d2b6da22fe": {
"action": "gfpoly_sort",
"arguments": {
"polys": [
[
"NeverGonnaGiveYouUpAAA==",
"NeverGonnaLetYouDownAA==",
"NeverGonnaRunAroundAAA==",
"AndDesertYouAAAAAAAAAA=="
],
[
"WereNoStrangersToLoveA==",
"YouKnowTheRulesAAAAAAA==",
"AndSoDoIAAAAAAAAAAAAAA=="
],
[
"NeverGonnaMakeYouCryAA==",
"NeverGonnaSayGoodbyeAA==",
"NeverGonnaTellALieAAAA==",
"AndHurtYouAAAAAAAAAAAA=="
]
]
}
}
}
}

View file

@ -1,29 +0,0 @@
{
"testcases": {
"gcm_crack1": {
"action": "gcm_crack",
"arguments": {
"nonce": "4gF+BtR3ku/PUQci",
"m1": {
"ciphertext": "CGOkZDnJEt24aVV8mqQq+P4pouVDWhAYj0SN5MDAgg==",
"associated_data": "TmFjaHJpY2h0IDE=",
"tag": "GC9neV3aZLnmznTIWqCC4A=="
},
"m2": {
"ciphertext": "FnWyLSTfRrO8Y1MuhLIs6A==",
"associated_data": "",
"tag": "gb2ph1vzwU85/FsUg51t3Q=="
},
"m3": {
"ciphertext": "CGOkZDnJEt25aV58iaMt6O8+8chKVh0Eg1XFxA==",
"associated_data": "TmFjaHJpY2h0IDM=",
"tag": "+/aDjsAzTseDLuM4jt5Q6Q=="
},
"forgery": {
"ciphertext": "AXe/ZQ==",
"associated_data": ""
}
}
}
}
}