diff --git a/Cargo.toml b/Cargo.toml index 0d58d2b..28fc780 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -12,15 +12,9 @@ serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" num = "0.4" rand = "0.8" -threadpool = "1.8" -num_cpus = "1.16.0" [source.crates-io] replace-with = "vendored-sources" [source.vendored-sources] directory = "vendor" - -[profile.profiling] -inherits = "release" -debug = true diff --git a/src/main.rs b/src/main.rs index 0bb3127..fd69ac4 100644 --- a/src/main.rs +++ b/src/main.rs @@ -14,7 +14,7 @@ fn main() -> Result<()> { let json = fs::read_to_string(path_to_workload).unwrap(); 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)?); Ok(()) diff --git a/src/tasks/mod.rs b/src/tasks/mod.rs index 8a8b782..84a4f31 100644 --- a/src/tasks/mod.rs +++ b/src/tasks/mod.rs @@ -6,7 +6,6 @@ use crate::utils::parse::{Responses, Testcase, Testcases}; use tasks01::{ block2poly::block2poly, gcm::{gcm_decrypt, gcm_encrypt}, - gcm_crack::gcm_crack, gfmul::gfmul_task, pad_oracle::padding_oracle, pfmath::{ @@ -106,7 +105,7 @@ pub fn task_deploy(testcase: &Testcase) -> Result { } "gfdiv" => { let result = gfdiv(args)?; - let out = result.to_b64(); + let out = BASE64_STANDARD.encode(result); let json = json!({"q" : out}); Ok(json) @@ -177,12 +176,6 @@ pub fn task_deploy(testcase: &Testcase) -> Result { Ok(json) } - "gcm_crack" => { - let result = gcm_crack(args)?; - let json = json!(result); - - Ok(json) - } _ => Err(anyhow!( "Fatal. No compatible action found. Json data was {:?}. Arguments were; {:?}", @@ -192,60 +185,16 @@ pub fn task_deploy(testcase: &Testcase) -> Result { } } -fn task_distribute_mt(testcases: &Testcases) -> Result { - eprintln!("USING MULTITHREADED"); - let mut responses: HashMap = 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 { - //eprintln!("USING SINGLETHREADED"); +pub fn task_distrubute(testcases: &Testcases) -> Result { let mut responses: HashMap = HashMap::new(); for (id, testcase) in &testcases.testcases { responses.insert(id.to_owned(), task_deploy(testcase).unwrap()); } - Ok(Responses { responses }) -} - -pub fn task_distribute(testcases: &Testcases) -> Result { - let cpus = num_cpus::get(); - if cpus > 1 { - task_distribute_mt(testcases) - } else { - task_distribute_st(testcases) - } + Ok(Responses { + responses: responses, + }) } #[cfg(test)] @@ -278,7 +227,7 @@ mod tests { let expected = json!({ "responses": { "b856d760-023d-4b00-bad2-15d2b6da22fe": {"block": "ARIAAAAAAAAAAAAAAAAAgA=="}}}); assert_eq!( - serde_json::to_value(task_distribute(&parsed)?).unwrap(), + serde_json::to_value(task_distrubute(&parsed)?).unwrap(), serde_json::to_value(expected).unwrap() ); @@ -302,7 +251,7 @@ mod tests { }); assert_eq!( - serde_json::to_value(task_distribute(&parsed)?).unwrap(), + serde_json::to_value(task_distrubute(&parsed)?).unwrap(), serde_json::to_value(expected).unwrap() ); @@ -317,7 +266,7 @@ mod tests { let expected = json!({ "responses": { "b856d760-023d-4b00-bad2-15d2b6da22fe": {"product": "hSQAAAAAAAAAAAAAAAAAAA=="}}}); assert_eq!( - serde_json::to_value(task_distribute(&parsed)?).unwrap(), + serde_json::to_value(task_distrubute(&parsed)?).unwrap(), serde_json::to_value(expected).unwrap() ); @@ -335,7 +284,7 @@ mod tests { }}); assert_eq!( - serde_json::to_value(task_distribute(&parsed)?).unwrap(), + serde_json::to_value(task_distrubute(&parsed)?).unwrap(), serde_json::to_value(expected).unwrap() ); @@ -355,7 +304,7 @@ mod tests { }}}); assert_eq!( - serde_json::to_value(task_distribute(&parsed)?).unwrap(), + serde_json::to_value(task_distrubute(&parsed)?).unwrap(), serde_json::to_value(expected).unwrap() ); @@ -375,7 +324,7 @@ mod tests { }}}); assert_eq!( - serde_json::to_value(task_distribute(&parsed)?).unwrap(), + serde_json::to_value(task_distrubute(&parsed)?).unwrap(), serde_json::to_value(expected).unwrap() ); @@ -393,7 +342,7 @@ mod tests { }}}); assert_eq!( - serde_json::to_value(task_distribute(&parsed)?).unwrap(), + serde_json::to_value(task_distrubute(&parsed)?).unwrap(), serde_json::to_value(expected).unwrap() ); @@ -411,7 +360,7 @@ mod tests { }}}); assert_eq!( - serde_json::to_value(task_distribute(&parsed)?).unwrap(), + serde_json::to_value(task_distrubute(&parsed)?).unwrap(), serde_json::to_value(expected).unwrap() ); @@ -429,7 +378,7 @@ mod tests { }}}); assert_eq!( - serde_json::to_value(task_distribute(&parsed)?).unwrap(), + serde_json::to_value(task_distrubute(&parsed)?).unwrap(), serde_json::to_value(expected).unwrap() ); diff --git a/src/tasks/tasks01/block2poly.rs b/src/tasks/tasks01/block2poly.rs index 3377bf6..3e636eb 100644 --- a/src/tasks/tasks01/block2poly.rs +++ b/src/tasks/tasks01/block2poly.rs @@ -19,6 +19,7 @@ pub fn block2poly(val: &Value) -> Result> { #[cfg(test)] mod tests { use serde_json::json; + use std::str::FromStr; // Note this useful idiom: importing names from outer (for mod tests) scope. use super::*; diff --git a/src/tasks/tasks01/gcm_crack.rs b/src/tasks/tasks01/gcm_crack.rs deleted file mode 100644 index 09ccb2c..0000000 --- a/src/tasks/tasks01/gcm_crack.rs +++ /dev/null @@ -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, - ad: Vec, - tag: Vec, - l_field: Vec, -} - -fn parse_message(val: &Value) -> Result<(Message, Polynomial)> { - let ciphertext_text: String = serde_json::from_value(val["ciphertext"].clone())?; - let mut ciphertext_bytes: Vec = BASE64_STANDARD.decode(ciphertext_text)?; - let mut c_len: Vec = ((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 = 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 = BASE64_STANDARD.decode(ad_text)?; - let mut l_field: Vec = ((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 = 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 = 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 = - 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 { - // 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 = vec![]; - for (factor, degree) in combine_ddf { - if degree == 1 { - combine_edf.extend(edf(factor, degree as u32)); - } - } - - let mut m3_auth_tag: Vec = vec![]; - let mut h_candidate: FieldElement = FieldElement::zero(); - let mut eky0: Vec = 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), - }) -} diff --git a/src/tasks/tasks01/gfmul.rs b/src/tasks/tasks01/gfmul.rs index 8bca55f..70ab788 100644 --- a/src/tasks/tasks01/gfmul.rs +++ b/src/tasks/tasks01/gfmul.rs @@ -21,6 +21,7 @@ pub fn gfmul_task(args: &Value) -> Result> { #[cfg(test)] mod tests { use serde_json::json; + use std::str::FromStr; // Note this useful idiom: importing names from outer (for mod tests) scope. use super::*; diff --git a/src/tasks/tasks01/mod.rs b/src/tasks/tasks01/mod.rs index 64d24da..8200de5 100644 --- a/src/tasks/tasks01/mod.rs +++ b/src/tasks/tasks01/mod.rs @@ -1,6 +1,5 @@ pub mod block2poly; pub mod gcm; -pub mod gcm_crack; pub mod gfmul; pub mod pad_oracle; pub mod pfmath; diff --git a/src/tasks/tasks01/pad_oracle.rs b/src/tasks/tasks01/pad_oracle.rs index 234babf..4286e37 100644 --- a/src/tasks/tasks01/pad_oracle.rs +++ b/src/tasks/tasks01/pad_oracle.rs @@ -29,7 +29,6 @@ pub fn padding_oracle(args: &Value) -> Result> { for chunk in &cipher_chunks { let mut stream = TcpStream::connect(format!("{}:{}", hostname, port))?; - stream.set_nodelay(true).expect("Error on no delay"); stream.set_nonblocking(false)?; // Track value sent to server @@ -40,6 +39,7 @@ pub fn padding_oracle(args: &Value) -> Result> { let q_block_count: u16 = 256; //Send the first ciphertext chunk + //eprintln!("Sending Ciphertext chunk: {:002X?}", chunk); stream.flush()?; stream.write_all(&chunk)?; stream.flush()?; @@ -49,16 +49,24 @@ pub fn padding_oracle(args: &Value) -> Result> { // FIXME: Assignment is redundant for now // TODO: Goal is to maybe add speed increase in the future 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 // TODO: Collect all and send in one - let mut payload: Vec = Vec::with_capacity(2 + 16 * 265); - payload.extend(l_msg.to_vec()); - for _j in 0..q_block_count { + let mut payload: Vec = l_msg.to_vec(); + for j in 0..q_block_count { // Next byte + //eprintln!("Sending attack block: {:02X?}", attack_counter); + + //thread::sleep(Duration::from_millis(1000)); payload.extend(&attack_counter); + //eprintln!("I in q builder {}", i); attack_counter[i as usize] += 1; } + //eprintln!("Time for qblocks: {:?}", start.elapsed()); stream.write_all(&payload)?; stream.flush()?; @@ -66,6 +74,7 @@ pub fn padding_oracle(args: &Value) -> Result> { // Read server response let mut server_q_resp = [0u8; 256]; stream.read_exact(&mut server_q_resp)?; + //eprintln!("{:02X?}", buf); // extract valid position let valid_val = server_q_resp @@ -75,6 +84,7 @@ pub fn padding_oracle(args: &Value) -> Result> { if valid_val == 0x00 { eprintln!("No valid found in main loop"); } + //eprintln!("Valid value found: {:02X?}", valid_val); // Craft next attack vector padding; 0x01, 0x02, ... attack_counter[i as usize] = valid_val; @@ -88,10 +98,15 @@ pub fn padding_oracle(args: &Value) -> Result> { l_msg_check.extend(check_q_block.as_slice()); stream.write_all(&l_msg_check)?; + //stream.write_all(&check_q_block)?; let mut buf = [0u8; 0x01]; stream.read(&mut buf)?; + //eprintln!("I = {}", i); + //eprintln!("Buffer from pad check: {:02X?}", buf); if buf == [0x01] { + //eprintln!("Valid padding"); } else { + //eprintln!("Invalid padding"); // Search for second hit let valid_val = 255 - server_q_resp @@ -102,21 +117,38 @@ pub fn padding_oracle(args: &Value) -> Result> { if valid_val == 0x00 { eprintln!("No valid found"); } + //eprintln!("Valid value found: {:02X?}", valid_val); // Craft next attack vector padding; 0x01, 0x02, ... attack_counter[i as usize] = valid_val; } } if chunk_counter + 1 < cipher_chunks.len() { + //eprintln!("XOR Next Ciph block"); plaintext.push( cipher_chunks[chunk_counter + 1][i] ^ (attack_counter[i as usize] ^ (15 - i as u8 + 1)), ); } else { + //seprintln!("XOR IV"); + 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; 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); attack_counter[pos as usize] = intermediate ^ ((15 - i as u8 + 1) + 1); @@ -125,10 +157,13 @@ pub fn padding_oracle(args: &Value) -> Result> { stream.flush()?; // Write plaintext + //eprintln!("{:02X?}", plaintext); } chunk_counter += 1; stream.flush()?; + // break; drop(stream); + //eprintln!("Time rest of calc: {:?}", start.elapsed()); } plaintext.reverse(); @@ -140,6 +175,7 @@ pub fn padding_oracle(args: &Value) -> Result> { #[cfg(test)] mod tests { use super::*; + use serde_json::json; #[test] fn test_connection() -> Result<()> { diff --git a/src/tasks/tasks01/pfmath.rs b/src/tasks/tasks01/pfmath.rs index 6830e1a..0f5d134 100644 --- a/src/tasks/tasks01/pfmath.rs +++ b/src/tasks/tasks01/pfmath.rs @@ -1,16 +1,20 @@ +use std::usize; use anyhow::Result; use base64::{prelude::BASE64_STANDARD, Engine}; use serde_json::Value; -use crate::utils::{ +use crate::{ + tasks, + utils::{ self, dff::ddf, edf::edf, field::FieldElement, poly::{gcd, Polynomial}, sff::{sff, Factors}, - }; + }, +}; pub fn gfpoly_add(args: &Value) -> Result { let poly_a = Polynomial::from_c_array(&args["A"].clone()); @@ -122,7 +126,7 @@ pub fn gfpoly_gcd(args: &Value) -> Result { Ok(result) } -pub fn gfpoly_factor_sff(arsg: &Value) -> Result> { +pub fn gfpoly_factor_sff(arsg: &Value) -> Result> { let poly_f = Polynomial::from_c_array(&arsg["F"].clone()); let mut factors = sff(poly_f); @@ -139,7 +143,7 @@ pub fn gfpoly_factor_sff(arsg: &Value) -> Result> { Ok(result) } -pub fn gfpoly_factor_ddf(arsg: &Value) -> Result> { +pub fn gfpoly_factor_ddf(arsg: &Value) -> Result> { let poly_f = Polynomial::from_c_array(&arsg["F"].clone()); let mut factors = ddf(poly_f); diff --git a/src/tasks/tasks01/poly2block.rs b/src/tasks/tasks01/poly2block.rs index 7557981..6d5ad95 100644 --- a/src/tasks/tasks01/poly2block.rs +++ b/src/tasks/tasks01/poly2block.rs @@ -1,4 +1,4 @@ -use crate::utils::poly::polynomial_2_block; +use crate::utils::poly::{polynomial_2_block}; use anyhow::{Ok, Result}; use serde_json::Value; diff --git a/src/tasks/tasks01/sea128.rs b/src/tasks/tasks01/sea128.rs index 2a6a7e2..6d76909 100644 --- a/src/tasks/tasks01/sea128.rs +++ b/src/tasks/tasks01/sea128.rs @@ -6,13 +6,18 @@ use crate::utils::ciphers::{sea_128_decrypt, sea_128_encrypt}; pub fn sea128(args: &Value) -> Result { 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)?; + //eprintln!("{:?}", key); 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 mode: String = serde_json::from_value(args["mode"].clone())?; match mode.as_str() { "encrypt" => { + //eprintln!("{:?}", plaintexts); + let output = BASE64_STANDARD.encode(sea_128_encrypt(&key, &input)?); Ok(output) diff --git a/src/utils/ciphers.rs b/src/utils/ciphers.rs index 0b558af..35181a5 100644 --- a/src/utils/ciphers.rs +++ b/src/utils/ciphers.rs @@ -1,5 +1,6 @@ use crate::utils::{field::ByteArray, poly::gfmul}; use anyhow::Result; +use base64::prelude::*; use openssl::symm::{Cipher, Crypter, Mode}; use super::math::xor_bytes; @@ -118,8 +119,10 @@ pub fn gcm_encrypt_aes( let mut counter: u32 = 1; 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)?; + eprintln!("Y0 {:001X?}", auth_tag_xor); let auth_key_h = aes_128_encrypt(&key, &0u128.to_be_bytes().to_vec())?; @@ -130,6 +133,8 @@ pub fn gcm_encrypt_aes( nonce.drain(12..); nonce.append(counter.to_be_bytes().to_vec().as_mut()); + eprintln!("{:001X?}", nonce); + let inter1 = aes_128_encrypt(&key, &nonce)?; let mut inter2 = xor_bytes(&inter1, chunk.clone())?; @@ -146,6 +151,7 @@ pub fn gcm_encrypt_aes( &ghash(auth_key_h.clone(), ad, ciphertext.clone(), l_field.clone())?, auth_tag_xor, )?; + eprintln!("aes auth tag: {:001X?}", &auth_tag); Ok((ciphertext, auth_tag, l_field, auth_key_h)) } @@ -161,6 +167,8 @@ pub fn gcm_decrypt_aes( let mut counter: u32 = 1; 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)?; @@ -173,6 +181,8 @@ pub fn gcm_decrypt_aes( nonce.drain(12..); nonce.append(counter.to_be_bytes().to_vec().as_mut()); + eprintln!("{:001X?}", nonce); + let inter1 = aes_128_encrypt(&key, &nonce)?; let mut inter2 = xor_bytes(&inter1, chunk.clone())?; @@ -191,6 +201,7 @@ pub fn gcm_decrypt_aes( )?; let valid = auth_tag == tag; + eprintln!("aes auth tag: {:001X?}", auth_tag); Ok((plaintext, valid)) } @@ -206,6 +217,7 @@ pub fn gcm_encrypt_sea( let mut counter: u32 = 1; 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 = sea_128_encrypt(&key, &nonce)?; @@ -218,6 +230,8 @@ pub fn gcm_encrypt_sea( nonce.drain(12..); nonce.append(counter.to_be_bytes().to_vec().as_mut()); + eprintln!("{:001X?}", nonce); + let inter1 = sea_128_encrypt(&key, &nonce)?; let mut inter2 = xor_bytes(&inter1, chunk.clone())?; @@ -249,6 +263,8 @@ pub fn gcm_decrypt_sea( let mut counter: u32 = 1; 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)?; @@ -256,11 +272,17 @@ pub fn gcm_decrypt_sea( let plaintext_chunks: Vec> = ciphertext.chunks(16).map(|x| x.to_vec()).collect(); + eprintln!("{:?}", plaintext_chunks); + counter = 2; for chunk in plaintext_chunks { + eprintln!("Inside loop"); + nonce.drain(12..); nonce.append(counter.to_be_bytes().to_vec().as_mut()); + eprintln!("Nonce 2: {:001X?}", nonce); + let inter1 = sea_128_encrypt(&key, &nonce)?; let mut inter2 = xor_bytes(&inter1, chunk.clone())?; @@ -273,11 +295,15 @@ pub fn gcm_decrypt_sea( let mut c_len: Vec = ((plaintext.len() * 8) as u64).to_be_bytes().to_vec(); l_field.append(c_len.as_mut()); + eprintln!("Ciphertext: {}", BASE64_STANDARD.encode(&ciphertext)); + let auth_tag = xor_bytes( &ghash(auth_key_h.clone(), ad, ciphertext.clone(), l_field.clone())?, auth_tag_xor, )?; + eprintln!("sea dec auth tag: {}", BASE64_STANDARD.encode(&auth_tag)); + let valid = auth_tag == tag; Ok((plaintext, valid)) @@ -291,6 +317,10 @@ pub fn ghash( ) -> Result> { let output: Vec = 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() { ad.append(vec![0u8; 16 - (ad.len() % 16)].as_mut()); } @@ -299,12 +329,20 @@ pub fn ghash( ciphertext.append(vec![0u8; 16 - (ciphertext.len() % 16)].as_mut()); } + eprintln!("{:001X?}", ad); + eprintln!("{:001X?}", ciphertext); + 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 mut inter_loop = gfmul(&inter1, &auth_key_h, "gcm")?; + eprintln!("Ad chunks after first next {:001X?}", 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())?; inter_loop = gfmul(&inter2, &auth_key_h, "gcm")?; } @@ -319,9 +357,18 @@ pub fn ghash( let inter4 = xor_bytes(&inter_loop, l_field)?; inter_loop = gfmul(&inter4, &auth_key_h, "gcm")?; + eprintln!("GHASH auth tag: {:001X?}", inter_loop); + Ok(inter_loop) } +/* +* let mut bytes: [u8; 16] = [0u8; 16]; + bytes.copy_from_slice(&ciphertext); + let number: u128 = ::from_be_bytes(bytes); + +* */ + #[cfg(test)] mod tests { use super::*; diff --git a/src/utils/dff.rs b/src/utils/dff.rs index 21dde69..be63040 100644 --- a/src/utils/dff.rs +++ b/src/utils/dff.rs @@ -1,6 +1,6 @@ use std::usize; -use num::{pow::Pow, BigUint, FromPrimitive}; +use num::{cast::AsPrimitive, pow::Pow, traits::ToBytes, BigUint, FromPrimitive}; use serde::{Deserialize, Serialize}; use super::poly::{gcd, Polynomial}; @@ -25,14 +25,20 @@ pub fn ddf(f: Polynomial) -> Vec<(Polynomial, u128)> { let g = gcd(&h, &f_star); if g != one_cmp { + eprintln!("d is: {}", d); + eprintln!("g is: {:?}", &g.clone().to_c_array()); + z.push((g.clone(), d)); f_star = f_star.div(&g).0; } + eprintln!("d outer is: {}", d); + eprintln!("F star degree is {:?}", &f_star.degree()); d += 1; } if f_star != one_cmp { + eprintln!("fstar not one"); z.push((f_star.clone(), f_star.degree() as u128)); } else if z.len() == 0 { z.push((f.clone(), 1)); @@ -75,7 +81,7 @@ mod tests { } println!("Result: {:?}", result); - let _bit_indices: Vec = vec![0]; + let bit_indices: Vec = vec![0]; assert!(false) } } diff --git a/src/utils/edf.rs b/src/utils/edf.rs index dfb59cf..134a743 100644 --- a/src/utils/edf.rs +++ b/src/utils/edf.rs @@ -1,25 +1,42 @@ -use num::{BigUint, FromPrimitive, One}; +use base64::{prelude::BASE64_STANDARD, Engine}; +use num::{BigUint, FromPrimitive, Integer, One}; use rand::Rng; +use crate::utils::{field::FieldElement, poly::non_monic_gcd}; + use super::poly::{gcd, Polynomial}; pub fn edf(f: Polynomial, d: u32) -> Vec { + eprintln!("Starting edf"); + let q = BigUint::pow(&BigUint::from_u8(2).unwrap(), 128); let n: u32 = (f.degree() as u32) / (d); let mut z: Vec = 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())); + //eprintln!("z len {}", z.len()); + //eprintln!("n len {}", n); + + let h = Polynomial::rand(&rand::thread_rng().gen_range(0..f.degree())); + //eprintln!("h: {:02X?}", h); let exponent = (q.pow(d) - BigUint::one()) / BigUint::from_u8(3).unwrap(); + eprintln!("q before for {:0X?}", exponent); let g = h.bpow_mod(exponent, &f) + Polynomial::one(); + //eprintln!("g before for {:0X?}", g); - for i in (0..z.len()).rev() { + //eprintln!("z before for {:0X?}", z); + + for i in 0..z.len() { if z[i].degree() as u32 > d { + //eprintln!("Inside if"); let j = gcd(&z[i], &g); + + eprintln!("j: {:02X?}", j); if j != one_cmp && j != z[i] { + eprintln!("Working on Z"); let intemediate = z[i].div(&j).0; z.remove(i); z.push(j.clone()); @@ -27,6 +44,8 @@ pub fn edf(f: Polynomial, d: u32) -> Vec { } } } + + //eprintln!("z after for {:0X?}", z); } z diff --git a/src/utils/field.rs b/src/utils/field.rs index 739b466..2dea48b 100644 --- a/src/utils/field.rs +++ b/src/utils/field.rs @@ -1,4 +1,5 @@ use base64::prelude::*; +use rand::{random, Rng, RngCore}; use std::{u128, u8, usize}; use std::{ @@ -8,6 +9,7 @@ use std::{ use anyhow::{anyhow, Ok, Result}; +use super::poly::polynomial_2_block; use super::{ math::{reverse_bits_in_bytevec, xor_bytes}, poly::gfmul, @@ -20,33 +22,19 @@ pub struct FieldElement { impl FieldElement { 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 { let rand_field: [u8; 16] = rand::random(); - FieldElement::new_no_convert(rand_field.to_vec()) + FieldElement::new(rand_field.to_vec()) } - pub fn zero() -> Self { - FieldElement::new_no_convert(vec![0; 16]) + pub fn zero(self) -> Self { + FieldElement::new(vec![0]) } - 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 { - self.field_element.clone() - } - - pub fn new(field_element: Vec) -> Self { - Self { - field_element: reverse_bits_in_bytevec(field_element), - } - } - - pub fn new_no_convert(field_element: Vec) -> Self { + pub const fn new(field_element: Vec) -> Self { Self { field_element } } @@ -55,52 +43,68 @@ impl FieldElement { } 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 { - let mut result: FieldElement = FieldElement::one(); + let mut result: FieldElement = + FieldElement::new(polynomial_2_block(vec![0], "gcm").unwrap()); if exponent == 1 { + eprintln!("special case 1: {:02X?}", self.clone()); + return self; } if exponent == 0 { - let result = FieldElement::one(); + let result = 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!("Mult"); + //eprintln!("After mod: {:?}", temp); result = temp } let temp_square = &self * &self; + // eprintln!("Square"); + // eprintln!("After squaring: {:?}", temp_square); self = temp_square; + //eprintln!("After mod: {:?}", self); exponent >>= 1; } + // eprintln!("result in powmod before reduction: {:02X?}", result); + + // eprintln!("result in powmod after reduction: {:02X?}", result); + result } pub fn inv(mut self) -> Self { - const INVERSER_START: u128 = 0xfffffffffffffffffffffffffffffffe; - - let mut inverser = INVERSER_START; - let mut inverse: Vec = vec![0x01, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]; + let mut inverser: u128 = 0xfffffffffffffffffffffffffffffffe; + let mut inverse: Vec = polynomial_2_block(vec![0], "gcm").unwrap(); + //eprintln!("Inverse start {:02X?}", inverse); while inverser > 0 { + //eprintln!("{:02X}", inverser); if inverser & 1 == 1 { - inverse = gfmul(&self.field_element, &inverse, "xex").unwrap(); + inverse = gfmul(&self.field_element, &inverse, "gcm").unwrap(); } 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"); } - FieldElement::new_no_convert(inverse) + //eprintln!("Inverse rhs {:?}", inverse); + FieldElement::new(inverse) } pub fn is_zero(&self) -> bool { @@ -108,7 +112,7 @@ impl FieldElement { } pub fn reverse_bits(&self) -> Self { - FieldElement::new_no_convert(reverse_bits_in_bytevec(self.field_element.clone())) + FieldElement::new(reverse_bits_in_bytevec(self.field_element.clone())) } } @@ -116,8 +120,8 @@ impl Mul for FieldElement { type Output = Self; fn mul(self, rhs: Self) -> Self::Output { - FieldElement::new_no_convert( - gfmul(&self.field_element, &rhs.field_element, "xex") + FieldElement::new( + gfmul(&self.field_element, &rhs.field_element, "gcm") .expect("Error during multiplication"), ) } @@ -127,8 +131,8 @@ impl Mul for &FieldElement { type Output = FieldElement; fn mul(self, rhs: &FieldElement) -> FieldElement { - FieldElement::new_no_convert( - gfmul(&self.field_element, &rhs.field_element, "xex") + FieldElement::new( + gfmul(&self.field_element, &rhs.field_element, "gcm") .expect("Error during multiplication"), ) } @@ -137,7 +141,7 @@ impl Mul for &FieldElement { impl Add for FieldElement { type Output = Self; 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"), ) } @@ -146,7 +150,7 @@ impl Add for FieldElement { impl Add for &FieldElement { type Output = FieldElement; 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"), ) } @@ -175,7 +179,7 @@ impl BitXor for FieldElement { .zip(rhs.field_element.iter()) .map(|(&x1, &x2)| x1 ^ x2) .collect(); - FieldElement::new_no_convert(result) + FieldElement::new(result) } } @@ -183,7 +187,7 @@ impl Div for FieldElement { type Output = Self; fn div(self, rhs: Self) -> Self::Output { let inverse = rhs.inv(); - self * inverse + self.clone() * inverse } } @@ -191,7 +195,10 @@ impl Div for &FieldElement { type Output = FieldElement; 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 } } @@ -337,6 +344,7 @@ impl ByteArray { #[cfg(test)] mod tests { use super::*; + use serde_json::json; #[test] fn test_byte_array_shift1() { @@ -439,7 +447,7 @@ mod tests { FieldElement::new(BASE64_STANDARD.decode("KryptoanalyseAAAAAAAAA==").unwrap()); let sum = element2 + element1; - assert_eq!(sum.to_b64(), "H1d3GuyA9/0OxeYouUpAAA=="); + assert_eq!(BASE64_STANDARD.encode(sum), "H1d3GuyA9/0OxeYouUpAAA=="); } #[test] @@ -450,19 +458,6 @@ mod tests { FieldElement::new(BASE64_STANDARD.decode("DHBWMannheimAAAAAAAAAA==").unwrap()); let sum = element2 + element1; - assert_eq!(sum.to_b64(), "OZuIncPAGEp4tYouDownAA=="); - } - - #[test] - fn test_field_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!(result.to_b64(), "OAAAAAAAAAAAAAAAAAAAAA=="); + assert_eq!(BASE64_STANDARD.encode(sum), "OZuIncPAGEp4tYouDownAA=="); } } diff --git a/src/utils/parse.rs b/src/utils/parse.rs index 4b71b29..6e5d2dd 100644 --- a/src/utils/parse.rs +++ b/src/utils/parse.rs @@ -8,13 +8,13 @@ pub struct Testcases { pub testcases: HashMap, } -#[derive(Debug, Serialize, Deserialize, Clone)] +#[derive(Debug, Serialize, Deserialize)] pub struct Testcase { pub action: String, pub arguments: Value, } -#[derive(Debug, Serialize, Deserialize, Clone)] +#[derive(Debug, Serialize, Deserialize)] pub struct Responses { pub responses: HashMap, } diff --git a/src/utils/poly.rs b/src/utils/poly.rs index 6a61853..48242ab 100644 --- a/src/utils/poly.rs +++ b/src/utils/poly.rs @@ -1,14 +1,12 @@ use crate::utils::field::ByteArray; +use base64::alphabet::BIN_HEX; use base64::prelude::*; - -use num::traits::FromBytes; -use num::{BigUint, One, Zero}; - +use num::{BigInt, BigUint, One, Zero}; use std::{str::FromStr, u128, u8, usize}; use std::{ cmp::Ordering, - ops::{Add, Mul}, + ops::{Add, Div, Mul}, }; use anyhow::{anyhow, Ok, Result}; @@ -30,18 +28,16 @@ impl Polynomial { self.polynomial.len() - 1 } - pub fn empty() -> Polynomial { - Polynomial::new(vec![]) - } - pub fn one() -> Self { - Polynomial::new(vec![FieldElement::one()]) + Polynomial::new(vec![FieldElement::new( + polynomial_2_block(vec![0], "gcm").unwrap(), + )]) } pub fn x() -> Self { Polynomial::new(vec![ FieldElement::new(vec![0; 16]), - FieldElement::new(polynomial_2_block(vec![0], "xex").unwrap()), + FieldElement::new(polynomial_2_block(vec![0], "gcm").unwrap()), ]) } @@ -55,7 +51,7 @@ impl Polynomial { } pub fn zero() -> Self { - Polynomial::new(vec![FieldElement::zero()]) + Polynomial::new(vec![FieldElement::new(vec![0; 16])]) } pub fn from_c_array(array: &Value) -> Self { @@ -71,6 +67,8 @@ impl Polynomial { }) .collect(); + eprintln!("{:?}", c_array); + for coefficient in c_array { polynomial.push(FieldElement::new( BASE64_STANDARD @@ -84,7 +82,7 @@ impl Polynomial { pub fn to_c_array(self) -> Vec { let mut output: Vec = vec![]; for coeff in self.polynomial { - output.push(coeff.to_b64()); + output.push(BASE64_STANDARD.encode(coeff)); } output @@ -96,6 +94,8 @@ impl Polynomial { )]); if exponent == 1 { + eprintln!("special case 1: {:02X?}", self.clone()); + return self; } @@ -104,21 +104,31 @@ impl Polynomial { 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!("Mult"); + //eprintln!("After mod: {:?}", temp); result = temp } let temp_square = &self * &self; + //eprintln!("Square"); + //eprintln!("After squaring: {:?}", temp_square); self = temp_square; + //eprintln!("After mod: {:?}", self); exponent >>= 1; } + //eprintln!("result in powmod before reduction: {:02X?}", result); + while !result.polynomial.is_empty() && result .polynomial @@ -131,8 +141,10 @@ impl Polynomial { result.polynomial.pop(); } + //eprintln!("result in powmod after reduction: {:02X?}", result); + if result.is_empty() { - result = Polynomial::zero(); + result = Polynomial::new(vec![FieldElement::new(vec![0; 16])]); } result @@ -144,6 +156,8 @@ impl Polynomial { )]); if exponent == BigUint::one() { + eprintln!("special case 1: {:02X?}", self.clone().div(&modulus).1); + return self.div(&modulus).1; } @@ -152,16 +166,23 @@ impl Polynomial { polynomial_2_block(vec![0], "gcm").unwrap(), )]); + eprintln!("Returned value is: {:02X?}", result); return result; } + //eprintln!("Initial result: {:?}", result); while &exponent > &BigUint::zero() { + //eprintln!("Current exponent: {:02X}", exponent); if &exponent & BigUint::one() == BigUint::one() { 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; } @@ -178,7 +199,7 @@ impl Polynomial { } if result.is_empty() { - result = Polynomial::zero(); + result = Polynomial::new(vec![FieldElement::new(vec![0; 16])]); } result @@ -189,25 +210,38 @@ impl Polynomial { )]); 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::one()]); + 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 @@ -220,16 +254,26 @@ impl Polynomial { result.polynomial.pop(); } + eprintln!("result in powmod after reduction: {:02X?}", result); + if result.is_empty() { - result = Polynomial::zero(); + 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::zero()]), self.clone()); + return ( + Polynomial::new(vec![FieldElement::new(vec![0; 16])]), + self.clone(), + ); } let mut remainder = self.clone(); @@ -238,36 +282,57 @@ impl Polynomial { let divisor_deg = divisor.polynomial.len() - 1; if dividend_deg < divisor_deg { - return (Polynomial::new(vec![FieldElement::zero()]), remainder); + return ( + Polynomial::new(vec![FieldElement::new( + polynomial_2_block(vec![0; 16], "gcm").unwrap(), + )]), + remainder, + ); } - let mut quotient_coeffs = vec![FieldElement::zero(); dividend_deg - divisor_deg + 1]; + 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 pos; - for (i, divisor_coeff) in divisor.polynomial.iter().enumerate() { - pos = deg_diff + i; - let a: &FieldElement = &remainder.polynomial[pos]; - let c: &FieldElement = "_coeff; - remainder.polynomial[pos] = a + &(divisor_coeff * c); - } + 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); - while !remainder.polynomial.is_empty() && remainder.polynomial.last().unwrap().is_zero() + 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::zero(); + remainder = Polynomial::new(vec![FieldElement::new(vec![0; 16])]); } - (Polynomial::new(quotient_coeffs), remainder) } @@ -353,10 +418,6 @@ impl Polynomial { self } - - pub fn extract_component(&self, i: u32) -> FieldElement { - self.polynomial[i as usize].clone() - } } impl Clone for Polynomial { @@ -371,10 +432,10 @@ impl Mul for Polynomial { type Output = Self; fn mul(self, rhs: Self) -> Self::Output { if self.is_zero() || rhs.is_zero() { - return Polynomial::zero(); + return Polynomial::new(vec![FieldElement::new(vec![0; 16])]); } let mut polynomial: Vec = - vec![FieldElement::zero(); self.polynomial.len() + rhs.polynomial.len() - 1]; + 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] @@ -389,10 +450,10 @@ impl Mul for &Polynomial { type Output = Polynomial; fn mul(self, rhs: Self) -> Self::Output { if self.is_zero() || rhs.is_zero() { - return Polynomial::zero(); + return Polynomial::new(vec![FieldElement::new(vec![0])]); } let mut polynomial: Vec = - vec![FieldElement::zero(); self.polynomial.len() + rhs.polynomial.len() - 1]; + 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] @@ -426,7 +487,7 @@ impl Add for Polynomial { } if polynomial.is_empty() { - return Polynomial::new(vec![FieldElement::zero()]); + return Polynomial::new(vec![FieldElement::new(vec![0; 16])]); } Polynomial::new(polynomial) @@ -468,9 +529,15 @@ impl PartialOrd for Polynomial { 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() + .partial_cmp(&field_b.reverse_bits()) .unwrap() { Ordering::Equal => continue, @@ -493,10 +560,7 @@ impl Ord for Polynomial { 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) - { + match field_a.reverse_bits().cmp(&field_b.reverse_bits()) { Ordering::Equal => continue, other => return other, } @@ -512,21 +576,9 @@ pub fn gcd(a: &Polynomial, b: &Polynomial) -> Polynomial { if a.is_zero() { return b.clone(); } - if b.is_zero() { - return a.clone(); - } - if a.degree() > b.degree() { - return gcd(b, a); - } - - let (_, remainder) = b.div(a); - - if remainder.is_zero() { - return a.clone().monic(); - } - - gcd(&remainder, a) + let monic_b = b.div(&a).1.monic(); + return gcd(&monic_b, a); } pub fn non_monic_gcd(a: &Polynomial, b: &Polynomial) -> Polynomial { @@ -550,18 +602,21 @@ pub fn sort_polynomial_array(mut polys: Vec) -> Result, poly_b: &Vec, semantic: &str) -> Result> { - let red_poly_bytes: ByteArray = ByteArray(RED_POLY.to_be_bytes().to_vec()); + let mut red_poly_bytes: ByteArray = ByteArray(RED_POLY.to_be_bytes().to_vec()); + red_poly_bytes.0.push(0x01); - let mut poly1: ByteArray = ByteArray(poly_a.to_vec()); + let mut poly1: ByteArray = ByteArray(poly_a.to_owned()); + poly1.0.push(0x00); - let mut poly2: ByteArray = ByteArray(poly_b.to_vec()); + let mut poly2: ByteArray = ByteArray(poly_b.to_owned()); + poly2.0.push(0x00); if semantic == "gcm" { poly1.reverse_bits_in_bytevec(); poly2.reverse_bits_in_bytevec(); } - let mut result: ByteArray = ByteArray(vec![0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]); + let mut result: ByteArray = ByteArray(vec![0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]); if poly2.LSB_is_one() { result.xor_byte_arrays(&poly1); @@ -569,9 +624,9 @@ pub fn gfmul(poly_a: &Vec, poly_b: &Vec, semantic: &str) -> Result, poly_b: &Vec, semantic: &str) -> Result) -> Result> { pub fn get_alpha_rep(num: u128) -> String { let powers: Vec = get_coefficients(num); + //println!("{:?}", powers); + let mut alpha_rep = String::new(); if powers.len() == 1 { @@ -629,6 +686,7 @@ pub fn b64_2_num(string: &String) -> Result { pub fn get_coefficients(num: u128) -> Vec { let mut powers: Vec = vec![]; for shift in 0..128 { + //println!("{:?}", ((num >> shift) & 1)); if ((num >> shift) & 1) == 1 { powers.push(shift); } @@ -725,7 +783,7 @@ pub fn coefficient_to_binary(coefficients: Vec) -> u128 { #[cfg(test)] mod tests { - use crate::utils::poly::{b64_2_num, gcd}; + use crate::utils::poly::b64_2_num; use anyhow::Result; use serde_json::json; // Note this useful idiom: importing names from outer (for mod tests) scope. @@ -755,7 +813,7 @@ mod tests { #[test] fn coeff_to_binary() { let coefficients: Vec = vec![12, 127, 9, 0]; - let _b64: &str = "ARIAAAAAAAAAAAAAAAAAgA=="; + let b64: &str = "ARIAAAAAAAAAAAAAAAAAgA=="; let calculated_num: u128 = coefficient_to_binary(coefficients); assert_eq!( BASE64_STANDARD.encode(calculated_num.to_ne_bytes()), @@ -1020,6 +1078,19 @@ mod tests { //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!([ @@ -1346,17 +1417,4 @@ mod tests { assert_eq!(json!(result.to_c_array()), expected); } - - #[test] - fn test_poly_gcd_stress() { - eprintln!("{:?}", Polynomial::one()); - - let poly1 = Polynomial::rand(&(500 as usize)); - let poly2 = Polynomial::rand(&(500 as usize)); - - let result = gcd(&poly1.monic(), &poly2.monic()); - - eprintln!("{:02X?}", result.to_c_array()); - assert!(true); - } } diff --git a/src/utils/sff.rs b/src/utils/sff.rs index de2bef6..e7a154a 100644 --- a/src/utils/sff.rs +++ b/src/utils/sff.rs @@ -86,7 +86,7 @@ mod tests { } println!("{:?}", result); - let _bit_indices: Vec = vec![0]; + let bit_indices: Vec = vec![0]; assert!(false) } } diff --git a/test_json/sandbox.json b/test_json/sandbox.json index e3f5e1f..d0a0f3c 100644 --- a/test_json/sandbox.json +++ b/test_json/sandbox.json @@ -1,29 +1,19 @@ { - "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": "" - } - } - } + "testcases": { + "sandbox": { + "action": "gfpoly_factor_ddf", + "arguments": { + "F": [ + "tpkgAAAAAAAAAAAAAAAAAA==", + "m6MQAAAAAAAAAAAAAAAAAA==", + "8roAAAAAAAAAAAAAAAAAAA==", + "3dUAAAAAAAAAAAAAAAAAAA==", + "FwAAAAAAAAAAAAAAAAAAAA==", + "/kAAAAAAAAAAAAAAAAAAAA==", + "a4AAAAAAAAAAAAAAAAAAAA==", + "gAAAAAAAAAAAAAAAAAAAAA==" + ] + } } + } }