Compare commits
38 commits
feat_poly_
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
bec16d090e | ||
|
|
0a573d84da | ||
|
|
848ad15bb8 | ||
|
|
c9c26b3971 | ||
|
|
b24c703429 | ||
|
|
2f0e265ed6 | ||
|
|
0da047110f | ||
|
|
6d1b735a0b | ||
|
|
7a0d1219f9 | ||
|
|
90d61a655e | ||
|
|
555ee45aad | ||
|
|
9e31b6cc5b | ||
|
|
6a2f631e46 | ||
|
|
274b65c6fd | ||
|
|
b348c19c6c | ||
|
|
b632e0c803 | ||
|
|
4c9adb9fdc | ||
|
|
16b65b0de4 | ||
|
|
e8f4a58732 | ||
|
|
e2ef29bfd5 | ||
|
|
7fa3586e49 | ||
|
|
8064dcb9e8 | ||
|
|
3687733b7f | ||
|
|
8f0356e2ba | ||
|
|
7dbcf20891 | ||
|
|
60d73968fb | ||
|
|
2623bd9a8d | ||
|
|
bf4c3ee4ca | ||
|
|
007bbddfcd | ||
|
|
12254744d4 | ||
|
|
679c0223af | ||
|
|
c24d47e4b6 | ||
|
|
e8c9cb1ade | ||
|
|
5b27a4ad9c | ||
|
|
e934d4317f | ||
|
|
270abdb7b7 | ||
|
|
dd19c90ae1 | ||
|
|
c0685e9b7b |
19 changed files with 425 additions and 355 deletions
|
|
@ -12,9 +12,15 @@ serde = { version = "1.0", features = ["derive"] }
|
||||||
serde_json = "1.0"
|
serde_json = "1.0"
|
||||||
num = "0.4"
|
num = "0.4"
|
||||||
rand = "0.8"
|
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
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,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_distrubute(&workload)?;
|
let response = kauma::tasks::task_distribute(&workload)?;
|
||||||
println!("{}", serde_json::to_string(&response)?);
|
println!("{}", serde_json::to_string(&response)?);
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@ use crate::utils::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::{
|
||||||
|
|
@ -105,7 +106,7 @@ pub fn task_deploy(testcase: &Testcase) -> Result<Value> {
|
||||||
}
|
}
|
||||||
"gfdiv" => {
|
"gfdiv" => {
|
||||||
let result = gfdiv(args)?;
|
let result = gfdiv(args)?;
|
||||||
let out = BASE64_STANDARD.encode(result);
|
let out = result.to_b64();
|
||||||
let json = json!({"q" : out});
|
let json = json!({"q" : out});
|
||||||
|
|
||||||
Ok(json)
|
Ok(json)
|
||||||
|
|
@ -176,6 +177,12 @@ pub fn task_deploy(testcase: &Testcase) -> Result<Value> {
|
||||||
|
|
||||||
Ok(json)
|
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; {:?}",
|
||||||
|
|
@ -185,16 +192,60 @@ pub fn task_deploy(testcase: &Testcase) -> Result<Value> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn task_distrubute(testcases: &Testcases) -> Result<Responses> {
|
fn task_distribute_mt(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 {
|
Ok(Responses { 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)]
|
||||||
|
|
@ -227,7 +278,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_distrubute(&parsed)?).unwrap(),
|
serde_json::to_value(task_distribute(&parsed)?).unwrap(),
|
||||||
serde_json::to_value(expected).unwrap()
|
serde_json::to_value(expected).unwrap()
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
@ -251,7 +302,7 @@ mod tests {
|
||||||
});
|
});
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
serde_json::to_value(task_distrubute(&parsed)?).unwrap(),
|
serde_json::to_value(task_distribute(&parsed)?).unwrap(),
|
||||||
serde_json::to_value(expected).unwrap()
|
serde_json::to_value(expected).unwrap()
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
@ -266,7 +317,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_distrubute(&parsed)?).unwrap(),
|
serde_json::to_value(task_distribute(&parsed)?).unwrap(),
|
||||||
serde_json::to_value(expected).unwrap()
|
serde_json::to_value(expected).unwrap()
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
@ -284,7 +335,7 @@ mod tests {
|
||||||
}});
|
}});
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
serde_json::to_value(task_distrubute(&parsed)?).unwrap(),
|
serde_json::to_value(task_distribute(&parsed)?).unwrap(),
|
||||||
serde_json::to_value(expected).unwrap()
|
serde_json::to_value(expected).unwrap()
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
@ -304,7 +355,7 @@ mod tests {
|
||||||
}}});
|
}}});
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
serde_json::to_value(task_distrubute(&parsed)?).unwrap(),
|
serde_json::to_value(task_distribute(&parsed)?).unwrap(),
|
||||||
serde_json::to_value(expected).unwrap()
|
serde_json::to_value(expected).unwrap()
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
@ -324,7 +375,7 @@ mod tests {
|
||||||
}}});
|
}}});
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
serde_json::to_value(task_distrubute(&parsed)?).unwrap(),
|
serde_json::to_value(task_distribute(&parsed)?).unwrap(),
|
||||||
serde_json::to_value(expected).unwrap()
|
serde_json::to_value(expected).unwrap()
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
@ -342,7 +393,7 @@ mod tests {
|
||||||
}}});
|
}}});
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
serde_json::to_value(task_distrubute(&parsed)?).unwrap(),
|
serde_json::to_value(task_distribute(&parsed)?).unwrap(),
|
||||||
serde_json::to_value(expected).unwrap()
|
serde_json::to_value(expected).unwrap()
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
@ -360,7 +411,7 @@ mod tests {
|
||||||
}}});
|
}}});
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
serde_json::to_value(task_distrubute(&parsed)?).unwrap(),
|
serde_json::to_value(task_distribute(&parsed)?).unwrap(),
|
||||||
serde_json::to_value(expected).unwrap()
|
serde_json::to_value(expected).unwrap()
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
@ -378,7 +429,7 @@ mod tests {
|
||||||
}}});
|
}}});
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
serde_json::to_value(task_distrubute(&parsed)?).unwrap(),
|
serde_json::to_value(task_distribute(&parsed)?).unwrap(),
|
||||||
serde_json::to_value(expected).unwrap()
|
serde_json::to_value(expected).unwrap()
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -19,7 +19,6 @@ 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::*;
|
||||||
|
|
|
||||||
174
src/tasks/tasks01/gcm_crack.rs
Normal file
174
src/tasks/tasks01/gcm_crack.rs
Normal file
|
|
@ -0,0 +1,174 @@
|
||||||
|
|
||||||
|
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),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
@ -21,7 +21,6 @@ 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::*;
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
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;
|
||||||
|
|
|
||||||
|
|
@ -29,6 +29,7 @@ pub fn padding_oracle(args: &Value) -> Result<Vec<u8>> {
|
||||||
|
|
||||||
for chunk in &cipher_chunks {
|
for chunk in &cipher_chunks {
|
||||||
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
|
||||||
|
|
@ -39,7 +40,6 @@ 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,24 +49,16 @@ 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> = l_msg.to_vec();
|
let mut payload: Vec<u8> = Vec::with_capacity(2 + 16 * 265);
|
||||||
for j in 0..q_block_count {
|
payload.extend(l_msg.to_vec());
|
||||||
|
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()?;
|
||||||
|
|
@ -74,7 +66,6 @@ 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
|
||||||
|
|
@ -84,7 +75,6 @@ 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;
|
||||||
|
|
||||||
|
|
@ -98,15 +88,10 @@ 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
|
||||||
|
|
@ -117,38 +102,21 @@ pub fn padding_oracle(args: &Value) -> Result<Vec<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);
|
||||||
|
|
@ -157,13 +125,10 @@ 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();
|
||||||
|
|
@ -175,7 +140,6 @@ 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<()> {
|
||||||
|
|
|
||||||
|
|
@ -1,20 +1,16 @@
|
||||||
use std::usize;
|
|
||||||
|
|
||||||
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::{
|
use crate::utils::{
|
||||||
tasks,
|
|
||||||
utils::{
|
|
||||||
self,
|
self,
|
||||||
dff::ddf,
|
dff::ddf,
|
||||||
edf::edf,
|
edf::edf,
|
||||||
field::FieldElement,
|
field::FieldElement,
|
||||||
poly::{gcd, Polynomial},
|
poly::{gcd, Polynomial},
|
||||||
sff::{sff, Factors},
|
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());
|
||||||
|
|
@ -126,7 +122,7 @@ pub fn gfpoly_gcd(args: &Value) -> Result<Polynomial> {
|
||||||
Ok(result)
|
Ok(result)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn gfpoly_factor_sff(arsg: &Value) -> Result<Vec<(Factors)>> {
|
pub fn gfpoly_factor_sff(arsg: &Value) -> Result<Vec<Factors>> {
|
||||||
let poly_f = Polynomial::from_c_array(&arsg["F"].clone());
|
let poly_f = Polynomial::from_c_array(&arsg["F"].clone());
|
||||||
|
|
||||||
let mut factors = sff(poly_f);
|
let mut factors = sff(poly_f);
|
||||||
|
|
@ -143,7 +139,7 @@ pub fn gfpoly_factor_sff(arsg: &Value) -> Result<Vec<(Factors)>> {
|
||||||
Ok(result)
|
Ok(result)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn gfpoly_factor_ddf(arsg: &Value) -> Result<Vec<(utils::dff::Factors)>> {
|
pub fn gfpoly_factor_ddf(arsg: &Value) -> Result<Vec<utils::dff::Factors>> {
|
||||||
let poly_f = Polynomial::from_c_array(&arsg["F"].clone());
|
let poly_f = Polynomial::from_c_array(&arsg["F"].clone());
|
||||||
|
|
||||||
let mut factors = ddf(poly_f);
|
let mut factors = ddf(poly_f);
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
use crate::utils::poly::{polynomial_2_block};
|
use crate::utils::poly::polynomial_2_block;
|
||||||
use anyhow::{Ok, Result};
|
use anyhow::{Ok, Result};
|
||||||
use serde_json::Value;
|
use serde_json::Value;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -6,18 +6,13 @@ 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 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)
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,5 @@
|
||||||
use crate::utils::{field::ByteArray, poly::gfmul};
|
use crate::utils::{field::ByteArray, 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;
|
||||||
|
|
@ -119,10 +118,8 @@ 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())?;
|
||||||
|
|
||||||
|
|
@ -133,8 +130,6 @@ 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())?;
|
||||||
|
|
@ -151,7 +146,6 @@ 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))
|
||||||
}
|
}
|
||||||
|
|
@ -167,8 +161,6 @@ 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)?;
|
||||||
|
|
||||||
|
|
@ -181,8 +173,6 @@ 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())?;
|
||||||
|
|
@ -201,7 +191,6 @@ 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))
|
||||||
}
|
}
|
||||||
|
|
@ -217,7 +206,6 @@ 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)?;
|
||||||
|
|
||||||
|
|
@ -230,8 +218,6 @@ 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())?;
|
||||||
|
|
@ -263,8 +249,6 @@ 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)?;
|
||||||
|
|
||||||
|
|
@ -272,17 +256,11 @@ 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())?;
|
||||||
|
|
@ -295,15 +273,11 @@ 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))
|
||||||
|
|
@ -317,10 +291,6 @@ 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());
|
||||||
}
|
}
|
||||||
|
|
@ -329,20 +299,12 @@ 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")?;
|
||||||
}
|
}
|
||||||
|
|
@ -357,18 +319,9 @@ 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::*;
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
use std::usize;
|
use std::usize;
|
||||||
|
|
||||||
use num::{cast::AsPrimitive, pow::Pow, traits::ToBytes, BigUint, FromPrimitive};
|
use num::{pow::Pow, BigUint, FromPrimitive};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
use super::poly::{gcd, Polynomial};
|
use super::poly::{gcd, Polynomial};
|
||||||
|
|
@ -25,20 +25,14 @@ pub fn ddf(f: Polynomial) -> Vec<(Polynomial, u128)> {
|
||||||
|
|
||||||
let g = gcd(&h, &f_star);
|
let g = gcd(&h, &f_star);
|
||||||
if g != one_cmp {
|
if g != one_cmp {
|
||||||
eprintln!("d is: {}", d);
|
|
||||||
eprintln!("g is: {:?}", &g.clone().to_c_array());
|
|
||||||
|
|
||||||
z.push((g.clone(), d));
|
z.push((g.clone(), d));
|
||||||
f_star = f_star.div(&g).0;
|
f_star = f_star.div(&g).0;
|
||||||
}
|
}
|
||||||
eprintln!("d outer is: {}", d);
|
|
||||||
eprintln!("F star degree is {:?}", &f_star.degree());
|
|
||||||
|
|
||||||
d += 1;
|
d += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if f_star != one_cmp {
|
if f_star != one_cmp {
|
||||||
eprintln!("fstar not one");
|
|
||||||
z.push((f_star.clone(), f_star.degree() as u128));
|
z.push((f_star.clone(), f_star.degree() as u128));
|
||||||
} else if z.len() == 0 {
|
} else if z.len() == 0 {
|
||||||
z.push((f.clone(), 1));
|
z.push((f.clone(), 1));
|
||||||
|
|
@ -81,7 +75,7 @@ mod tests {
|
||||||
}
|
}
|
||||||
|
|
||||||
println!("Result: {:?}", result);
|
println!("Result: {:?}", result);
|
||||||
let bit_indices: Vec<u8> = vec![0];
|
let _bit_indices: Vec<u8> = vec![0];
|
||||||
assert!(false)
|
assert!(false)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,42 +1,25 @@
|
||||||
use base64::{prelude::BASE64_STANDARD, Engine};
|
use num::{BigUint, FromPrimitive, One};
|
||||||
use num::{BigUint, FromPrimitive, Integer, One};
|
|
||||||
use rand::Rng;
|
use rand::Rng;
|
||||||
|
|
||||||
use crate::utils::{field::FieldElement, poly::non_monic_gcd};
|
|
||||||
|
|
||||||
use super::poly::{gcd, Polynomial};
|
use super::poly::{gcd, Polynomial};
|
||||||
|
|
||||||
pub fn edf(f: Polynomial, d: u32) -> Vec<Polynomial> {
|
pub fn edf(f: Polynomial, d: u32) -> Vec<Polynomial> {
|
||||||
eprintln!("Starting edf");
|
|
||||||
|
|
||||||
let q = BigUint::pow(&BigUint::from_u8(2).unwrap(), 128);
|
let q = BigUint::pow(&BigUint::from_u8(2).unwrap(), 128);
|
||||||
let n: u32 = (f.degree() as u32) / (d);
|
let n: u32 = (f.degree() as u32) / (d);
|
||||||
let mut z: Vec<Polynomial> = vec![f.clone()];
|
let mut z: Vec<Polynomial> = vec![f.clone()];
|
||||||
let one_cmp = Polynomial::one();
|
let one_cmp = Polynomial::one();
|
||||||
|
|
||||||
while (z.len() as u32) < n {
|
while (z.len() as u32) < n {
|
||||||
//eprintln!("z len {}", z.len());
|
let h = Polynomial::rand(&rand::thread_rng().gen_range(1..=f.degree()));
|
||||||
//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();
|
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();
|
let g = h.bpow_mod(exponent, &f) + Polynomial::one();
|
||||||
//eprintln!("g before for {:0X?}", g);
|
|
||||||
|
|
||||||
//eprintln!("z before for {:0X?}", z);
|
for i in (0..z.len()).rev() {
|
||||||
|
|
||||||
for i in 0..z.len() {
|
|
||||||
if z[i].degree() as u32 > d {
|
if z[i].degree() as u32 > d {
|
||||||
//eprintln!("Inside if");
|
|
||||||
let j = gcd(&z[i], &g);
|
let j = gcd(&z[i], &g);
|
||||||
|
|
||||||
eprintln!("j: {:02X?}", j);
|
|
||||||
if j != one_cmp && j != z[i] {
|
if j != one_cmp && j != z[i] {
|
||||||
eprintln!("Working on Z");
|
|
||||||
let intemediate = z[i].div(&j).0;
|
let intemediate = z[i].div(&j).0;
|
||||||
z.remove(i);
|
z.remove(i);
|
||||||
z.push(j.clone());
|
z.push(j.clone());
|
||||||
|
|
@ -44,8 +27,6 @@ pub fn edf(f: Polynomial, d: u32) -> Vec<Polynomial> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//eprintln!("z after for {:0X?}", z);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
z
|
z
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,4 @@
|
||||||
use base64::prelude::*;
|
use base64::prelude::*;
|
||||||
use rand::{random, Rng, RngCore};
|
|
||||||
use std::{u128, u8, usize};
|
use std::{u128, u8, usize};
|
||||||
|
|
||||||
use std::{
|
use std::{
|
||||||
|
|
@ -9,7 +8,6 @@ use std::{
|
||||||
|
|
||||||
use anyhow::{anyhow, Ok, Result};
|
use anyhow::{anyhow, Ok, Result};
|
||||||
|
|
||||||
use super::poly::polynomial_2_block;
|
|
||||||
use super::{
|
use super::{
|
||||||
math::{reverse_bits_in_bytevec, xor_bytes},
|
math::{reverse_bits_in_bytevec, xor_bytes},
|
||||||
poly::gfmul,
|
poly::gfmul,
|
||||||
|
|
@ -22,19 +20,33 @@ pub struct FieldElement {
|
||||||
|
|
||||||
impl FieldElement {
|
impl FieldElement {
|
||||||
pub const IRREDUCIBLE_POLYNOMIAL: [u8; 17] = [
|
pub const IRREDUCIBLE_POLYNOMIAL: [u8; 17] = [
|
||||||
87, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 01,
|
0x87, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 0x01,
|
||||||
];
|
];
|
||||||
|
|
||||||
pub fn rand() -> Self {
|
pub fn rand() -> Self {
|
||||||
let rand_field: [u8; 16] = rand::random();
|
let rand_field: [u8; 16] = rand::random();
|
||||||
FieldElement::new(rand_field.to_vec())
|
FieldElement::new_no_convert(rand_field.to_vec())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn zero(self) -> Self {
|
pub fn zero() -> Self {
|
||||||
FieldElement::new(vec![0])
|
FieldElement::new_no_convert(vec![0; 16])
|
||||||
}
|
}
|
||||||
|
|
||||||
pub const fn new(field_element: Vec<u8>) -> Self {
|
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 }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -43,68 +55,52 @@ impl FieldElement {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn to_b64(&self) -> String {
|
pub fn to_b64(&self) -> String {
|
||||||
BASE64_STANDARD.encode(&self.field_element)
|
BASE64_STANDARD.encode(reverse_bits_in_bytevec(self.field_element.to_owned()))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn pow(mut self, mut exponent: u128) -> FieldElement {
|
pub fn pow(mut self, mut exponent: u128) -> FieldElement {
|
||||||
let mut result: FieldElement =
|
let mut result: FieldElement = FieldElement::one();
|
||||||
FieldElement::new(polynomial_2_block(vec![0], "gcm").unwrap());
|
|
||||||
|
|
||||||
if exponent == 1 {
|
if exponent == 1 {
|
||||||
eprintln!("special case 1: {:02X?}", self.clone());
|
|
||||||
|
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
|
||||||
if exponent == 0 {
|
if exponent == 0 {
|
||||||
let result = FieldElement::new(polynomial_2_block(vec![0], "gcm").unwrap());
|
let result = FieldElement::one();
|
||||||
|
|
||||||
eprintln!("Returned value is: {:02X?}", result);
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
//eprintln!("Initial result: {:?}", result);
|
|
||||||
while exponent > 0 {
|
while exponent > 0 {
|
||||||
//eprintln!("Current exponent: {:02X}", exponent);
|
|
||||||
if exponent & 1 == 1 {
|
if exponent & 1 == 1 {
|
||||||
let temp = &self * &result;
|
let temp = &self * &result;
|
||||||
//eprintln!("Mult");
|
|
||||||
//eprintln!("After mod: {:?}", temp);
|
|
||||||
|
|
||||||
result = temp
|
result = temp
|
||||||
}
|
}
|
||||||
let temp_square = &self * &self;
|
let temp_square = &self * &self;
|
||||||
// eprintln!("Square");
|
|
||||||
|
|
||||||
// eprintln!("After squaring: {:?}", temp_square);
|
|
||||||
self = temp_square;
|
self = temp_square;
|
||||||
//eprintln!("After mod: {:?}", self);
|
|
||||||
exponent >>= 1;
|
exponent >>= 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// eprintln!("result in powmod before reduction: {:02X?}", result);
|
|
||||||
|
|
||||||
// eprintln!("result in powmod after reduction: {:02X?}", result);
|
|
||||||
|
|
||||||
result
|
result
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn inv(mut self) -> Self {
|
pub fn inv(mut self) -> Self {
|
||||||
let mut inverser: u128 = 0xfffffffffffffffffffffffffffffffe;
|
const INVERSER_START: u128 = 0xfffffffffffffffffffffffffffffffe;
|
||||||
let mut inverse: Vec<u8> = polynomial_2_block(vec![0], "gcm").unwrap();
|
|
||||||
//eprintln!("Inverse start {:02X?}", inverse);
|
let mut inverser = INVERSER_START;
|
||||||
|
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, "gcm").unwrap();
|
inverse = gfmul(&self.field_element, &inverse, "xex").unwrap();
|
||||||
}
|
}
|
||||||
inverser >>= 1;
|
inverser >>= 1;
|
||||||
self.field_element = gfmul(&self.field_element, &self.field_element, "gcm")
|
self.field_element = gfmul(&self.field_element, &self.field_element, "xex")
|
||||||
.expect("Error in sqrmul sqr");
|
.expect("Error in sqrmul sqr");
|
||||||
}
|
}
|
||||||
//eprintln!("Inverse rhs {:?}", inverse);
|
FieldElement::new_no_convert(inverse)
|
||||||
FieldElement::new(inverse)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn is_zero(&self) -> bool {
|
pub fn is_zero(&self) -> bool {
|
||||||
|
|
@ -112,7 +108,7 @@ impl FieldElement {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn reverse_bits(&self) -> Self {
|
pub fn reverse_bits(&self) -> Self {
|
||||||
FieldElement::new(reverse_bits_in_bytevec(self.field_element.clone()))
|
FieldElement::new_no_convert(reverse_bits_in_bytevec(self.field_element.clone()))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -120,8 +116,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(
|
FieldElement::new_no_convert(
|
||||||
gfmul(&self.field_element, &rhs.field_element, "gcm")
|
gfmul(&self.field_element, &rhs.field_element, "xex")
|
||||||
.expect("Error during multiplication"),
|
.expect("Error during multiplication"),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
@ -131,8 +127,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(
|
FieldElement::new_no_convert(
|
||||||
gfmul(&self.field_element, &rhs.field_element, "gcm")
|
gfmul(&self.field_element, &rhs.field_element, "xex")
|
||||||
.expect("Error during multiplication"),
|
.expect("Error during multiplication"),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
@ -141,7 +137,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(
|
FieldElement::new_no_convert(
|
||||||
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"),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
@ -150,7 +146,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(
|
FieldElement::new_no_convert(
|
||||||
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"),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
@ -179,7 +175,7 @@ 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(result)
|
FieldElement::new_no_convert(result)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -187,7 +183,7 @@ impl Div for FieldElement {
|
||||||
type Output = Self;
|
type Output = Self;
|
||||||
fn div(self, rhs: Self) -> Self::Output {
|
fn div(self, rhs: Self) -> Self::Output {
|
||||||
let inverse = rhs.inv();
|
let inverse = rhs.inv();
|
||||||
self.clone() * inverse
|
self * inverse
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -195,10 +191,7 @@ impl Div for &FieldElement {
|
||||||
type Output = FieldElement;
|
type Output = FieldElement;
|
||||||
|
|
||||||
fn div(self, rhs: Self) -> Self::Output {
|
fn div(self, rhs: Self) -> Self::Output {
|
||||||
// First clone and invert the divisor (rhs)
|
self.clone() * rhs.clone().inv()
|
||||||
let rhs_inv = rhs.clone().inv();
|
|
||||||
// Multiply original number by the inverse
|
|
||||||
self.clone() * rhs_inv
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -344,7 +337,6 @@ impl ByteArray {
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
use serde_json::json;
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_byte_array_shift1() {
|
fn test_byte_array_shift1() {
|
||||||
|
|
@ -447,7 +439,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!(BASE64_STANDARD.encode(sum), "H1d3GuyA9/0OxeYouUpAAA==");
|
assert_eq!(sum.to_b64(), "H1d3GuyA9/0OxeYouUpAAA==");
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|
@ -458,6 +450,19 @@ 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!(BASE64_STANDARD.encode(sum), "OZuIncPAGEp4tYouDownAA==");
|
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==");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -8,13 +8,13 @@ pub struct Testcases {
|
||||||
pub testcases: HashMap<String, Testcase>,
|
pub testcases: HashMap<String, Testcase>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Serialize, Deserialize)]
|
#[derive(Debug, Serialize, Deserialize, Clone)]
|
||||||
pub struct Testcase {
|
pub struct Testcase {
|
||||||
pub action: String,
|
pub action: String,
|
||||||
pub arguments: Value,
|
pub arguments: Value,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Serialize, Deserialize)]
|
#[derive(Debug, Serialize, Deserialize, Clone)]
|
||||||
pub struct Responses {
|
pub struct Responses {
|
||||||
pub responses: HashMap<String, Value>,
|
pub responses: HashMap<String, Value>,
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,14 @@
|
||||||
use crate::utils::field::ByteArray;
|
use crate::utils::field::ByteArray;
|
||||||
use base64::alphabet::BIN_HEX;
|
|
||||||
use base64::prelude::*;
|
use base64::prelude::*;
|
||||||
use num::{BigInt, BigUint, One, Zero};
|
|
||||||
|
use num::traits::FromBytes;
|
||||||
|
use num::{BigUint, One, Zero};
|
||||||
|
|
||||||
use std::{str::FromStr, u128, u8, usize};
|
use std::{str::FromStr, u128, u8, usize};
|
||||||
|
|
||||||
use std::{
|
use std::{
|
||||||
cmp::Ordering,
|
cmp::Ordering,
|
||||||
ops::{Add, Div, Mul},
|
ops::{Add, Mul},
|
||||||
};
|
};
|
||||||
|
|
||||||
use anyhow::{anyhow, Ok, Result};
|
use anyhow::{anyhow, Ok, Result};
|
||||||
|
|
@ -28,16 +30,18 @@ impl Polynomial {
|
||||||
self.polynomial.len() - 1
|
self.polynomial.len() - 1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn empty() -> Polynomial {
|
||||||
|
Polynomial::new(vec![])
|
||||||
|
}
|
||||||
|
|
||||||
pub fn one() -> Self {
|
pub fn one() -> Self {
|
||||||
Polynomial::new(vec![FieldElement::new(
|
Polynomial::new(vec![FieldElement::one()])
|
||||||
polynomial_2_block(vec![0], "gcm").unwrap(),
|
|
||||||
)])
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn x() -> Self {
|
pub fn x() -> Self {
|
||||||
Polynomial::new(vec![
|
Polynomial::new(vec![
|
||||||
FieldElement::new(vec![0; 16]),
|
FieldElement::new(vec![0; 16]),
|
||||||
FieldElement::new(polynomial_2_block(vec![0], "gcm").unwrap()),
|
FieldElement::new(polynomial_2_block(vec![0], "xex").unwrap()),
|
||||||
])
|
])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -51,7 +55,7 @@ impl Polynomial {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn zero() -> Self {
|
pub fn zero() -> Self {
|
||||||
Polynomial::new(vec![FieldElement::new(vec![0; 16])])
|
Polynomial::new(vec![FieldElement::zero()])
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn from_c_array(array: &Value) -> Self {
|
pub fn from_c_array(array: &Value) -> Self {
|
||||||
|
|
@ -67,8 +71,6 @@ impl Polynomial {
|
||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
eprintln!("{:?}", c_array);
|
|
||||||
|
|
||||||
for coefficient in c_array {
|
for coefficient in c_array {
|
||||||
polynomial.push(FieldElement::new(
|
polynomial.push(FieldElement::new(
|
||||||
BASE64_STANDARD
|
BASE64_STANDARD
|
||||||
|
|
@ -82,7 +84,7 @@ impl Polynomial {
|
||||||
pub fn to_c_array(self) -> Vec<String> {
|
pub fn to_c_array(self) -> Vec<String> {
|
||||||
let mut output: Vec<String> = vec![];
|
let mut output: Vec<String> = vec![];
|
||||||
for coeff in self.polynomial {
|
for coeff in self.polynomial {
|
||||||
output.push(BASE64_STANDARD.encode(coeff));
|
output.push(coeff.to_b64());
|
||||||
}
|
}
|
||||||
|
|
||||||
output
|
output
|
||||||
|
|
@ -94,8 +96,6 @@ impl Polynomial {
|
||||||
)]);
|
)]);
|
||||||
|
|
||||||
if exponent == 1 {
|
if exponent == 1 {
|
||||||
eprintln!("special case 1: {:02X?}", self.clone());
|
|
||||||
|
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -104,31 +104,21 @@ impl Polynomial {
|
||||||
polynomial_2_block(vec![0], "gcm").unwrap(),
|
polynomial_2_block(vec![0], "gcm").unwrap(),
|
||||||
)]);
|
)]);
|
||||||
|
|
||||||
eprintln!("Returned value is: {:02X?}", result);
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
//eprintln!("Initial result: {:?}", result);
|
|
||||||
while exponent > 0 {
|
while exponent > 0 {
|
||||||
//eprintln!("Current exponent: {:02X}", exponent);
|
|
||||||
if exponent & 1 == 1 {
|
if exponent & 1 == 1 {
|
||||||
let temp = &self * &result;
|
let temp = &self * &result;
|
||||||
//eprintln!("Mult");
|
|
||||||
//eprintln!("After mod: {:?}", temp);
|
|
||||||
|
|
||||||
result = temp
|
result = temp
|
||||||
}
|
}
|
||||||
let temp_square = &self * &self;
|
let temp_square = &self * &self;
|
||||||
//eprintln!("Square");
|
|
||||||
|
|
||||||
//eprintln!("After squaring: {:?}", temp_square);
|
|
||||||
self = temp_square;
|
self = temp_square;
|
||||||
//eprintln!("After mod: {:?}", self);
|
|
||||||
exponent >>= 1;
|
exponent >>= 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
//eprintln!("result in powmod before reduction: {:02X?}", result);
|
|
||||||
|
|
||||||
while !result.polynomial.is_empty()
|
while !result.polynomial.is_empty()
|
||||||
&& result
|
&& result
|
||||||
.polynomial
|
.polynomial
|
||||||
|
|
@ -141,10 +131,8 @@ impl Polynomial {
|
||||||
result.polynomial.pop();
|
result.polynomial.pop();
|
||||||
}
|
}
|
||||||
|
|
||||||
//eprintln!("result in powmod after reduction: {:02X?}", result);
|
|
||||||
|
|
||||||
if result.is_empty() {
|
if result.is_empty() {
|
||||||
result = Polynomial::new(vec![FieldElement::new(vec![0; 16])]);
|
result = Polynomial::zero();
|
||||||
}
|
}
|
||||||
|
|
||||||
result
|
result
|
||||||
|
|
@ -156,8 +144,6 @@ impl Polynomial {
|
||||||
)]);
|
)]);
|
||||||
|
|
||||||
if exponent == BigUint::one() {
|
if exponent == BigUint::one() {
|
||||||
eprintln!("special case 1: {:02X?}", self.clone().div(&modulus).1);
|
|
||||||
|
|
||||||
return self.div(&modulus).1;
|
return self.div(&modulus).1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -166,23 +152,16 @@ impl Polynomial {
|
||||||
polynomial_2_block(vec![0], "gcm").unwrap(),
|
polynomial_2_block(vec![0], "gcm").unwrap(),
|
||||||
)]);
|
)]);
|
||||||
|
|
||||||
eprintln!("Returned value is: {:02X?}", result);
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
//eprintln!("Initial result: {:?}", result);
|
|
||||||
while &exponent > &BigUint::zero() {
|
while &exponent > &BigUint::zero() {
|
||||||
//eprintln!("Current exponent: {:02X}", exponent);
|
|
||||||
if &exponent & BigUint::one() == BigUint::one() {
|
if &exponent & BigUint::one() == BigUint::one() {
|
||||||
let temp = &self * &result;
|
let temp = &self * &result;
|
||||||
//eprintln!("After multiplication: {:?}", temp);
|
|
||||||
result = temp.div(&modulus).1;
|
result = temp.div(&modulus).1;
|
||||||
//eprintln!("After mod: {:?}", result);
|
|
||||||
}
|
}
|
||||||
let temp_square = &self * &self;
|
let temp_square = &self * &self;
|
||||||
//eprintln!("After squaring: {:?}", temp_square);
|
|
||||||
self = temp_square.div(&modulus).1;
|
self = temp_square.div(&modulus).1;
|
||||||
//eprintln!("After mod: {:?}", self);
|
|
||||||
exponent >>= 1;
|
exponent >>= 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -199,7 +178,7 @@ impl Polynomial {
|
||||||
}
|
}
|
||||||
|
|
||||||
if result.is_empty() {
|
if result.is_empty() {
|
||||||
result = Polynomial::new(vec![FieldElement::new(vec![0; 16])]);
|
result = Polynomial::zero();
|
||||||
}
|
}
|
||||||
|
|
||||||
result
|
result
|
||||||
|
|
@ -210,38 +189,25 @@ impl Polynomial {
|
||||||
)]);
|
)]);
|
||||||
|
|
||||||
if exponent == 1 {
|
if exponent == 1 {
|
||||||
eprintln!("special case 1: {:02X?}", self.clone().div(&modulus).1);
|
|
||||||
|
|
||||||
return self.div(&modulus).1;
|
return self.div(&modulus).1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if exponent == 0 {
|
if exponent == 0 {
|
||||||
let result = Polynomial::new(vec![FieldElement::new(
|
let result = Polynomial::new(vec![FieldElement::one()]);
|
||||||
polynomial_2_block(vec![0], "gcm").unwrap(),
|
|
||||||
)]);
|
|
||||||
|
|
||||||
eprintln!("Returned value is: {:02X?}", result);
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
//eprintln!("Initial result: {:?}", result);
|
|
||||||
while exponent > 0 {
|
while exponent > 0 {
|
||||||
//eprintln!("Current exponent: {:02X}", exponent);
|
|
||||||
if exponent & 1 == 1 {
|
if exponent & 1 == 1 {
|
||||||
let temp = &self * &result;
|
let temp = &self * &result;
|
||||||
//eprintln!("After multiplication: {:?}", temp);
|
|
||||||
result = temp.div(&modulus).1;
|
result = temp.div(&modulus).1;
|
||||||
//eprintln!("After mod: {:?}", result);
|
|
||||||
}
|
}
|
||||||
let temp_square = &self * &self;
|
let temp_square = &self * &self;
|
||||||
//eprintln!("After squaring: {:?}", temp_square);
|
|
||||||
self = temp_square.div(&modulus).1;
|
self = temp_square.div(&modulus).1;
|
||||||
//eprintln!("After mod: {:?}", self);
|
|
||||||
exponent >>= 1;
|
exponent >>= 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
eprintln!("result in powmod before reduction: {:02X?}", result);
|
|
||||||
|
|
||||||
while !result.polynomial.is_empty()
|
while !result.polynomial.is_empty()
|
||||||
&& result
|
&& result
|
||||||
.polynomial
|
.polynomial
|
||||||
|
|
@ -254,26 +220,16 @@ impl Polynomial {
|
||||||
result.polynomial.pop();
|
result.polynomial.pop();
|
||||||
}
|
}
|
||||||
|
|
||||||
eprintln!("result in powmod after reduction: {:02X?}", result);
|
|
||||||
|
|
||||||
if result.is_empty() {
|
if result.is_empty() {
|
||||||
result = Polynomial::new(vec![FieldElement::new(vec![0; 16])]);
|
result = Polynomial::zero();
|
||||||
}
|
}
|
||||||
|
|
||||||
result
|
result
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns (quotient, remainder)
|
|
||||||
pub fn div(&self, rhs: &Self) -> (Self, Self) {
|
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() {
|
if self.polynomial.len() < rhs.polynomial.len() {
|
||||||
return (
|
return (Polynomial::new(vec![FieldElement::zero()]), self.clone());
|
||||||
Polynomial::new(vec![FieldElement::new(vec![0; 16])]),
|
|
||||||
self.clone(),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut remainder = self.clone();
|
let mut remainder = self.clone();
|
||||||
|
|
@ -282,57 +238,36 @@ impl Polynomial {
|
||||||
let divisor_deg = divisor.polynomial.len() - 1;
|
let divisor_deg = divisor.polynomial.len() - 1;
|
||||||
|
|
||||||
if dividend_deg < divisor_deg {
|
if dividend_deg < divisor_deg {
|
||||||
return (
|
return (Polynomial::new(vec![FieldElement::zero()]), remainder);
|
||||||
Polynomial::new(vec![FieldElement::new(
|
|
||||||
polynomial_2_block(vec![0; 16], "gcm").unwrap(),
|
|
||||||
)]),
|
|
||||||
remainder,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut quotient_coeffs =
|
let mut quotient_coeffs = vec![FieldElement::zero(); dividend_deg - divisor_deg + 1];
|
||||||
vec![
|
|
||||||
FieldElement::new(polynomial_2_block(vec![0; 16], "gcm").unwrap());
|
|
||||||
dividend_deg - divisor_deg + 1
|
|
||||||
];
|
|
||||||
|
|
||||||
while remainder.polynomial.len() >= divisor.polynomial.len() {
|
while remainder.polynomial.len() >= divisor.polynomial.len() {
|
||||||
let deg_diff = remainder.polynomial.len() - divisor.polynomial.len();
|
let deg_diff = remainder.polynomial.len() - divisor.polynomial.len();
|
||||||
|
|
||||||
let leading_dividend = remainder.polynomial.last().unwrap();
|
let leading_dividend = remainder.polynomial.last().unwrap();
|
||||||
let leading_divisor = divisor.polynomial.last().unwrap();
|
let leading_divisor = divisor.polynomial.last().unwrap();
|
||||||
let quot_coeff = leading_dividend / leading_divisor;
|
let quot_coeff = leading_dividend / leading_divisor;
|
||||||
|
|
||||||
quotient_coeffs[deg_diff] = quot_coeff.clone();
|
quotient_coeffs[deg_diff] = quot_coeff.clone();
|
||||||
|
|
||||||
let mut subtrahend =
|
let mut pos;
|
||||||
vec![FieldElement::new(polynomial_2_block(vec![0; 16], "gcm").unwrap()); deg_diff];
|
for (i, divisor_coeff) in divisor.polynomial.iter().enumerate() {
|
||||||
subtrahend.extend(
|
pos = deg_diff + i;
|
||||||
divisor
|
let a: &FieldElement = &remainder.polynomial[pos];
|
||||||
.polynomial
|
let c: &FieldElement = "_coeff;
|
||||||
.iter()
|
remainder.polynomial[pos] = a + &(divisor_coeff * c);
|
||||||
.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().is_zero()
|
||||||
|
|
||||||
while !remainder.polynomial.is_empty()
|
|
||||||
&& remainder
|
|
||||||
.polynomial
|
|
||||||
.last()
|
|
||||||
.unwrap()
|
|
||||||
.as_ref()
|
|
||||||
.iter()
|
|
||||||
.all(|&x| x == 0)
|
|
||||||
{
|
{
|
||||||
remainder.polynomial.pop();
|
remainder.polynomial.pop();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if remainder.is_empty() {
|
if remainder.is_empty() {
|
||||||
remainder = Polynomial::new(vec![FieldElement::new(vec![0; 16])]);
|
remainder = Polynomial::zero();
|
||||||
}
|
}
|
||||||
|
|
||||||
(Polynomial::new(quotient_coeffs), remainder)
|
(Polynomial::new(quotient_coeffs), remainder)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -418,6 +353,10 @@ impl Polynomial {
|
||||||
|
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn extract_component(&self, i: u32) -> FieldElement {
|
||||||
|
self.polynomial[i as usize].clone()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Clone for Polynomial {
|
impl Clone for Polynomial {
|
||||||
|
|
@ -432,10 +371,10 @@ impl Mul for Polynomial {
|
||||||
type Output = Self;
|
type Output = Self;
|
||||||
fn mul(self, rhs: Self) -> Self::Output {
|
fn mul(self, rhs: Self) -> Self::Output {
|
||||||
if self.is_zero() || rhs.is_zero() {
|
if self.is_zero() || rhs.is_zero() {
|
||||||
return Polynomial::new(vec![FieldElement::new(vec![0; 16])]);
|
return Polynomial::zero();
|
||||||
}
|
}
|
||||||
let mut polynomial: Vec<FieldElement> =
|
let mut polynomial: Vec<FieldElement> =
|
||||||
vec![FieldElement::new(vec![0; 16]); self.polynomial.len() + rhs.polynomial.len() - 1];
|
vec![FieldElement::zero(); self.polynomial.len() + rhs.polynomial.len() - 1];
|
||||||
for i in 0..self.polynomial.len() {
|
for i in 0..self.polynomial.len() {
|
||||||
for j in 0..rhs.polynomial.len() {
|
for j in 0..rhs.polynomial.len() {
|
||||||
polynomial[i + j] = &polynomial[i + j]
|
polynomial[i + j] = &polynomial[i + j]
|
||||||
|
|
@ -450,10 +389,10 @@ impl Mul for &Polynomial {
|
||||||
type Output = Polynomial;
|
type Output = Polynomial;
|
||||||
fn mul(self, rhs: Self) -> Self::Output {
|
fn mul(self, rhs: Self) -> Self::Output {
|
||||||
if self.is_zero() || rhs.is_zero() {
|
if self.is_zero() || rhs.is_zero() {
|
||||||
return Polynomial::new(vec![FieldElement::new(vec![0])]);
|
return Polynomial::zero();
|
||||||
}
|
}
|
||||||
let mut polynomial: Vec<FieldElement> =
|
let mut polynomial: Vec<FieldElement> =
|
||||||
vec![FieldElement::new(vec![0; 16]); self.polynomial.len() + rhs.polynomial.len() - 1];
|
vec![FieldElement::zero(); self.polynomial.len() + rhs.polynomial.len() - 1];
|
||||||
for i in 0..self.polynomial.len() {
|
for i in 0..self.polynomial.len() {
|
||||||
for j in 0..rhs.polynomial.len() {
|
for j in 0..rhs.polynomial.len() {
|
||||||
polynomial[i + j] = &polynomial[i + j]
|
polynomial[i + j] = &polynomial[i + j]
|
||||||
|
|
@ -487,7 +426,7 @@ impl Add for Polynomial {
|
||||||
}
|
}
|
||||||
|
|
||||||
if polynomial.is_empty() {
|
if polynomial.is_empty() {
|
||||||
return Polynomial::new(vec![FieldElement::new(vec![0; 16])]);
|
return Polynomial::new(vec![FieldElement::zero()]);
|
||||||
}
|
}
|
||||||
|
|
||||||
Polynomial::new(polynomial)
|
Polynomial::new(polynomial)
|
||||||
|
|
@ -529,15 +468,9 @@ impl PartialOrd for Polynomial {
|
||||||
for (field_a, field_b) in
|
for (field_a, field_b) in
|
||||||
self.as_ref().iter().rev().zip(other.as_ref().iter().rev())
|
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
|
match field_a
|
||||||
.reverse_bits()
|
//.reverse_bits()
|
||||||
.partial_cmp(&field_b.reverse_bits())
|
.partial_cmp(&field_b)
|
||||||
.unwrap()
|
.unwrap()
|
||||||
{
|
{
|
||||||
Ordering::Equal => continue,
|
Ordering::Equal => continue,
|
||||||
|
|
@ -560,7 +493,10 @@ impl Ord for Polynomial {
|
||||||
for (field_a, field_b) in
|
for (field_a, field_b) in
|
||||||
self.as_ref().iter().rev().zip(other.as_ref().iter().rev())
|
self.as_ref().iter().rev().zip(other.as_ref().iter().rev())
|
||||||
{
|
{
|
||||||
match field_a.reverse_bits().cmp(&field_b.reverse_bits()) {
|
match field_a
|
||||||
|
//.reverse_bits()
|
||||||
|
.cmp(&field_b)
|
||||||
|
{
|
||||||
Ordering::Equal => continue,
|
Ordering::Equal => continue,
|
||||||
other => return other,
|
other => return other,
|
||||||
}
|
}
|
||||||
|
|
@ -576,9 +512,21 @@ pub fn gcd(a: &Polynomial, b: &Polynomial) -> Polynomial {
|
||||||
if a.is_zero() {
|
if a.is_zero() {
|
||||||
return b.clone();
|
return b.clone();
|
||||||
}
|
}
|
||||||
|
if b.is_zero() {
|
||||||
|
return a.clone();
|
||||||
|
}
|
||||||
|
|
||||||
let monic_b = b.div(&a).1.monic();
|
if a.degree() > b.degree() {
|
||||||
return gcd(&monic_b, a);
|
return gcd(b, a);
|
||||||
|
}
|
||||||
|
|
||||||
|
let (_, remainder) = b.div(a);
|
||||||
|
|
||||||
|
if remainder.is_zero() {
|
||||||
|
return a.clone().monic();
|
||||||
|
}
|
||||||
|
|
||||||
|
gcd(&remainder, a)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn non_monic_gcd(a: &Polynomial, b: &Polynomial) -> Polynomial {
|
pub fn non_monic_gcd(a: &Polynomial, b: &Polynomial) -> Polynomial {
|
||||||
|
|
@ -602,21 +550,18 @@ pub fn sort_polynomial_array(mut polys: Vec<Polynomial>) -> Result<Vec<Polynomia
|
||||||
pub const RED_POLY: u128 = 0x87000000_00000000_00000000_00000000;
|
pub const RED_POLY: u128 = 0x87000000_00000000_00000000_00000000;
|
||||||
|
|
||||||
pub fn gfmul(poly_a: &Vec<u8>, poly_b: &Vec<u8>, semantic: &str) -> Result<Vec<u8>> {
|
pub fn gfmul(poly_a: &Vec<u8>, poly_b: &Vec<u8>, semantic: &str) -> Result<Vec<u8>> {
|
||||||
let mut red_poly_bytes: ByteArray = ByteArray(RED_POLY.to_be_bytes().to_vec());
|
let 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_owned());
|
let mut poly1: ByteArray = ByteArray(poly_a.to_vec());
|
||||||
poly1.0.push(0x00);
|
|
||||||
|
|
||||||
let mut poly2: ByteArray = ByteArray(poly_b.to_owned());
|
let mut poly2: ByteArray = ByteArray(poly_b.to_vec());
|
||||||
poly2.0.push(0x00);
|
|
||||||
|
|
||||||
if semantic == "gcm" {
|
if semantic == "gcm" {
|
||||||
poly1.reverse_bits_in_bytevec();
|
poly1.reverse_bits_in_bytevec();
|
||||||
poly2.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, 0]);
|
let mut result: ByteArray = ByteArray(vec![0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]);
|
||||||
|
|
||||||
if poly2.LSB_is_one() {
|
if poly2.LSB_is_one() {
|
||||||
result.xor_byte_arrays(&poly1);
|
result.xor_byte_arrays(&poly1);
|
||||||
|
|
@ -624,9 +569,9 @@ pub fn gfmul(poly_a: &Vec<u8>, poly_b: &Vec<u8>, semantic: &str) -> Result<Vec<u
|
||||||
poly2.right_shift("xex")?;
|
poly2.right_shift("xex")?;
|
||||||
|
|
||||||
while !poly2.is_empty() {
|
while !poly2.is_empty() {
|
||||||
poly1.left_shift("xex")?;
|
let carry = poly1.left_shift("xex")?;
|
||||||
|
|
||||||
if poly1.msb_is_one() {
|
if carry == 1 {
|
||||||
poly1.xor_byte_arrays(&red_poly_bytes);
|
poly1.xor_byte_arrays(&red_poly_bytes);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -637,7 +582,7 @@ pub fn gfmul(poly_a: &Vec<u8>, poly_b: &Vec<u8>, semantic: &str) -> Result<Vec<u
|
||||||
poly2.right_shift("xex")?;
|
poly2.right_shift("xex")?;
|
||||||
}
|
}
|
||||||
|
|
||||||
result.0.remove(16);
|
//result.0.remove(16);
|
||||||
|
|
||||||
if semantic == "gcm" {
|
if semantic == "gcm" {
|
||||||
result.reverse_bits_in_bytevec();
|
result.reverse_bits_in_bytevec();
|
||||||
|
|
@ -658,8 +603,6 @@ pub fn convert_gcm_to_xex(gcm_poly: Vec<u8>) -> Result<Vec<u8>> {
|
||||||
pub fn get_alpha_rep(num: u128) -> String {
|
pub fn get_alpha_rep(num: u128) -> String {
|
||||||
let powers: Vec<u8> = get_coefficients(num);
|
let powers: Vec<u8> = get_coefficients(num);
|
||||||
|
|
||||||
//println!("{:?}", powers);
|
|
||||||
|
|
||||||
let mut alpha_rep = String::new();
|
let mut alpha_rep = String::new();
|
||||||
|
|
||||||
if powers.len() == 1 {
|
if powers.len() == 1 {
|
||||||
|
|
@ -686,7 +629,6 @@ pub fn b64_2_num(string: &String) -> Result<u128> {
|
||||||
pub fn get_coefficients(num: u128) -> Vec<u8> {
|
pub fn get_coefficients(num: u128) -> Vec<u8> {
|
||||||
let mut powers: Vec<u8> = vec![];
|
let mut powers: Vec<u8> = vec![];
|
||||||
for shift in 0..128 {
|
for shift in 0..128 {
|
||||||
//println!("{:?}", ((num >> shift) & 1));
|
|
||||||
if ((num >> shift) & 1) == 1 {
|
if ((num >> shift) & 1) == 1 {
|
||||||
powers.push(shift);
|
powers.push(shift);
|
||||||
}
|
}
|
||||||
|
|
@ -783,7 +725,7 @@ pub fn coefficient_to_binary(coefficients: Vec<u8>) -> u128 {
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use crate::utils::poly::b64_2_num;
|
use crate::utils::poly::{b64_2_num, gcd};
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use serde_json::json;
|
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.
|
||||||
|
|
@ -813,7 +755,7 @@ mod tests {
|
||||||
#[test]
|
#[test]
|
||||||
fn coeff_to_binary() {
|
fn coeff_to_binary() {
|
||||||
let coefficients: Vec<u8> = vec![12, 127, 9, 0];
|
let coefficients: Vec<u8> = vec![12, 127, 9, 0];
|
||||||
let b64: &str = "ARIAAAAAAAAAAAAAAAAAgA==";
|
let _b64: &str = "ARIAAAAAAAAAAAAAAAAAgA==";
|
||||||
let calculated_num: u128 = coefficient_to_binary(coefficients);
|
let calculated_num: u128 = coefficient_to_binary(coefficients);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
BASE64_STANDARD.encode(calculated_num.to_ne_bytes()),
|
BASE64_STANDARD.encode(calculated_num.to_ne_bytes()),
|
||||||
|
|
@ -1078,19 +1020,6 @@ mod tests {
|
||||||
//assert_eq!(BASE64_STANDARD.encode(product), "MoAAAAAAAAAAAAAAAAAAAA==");
|
//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]
|
#[test]
|
||||||
fn test_field_poly_div_01() {
|
fn test_field_poly_div_01() {
|
||||||
let json1 = json!([
|
let json1 = json!([
|
||||||
|
|
@ -1417,4 +1346,17 @@ mod tests {
|
||||||
|
|
||||||
assert_eq!(json!(result.to_c_array()), expected);
|
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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -86,7 +86,7 @@ mod tests {
|
||||||
}
|
}
|
||||||
|
|
||||||
println!("{:?}", result);
|
println!("{:?}", result);
|
||||||
let bit_indices: Vec<u8> = vec![0];
|
let _bit_indices: Vec<u8> = vec![0];
|
||||||
assert!(false)
|
assert!(false)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,19 +1,29 @@
|
||||||
{
|
{
|
||||||
"testcases": {
|
"testcases": {
|
||||||
"sandbox": {
|
"gcm_crack1": {
|
||||||
"action": "gfpoly_factor_ddf",
|
"action": "gcm_crack",
|
||||||
"arguments": {
|
"arguments": {
|
||||||
"F": [
|
"nonce": "4gF+BtR3ku/PUQci",
|
||||||
"tpkgAAAAAAAAAAAAAAAAAA==",
|
"m1": {
|
||||||
"m6MQAAAAAAAAAAAAAAAAAA==",
|
"ciphertext": "CGOkZDnJEt24aVV8mqQq+P4pouVDWhAYj0SN5MDAgg==",
|
||||||
"8roAAAAAAAAAAAAAAAAAAA==",
|
"associated_data": "TmFjaHJpY2h0IDE=",
|
||||||
"3dUAAAAAAAAAAAAAAAAAAA==",
|
"tag": "GC9neV3aZLnmznTIWqCC4A=="
|
||||||
"FwAAAAAAAAAAAAAAAAAAAA==",
|
},
|
||||||
"/kAAAAAAAAAAAAAAAAAAAA==",
|
"m2": {
|
||||||
"a4AAAAAAAAAAAAAAAAAAAA==",
|
"ciphertext": "FnWyLSTfRrO8Y1MuhLIs6A==",
|
||||||
"gAAAAAAAAAAAAAAAAAAAAA=="
|
"associated_data": "",
|
||||||
]
|
"tag": "gb2ph1vzwU85/FsUg51t3Q=="
|
||||||
}
|
},
|
||||||
|
"m3": {
|
||||||
|
"ciphertext": "CGOkZDnJEt25aV58iaMt6O8+8chKVh0Eg1XFxA==",
|
||||||
|
"associated_data": "TmFjaHJpY2h0IDM=",
|
||||||
|
"tag": "+/aDjsAzTseDLuM4jt5Q6Q=="
|
||||||
|
},
|
||||||
|
"forgery": {
|
||||||
|
"ciphertext": "AXe/ZQ==",
|
||||||
|
"associated_data": ""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue