Compare commits
129 commits
feat_polyn
...
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 | ||
|
|
f7f3c44acb | ||
|
|
905e905c35 | ||
|
|
444000a101 | ||
|
|
9acddc2867 | ||
|
|
2cbda23e9c | ||
|
|
39c4d9b80d | ||
|
|
b898c32ded | ||
|
|
6532c576c6 | ||
|
|
4a2b0ab014 | ||
|
|
fa7d33aaf6 | ||
|
|
d599292d3a | ||
|
|
b54753fe7e | ||
|
|
361c6ab813 | ||
|
|
341b22e184 | ||
|
|
be4f8c9f14 | ||
|
|
6856420ff9 | ||
|
|
1c9948ac62 | ||
|
|
2d4f7a1110 | ||
|
|
17bade8a62 | ||
|
|
aa756b5144 | ||
|
|
69a2026c84 | ||
|
|
454790d24f | ||
|
|
2e73125e14 | ||
|
|
0b18ba1bff | ||
|
|
1a2910b28f | ||
|
|
ab755444c6 | ||
|
|
8be8dc7a54 | ||
|
|
4b1bca8ee0 | ||
|
|
b595276143 | ||
|
|
1290adcd9b | ||
|
|
1b45c192b3 | ||
|
|
5bb9bcebff | ||
|
|
f75e7de733 | ||
|
|
e90491a03c | ||
|
|
6391912bc4 | ||
|
|
5e50ef6091 | ||
|
|
a5a3ea61fa | ||
|
|
ad8326b51e | ||
|
|
922fdd04cc | ||
|
|
1db9b65dda | ||
|
|
a520a811b4 | ||
|
|
e92c8ddba8 | ||
|
|
81fe06941d | ||
|
|
b63dc86c7e | ||
|
|
279571dc00 | ||
|
|
bad946e9ac | ||
|
|
c3ea652c87 | ||
|
|
bb5e762a1d | ||
|
|
ca2067c04e | ||
|
|
c5d3db27f4 | ||
|
|
295ed98c1e | ||
|
|
7dc6fa1ac9 | ||
|
|
67bbf67f18 | ||
|
|
6a04e00fb2 | ||
|
|
c1bcb768ba | ||
|
|
0784c26456 | ||
|
|
2a9db307d9 | ||
|
|
5dc299372a | ||
|
|
9785b8d8aa | ||
|
|
a0ff95548e | ||
|
|
68d9f13a3d | ||
|
|
deb4261121 | ||
|
|
a05f2f02b6 | ||
|
|
11916e29f0 | ||
|
|
6431a6636e | ||
|
|
6e33e2e44c | ||
|
|
811e2b21f6 | ||
|
|
b5be86401d | ||
|
|
84d99f2414 | ||
|
|
7d0ca81a10 | ||
|
|
95de66aca0 | ||
|
|
10fd837be9 | ||
|
|
5953b98897 | ||
|
|
0f8d202a06 | ||
|
|
757afbdc95 | ||
|
|
9ae53e12fd | ||
|
|
b81bbab16c | ||
|
|
766a801071 | ||
|
|
1dfed264e9 | ||
|
|
aa1468c635 | ||
|
|
0d8f110902 | ||
|
|
f0fc2ea0e8 | ||
|
|
6b2775cde1 | ||
|
|
aa57e74b98 | ||
|
|
6bef350301 | ||
|
|
e33a26adab | ||
|
|
7a7483fade | ||
|
|
3f861d7a1e | ||
|
|
6d808aef54 | ||
|
|
3b0757132e | ||
|
|
c818d5cde4 |
31 changed files with 16554 additions and 322 deletions
|
|
@ -10,9 +10,17 @@ base64 = "0.22"
|
||||||
openssl = "0.10"
|
openssl = "0.10"
|
||||||
serde = { version = "1.0", features = ["derive"] }
|
serde = { version = "1.0", features = ["derive"] }
|
||||||
serde_json = "1.0"
|
serde_json = "1.0"
|
||||||
|
num = "0.4"
|
||||||
|
rand = "0.8"
|
||||||
|
threadpool = "1.8"
|
||||||
|
num_cpus = "1.16.0"
|
||||||
|
|
||||||
[source.crates-io]
|
[source.crates-io]
|
||||||
replace-with = "vendored-sources"
|
replace-with = "vendored-sources"
|
||||||
|
|
||||||
[source.vendored-sources]
|
[source.vendored-sources]
|
||||||
directory = "vendor"
|
directory = "vendor"
|
||||||
|
|
||||||
|
[profile.profiling]
|
||||||
|
inherits = "release"
|
||||||
|
debug = true
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,8 @@ use std::{
|
||||||
fs,
|
fs,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// TESTING 2
|
||||||
|
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
|
|
||||||
fn main() -> Result<()> {
|
fn main() -> Result<()> {
|
||||||
|
|
@ -12,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(())
|
||||||
|
|
|
||||||
291
src/tasks/mod.rs
291
src/tasks/mod.rs
|
|
@ -4,7 +4,19 @@ use std::collections::HashMap;
|
||||||
|
|
||||||
use crate::utils::parse::{Responses, Testcase, Testcases};
|
use crate::utils::parse::{Responses, Testcase, Testcases};
|
||||||
use tasks01::{
|
use tasks01::{
|
||||||
block2poly::block2poly, gfmul::gfmul_task, poly2block::poly2block, sea128::sea128, xex::fde_xex,
|
block2poly::block2poly,
|
||||||
|
gcm::{gcm_decrypt, gcm_encrypt},
|
||||||
|
gcm_crack::gcm_crack,
|
||||||
|
gfmul::gfmul_task,
|
||||||
|
pad_oracle::padding_oracle,
|
||||||
|
pfmath::{
|
||||||
|
gfdiv, gfpoly_add, gfpoly_diff, gfpoly_divmod, gfpoly_factor_ddf, gfpoly_factor_edf,
|
||||||
|
gfpoly_factor_sff, gfpoly_gcd, gfpoly_make_monic, gfpoly_mul, gfpoly_pow, gfpoly_powmod,
|
||||||
|
gfpoly_sort, gfpoly_sqrt,
|
||||||
|
},
|
||||||
|
poly2block::poly2block,
|
||||||
|
sea128::sea128,
|
||||||
|
xex::fde_xex,
|
||||||
};
|
};
|
||||||
|
|
||||||
use anyhow::{anyhow, Result};
|
use anyhow::{anyhow, Result};
|
||||||
|
|
@ -49,6 +61,129 @@ pub fn task_deploy(testcase: &Testcase) -> Result<Value> {
|
||||||
|
|
||||||
Ok(json)
|
Ok(json)
|
||||||
}
|
}
|
||||||
|
"gcm_encrypt" => {
|
||||||
|
let (ciphertext, auth_tag, l_field, auth_key_h) = gcm_encrypt(args)?;
|
||||||
|
let out_ciph = BASE64_STANDARD.encode(&ciphertext);
|
||||||
|
let out_tag = BASE64_STANDARD.encode(&auth_tag);
|
||||||
|
let out_l = BASE64_STANDARD.encode(&l_field);
|
||||||
|
let out_h = BASE64_STANDARD.encode(&auth_key_h);
|
||||||
|
|
||||||
|
let json = json!({"ciphertext" : out_ciph, "tag" : out_tag, "L" : out_l, "H" : out_h});
|
||||||
|
|
||||||
|
Ok(json)
|
||||||
|
}
|
||||||
|
"gcm_decrypt" => {
|
||||||
|
let (plaintext, valid) = gcm_decrypt(args)?;
|
||||||
|
let out_plain = BASE64_STANDARD.encode(&plaintext);
|
||||||
|
let json = json!({ "authentic" : valid, "plaintext" : out_plain});
|
||||||
|
|
||||||
|
Ok(json)
|
||||||
|
}
|
||||||
|
"padding_oracle" => {
|
||||||
|
let plaintext = padding_oracle(args)?;
|
||||||
|
let out_plain = BASE64_STANDARD.encode(&plaintext);
|
||||||
|
let json = json!({"plaintext" : out_plain});
|
||||||
|
|
||||||
|
Ok(json)
|
||||||
|
}
|
||||||
|
"gfpoly_add" => {
|
||||||
|
let result = gfpoly_add(args)?;
|
||||||
|
let json = json!({"S" : result.to_c_array()});
|
||||||
|
|
||||||
|
Ok(json)
|
||||||
|
}
|
||||||
|
"gfpoly_mul" => {
|
||||||
|
let result = gfpoly_mul(args)?;
|
||||||
|
let json = json!({"P" : result.to_c_array()});
|
||||||
|
|
||||||
|
Ok(json)
|
||||||
|
}
|
||||||
|
"gfpoly_pow" => {
|
||||||
|
let result = gfpoly_pow(args)?;
|
||||||
|
let json = json!({"Z" : result.to_c_array()});
|
||||||
|
|
||||||
|
Ok(json)
|
||||||
|
}
|
||||||
|
"gfdiv" => {
|
||||||
|
let result = gfdiv(args)?;
|
||||||
|
let out = result.to_b64();
|
||||||
|
let json = json!({"q" : out});
|
||||||
|
|
||||||
|
Ok(json)
|
||||||
|
}
|
||||||
|
"gfpoly_divmod" => {
|
||||||
|
let result = gfpoly_divmod(args)?;
|
||||||
|
let json = json!({"Q" : result.0.to_c_array(), "R" : result.1.to_c_array()});
|
||||||
|
|
||||||
|
Ok(json)
|
||||||
|
}
|
||||||
|
"gfpoly_powmod" => {
|
||||||
|
let result = gfpoly_powmod(args)?;
|
||||||
|
let json = json!({"Z" : result.to_c_array()});
|
||||||
|
|
||||||
|
Ok(json)
|
||||||
|
}
|
||||||
|
"gfpoly_sort" => {
|
||||||
|
let sorted_array = gfpoly_sort(args)?;
|
||||||
|
let mut result: Vec<Vec<String>> = vec![];
|
||||||
|
|
||||||
|
for poly in sorted_array {
|
||||||
|
result.push(poly.to_c_array());
|
||||||
|
}
|
||||||
|
|
||||||
|
let json = json!({"sorted_polys" : json!(result)});
|
||||||
|
|
||||||
|
Ok(json)
|
||||||
|
}
|
||||||
|
"gfpoly_make_monic" => {
|
||||||
|
let result = gfpoly_make_monic(args)?;
|
||||||
|
let json = json!({"A*" : result.to_c_array()});
|
||||||
|
|
||||||
|
Ok(json)
|
||||||
|
}
|
||||||
|
"gfpoly_sqrt" => {
|
||||||
|
let result = gfpoly_sqrt(args)?;
|
||||||
|
let json = json!({"S" : result.to_c_array()});
|
||||||
|
|
||||||
|
Ok(json)
|
||||||
|
}
|
||||||
|
"gfpoly_diff" => {
|
||||||
|
let result = gfpoly_diff(args)?;
|
||||||
|
let json = json!({"F'" : result.to_c_array()});
|
||||||
|
|
||||||
|
Ok(json)
|
||||||
|
}
|
||||||
|
"gfpoly_gcd" => {
|
||||||
|
let result = gfpoly_gcd(args)?;
|
||||||
|
let json = json!({"G" : result.to_c_array()});
|
||||||
|
|
||||||
|
Ok(json)
|
||||||
|
}
|
||||||
|
"gfpoly_factor_sff" => {
|
||||||
|
let result = gfpoly_factor_sff(args)?;
|
||||||
|
let json = json!({"factors" : result});
|
||||||
|
|
||||||
|
Ok(json)
|
||||||
|
}
|
||||||
|
"gfpoly_factor_ddf" => {
|
||||||
|
let result = gfpoly_factor_ddf(args)?;
|
||||||
|
let json = json!({"factors" : result});
|
||||||
|
|
||||||
|
Ok(json)
|
||||||
|
}
|
||||||
|
"gfpoly_factor_edf" => {
|
||||||
|
let result = gfpoly_factor_edf(args)?;
|
||||||
|
let json = json!({"factors" : result});
|
||||||
|
|
||||||
|
Ok(json)
|
||||||
|
}
|
||||||
|
"gcm_crack" => {
|
||||||
|
let result = gcm_crack(args)?;
|
||||||
|
let json = json!(result);
|
||||||
|
|
||||||
|
Ok(json)
|
||||||
|
}
|
||||||
|
|
||||||
_ => Err(anyhow!(
|
_ => Err(anyhow!(
|
||||||
"Fatal. No compatible action found. Json data was {:?}. Arguments were; {:?}",
|
"Fatal. No compatible action found. Json data was {:?}. Arguments were; {:?}",
|
||||||
testcase,
|
testcase,
|
||||||
|
|
@ -57,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)]
|
||||||
|
|
@ -99,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()
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
@ -123,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()
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
@ -138,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()
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
@ -156,7 +335,101 @@ 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()
|
||||||
|
);
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_task_gcm_encrypt_aes_case() -> Result<()> {
|
||||||
|
let json = fs::read_to_string("test_json/gcm_encrypt.json").unwrap();
|
||||||
|
let parsed = parse_json(json).unwrap();
|
||||||
|
|
||||||
|
let expected = json!({ "responses" : { "b856d760-023d-4b00-bad2-15d2b6da22fe" : {
|
||||||
|
"ciphertext": "ET3RmvH/Hbuxba63EuPRrw==",
|
||||||
|
"tag": "Mp0APJb/ZIURRwQlMgNN/w==",
|
||||||
|
"L": "AAAAAAAAAEAAAAAAAAAAgA==",
|
||||||
|
"H": "Bu6ywbsUKlpmZXMQyuGAng=="
|
||||||
|
}}});
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
serde_json::to_value(task_distribute(&parsed)?).unwrap(),
|
||||||
|
serde_json::to_value(expected).unwrap()
|
||||||
|
);
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_task_gcm_encrypt_sea_case() -> Result<()> {
|
||||||
|
let json = fs::read_to_string("test_json/gcm_encrypt_sea.json").unwrap();
|
||||||
|
let parsed = parse_json(json).unwrap();
|
||||||
|
|
||||||
|
let expected = json!({ "responses" : { "b856d760-023d-4b00-bad2-15d2b6da22fe" : {
|
||||||
|
"ciphertext": "0cI/Wg4R3URfrVFZ0hw/vg==",
|
||||||
|
"tag": "ysDdzOSnqLH0MQ+Mkb23gw==",
|
||||||
|
"L": "AAAAAAAAAEAAAAAAAAAAgA==",
|
||||||
|
"H": "xhFcAUT66qWIpYz+Ch5ujw=="
|
||||||
|
}}});
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
serde_json::to_value(task_distribute(&parsed)?).unwrap(),
|
||||||
|
serde_json::to_value(expected).unwrap()
|
||||||
|
);
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_task_gcm_decrypt_aes_case() -> Result<()> {
|
||||||
|
let json = fs::read_to_string("test_json/gcm_decrypt_aes.json").unwrap();
|
||||||
|
let parsed = parse_json(json).unwrap();
|
||||||
|
|
||||||
|
let expected = json!({ "responses" : { "b856d760-023d-4b00-bad2-15d2b6da22fe" : {
|
||||||
|
"plaintext": "RGFzIGlzdCBlaW4gVGVzdA==",
|
||||||
|
"authentic": true,
|
||||||
|
}}});
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
serde_json::to_value(task_distribute(&parsed)?).unwrap(),
|
||||||
|
serde_json::to_value(expected).unwrap()
|
||||||
|
);
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_task_gcm_decrypt_sea_case() -> Result<()> {
|
||||||
|
let json = fs::read_to_string("test_json/gcm_decrypt_sea.json").unwrap();
|
||||||
|
let parsed = parse_json(json).unwrap();
|
||||||
|
|
||||||
|
let expected = json!({ "responses" : { "b856d760-023d-4b00-bad2-15d2b6da22fe" : {
|
||||||
|
"plaintext": "RGFzIGlzdCBlaW4gVGVzdA==",
|
||||||
|
"authentic": true,
|
||||||
|
}}});
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
serde_json::to_value(task_distribute(&parsed)?).unwrap(),
|
||||||
|
serde_json::to_value(expected).unwrap()
|
||||||
|
);
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_task_gcm_gfpoly_add() -> Result<()> {
|
||||||
|
let json = fs::read_to_string("test_json/gcm_decrypt_sea.json").unwrap();
|
||||||
|
let parsed = parse_json(json).unwrap();
|
||||||
|
|
||||||
|
let expected = json!({ "responses" : { "b856d760-023d-4b00-bad2-15d2b6da22fe" : {
|
||||||
|
"plaintext": "RGFzIGlzdCBlaW4gVGVzdA==",
|
||||||
|
"authentic": true,
|
||||||
|
}}});
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
serde_json::to_value(task_distribute(&parsed)?).unwrap(),
|
||||||
serde_json::to_value(expected).unwrap()
|
serde_json::to_value(expected).unwrap()
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -20,7 +20,6 @@ pub fn block2poly(val: &Value) -> Result<Vec<u8>> {
|
||||||
mod tests {
|
mod tests {
|
||||||
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.
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
|
|
@ -51,46 +50,4 @@ mod tests {
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn block2poly_task03() -> Result<()> {
|
|
||||||
let block: Value = json!({"block" : "AAAAAAAAAAAAAAAAAAAAAA==", "semantic" : "gcm"});
|
|
||||||
let coefficients: Vec<u8> = vec![];
|
|
||||||
assert_eq!(
|
|
||||||
block2poly(&block)?,
|
|
||||||
coefficients,
|
|
||||||
"Coefficients were: {:?}",
|
|
||||||
block2poly(&block)?
|
|
||||||
);
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn block2poly_task04() -> Result<()> {
|
|
||||||
let block: Value = json!({"block" : "", "semantic" : "gcm"});
|
|
||||||
let coefficients: Vec<u8> = vec![];
|
|
||||||
assert_eq!(
|
|
||||||
block2poly(&block)?,
|
|
||||||
coefficients,
|
|
||||||
"Coefficients were: {:?}",
|
|
||||||
block2poly(&block)?
|
|
||||||
);
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn block2poly_task_empty_xex() -> Result<()> {
|
|
||||||
let block: Value = json!({"block" : "", "semantic" : "xex"});
|
|
||||||
let coefficients: Vec<u8> = vec![];
|
|
||||||
assert_eq!(
|
|
||||||
block2poly(&block)?,
|
|
||||||
coefficients,
|
|
||||||
"Coefficients were: {:?}",
|
|
||||||
block2poly(&block)?
|
|
||||||
);
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
52
src/tasks/tasks01/gcm.rs
Normal file
52
src/tasks/tasks01/gcm.rs
Normal file
|
|
@ -0,0 +1,52 @@
|
||||||
|
use anyhow::{anyhow, Result};
|
||||||
|
use base64::prelude::*;
|
||||||
|
use serde_json::Value;
|
||||||
|
|
||||||
|
use crate::utils::ciphers::{gcm_decrypt_aes, gcm_decrypt_sea, gcm_encrypt_aes, gcm_encrypt_sea};
|
||||||
|
|
||||||
|
pub fn gcm_encrypt(args: &Value) -> Result<(Vec<u8>, Vec<u8>, Vec<u8>, Vec<u8>)> {
|
||||||
|
let nonce_text: String = serde_json::from_value(args["nonce"].clone())?;
|
||||||
|
let nonce = BASE64_STANDARD.decode(nonce_text)?;
|
||||||
|
|
||||||
|
let key_text: String = serde_json::from_value(args["key"].clone())?;
|
||||||
|
let key = BASE64_STANDARD.decode(key_text)?;
|
||||||
|
|
||||||
|
let plaintext_text: String = serde_json::from_value(args["plaintext"].clone())?;
|
||||||
|
let plaintext = BASE64_STANDARD.decode(plaintext_text)?;
|
||||||
|
|
||||||
|
let ad_text: String = serde_json::from_value(args["ad"].clone())?;
|
||||||
|
let ad = BASE64_STANDARD.decode(ad_text)?;
|
||||||
|
|
||||||
|
let alg_text: String = serde_json::from_value(args["algorithm"].clone())?;
|
||||||
|
|
||||||
|
match alg_text.as_str() {
|
||||||
|
"aes128" => Ok(gcm_encrypt_aes(nonce, key, plaintext, ad)?),
|
||||||
|
"sea128" => Ok(gcm_encrypt_sea(nonce, key, plaintext, ad)?),
|
||||||
|
_ => Err(anyhow!("No compatible algorithm found")),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn gcm_decrypt(args: &Value) -> Result<(Vec<u8>, bool)> {
|
||||||
|
let nonce_text: String = serde_json::from_value(args["nonce"].clone())?;
|
||||||
|
let nonce = BASE64_STANDARD.decode(nonce_text)?;
|
||||||
|
|
||||||
|
let key_text: String = serde_json::from_value(args["key"].clone())?;
|
||||||
|
let key = BASE64_STANDARD.decode(key_text)?;
|
||||||
|
|
||||||
|
let plaintext_text: String = serde_json::from_value(args["ciphertext"].clone())?;
|
||||||
|
let plaintext = BASE64_STANDARD.decode(plaintext_text)?;
|
||||||
|
|
||||||
|
let ad_text: String = serde_json::from_value(args["ad"].clone())?;
|
||||||
|
let ad = BASE64_STANDARD.decode(ad_text)?;
|
||||||
|
|
||||||
|
let tag_text: String = serde_json::from_value(args["tag"].clone())?;
|
||||||
|
let tag = BASE64_STANDARD.decode(tag_text)?;
|
||||||
|
|
||||||
|
let alg_text: String = serde_json::from_value(args["algorithm"].clone())?;
|
||||||
|
|
||||||
|
match alg_text.as_str() {
|
||||||
|
"aes128" => Ok(gcm_decrypt_aes(nonce, key, plaintext, ad, tag)?),
|
||||||
|
"sea128" => Ok(gcm_decrypt_sea(nonce, key, plaintext, ad, tag)?),
|
||||||
|
_ => Err(anyhow!("No compatible algorithm found")),
|
||||||
|
}
|
||||||
|
}
|
||||||
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),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
@ -13,7 +13,7 @@ pub fn gfmul_task(args: &Value) -> Result<Vec<u8>> {
|
||||||
|
|
||||||
let semantic: String = serde_json::from_value(args["semantic"].clone())?;
|
let semantic: String = serde_json::from_value(args["semantic"].clone())?;
|
||||||
|
|
||||||
let result = gfmul(poly_a, poly_b, &semantic)?;
|
let result = gfmul(&poly_a, &poly_b, &semantic)?;
|
||||||
|
|
||||||
Ok(result)
|
Ok(result)
|
||||||
}
|
}
|
||||||
|
|
@ -22,8 +22,6 @@ pub fn gfmul_task(args: &Value) -> Result<Vec<u8>> {
|
||||||
mod tests {
|
mod tests {
|
||||||
use serde_json::json;
|
use serde_json::json;
|
||||||
|
|
||||||
use crate::utils::math::reverse_bits_in_bytevec;
|
|
||||||
|
|
||||||
// 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::*;
|
||||||
|
|
||||||
|
|
@ -37,7 +35,7 @@ mod tests {
|
||||||
let poly2_text: String = serde_json::from_value(args["b"].clone())?;
|
let poly2_text: String = serde_json::from_value(args["b"].clone())?;
|
||||||
let poly_b = BASE64_STANDARD.decode(poly2_text)?;
|
let poly_b = BASE64_STANDARD.decode(poly2_text)?;
|
||||||
|
|
||||||
let result = BASE64_STANDARD.encode(gfmul(poly_a, poly_b, "xex")?);
|
let result = BASE64_STANDARD.encode(gfmul(&poly_a, &poly_b, "xex")?);
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
result, "hSQAAAAAAAAAAAAAAAAAAA==",
|
result, "hSQAAAAAAAAAAAAAAAAAAA==",
|
||||||
|
|
@ -57,7 +55,7 @@ mod tests {
|
||||||
let poly2_text: String = serde_json::from_value(args["b"].clone())?;
|
let poly2_text: String = serde_json::from_value(args["b"].clone())?;
|
||||||
let poly_b = BASE64_STANDARD.decode(poly2_text)?;
|
let poly_b = BASE64_STANDARD.decode(poly2_text)?;
|
||||||
|
|
||||||
let result = BASE64_STANDARD.encode(gfmul(poly_a, poly_b, "xex")?);
|
let result = BASE64_STANDARD.encode(gfmul(&poly_a, &poly_b, "xex")?);
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
result, "QKgUAAAAAAAAAAAAAAAAAA==",
|
result, "QKgUAAAAAAAAAAAAAAAAAA==",
|
||||||
|
|
@ -77,7 +75,7 @@ mod tests {
|
||||||
let poly2_text: String = serde_json::from_value(args["b"].clone())?;
|
let poly2_text: String = serde_json::from_value(args["b"].clone())?;
|
||||||
let poly_b = BASE64_STANDARD.decode(poly2_text)?;
|
let poly_b = BASE64_STANDARD.decode(poly2_text)?;
|
||||||
|
|
||||||
let result = BASE64_STANDARD.encode(gfmul(poly_a, poly_b, "xex")?);
|
let result = BASE64_STANDARD.encode(gfmul(&poly_a, &poly_b, "xex")?);
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
result, "UIAUAAAAAAAAAAAAAAAAAA==",
|
result, "UIAUAAAAAAAAAAAAAAAAAA==",
|
||||||
|
|
@ -97,7 +95,7 @@ mod tests {
|
||||||
let poly2_text: String = serde_json::from_value(args["b"].clone())?;
|
let poly2_text: String = serde_json::from_value(args["b"].clone())?;
|
||||||
let poly_b = BASE64_STANDARD.decode(poly2_text)?;
|
let poly_b = BASE64_STANDARD.decode(poly2_text)?;
|
||||||
|
|
||||||
let result = BASE64_STANDARD.encode(gfmul(poly_a, poly_b, "xex")?);
|
let result = BASE64_STANDARD.encode(gfmul(&poly_a, &poly_b, "xex")?);
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
result, "hSQAAAAAAAAAAAAAAAAAAA==",
|
result, "hSQAAAAAAAAAAAAAAAAAAA==",
|
||||||
|
|
@ -106,26 +104,4 @@ mod tests {
|
||||||
);
|
);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn gfmul_task_gcm01() -> Result<()> {
|
|
||||||
let args: Value = json!({"a": "ARIAAAAAAAAAAAAAAAAAgA==", "b": "AgAAAAAAAAAAAAAAAAAAAA=="});
|
|
||||||
|
|
||||||
let poly1_text: String = serde_json::from_value(args["a"].clone())?;
|
|
||||||
let poly_a = reverse_bits_in_bytevec(BASE64_STANDARD.decode(poly1_text)?);
|
|
||||||
|
|
||||||
let poly2_text: String = serde_json::from_value(args["b"].clone())?;
|
|
||||||
let poly_b = reverse_bits_in_bytevec(BASE64_STANDARD.decode(poly2_text)?);
|
|
||||||
let result = BASE64_STANDARD.encode(gfmul(poly_a, poly_b, "gcm")?);
|
|
||||||
|
|
||||||
assert_eq!(
|
|
||||||
result,
|
|
||||||
BASE64_STANDARD.encode(reverse_bits_in_bytevec(
|
|
||||||
BASE64_STANDARD.decode("hSQAAAAAAAAAAAAAAAAAAA==")?
|
|
||||||
)),
|
|
||||||
"Failure. Calulated result was: {}",
|
|
||||||
result
|
|
||||||
);
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,9 @@
|
||||||
pub mod block2poly;
|
pub mod block2poly;
|
||||||
|
pub mod gcm;
|
||||||
|
pub mod gcm_crack;
|
||||||
pub mod gfmul;
|
pub mod gfmul;
|
||||||
|
pub mod pad_oracle;
|
||||||
|
pub mod pfmath;
|
||||||
pub mod poly2block;
|
pub mod poly2block;
|
||||||
pub mod sea128;
|
pub mod sea128;
|
||||||
pub mod xex;
|
pub mod xex;
|
||||||
|
|
|
||||||
148
src/tasks/tasks01/pad_oracle.rs
Normal file
148
src/tasks/tasks01/pad_oracle.rs
Normal file
|
|
@ -0,0 +1,148 @@
|
||||||
|
use anyhow::Result;
|
||||||
|
use base64::prelude::*;
|
||||||
|
use serde_json::Value;
|
||||||
|
use std::io::prelude::*;
|
||||||
|
use std::net::TcpStream;
|
||||||
|
use std::usize;
|
||||||
|
|
||||||
|
pub fn padding_oracle(args: &Value) -> Result<Vec<u8>> {
|
||||||
|
let hostname: String = serde_json::from_value(args["hostname"].clone())?;
|
||||||
|
|
||||||
|
let port_val: Value = serde_json::from_value(args["port"].clone())?;
|
||||||
|
let port: u64 = port_val.as_u64().expect("Failure in parsing port number");
|
||||||
|
|
||||||
|
let iv_string: String = serde_json::from_value(args["iv"].clone())?;
|
||||||
|
let iv: Vec<u8> = BASE64_STANDARD.decode(iv_string)?;
|
||||||
|
|
||||||
|
let cipher_text: String = serde_json::from_value(args["ciphertext"].clone())?;
|
||||||
|
let ciphertext: Vec<u8> = BASE64_STANDARD.decode(cipher_text)?;
|
||||||
|
|
||||||
|
// Initialise tracker to adapt correct byte
|
||||||
|
let byte_counter = 15;
|
||||||
|
eprintln!("byte_counter is: {}", byte_counter);
|
||||||
|
|
||||||
|
let mut plaintext: Vec<u8> = vec![];
|
||||||
|
eprintln!("Ciphertext: {:002X?}", ciphertext);
|
||||||
|
|
||||||
|
let cipher_chunks: Vec<&[u8]> = ciphertext.chunks(16).rev().collect();
|
||||||
|
let mut chunk_counter = 0;
|
||||||
|
|
||||||
|
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
|
||||||
|
let mut attack_counter: Vec<u8> = vec![0; 16];
|
||||||
|
|
||||||
|
// Amount of q blocks to send to server.
|
||||||
|
// TODO:: May be increased via function
|
||||||
|
let q_block_count: u16 = 256;
|
||||||
|
|
||||||
|
//Send the first ciphertext chunk
|
||||||
|
stream.flush()?;
|
||||||
|
stream.write_all(&chunk)?;
|
||||||
|
stream.flush()?;
|
||||||
|
|
||||||
|
for i in (0..=15).rev() {
|
||||||
|
// Craft length message
|
||||||
|
// 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();
|
||||||
|
|
||||||
|
// Generate attack blocks
|
||||||
|
// TODO: Collect all and send in one
|
||||||
|
let mut payload: Vec<u8> = Vec::with_capacity(2 + 16 * 265);
|
||||||
|
payload.extend(l_msg.to_vec());
|
||||||
|
for _j in 0..q_block_count {
|
||||||
|
// Next byte
|
||||||
|
payload.extend(&attack_counter);
|
||||||
|
attack_counter[i as usize] += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
stream.write_all(&payload)?;
|
||||||
|
stream.flush()?;
|
||||||
|
|
||||||
|
// Read server response
|
||||||
|
let mut server_q_resp = [0u8; 256];
|
||||||
|
stream.read_exact(&mut server_q_resp)?;
|
||||||
|
|
||||||
|
// extract valid position
|
||||||
|
let valid_val = server_q_resp
|
||||||
|
.iter()
|
||||||
|
.position(|&r| r == 0x01)
|
||||||
|
.unwrap_or(0x00) as u8;
|
||||||
|
if valid_val == 0x00 {
|
||||||
|
eprintln!("No valid found in main loop");
|
||||||
|
}
|
||||||
|
// Craft next attack vector padding; 0x01, 0x02, ...
|
||||||
|
attack_counter[i as usize] = valid_val;
|
||||||
|
|
||||||
|
// Check for edgecase
|
||||||
|
if i == 15 {
|
||||||
|
let mut l_msg_check: Vec<u8> = vec![0x01, 0x00];
|
||||||
|
let mut check_q_block: Vec<u8> = vec![0; 16];
|
||||||
|
check_q_block[15] = attack_counter[15];
|
||||||
|
check_q_block[14] = !check_q_block[15];
|
||||||
|
|
||||||
|
l_msg_check.extend(check_q_block.as_slice());
|
||||||
|
|
||||||
|
stream.write_all(&l_msg_check)?;
|
||||||
|
let mut buf = [0u8; 0x01];
|
||||||
|
stream.read(&mut buf)?;
|
||||||
|
if buf == [0x01] {
|
||||||
|
} else {
|
||||||
|
// Search for second hit
|
||||||
|
let valid_val = 255
|
||||||
|
- server_q_resp
|
||||||
|
.iter()
|
||||||
|
.rev()
|
||||||
|
.position(|&r| r == 0x01)
|
||||||
|
.unwrap_or(0x00) as u8;
|
||||||
|
if valid_val == 0x00 {
|
||||||
|
eprintln!("No valid found");
|
||||||
|
}
|
||||||
|
// Craft next attack vector padding; 0x01, 0x02, ...
|
||||||
|
attack_counter[i as usize] = valid_val;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if chunk_counter + 1 < cipher_chunks.len() {
|
||||||
|
plaintext.push(
|
||||||
|
cipher_chunks[chunk_counter + 1][i]
|
||||||
|
^ (attack_counter[i as usize] ^ (15 - i as u8 + 1)),
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
plaintext.push(iv[i] ^ (attack_counter[i as usize] ^ (15 - i as u8 + 1)));
|
||||||
|
}
|
||||||
|
let range = i;
|
||||||
|
for pos in range..=15 {
|
||||||
|
let intermediate = attack_counter[pos as usize] ^ (15 - i as u8 + 1);
|
||||||
|
|
||||||
|
attack_counter[pos as usize] = intermediate ^ ((15 - i as u8 + 1) + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
stream.flush()?;
|
||||||
|
|
||||||
|
// Write plaintext
|
||||||
|
}
|
||||||
|
chunk_counter += 1;
|
||||||
|
stream.flush()?;
|
||||||
|
drop(stream);
|
||||||
|
}
|
||||||
|
|
||||||
|
plaintext.reverse();
|
||||||
|
|
||||||
|
eprintln!("{:02X?}", BASE64_STANDARD.encode(&plaintext));
|
||||||
|
Ok(plaintext)
|
||||||
|
} // the stream is closed here
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_connection() -> Result<()> {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
282
src/tasks/tasks01/pfmath.rs
Normal file
282
src/tasks/tasks01/pfmath.rs
Normal file
|
|
@ -0,0 +1,282 @@
|
||||||
|
|
||||||
|
use anyhow::Result;
|
||||||
|
use base64::{prelude::BASE64_STANDARD, Engine};
|
||||||
|
use serde_json::Value;
|
||||||
|
|
||||||
|
use crate::utils::{
|
||||||
|
self,
|
||||||
|
dff::ddf,
|
||||||
|
edf::edf,
|
||||||
|
field::FieldElement,
|
||||||
|
poly::{gcd, Polynomial},
|
||||||
|
sff::{sff, Factors},
|
||||||
|
};
|
||||||
|
|
||||||
|
pub fn gfpoly_add(args: &Value) -> Result<Polynomial> {
|
||||||
|
let poly_a = Polynomial::from_c_array(&args["A"].clone());
|
||||||
|
|
||||||
|
let poly_b = Polynomial::from_c_array(&args["B"].clone());
|
||||||
|
|
||||||
|
let result = poly_a + poly_b;
|
||||||
|
|
||||||
|
Ok(result)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn gfpoly_mul(args: &Value) -> Result<Polynomial> {
|
||||||
|
let poly_a = Polynomial::from_c_array(&args["A"].clone());
|
||||||
|
|
||||||
|
let poly_b = Polynomial::from_c_array(&args["B"].clone());
|
||||||
|
|
||||||
|
let result = poly_a * poly_b;
|
||||||
|
|
||||||
|
Ok(result)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn gfpoly_pow(args: &Value) -> Result<Polynomial> {
|
||||||
|
let poly_a = Polynomial::from_c_array(&args["A"].clone());
|
||||||
|
|
||||||
|
let k: u128 = serde_json::from_value(args["k"].clone())?;
|
||||||
|
|
||||||
|
let result = poly_a.pow(k);
|
||||||
|
|
||||||
|
Ok(result)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn gfdiv(args: &Value) -> Result<FieldElement> {
|
||||||
|
let f1_text: String = serde_json::from_value(args["a"].clone())?;
|
||||||
|
let f_a = FieldElement::new(BASE64_STANDARD.decode(f1_text)?);
|
||||||
|
|
||||||
|
let f2_text: String = serde_json::from_value(args["b"].clone())?;
|
||||||
|
let f_b = FieldElement::new(BASE64_STANDARD.decode(f2_text)?);
|
||||||
|
|
||||||
|
let result = f_a / f_b;
|
||||||
|
|
||||||
|
Ok(result)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn gfpoly_divmod(args: &Value) -> Result<(Polynomial, Polynomial)> {
|
||||||
|
let poly_a = Polynomial::from_c_array(&args["A"].clone());
|
||||||
|
|
||||||
|
let poly_b = Polynomial::from_c_array(&args["B"].clone());
|
||||||
|
|
||||||
|
let result = poly_a.div(&poly_b);
|
||||||
|
|
||||||
|
Ok(result)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn gfpoly_powmod(args: &Value) -> Result<Polynomial> {
|
||||||
|
let poly_a = Polynomial::from_c_array(&args["A"].clone());
|
||||||
|
|
||||||
|
let poly_m = Polynomial::from_c_array(&args["M"].clone());
|
||||||
|
|
||||||
|
let k: u128 = serde_json::from_value(args["k"].clone())?;
|
||||||
|
|
||||||
|
let result = poly_a.pow_mod(k, poly_m);
|
||||||
|
|
||||||
|
Ok(result)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn gfpoly_sort(args: &Value) -> Result<Vec<Polynomial>> {
|
||||||
|
let poly_arrays: Vec<Value> = serde_json::from_value(args["polys"].clone())?;
|
||||||
|
let mut polys: Vec<Polynomial> = vec![];
|
||||||
|
|
||||||
|
for array in poly_arrays {
|
||||||
|
polys.push(Polynomial::from_c_array(&array));
|
||||||
|
}
|
||||||
|
|
||||||
|
polys.sort();
|
||||||
|
//polys.sort();
|
||||||
|
Ok(polys)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn gfpoly_make_monic(args: &Value) -> Result<Polynomial> {
|
||||||
|
let poly_a = Polynomial::from_c_array(&args["A"].clone());
|
||||||
|
|
||||||
|
let result = poly_a.monic();
|
||||||
|
|
||||||
|
Ok(result)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn gfpoly_sqrt(args: &Value) -> Result<Polynomial> {
|
||||||
|
let poly_a = Polynomial::from_c_array(&args["Q"].clone());
|
||||||
|
|
||||||
|
let result = poly_a.sqrt();
|
||||||
|
|
||||||
|
Ok(result)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn gfpoly_diff(args: &Value) -> Result<Polynomial> {
|
||||||
|
let poly_f = Polynomial::from_c_array(&args["F"].clone());
|
||||||
|
|
||||||
|
let result = poly_f.diff();
|
||||||
|
|
||||||
|
Ok(result)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn gfpoly_gcd(args: &Value) -> Result<Polynomial> {
|
||||||
|
let poly_a = Polynomial::from_c_array(&args["A"].clone());
|
||||||
|
let poly_b = Polynomial::from_c_array(&args["B"].clone());
|
||||||
|
|
||||||
|
let result = gcd(&poly_a.monic(), &poly_b.monic());
|
||||||
|
|
||||||
|
Ok(result)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn gfpoly_factor_sff(arsg: &Value) -> Result<Vec<Factors>> {
|
||||||
|
let poly_f = Polynomial::from_c_array(&arsg["F"].clone());
|
||||||
|
|
||||||
|
let mut factors = sff(poly_f);
|
||||||
|
factors.sort();
|
||||||
|
let mut result: Vec<Factors> = vec![];
|
||||||
|
|
||||||
|
for (factor, exponent) in factors {
|
||||||
|
result.push(Factors {
|
||||||
|
factor: factor.to_c_array(),
|
||||||
|
exponent,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(result)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn gfpoly_factor_ddf(arsg: &Value) -> Result<Vec<utils::dff::Factors>> {
|
||||||
|
let poly_f = Polynomial::from_c_array(&arsg["F"].clone());
|
||||||
|
|
||||||
|
let mut factors = ddf(poly_f);
|
||||||
|
factors.sort();
|
||||||
|
let mut result: Vec<utils::dff::Factors> = vec![];
|
||||||
|
|
||||||
|
for (factor, degree) in factors {
|
||||||
|
result.push(utils::dff::Factors {
|
||||||
|
factor: factor.to_c_array(),
|
||||||
|
degree: degree as u32,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(result)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn gfpoly_factor_edf(arsg: &Value) -> Result<Vec<Vec<String>>> {
|
||||||
|
let poly_f = Polynomial::from_c_array(&arsg["F"].clone());
|
||||||
|
let d: u32 = serde_json::from_value(arsg["d"].clone())?;
|
||||||
|
|
||||||
|
let mut factors = edf(poly_f, d);
|
||||||
|
|
||||||
|
factors.sort();
|
||||||
|
|
||||||
|
let mut result: Vec<Vec<String>> = vec![];
|
||||||
|
|
||||||
|
for factor in factors {
|
||||||
|
result.push(factor.to_c_array())
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(result)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::*;
|
||||||
|
use serde_json::json;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_poly_sorting() {
|
||||||
|
let json1 = json!(
|
||||||
|
{"polys": [
|
||||||
|
[
|
||||||
|
"NeverGonnaGiveYouUpAAA==",
|
||||||
|
"NeverGonnaLetYouDownAA==",
|
||||||
|
"NeverGonnaRunAroundAAA==",
|
||||||
|
"AndDesertYouAAAAAAAAAA=="
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"WereNoStrangersToLoveA==",
|
||||||
|
"YouKnowTheRulesAAAAAAA==",
|
||||||
|
"AndSoDoIAAAAAAAAAAAAAA=="
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"NeverGonnaMakeYouCryAA==",
|
||||||
|
"NeverGonnaSayGoodbyeAA==",
|
||||||
|
"NeverGonnaTellALieAAAA==",
|
||||||
|
"AndHurtYouAAAAAAAAAAAA=="
|
||||||
|
]
|
||||||
|
]});
|
||||||
|
|
||||||
|
let expected = json!([
|
||||||
|
[
|
||||||
|
"WereNoStrangersToLoveA==",
|
||||||
|
"YouKnowTheRulesAAAAAAA==",
|
||||||
|
"AndSoDoIAAAAAAAAAAAAAA=="
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"NeverGonnaMakeYouCryAA==",
|
||||||
|
"NeverGonnaSayGoodbyeAA==",
|
||||||
|
"NeverGonnaTellALieAAAA==",
|
||||||
|
"AndHurtYouAAAAAAAAAAAA=="
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"NeverGonnaGiveYouUpAAA==",
|
||||||
|
"NeverGonnaLetYouDownAA==",
|
||||||
|
"NeverGonnaRunAroundAAA==",
|
||||||
|
"AndDesertYouAAAAAAAAAA=="
|
||||||
|
]
|
||||||
|
]);
|
||||||
|
|
||||||
|
let sorted_array = gfpoly_sort(&json1).unwrap();
|
||||||
|
let mut result: Vec<Vec<String>> = vec![];
|
||||||
|
for poly in sorted_array {
|
||||||
|
result.push(poly.to_c_array());
|
||||||
|
}
|
||||||
|
|
||||||
|
assert_eq!(json!(result), expected);
|
||||||
|
//assert_eq!(BASE64_STANDARD.encode(product), "MoAAAAAAAAAAAAAAAAAAAA==");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_poly_sorting_02() {
|
||||||
|
let json1 = json!(
|
||||||
|
{"polys": [
|
||||||
|
[
|
||||||
|
"AQAAAAAAAAAAAAAAAAAAAA==", // 0x01
|
||||||
|
"AgAAAAAAAAAAAAAAAAAAAA==", // 0x02
|
||||||
|
"AwAAAAAAAAAAAAAAAAAAAA==" // 0x03
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"AQAAAAAAAAAAAAAAAAAAAA==", // 0x01
|
||||||
|
"AgAAAAAAAAAAAAAAAAAAAA==", // 0x02
|
||||||
|
"BAAAAAAAAAAAAAAAAAAAAA==" // 0x04
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"AQAAAAAAAAAAAAAAAAAAAA==", // 0x01
|
||||||
|
"AgAAAAAAAAAAAAAAAAAAAA==" // 0x02
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"AQAAAAAAAAAAAAAAAAAAAA==", // 0x01
|
||||||
|
"AwAAAAAAAAAAAAAAAAAAAA==" // 0x03
|
||||||
|
]
|
||||||
|
],});
|
||||||
|
|
||||||
|
let expected = json!([
|
||||||
|
["AQAAAAAAAAAAAAAAAAAAAA==", "AgAAAAAAAAAAAAAAAAAAAA=="],
|
||||||
|
["AQAAAAAAAAAAAAAAAAAAAA==", "AwAAAAAAAAAAAAAAAAAAAA=="],
|
||||||
|
[
|
||||||
|
"AQAAAAAAAAAAAAAAAAAAAA==",
|
||||||
|
"AgAAAAAAAAAAAAAAAAAAAA==",
|
||||||
|
"BAAAAAAAAAAAAAAAAAAAAA=="
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"AQAAAAAAAAAAAAAAAAAAAA==",
|
||||||
|
"AgAAAAAAAAAAAAAAAAAAAA==",
|
||||||
|
"AwAAAAAAAAAAAAAAAAAAAA=="
|
||||||
|
]
|
||||||
|
]);
|
||||||
|
|
||||||
|
let sorted_array = gfpoly_sort(&json1).unwrap();
|
||||||
|
let mut result: Vec<Vec<String>> = vec![];
|
||||||
|
for poly in sorted_array {
|
||||||
|
result.push(poly.to_c_array());
|
||||||
|
}
|
||||||
|
|
||||||
|
assert_eq!(json!(result), expected);
|
||||||
|
//assert_eq!(BASE64_STANDARD.encode(product), "MoAAAAAAAAAAAAAAAAAAAA==");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -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,19 +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 xor_val: u128 = 0xc0ffeec0ffeec0ffeec0ffeec0ffee11;
|
|
||||||
|
|
||||||
let mode: String = serde_json::from_value(args["mode"].clone())?;
|
let mode: String = serde_json::from_value(args["mode"].clone())?;
|
||||||
match mode.as_str() {
|
match mode.as_str() {
|
||||||
"encrypt" => {
|
"encrypt" => {
|
||||||
//eprintln!("{:?}", plaintexts);
|
|
||||||
|
|
||||||
let output = BASE64_STANDARD.encode(sea_128_encrypt(&key, &input)?);
|
let output = BASE64_STANDARD.encode(sea_128_encrypt(&key, &input)?);
|
||||||
|
|
||||||
Ok(output)
|
Ok(output)
|
||||||
|
|
@ -35,7 +29,6 @@ pub fn sea128(args: &Value) -> Result<String> {
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
|
|
||||||
|
|
||||||
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.
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,12 @@
|
||||||
|
use crate::utils::{field::ByteArray, poly::gfmul};
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use openssl::symm::{Cipher, Crypter, Mode};
|
use openssl::symm::{Cipher, Crypter, Mode};
|
||||||
|
|
||||||
use crate::utils::field::ByteArray;
|
|
||||||
|
|
||||||
use super::math::xor_bytes;
|
use super::math::xor_bytes;
|
||||||
|
|
||||||
|
/// AES ENCRYPT
|
||||||
|
/// Function to perform encryption with AES ECB mode
|
||||||
|
/// Function does not use padding for blocks
|
||||||
pub fn aes_128_encrypt(key: &Vec<u8>, input: &Vec<u8>) -> Result<Vec<u8>> {
|
pub fn aes_128_encrypt(key: &Vec<u8>, input: &Vec<u8>) -> Result<Vec<u8>> {
|
||||||
let mut encrypter = Crypter::new(Cipher::aes_128_ecb(), Mode::Encrypt, &key, None)?;
|
let mut encrypter = Crypter::new(Cipher::aes_128_ecb(), Mode::Encrypt, &key, None)?;
|
||||||
encrypter.pad(false);
|
encrypter.pad(false);
|
||||||
|
|
@ -21,6 +22,9 @@ pub fn aes_128_encrypt(key: &Vec<u8>, input: &Vec<u8>) -> Result<Vec<u8>> {
|
||||||
Ok(ciphertext)
|
Ok(ciphertext)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// AES DECRPYT
|
||||||
|
/// Function to perform decryption with AES ECB mode
|
||||||
|
/// Function does not use padding for blocks
|
||||||
pub fn aes_128_decrypt(key: &Vec<u8>, input: &Vec<u8>) -> Result<Vec<u8>> {
|
pub fn aes_128_decrypt(key: &Vec<u8>, input: &Vec<u8>) -> Result<Vec<u8>> {
|
||||||
let mut decrypter = Crypter::new(Cipher::aes_128_ecb(), Mode::Decrypt, key, None)?;
|
let mut decrypter = Crypter::new(Cipher::aes_128_ecb(), Mode::Decrypt, key, None)?;
|
||||||
decrypter.pad(false);
|
decrypter.pad(false);
|
||||||
|
|
@ -33,13 +37,18 @@ pub fn aes_128_decrypt(key: &Vec<u8>, input: &Vec<u8>) -> Result<Vec<u8>> {
|
||||||
|
|
||||||
let mut bytes: [u8; 16] = [0u8; 16];
|
let mut bytes: [u8; 16] = [0u8; 16];
|
||||||
bytes.copy_from_slice(&plaintext);
|
bytes.copy_from_slice(&plaintext);
|
||||||
let number: u128 = <u128>::from_be_bytes(bytes);
|
|
||||||
|
|
||||||
Ok(plaintext)
|
Ok(plaintext)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// SEA ENCRYPT
|
||||||
|
/// Function to perform sea encrption.
|
||||||
|
/// At its core, the function ses the AES ENCRYPT, but then xors with a constant value of:
|
||||||
|
/// 0xc0ffeec0ffeec0ffeec0ffeec0ffee11
|
||||||
pub fn sea_128_encrypt(key: &Vec<u8>, input: &Vec<u8>) -> Result<Vec<u8>> {
|
pub fn sea_128_encrypt(key: &Vec<u8>, input: &Vec<u8>) -> Result<Vec<u8>> {
|
||||||
|
// Constant value used for XOR
|
||||||
let xor_val: u128 = 0xc0ffeec0ffeec0ffeec0ffeec0ffee11;
|
let xor_val: u128 = 0xc0ffeec0ffeec0ffeec0ffeec0ffee11;
|
||||||
|
|
||||||
let sea128_out = xor_bytes(
|
let sea128_out = xor_bytes(
|
||||||
&aes_128_encrypt(key, input)?,
|
&aes_128_encrypt(key, input)?,
|
||||||
xor_val.to_be_bytes().to_vec(),
|
xor_val.to_be_bytes().to_vec(),
|
||||||
|
|
@ -47,40 +56,32 @@ pub fn sea_128_encrypt(key: &Vec<u8>, input: &Vec<u8>) -> Result<Vec<u8>> {
|
||||||
Ok(sea128_out)
|
Ok(sea128_out)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// SEA DECRYPT
|
||||||
|
/// Function to perform sea decryption.
|
||||||
|
/// At its core, the function ses the AES DECRYPT, but then xors with a constant value of:
|
||||||
|
/// 0xc0ffeec0ffeec0ffeec0ffeec0ffee11
|
||||||
pub fn sea_128_decrypt(key: &Vec<u8>, input: &Vec<u8>) -> Result<Vec<u8>> {
|
pub fn sea_128_decrypt(key: &Vec<u8>, input: &Vec<u8>) -> Result<Vec<u8>> {
|
||||||
|
// Constant value used for XOR
|
||||||
let xor_val: u128 = 0xc0ffeec0ffeec0ffeec0ffeec0ffee11;
|
let xor_val: u128 = 0xc0ffeec0ffeec0ffeec0ffeec0ffee11;
|
||||||
|
|
||||||
let intermediate = xor_bytes(input, xor_val.to_be_bytes().to_vec())?;
|
let intermediate = xor_bytes(input, xor_val.to_be_bytes().to_vec())?;
|
||||||
Ok(aes_128_decrypt(&key, &intermediate)?)
|
Ok(aes_128_decrypt(&key, &intermediate)?)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Function to perform xex encryption.
|
||||||
|
/// The function performs the encryption for XEX on the basis of the SEA ENCRYPT.
|
||||||
pub fn xex_encrypt(mut key: Vec<u8>, tweak: &Vec<u8>, input: &Vec<u8>) -> Result<Vec<u8>> {
|
pub fn xex_encrypt(mut key: Vec<u8>, tweak: &Vec<u8>, input: &Vec<u8>) -> Result<Vec<u8>> {
|
||||||
let key2: Vec<u8> = key.split_off(16);
|
let key2: Vec<u8> = key.split_off(16);
|
||||||
//let key1: ByteArray = ByteArray(vec![key_parts[0]]);
|
|
||||||
//let key2: ByteArray = ByteArray(vec![key_parts[1]]);
|
|
||||||
|
|
||||||
let input_chunks: Vec<Vec<u8>> = input.chunks(16).map(|x| x.to_vec()).collect();
|
let input_chunks: Vec<Vec<u8>> = input.chunks(16).map(|x| x.to_vec()).collect();
|
||||||
|
|
||||||
let mut output: Vec<u8> = vec![];
|
let mut output: Vec<u8> = vec![];
|
||||||
//assert!(key.len() % 16 == 0, "Failure: Key len {}", key.len());
|
let mut tweak_block: ByteArray = ByteArray(sea_128_encrypt(&key2, tweak)?);
|
||||||
//assert!(key2.len() % 16 == 0, "Failure: Key2 len {}", key2.len());
|
|
||||||
let mut tweak_block: ByteArray = ByteArray::from(sea_128_encrypt(&key2, tweak)?);
|
|
||||||
|
|
||||||
//dbg!("input_chunks: {:001X?}", &input_chunks);
|
|
||||||
|
|
||||||
for chunk in input_chunks {
|
for chunk in input_chunks {
|
||||||
let plaintext_intermediate = xor_bytes(&tweak_block.vector, chunk)?;
|
let plaintext_intermediate = xor_bytes(&tweak_block.0, chunk)?;
|
||||||
/*
|
|
||||||
assert!(
|
|
||||||
plaintext_intermediate.len() % 16 == 0,
|
|
||||||
"Failure: plaintext_intermediate len was {}",
|
|
||||||
plaintext_intermediate.len()
|
|
||||||
);
|
|
||||||
*/
|
|
||||||
//assert!(key.len() % 16 == 0, "Failure: Key len {}", key.len());
|
|
||||||
//assert!(key2.len() % 16 == 0, "Failure: Key2 len {}", key2.len());
|
|
||||||
let cypher_block_intermediate = sea_128_encrypt(&key, &plaintext_intermediate)?;
|
let cypher_block_intermediate = sea_128_encrypt(&key, &plaintext_intermediate)?;
|
||||||
let mut cypher_block = xor_bytes(&tweak_block.vector, cypher_block_intermediate)?;
|
let mut cypher_block = xor_bytes(&tweak_block.0, cypher_block_intermediate)?;
|
||||||
output.append(cypher_block.as_mut());
|
output.append(cypher_block.as_mut());
|
||||||
tweak_block.left_shift_reduce("xex");
|
tweak_block.left_shift_reduce("xex");
|
||||||
}
|
}
|
||||||
|
|
@ -90,30 +91,15 @@ pub fn xex_encrypt(mut key: Vec<u8>, tweak: &Vec<u8>, input: &Vec<u8>) -> Result
|
||||||
|
|
||||||
pub fn xex_decrypt(mut key: Vec<u8>, tweak: &Vec<u8>, input: &Vec<u8>) -> Result<Vec<u8>> {
|
pub fn xex_decrypt(mut key: Vec<u8>, tweak: &Vec<u8>, input: &Vec<u8>) -> Result<Vec<u8>> {
|
||||||
let key2: Vec<u8> = key.split_off(16);
|
let key2: Vec<u8> = key.split_off(16);
|
||||||
//let key1: ByteArray = ByteArray(vec![key_parts[0]]);
|
|
||||||
//let key2: ByteArray = ByteArray(vec![key_parts[1]]);
|
|
||||||
|
|
||||||
let input_chunks: Vec<Vec<u8>> = input.chunks(16).map(|x| x.to_vec()).collect();
|
let input_chunks: Vec<Vec<u8>> = input.chunks(16).map(|x| x.to_vec()).collect();
|
||||||
|
|
||||||
let mut output: Vec<u8> = vec![];
|
let mut output: Vec<u8> = vec![];
|
||||||
//assert!(key.len() % 16 == 0, "Failure: Key len {}", key.len());
|
let mut tweak_block: ByteArray = ByteArray(sea_128_encrypt(&key2, tweak)?);
|
||||||
//assert!(key2.len() % 16 == 0, "Failure: Key2 len {}", key2.len());
|
|
||||||
let mut tweak_block: ByteArray = ByteArray::from(sea_128_encrypt(&key2, tweak)?);
|
|
||||||
|
|
||||||
for chunk in input_chunks {
|
for chunk in input_chunks {
|
||||||
let cyphertext_intermediate = xor_bytes(&tweak_block.vector, chunk)?;
|
let cyphertext_intermediate = xor_bytes(&tweak_block.0, chunk)?;
|
||||||
|
|
||||||
/*
|
|
||||||
assert!(
|
|
||||||
cyphertext_intermediate.len() % 16 == 0,
|
|
||||||
"Failure: plaintext_intermediate len was {}",
|
|
||||||
cyphertext_intermediate.len()
|
|
||||||
);
|
|
||||||
assert!(key.len() % 16 == 0, "Failure: Key len {}", key.len());
|
|
||||||
assert!(key2.len() % 16 == 0, "Failure: Key2 len {}", key2.len());
|
|
||||||
*/
|
|
||||||
let plaintext_block_intermediate = sea_128_decrypt(&key, &cyphertext_intermediate)?;
|
let plaintext_block_intermediate = sea_128_decrypt(&key, &cyphertext_intermediate)?;
|
||||||
let mut cypher_block = xor_bytes(&tweak_block.vector, plaintext_block_intermediate)?;
|
let mut cypher_block = xor_bytes(&tweak_block.0, plaintext_block_intermediate)?;
|
||||||
output.append(cypher_block.as_mut());
|
output.append(cypher_block.as_mut());
|
||||||
tweak_block.left_shift_reduce("xex");
|
tweak_block.left_shift_reduce("xex");
|
||||||
}
|
}
|
||||||
|
|
@ -121,48 +107,220 @@ pub fn xex_decrypt(mut key: Vec<u8>, tweak: &Vec<u8>, input: &Vec<u8>) -> Result
|
||||||
Ok(output)
|
Ok(output)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn gcm_aes_encrypt(
|
pub fn gcm_encrypt_aes(
|
||||||
action: &str,
|
|
||||||
mut nonce: Vec<u8>,
|
mut nonce: Vec<u8>,
|
||||||
key: Vec<u8>,
|
key: Vec<u8>,
|
||||||
plaintext: Vec<u8>,
|
plaintext: Vec<u8>,
|
||||||
ad: ByteArray,
|
ad: Vec<u8>,
|
||||||
) -> Result<Vec<u8>> {
|
) -> Result<(Vec<u8>, Vec<u8>, Vec<u8>, Vec<u8>)> {
|
||||||
nonce.append(vec![0x01].as_mut());
|
let mut ciphertext: Vec<u8> = vec![];
|
||||||
|
|
||||||
let auth_text_xor_block = aes_128_encrypt(&key, &nonce);
|
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());
|
||||||
|
|
||||||
let auth_key_h = aes_128_encrypt(&key, &vec![0]);
|
let auth_tag_xor = aes_128_encrypt(&key, &nonce)?;
|
||||||
|
|
||||||
let plaintext: Vec<Vec<u8>> = plaintext.chunks(16).map(|x| x.to_vec()).collect();
|
let auth_key_h = aes_128_encrypt(&key, &0u128.to_be_bytes().to_vec())?;
|
||||||
|
|
||||||
let mut output: Vec<Vec<u8>> = vec![];
|
let plaintext_chunks: Vec<Vec<u8>> = plaintext.chunks(16).map(|x| x.to_vec()).collect();
|
||||||
|
|
||||||
for (ctr, chunk) in plaintext.iter().enumerate() {
|
counter = 2;
|
||||||
nonce.pop();
|
for chunk in plaintext_chunks {
|
||||||
nonce.push(ctr as u8);
|
nonce.drain(12..);
|
||||||
|
nonce.append(counter.to_be_bytes().to_vec().as_mut());
|
||||||
|
|
||||||
let intermediate = aes_128_encrypt(&key, &nonce)?;
|
let inter1 = aes_128_encrypt(&key, &nonce)?;
|
||||||
|
|
||||||
let intermediate2 = xor_bytes(chunk, intermediate)?;
|
let mut inter2 = xor_bytes(&inter1, chunk.clone())?;
|
||||||
|
|
||||||
output.push(intermediate2);
|
ciphertext.append(inter2.as_mut());
|
||||||
|
counter += 1;
|
||||||
}
|
}
|
||||||
todo!();
|
|
||||||
|
let mut l_field: Vec<u8> = ((ad.len() * 8) as u64).to_be_bytes().to_vec();
|
||||||
|
let mut c_len: Vec<u8> = ((ciphertext.len() * 8) as u64).to_be_bytes().to_vec();
|
||||||
|
l_field.append(c_len.as_mut());
|
||||||
|
|
||||||
|
let auth_tag = xor_bytes(
|
||||||
|
&ghash(auth_key_h.clone(), ad, ciphertext.clone(), l_field.clone())?,
|
||||||
|
auth_tag_xor,
|
||||||
|
)?;
|
||||||
|
|
||||||
|
Ok((ciphertext, auth_tag, l_field, auth_key_h))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn ghash(auth_key_h: Vec<u8>, ad: Vec<u8>, ciphertext: Vec<Vec<u8>>) {
|
pub fn gcm_decrypt_aes(
|
||||||
let output: Vec<u8> = vec![0, 16];
|
mut nonce: Vec<u8>,
|
||||||
|
key: Vec<u8>,
|
||||||
|
ciphertext: Vec<u8>,
|
||||||
|
ad: Vec<u8>,
|
||||||
|
tag: Vec<u8>,
|
||||||
|
) -> Result<(Vec<u8>, bool)> {
|
||||||
|
let mut plaintext: Vec<u8> = vec![];
|
||||||
|
|
||||||
let inter1 = xor_bytes(&output, ad);
|
let mut counter: u32 = 1;
|
||||||
|
nonce.append(counter.to_be_bytes().to_vec().as_mut());
|
||||||
|
|
||||||
|
let auth_tag_xor = aes_128_encrypt(&key, &nonce)?;
|
||||||
|
|
||||||
|
let auth_key_h = aes_128_encrypt(&key, &0u128.to_be_bytes().to_vec())?;
|
||||||
|
|
||||||
|
let ciphertext_chunks: Vec<Vec<u8>> = ciphertext.chunks(16).map(|x| x.to_vec()).collect();
|
||||||
|
|
||||||
|
counter = 2;
|
||||||
|
for chunk in ciphertext_chunks {
|
||||||
|
nonce.drain(12..);
|
||||||
|
nonce.append(counter.to_be_bytes().to_vec().as_mut());
|
||||||
|
|
||||||
|
let inter1 = aes_128_encrypt(&key, &nonce)?;
|
||||||
|
|
||||||
|
let mut inter2 = xor_bytes(&inter1, chunk.clone())?;
|
||||||
|
|
||||||
|
plaintext.append(inter2.as_mut());
|
||||||
|
counter += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut l_field: Vec<u8> = ((ad.len() * 8) as u64).to_be_bytes().to_vec();
|
||||||
|
let mut c_len: Vec<u8> = ((ciphertext.len() * 8) as u64).to_be_bytes().to_vec();
|
||||||
|
l_field.append(c_len.as_mut());
|
||||||
|
|
||||||
|
let auth_tag = xor_bytes(
|
||||||
|
&ghash(auth_key_h.clone(), ad, ciphertext.clone(), l_field.clone())?,
|
||||||
|
auth_tag_xor,
|
||||||
|
)?;
|
||||||
|
|
||||||
|
let valid = auth_tag == tag;
|
||||||
|
|
||||||
|
Ok((plaintext, valid))
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
pub fn gcm_encrypt_sea(
|
||||||
* let mut bytes: [u8; 16] = [0u8; 16];
|
mut nonce: Vec<u8>,
|
||||||
bytes.copy_from_slice(&ciphertext);
|
key: Vec<u8>,
|
||||||
let number: u128 = <u128>::from_be_bytes(bytes);
|
plaintext: Vec<u8>,
|
||||||
|
ad: Vec<u8>,
|
||||||
|
) -> Result<(Vec<u8>, Vec<u8>, Vec<u8>, Vec<u8>)> {
|
||||||
|
let mut ciphertext: Vec<u8> = vec![];
|
||||||
|
|
||||||
* */
|
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());
|
||||||
|
|
||||||
|
let auth_tag_xor = sea_128_encrypt(&key, &nonce)?;
|
||||||
|
|
||||||
|
let auth_key_h = sea_128_encrypt(&key, &0u128.to_be_bytes().to_vec())?;
|
||||||
|
|
||||||
|
let plaintext_chunks: Vec<Vec<u8>> = plaintext.chunks(16).map(|x| x.to_vec()).collect();
|
||||||
|
|
||||||
|
counter = 2;
|
||||||
|
for chunk in plaintext_chunks {
|
||||||
|
nonce.drain(12..);
|
||||||
|
nonce.append(counter.to_be_bytes().to_vec().as_mut());
|
||||||
|
|
||||||
|
let inter1 = sea_128_encrypt(&key, &nonce)?;
|
||||||
|
|
||||||
|
let mut inter2 = xor_bytes(&inter1, chunk.clone())?;
|
||||||
|
|
||||||
|
ciphertext.append(inter2.as_mut());
|
||||||
|
counter += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut l_field: Vec<u8> = ((ad.len() * 8) as u64).to_be_bytes().to_vec();
|
||||||
|
let mut c_len: Vec<u8> = ((ciphertext.len() * 8) as u64).to_be_bytes().to_vec();
|
||||||
|
l_field.append(c_len.as_mut());
|
||||||
|
|
||||||
|
let auth_tag = xor_bytes(
|
||||||
|
&ghash(auth_key_h.clone(), ad, ciphertext.clone(), l_field.clone())?,
|
||||||
|
auth_tag_xor,
|
||||||
|
)?;
|
||||||
|
|
||||||
|
Ok((ciphertext, auth_tag, l_field, auth_key_h))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn gcm_decrypt_sea(
|
||||||
|
mut nonce: Vec<u8>,
|
||||||
|
key: Vec<u8>,
|
||||||
|
ciphertext: Vec<u8>,
|
||||||
|
ad: Vec<u8>,
|
||||||
|
tag: Vec<u8>,
|
||||||
|
) -> Result<(Vec<u8>, bool)> {
|
||||||
|
let mut plaintext: Vec<u8> = vec![];
|
||||||
|
|
||||||
|
let mut counter: u32 = 1;
|
||||||
|
nonce.append(counter.to_be_bytes().to_vec().as_mut());
|
||||||
|
|
||||||
|
let auth_tag_xor = sea_128_encrypt(&key, &nonce)?;
|
||||||
|
|
||||||
|
let auth_key_h = sea_128_encrypt(&key, &0u128.to_be_bytes().to_vec())?;
|
||||||
|
|
||||||
|
let plaintext_chunks: Vec<Vec<u8>> = ciphertext.chunks(16).map(|x| x.to_vec()).collect();
|
||||||
|
|
||||||
|
counter = 2;
|
||||||
|
for chunk in plaintext_chunks {
|
||||||
|
nonce.drain(12..);
|
||||||
|
nonce.append(counter.to_be_bytes().to_vec().as_mut());
|
||||||
|
|
||||||
|
let inter1 = sea_128_encrypt(&key, &nonce)?;
|
||||||
|
|
||||||
|
let mut inter2 = xor_bytes(&inter1, chunk.clone())?;
|
||||||
|
|
||||||
|
plaintext.append(inter2.as_mut());
|
||||||
|
counter += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut l_field: Vec<u8> = ((ad.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());
|
||||||
|
|
||||||
|
let auth_tag = xor_bytes(
|
||||||
|
&ghash(auth_key_h.clone(), ad, ciphertext.clone(), l_field.clone())?,
|
||||||
|
auth_tag_xor,
|
||||||
|
)?;
|
||||||
|
|
||||||
|
let valid = auth_tag == tag;
|
||||||
|
|
||||||
|
Ok((plaintext, valid))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn ghash(
|
||||||
|
auth_key_h: Vec<u8>,
|
||||||
|
mut ad: Vec<u8>,
|
||||||
|
mut ciphertext: Vec<u8>,
|
||||||
|
l_field: Vec<u8>,
|
||||||
|
) -> Result<Vec<u8>> {
|
||||||
|
let output: Vec<u8> = vec![0; 16];
|
||||||
|
|
||||||
|
if ad.len() % 16 != 0 || ad.is_empty() {
|
||||||
|
ad.append(vec![0u8; 16 - (ad.len() % 16)].as_mut());
|
||||||
|
}
|
||||||
|
|
||||||
|
if ciphertext.len() % 16 != 0 {
|
||||||
|
ciphertext.append(vec![0u8; 16 - (ciphertext.len() % 16)].as_mut());
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut ad_chunks = ad.chunks(16);
|
||||||
|
|
||||||
|
let inter1 = xor_bytes(&output, ad_chunks.next().unwrap().to_vec())?;
|
||||||
|
let mut inter_loop = gfmul(&inter1, &auth_key_h, "gcm")?;
|
||||||
|
|
||||||
|
for chunk in ad_chunks {
|
||||||
|
let inter2 = xor_bytes(&inter_loop, chunk.to_vec())?;
|
||||||
|
inter_loop = gfmul(&inter2, &auth_key_h, "gcm")?;
|
||||||
|
}
|
||||||
|
|
||||||
|
let cipher_chunks = ciphertext.chunks(16);
|
||||||
|
|
||||||
|
for chunk in cipher_chunks {
|
||||||
|
let inter3 = xor_bytes(&inter_loop, chunk.to_vec())?;
|
||||||
|
inter_loop = gfmul(&inter3, &auth_key_h, "gcm")?;
|
||||||
|
}
|
||||||
|
|
||||||
|
let inter4 = xor_bytes(&inter_loop, l_field)?;
|
||||||
|
inter_loop = gfmul(&inter4, &auth_key_h, "gcm")?;
|
||||||
|
|
||||||
|
Ok(inter_loop)
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
|
|
@ -215,4 +373,190 @@ mod tests {
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_gcm_encrypt_aes() -> Result<()> {
|
||||||
|
let nonce = BASE64_STANDARD.decode("4gF+BtR3ku/PUQci")?;
|
||||||
|
let key = BASE64_STANDARD.decode("Xjq/GkpTSWoe3ZH0F+tjrQ==")?;
|
||||||
|
let plaintext = BASE64_STANDARD.decode("RGFzIGlzdCBlaW4gVGVzdA==")?;
|
||||||
|
let ad = BASE64_STANDARD.decode("QUQtRGF0ZW4=")?;
|
||||||
|
|
||||||
|
let (ciphertext, auth_tag, l_field, auth_key_h) =
|
||||||
|
gcm_encrypt_aes(nonce, key, plaintext, ad)?;
|
||||||
|
|
||||||
|
eprintln!(
|
||||||
|
"Cipher: {:001X?} \n Tag: {:001X?} \n L_Field: {:001X?} \n H: {:001X?}",
|
||||||
|
BASE64_STANDARD.encode(&ciphertext),
|
||||||
|
BASE64_STANDARD.encode(&auth_tag),
|
||||||
|
BASE64_STANDARD.encode(&l_field),
|
||||||
|
BASE64_STANDARD.encode(&auth_key_h)
|
||||||
|
);
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
BASE64_STANDARD.encode(ciphertext),
|
||||||
|
"ET3RmvH/Hbuxba63EuPRrw=="
|
||||||
|
);
|
||||||
|
assert_eq!(BASE64_STANDARD.encode(auth_tag), "Mp0APJb/ZIURRwQlMgNN/w==");
|
||||||
|
assert_eq!(BASE64_STANDARD.encode(l_field), "AAAAAAAAAEAAAAAAAAAAgA==");
|
||||||
|
assert_eq!(
|
||||||
|
BASE64_STANDARD.encode(auth_key_h),
|
||||||
|
"Bu6ywbsUKlpmZXMQyuGAng=="
|
||||||
|
);
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_gcm_encrypt_aes_long_ad() -> Result<()> {
|
||||||
|
let nonce = BASE64_STANDARD.decode("yv66vvrO263eyviI")?;
|
||||||
|
let key = BASE64_STANDARD.decode("/v/pkoZlcxxtao+UZzCDCA==")?;
|
||||||
|
let plaintext = BASE64_STANDARD.decode(
|
||||||
|
"2TEyJfiEBuWlWQnFr/UmmoanqVMVNPfaLkwwPYoxinIcPAyVlWgJUy/PDiRJprUlsWrt9aoN5le6Y3s5",
|
||||||
|
)?;
|
||||||
|
let ad = BASE64_STANDARD.decode("/u36zt6tvu/+7frO3q2+76ut2tI=")?;
|
||||||
|
|
||||||
|
let (ciphertext, auth_tag, l_field, auth_key_h) =
|
||||||
|
gcm_encrypt_aes(nonce, key, plaintext, ad)?;
|
||||||
|
|
||||||
|
eprintln!(
|
||||||
|
"Cipher: {:001X?} \n Tag: {:001X?} \n L_Field: {:001X?} \n H: {:001X?}",
|
||||||
|
BASE64_STANDARD.encode(&ciphertext),
|
||||||
|
BASE64_STANDARD.encode(&auth_tag),
|
||||||
|
BASE64_STANDARD.encode(&l_field),
|
||||||
|
BASE64_STANDARD.encode(&auth_key_h)
|
||||||
|
);
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
BASE64_STANDARD.encode(ciphertext),
|
||||||
|
"QoMewiF3dCRLciG3hNDUnOOqIS8sAqTgNcF+IymsoS4h1RSyVGaTHH2PalqshKoFG6MLOWoKrJc9WOCR"
|
||||||
|
);
|
||||||
|
assert_eq!(BASE64_STANDARD.encode(auth_tag), "W8lPvDIhpduU+ula5xIaRw==");
|
||||||
|
assert_eq!(BASE64_STANDARD.encode(l_field), "AAAAAAAAAKAAAAAAAAAB4A==");
|
||||||
|
assert_eq!(
|
||||||
|
BASE64_STANDARD.encode(auth_key_h),
|
||||||
|
"uDtTNwi/U10KpuUpgNU7eA=="
|
||||||
|
);
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
* TODO:Not sure if this case can really happen in our data
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_gcm_encrypt_aes_long_0000() -> Result<()> {
|
||||||
|
let nonce = BASE64_STANDARD.decode(
|
||||||
|
"kxMiXfiEBuVVkJxa/1Jpqmp6lThTT32h5MMD0qMYpyjDwMlRVoCVOfzw4kKaa1JUFq7b9aDealemN7Ob",
|
||||||
|
)?;
|
||||||
|
let key = BASE64_STANDARD.decode("/v/pkoZlcxxtao+UZzCDCP7/6ZKGZXMcbWqPlGcwgwg=")?;
|
||||||
|
let plaintext = BASE64_STANDARD.decode(
|
||||||
|
"2TEyJfiEBuWlWQnFr/UmmoanqVMVNPfaLkwwPYoxinIcPAyVlWgJUy/PDiRJprUlsWrt9aoN5le6Y3s5",
|
||||||
|
)?;
|
||||||
|
let ad = BASE64_STANDARD.decode("/u36zt6tvu/+7frO3q2+76ut2tI=")?;
|
||||||
|
|
||||||
|
let (ciphertext, auth_tag, l_field, auth_key_h) =
|
||||||
|
gcm_encrypt_aes(nonce, key, plaintext, ad)?;
|
||||||
|
|
||||||
|
eprintln!(
|
||||||
|
"Cipher: {:001X?} \n Tag: {:001X?} \n L_Field: {:001X?} \n H: {:001X?}",
|
||||||
|
BASE64_STANDARD.encode(&ciphertext),
|
||||||
|
BASE64_STANDARD.encode(&auth_tag),
|
||||||
|
BASE64_STANDARD.encode(&l_field),
|
||||||
|
BASE64_STANDARD.encode(&auth_key_h)
|
||||||
|
);
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
BASE64_STANDARD.encode(ciphertext),
|
||||||
|
"Wo3vLwyeU/H3XXhTZZ4qIO6ysiqv3mQZoFirT290a/QPwMO3gPJERS2j6/HF2CzeokGJlyAO+C5Ern4/"
|
||||||
|
);
|
||||||
|
assert_eq!(BASE64_STANDARD.encode(auth_tag), "pEqCZu4cjrDItdTPWunxmg==");
|
||||||
|
assert_eq!(BASE64_STANDARD.encode(l_field), "AAAAAAAAAKAAAAAAAAAB4A==");
|
||||||
|
assert_eq!(
|
||||||
|
BASE64_STANDARD.encode(auth_key_h),
|
||||||
|
"rL7yBXm0uOvOiJushzLa1w=="
|
||||||
|
);
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
#[test]
|
||||||
|
fn test_gcm_encrypt_sea() -> Result<()> {
|
||||||
|
let nonce = BASE64_STANDARD.decode("4gF+BtR3ku/PUQci")?;
|
||||||
|
let key = BASE64_STANDARD.decode("Xjq/GkpTSWoe3ZH0F+tjrQ==")?;
|
||||||
|
let plaintext = BASE64_STANDARD.decode("RGFzIGlzdCBlaW4gVGVzdA==")?;
|
||||||
|
let ad = BASE64_STANDARD.decode("QUQtRGF0ZW4=")?;
|
||||||
|
|
||||||
|
let (ciphertext, auth_tag, l_field, auth_key_h) =
|
||||||
|
gcm_encrypt_sea(nonce, key, plaintext, ad)?;
|
||||||
|
|
||||||
|
eprintln!(
|
||||||
|
"Cipher: {:001X?} \n Tag: {:001X?} \n L_Field: {:001X?} \n H: {:001X?}",
|
||||||
|
BASE64_STANDARD.encode(&ciphertext),
|
||||||
|
BASE64_STANDARD.encode(&auth_tag),
|
||||||
|
BASE64_STANDARD.encode(&l_field),
|
||||||
|
BASE64_STANDARD.encode(&auth_key_h)
|
||||||
|
);
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
BASE64_STANDARD.encode(ciphertext),
|
||||||
|
"0cI/Wg4R3URfrVFZ0hw/vg=="
|
||||||
|
);
|
||||||
|
assert_eq!(BASE64_STANDARD.encode(auth_tag), "ysDdzOSnqLH0MQ+Mkb23gw==");
|
||||||
|
assert_eq!(BASE64_STANDARD.encode(l_field), "AAAAAAAAAEAAAAAAAAAAgA==");
|
||||||
|
assert_eq!(
|
||||||
|
BASE64_STANDARD.encode(auth_key_h),
|
||||||
|
"xhFcAUT66qWIpYz+Ch5ujw=="
|
||||||
|
);
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_gcm_decrypt_aes() -> Result<()> {
|
||||||
|
let nonce = BASE64_STANDARD.decode("4gF+BtR3ku/PUQci")?;
|
||||||
|
let key = BASE64_STANDARD.decode("Xjq/GkpTSWoe3ZH0F+tjrQ==")?;
|
||||||
|
let ciphertext = BASE64_STANDARD.decode("ET3RmvH/Hbuxba63EuPRrw==")?;
|
||||||
|
let ad = BASE64_STANDARD.decode("QUQtRGF0ZW4=")?;
|
||||||
|
let tag = BASE64_STANDARD.decode("Mp0APJb/ZIURRwQlMgNN/w==")?;
|
||||||
|
|
||||||
|
let (plaintext, valid) = gcm_decrypt_aes(nonce, key, ciphertext, ad, tag)?;
|
||||||
|
|
||||||
|
eprintln!(
|
||||||
|
"Cipher: {:001X?} \n Valids: {:001X?}",
|
||||||
|
BASE64_STANDARD.encode(&plaintext),
|
||||||
|
&valid,
|
||||||
|
);
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
BASE64_STANDARD.encode(plaintext),
|
||||||
|
"RGFzIGlzdCBlaW4gVGVzdA=="
|
||||||
|
);
|
||||||
|
assert_eq!(valid, true);
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_gcm_decrypt_sea() -> Result<()> {
|
||||||
|
let nonce = BASE64_STANDARD.decode("4gF+BtR3ku/PUQci")?;
|
||||||
|
let key = BASE64_STANDARD.decode("Xjq/GkpTSWoe3ZH0F+tjrQ==")?;
|
||||||
|
let ciphertext = BASE64_STANDARD.decode("0cI/Wg4R3URfrVFZ0hw/vg==")?;
|
||||||
|
let ad = BASE64_STANDARD.decode("QUQtRGF0ZW4=")?;
|
||||||
|
let tag = BASE64_STANDARD.decode("ysDdzOSnqLH0MQ+Mkb23gw==")?;
|
||||||
|
|
||||||
|
let (plaintext, valid) = gcm_decrypt_sea(nonce, key, ciphertext, ad, tag)?;
|
||||||
|
|
||||||
|
eprintln!(
|
||||||
|
"Plaintext: {:001X?} \n Valid: {:001X?}",
|
||||||
|
BASE64_STANDARD.encode(&plaintext),
|
||||||
|
&valid,
|
||||||
|
);
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
BASE64_STANDARD.encode(plaintext),
|
||||||
|
"RGFzIGlzdCBlaW4gVGVzdA=="
|
||||||
|
);
|
||||||
|
assert_eq!(valid, true);
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
81
src/utils/dff.rs
Normal file
81
src/utils/dff.rs
Normal file
|
|
@ -0,0 +1,81 @@
|
||||||
|
use std::usize;
|
||||||
|
|
||||||
|
use num::{pow::Pow, BigUint, FromPrimitive};
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
|
use super::poly::{gcd, Polynomial};
|
||||||
|
|
||||||
|
#[derive(Debug, Serialize, Deserialize)]
|
||||||
|
pub struct Factors {
|
||||||
|
pub factor: Vec<String>,
|
||||||
|
pub degree: u32,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn ddf(f: Polynomial) -> Vec<(Polynomial, u128)> {
|
||||||
|
let q = BigUint::pow(&BigUint::from_u8(2).unwrap(), 128);
|
||||||
|
|
||||||
|
let mut z: Vec<(Polynomial, u128)> = vec![];
|
||||||
|
let mut d: u128 = 1;
|
||||||
|
let mut f_star = f.clone();
|
||||||
|
|
||||||
|
let one_cmp = Polynomial::one();
|
||||||
|
|
||||||
|
while f_star.degree() as u128 >= (2 * d) {
|
||||||
|
let h = Polynomial::x().bpow_mod(q.clone().pow(d), &f_star.clone()) + Polynomial::x();
|
||||||
|
|
||||||
|
let g = gcd(&h, &f_star);
|
||||||
|
if g != one_cmp {
|
||||||
|
z.push((g.clone(), d));
|
||||||
|
f_star = f_star.div(&g).0;
|
||||||
|
}
|
||||||
|
|
||||||
|
d += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if f_star != one_cmp {
|
||||||
|
z.push((f_star.clone(), f_star.degree() as u128));
|
||||||
|
} else if z.len() == 0 {
|
||||||
|
z.push((f.clone(), 1));
|
||||||
|
}
|
||||||
|
|
||||||
|
z
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
|
||||||
|
use serde_json::json;
|
||||||
|
|
||||||
|
// Note this useful idiom: importing names from outer (for mod tests) scope.
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_dff_sheet() {
|
||||||
|
let json_f = json!([
|
||||||
|
"tpkgAAAAAAAAAAAAAAAAAA==",
|
||||||
|
"m6MQAAAAAAAAAAAAAAAAAA==",
|
||||||
|
"8roAAAAAAAAAAAAAAAAAAA==",
|
||||||
|
"3dUAAAAAAAAAAAAAAAAAAA==",
|
||||||
|
"FwAAAAAAAAAAAAAAAAAAAA==",
|
||||||
|
"/kAAAAAAAAAAAAAAAAAAAA==",
|
||||||
|
"a4AAAAAAAAAAAAAAAAAAAA==",
|
||||||
|
"gAAAAAAAAAAAAAAAAAAAAA=="
|
||||||
|
]);
|
||||||
|
let poly_f = Polynomial::from_c_array(&json_f);
|
||||||
|
|
||||||
|
let mut factors = ddf(poly_f);
|
||||||
|
factors.sort();
|
||||||
|
let mut result: Vec<Factors> = vec![];
|
||||||
|
|
||||||
|
for (factor, degree) in factors {
|
||||||
|
result.push(Factors {
|
||||||
|
factor: factor.to_c_array(),
|
||||||
|
degree: degree as u32,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
println!("Result: {:?}", result);
|
||||||
|
let _bit_indices: Vec<u8> = vec![0];
|
||||||
|
assert!(false)
|
||||||
|
}
|
||||||
|
}
|
||||||
86
src/utils/edf.rs
Normal file
86
src/utils/edf.rs
Normal file
|
|
@ -0,0 +1,86 @@
|
||||||
|
use num::{BigUint, FromPrimitive, One};
|
||||||
|
use rand::Rng;
|
||||||
|
|
||||||
|
use super::poly::{gcd, Polynomial};
|
||||||
|
|
||||||
|
pub fn edf(f: Polynomial, d: u32) -> Vec<Polynomial> {
|
||||||
|
let q = BigUint::pow(&BigUint::from_u8(2).unwrap(), 128);
|
||||||
|
let n: u32 = (f.degree() as u32) / (d);
|
||||||
|
let mut z: Vec<Polynomial> = vec![f.clone()];
|
||||||
|
let one_cmp = Polynomial::one();
|
||||||
|
|
||||||
|
while (z.len() as u32) < n {
|
||||||
|
let h = Polynomial::rand(&rand::thread_rng().gen_range(1..=f.degree()));
|
||||||
|
|
||||||
|
let exponent = (q.pow(d) - BigUint::one()) / BigUint::from_u8(3).unwrap();
|
||||||
|
|
||||||
|
let g = h.bpow_mod(exponent, &f) + Polynomial::one();
|
||||||
|
|
||||||
|
for i in (0..z.len()).rev() {
|
||||||
|
if z[i].degree() as u32 > d {
|
||||||
|
let j = gcd(&z[i], &g);
|
||||||
|
if j != one_cmp && j != z[i] {
|
||||||
|
let intemediate = z[i].div(&j).0;
|
||||||
|
z.remove(i);
|
||||||
|
z.push(j.clone());
|
||||||
|
z.push(intemediate);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
z
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
|
||||||
|
use serde_json::json;
|
||||||
|
|
||||||
|
// Note this useful idiom: importing names from outer (for mod tests) scope.
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_edf_sheet() {
|
||||||
|
let json_f = json!([
|
||||||
|
"mmAAAAAAAAAAAAAAAAAAAA==",
|
||||||
|
"AbAAAAAAAAAAAAAAAAAAAA==",
|
||||||
|
"zgAAAAAAAAAAAAAAAAAAAA==",
|
||||||
|
"FwAAAAAAAAAAAAAAAAAAAA==",
|
||||||
|
"AAAAAAAAAAAAAAAAAAAAAA==",
|
||||||
|
"wAAAAAAAAAAAAAAAAAAAAA==",
|
||||||
|
"gAAAAAAAAAAAAAAAAAAAAA=="
|
||||||
|
]);
|
||||||
|
let d = 3;
|
||||||
|
let poly_f = Polynomial::from_c_array(&json_f);
|
||||||
|
|
||||||
|
let mut factors = edf(poly_f, d);
|
||||||
|
factors.sort();
|
||||||
|
|
||||||
|
let mut result: Vec<Vec<String>> = vec![];
|
||||||
|
|
||||||
|
for factor in factors {
|
||||||
|
result.push(factor.to_c_array())
|
||||||
|
}
|
||||||
|
|
||||||
|
println!("Result: {:?}", result);
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
result,
|
||||||
|
vec![
|
||||||
|
[
|
||||||
|
"iwAAAAAAAAAAAAAAAAAAAA==",
|
||||||
|
"CAAAAAAAAAAAAAAAAAAAAA==",
|
||||||
|
"AAAAAAAAAAAAAAAAAAAAAA==",
|
||||||
|
"gAAAAAAAAAAAAAAAAAAAAA=="
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"kAAAAAAAAAAAAAAAAAAAAA==",
|
||||||
|
"CAAAAAAAAAAAAAAAAAAAAA==",
|
||||||
|
"wAAAAAAAAAAAAAAAAAAAAA==",
|
||||||
|
"gAAAAAAAAAAAAAAAAAAAAA=="
|
||||||
|
]
|
||||||
|
]
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,19 +1,249 @@
|
||||||
use anyhow::{anyhow, Ok, Result};
|
use base64::prelude::*;
|
||||||
use base64::Engine;
|
use std::{u128, u8, usize};
|
||||||
|
|
||||||
use super::poly::gfmul;
|
use std::{
|
||||||
|
cmp::Ordering,
|
||||||
|
ops::{Add, BitXor, Div, Mul},
|
||||||
|
};
|
||||||
|
|
||||||
|
use anyhow::{anyhow, Ok, Result};
|
||||||
|
|
||||||
|
use super::{
|
||||||
|
math::{reverse_bits_in_bytevec, xor_bytes},
|
||||||
|
poly::gfmul,
|
||||||
|
};
|
||||||
|
|
||||||
|
#[derive(Debug, serde::Serialize, serde::Deserialize)]
|
||||||
|
pub struct FieldElement {
|
||||||
|
field_element: Vec<u8>,
|
||||||
|
}
|
||||||
|
|
||||||
|
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,
|
||||||
|
];
|
||||||
|
|
||||||
|
pub fn rand() -> Self {
|
||||||
|
let rand_field: [u8; 16] = rand::random();
|
||||||
|
FieldElement::new_no_convert(rand_field.to_vec())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn zero() -> Self {
|
||||||
|
FieldElement::new_no_convert(vec![0; 16])
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn one() -> Self {
|
||||||
|
FieldElement::new_no_convert(vec![0x01, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0])
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn to_vec(&self) -> Vec<u8> {
|
||||||
|
self.field_element.clone()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn new(field_element: Vec<u8>) -> Self {
|
||||||
|
Self {
|
||||||
|
field_element: reverse_bits_in_bytevec(field_element),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn new_no_convert(field_element: Vec<u8>) -> Self {
|
||||||
|
Self { field_element }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn mul(&self, poly_a: Vec<u8>, poly_b: Vec<u8>) -> Result<Vec<u8>> {
|
||||||
|
gfmul(&poly_a, &poly_b, "gcm")
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn to_b64(&self) -> String {
|
||||||
|
BASE64_STANDARD.encode(reverse_bits_in_bytevec(self.field_element.to_owned()))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn pow(mut self, mut exponent: u128) -> FieldElement {
|
||||||
|
let mut result: FieldElement = FieldElement::one();
|
||||||
|
|
||||||
|
if exponent == 1 {
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
if exponent == 0 {
|
||||||
|
let result = FieldElement::one();
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
while exponent > 0 {
|
||||||
|
if exponent & 1 == 1 {
|
||||||
|
let temp = &self * &result;
|
||||||
|
|
||||||
|
result = temp
|
||||||
|
}
|
||||||
|
let temp_square = &self * &self;
|
||||||
|
|
||||||
|
self = temp_square;
|
||||||
|
exponent >>= 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
result
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn inv(mut self) -> Self {
|
||||||
|
const INVERSER_START: u128 = 0xfffffffffffffffffffffffffffffffe;
|
||||||
|
|
||||||
|
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 {
|
||||||
|
if inverser & 1 == 1 {
|
||||||
|
inverse = gfmul(&self.field_element, &inverse, "xex").unwrap();
|
||||||
|
}
|
||||||
|
inverser >>= 1;
|
||||||
|
self.field_element = gfmul(&self.field_element, &self.field_element, "xex")
|
||||||
|
.expect("Error in sqrmul sqr");
|
||||||
|
}
|
||||||
|
FieldElement::new_no_convert(inverse)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn is_zero(&self) -> bool {
|
||||||
|
self.field_element.iter().all(|&x| x == 0x00)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn reverse_bits(&self) -> Self {
|
||||||
|
FieldElement::new_no_convert(reverse_bits_in_bytevec(self.field_element.clone()))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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")
|
||||||
|
.expect("Error during multiplication"),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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")
|
||||||
|
.expect("Error during multiplication"),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Add for FieldElement {
|
||||||
|
type Output = Self;
|
||||||
|
fn add(self, rhs: Self) -> Self::Output {
|
||||||
|
FieldElement::new_no_convert(
|
||||||
|
xor_bytes(&self.field_element, rhs.field_element).expect("Error in poly add"),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Add for &FieldElement {
|
||||||
|
type Output = FieldElement;
|
||||||
|
fn add(self, rhs: Self) -> Self::Output {
|
||||||
|
FieldElement::new_no_convert(
|
||||||
|
xor_bytes(&self.field_element, rhs.field_element.clone()).expect("Error in poly add"),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl AsRef<[u8]> for FieldElement {
|
||||||
|
fn as_ref(&self) -> &[u8] {
|
||||||
|
&self.field_element.as_ref()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Clone for FieldElement {
|
||||||
|
fn clone(&self) -> Self {
|
||||||
|
FieldElement {
|
||||||
|
field_element: self.field_element.clone(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl BitXor for FieldElement {
|
||||||
|
type Output = Self;
|
||||||
|
fn bitxor(self, rhs: Self) -> Self::Output {
|
||||||
|
let result: Vec<u8> = self
|
||||||
|
.field_element
|
||||||
|
.iter()
|
||||||
|
.zip(rhs.field_element.iter())
|
||||||
|
.map(|(&x1, &x2)| x1 ^ x2)
|
||||||
|
.collect();
|
||||||
|
FieldElement::new_no_convert(result)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Div for FieldElement {
|
||||||
|
type Output = Self;
|
||||||
|
fn div(self, rhs: Self) -> Self::Output {
|
||||||
|
let inverse = rhs.inv();
|
||||||
|
self * inverse
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Div for &FieldElement {
|
||||||
|
type Output = FieldElement;
|
||||||
|
|
||||||
|
fn div(self, rhs: Self) -> Self::Output {
|
||||||
|
self.clone() * rhs.clone().inv()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PartialOrd for FieldElement {
|
||||||
|
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
|
||||||
|
for (byte_a, byte_b) in self.as_ref().iter().rev().zip(other.as_ref().iter().rev()) {
|
||||||
|
if byte_a > byte_b {
|
||||||
|
return Some(Ordering::Greater);
|
||||||
|
} else if byte_a < byte_b {
|
||||||
|
return Some(Ordering::Less);
|
||||||
|
} else {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Some(Ordering::Equal)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PartialEq for FieldElement {
|
||||||
|
fn eq(&self, other: &Self) -> bool {
|
||||||
|
self.field_element == other.field_element
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Eq for FieldElement {
|
||||||
|
// add code here
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Ord for FieldElement {
|
||||||
|
fn cmp(&self, other: &Self) -> Ordering {
|
||||||
|
for (byte_a, byte_b) in self.as_ref().iter().rev().zip(other.as_ref().iter().rev()) {
|
||||||
|
if byte_a > byte_b {
|
||||||
|
return Ordering::Greater;
|
||||||
|
} else if byte_a < byte_b {
|
||||||
|
return Ordering::Less;
|
||||||
|
} else {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ordering::Equal
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct ByteArray {
|
pub struct ByteArray(pub Vec<u8>);
|
||||||
pub vector: Vec<u8>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ByteArray {
|
impl ByteArray {
|
||||||
pub fn left_shift(&mut self, semantic: &str) -> Result<u8> {
|
pub fn left_shift(&mut self, semantic: &str) -> Result<u8> {
|
||||||
match semantic {
|
match semantic {
|
||||||
"xex" => {
|
"xex" => {
|
||||||
let mut carry = 0u8;
|
let mut carry = 0u8;
|
||||||
for byte in self.vector.iter_mut() {
|
for byte in self.0.iter_mut() {
|
||||||
let new_carry = *byte >> 7;
|
let new_carry = *byte >> 7;
|
||||||
*byte = (*byte << 1) | carry;
|
*byte = (*byte << 1) | carry;
|
||||||
carry = new_carry;
|
carry = new_carry;
|
||||||
|
|
@ -22,9 +252,9 @@ impl ByteArray {
|
||||||
}
|
}
|
||||||
"gcm" => {
|
"gcm" => {
|
||||||
let mut carry = 0u8;
|
let mut carry = 0u8;
|
||||||
for byte in self.vector.iter_mut() {
|
for byte in self.0.iter_mut() {
|
||||||
let new_carry = *byte & 1;
|
let new_carry = *byte & 1;
|
||||||
*byte = (*byte >> 1) | carry << 7;
|
*byte = (*byte >> 1) | (carry << 7);
|
||||||
carry = new_carry;
|
carry = new_carry;
|
||||||
}
|
}
|
||||||
Ok(carry)
|
Ok(carry)
|
||||||
|
|
@ -39,13 +269,13 @@ impl ByteArray {
|
||||||
let alpha_poly: Vec<u8> = base64::prelude::BASE64_STANDARD
|
let alpha_poly: Vec<u8> = base64::prelude::BASE64_STANDARD
|
||||||
.decode("AgAAAAAAAAAAAAAAAAAAAA==")
|
.decode("AgAAAAAAAAAAAAAAAAAAAA==")
|
||||||
.expect("Decode failed");
|
.expect("Decode failed");
|
||||||
self.vector = gfmul(self.vector.clone(), alpha_poly, "xex").unwrap();
|
self.0 = gfmul(&self.0, &alpha_poly, "xex").unwrap();
|
||||||
}
|
}
|
||||||
"gcm" => {
|
"gcm" => {
|
||||||
let alpha_poly: Vec<u8> = base64::prelude::BASE64_STANDARD
|
let alpha_poly: Vec<u8> = base64::prelude::BASE64_STANDARD
|
||||||
.decode("AgAAAAAAAAAAAAAAAAAAAA==")
|
.decode("AgAAAAAAAAAAAAAAAAAAAA==")
|
||||||
.expect("Decode failed");
|
.expect("Decode failed");
|
||||||
self.vector = gfmul(self.vector.clone(), alpha_poly, "gcm").unwrap();
|
self.0 = gfmul(&self.0, &alpha_poly, "gcm").unwrap();
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
|
|
@ -55,7 +285,7 @@ impl ByteArray {
|
||||||
match semantic {
|
match semantic {
|
||||||
"xex" => {
|
"xex" => {
|
||||||
let mut carry = 0u8;
|
let mut carry = 0u8;
|
||||||
for byte in self.vector.iter_mut().rev() {
|
for byte in self.0.iter_mut().rev() {
|
||||||
let new_carry = *byte & 1;
|
let new_carry = *byte & 1;
|
||||||
*byte = (*byte >> 1) | (carry << 7);
|
*byte = (*byte >> 1) | (carry << 7);
|
||||||
carry = new_carry;
|
carry = new_carry;
|
||||||
|
|
@ -64,7 +294,7 @@ impl ByteArray {
|
||||||
}
|
}
|
||||||
"gcm" => {
|
"gcm" => {
|
||||||
let mut carry = 0u8;
|
let mut carry = 0u8;
|
||||||
for byte in self.vector.iter_mut().rev() {
|
for byte in self.0.iter_mut().rev() {
|
||||||
let new_carry = *byte & 1;
|
let new_carry = *byte & 1;
|
||||||
*byte = (*byte << 1) | carry;
|
*byte = (*byte << 1) | carry;
|
||||||
carry = new_carry;
|
carry = new_carry;
|
||||||
|
|
@ -75,41 +305,23 @@ impl ByteArray {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn left_shift_reduce(&mut self, semantic: &str) {
|
|
||||||
match semantic {
|
|
||||||
"xex" => {
|
|
||||||
let alpha_poly: Vec<u8> = base64::prelude::BASE64_STANDARD
|
|
||||||
.decode("AgAAAAAAAAAAAAAAAAAAAA==")
|
|
||||||
.expect("Decode failed");
|
|
||||||
self.0 = gfmul(self.0.clone(), alpha_poly, "xex").unwrap();
|
|
||||||
}
|
|
||||||
"gcm" => {
|
|
||||||
let alpha_poly: Vec<u8> = base64::prelude::BASE64_STANDARD
|
|
||||||
.decode("AgAAAAAAAAAAAAAAAAAAAA==")
|
|
||||||
.expect("Decode failed");
|
|
||||||
self.0 = gfmul(self.0.clone(), alpha_poly, "gcm").unwrap();
|
|
||||||
}
|
|
||||||
_ => {}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn xor_byte_arrays(&mut self, vec2: &ByteArray) {
|
pub fn xor_byte_arrays(&mut self, vec2: &ByteArray) {
|
||||||
self.vector
|
self.0
|
||||||
.iter_mut()
|
.iter_mut()
|
||||||
.zip(vec2.vector.iter())
|
.zip(vec2.0.iter())
|
||||||
.for_each(|(x1, x2)| *x1 ^= *x2);
|
.for_each(|(x1, x2)| *x1 ^= *x2);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn lsb_is_one(&self) -> bool {
|
pub fn LSB_is_one(&self) -> bool {
|
||||||
(self.0.first().unwrap() & 1) == 1
|
(self.0.first().unwrap() & 1) == 1
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn msb_is_one(&self) -> bool {
|
pub fn msb_is_one(&self) -> bool {
|
||||||
(self.vector.last().unwrap() & 1) == 1
|
(self.0.last().unwrap() & 1) == 1
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn is_empty(&self) -> bool {
|
pub fn is_empty(&self) -> bool {
|
||||||
for i in self.vector.iter() {
|
for i in self.0.iter() {
|
||||||
if *i != 0 {
|
if *i != 0 {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
@ -120,16 +332,6 @@ impl ByteArray {
|
||||||
pub fn reverse_bits_in_bytevec(&mut self) {
|
pub fn reverse_bits_in_bytevec(&mut self) {
|
||||||
self.0 = self.0.iter_mut().map(|byte| byte.reverse_bits()).collect();
|
self.0 = self.0.iter_mut().map(|byte| byte.reverse_bits()).collect();
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn append_vec(&mut self, mut other: Vec<u8>) {
|
|
||||||
self.vector.append(other.as_mut());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<Vec<u8>> for ByteArray {
|
|
||||||
fn from(item: Vec<u8>) -> Self {
|
|
||||||
ByteArray { vector: item }
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
|
@ -138,94 +340,129 @@ mod tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_byte_array_shift1() {
|
fn test_byte_array_shift1() {
|
||||||
let mut byte_array: ByteArray = ByteArray::from(vec![0x00, 0x01]);
|
let mut byte_array: ByteArray = ByteArray(vec![0x00, 0x01]);
|
||||||
let shifted_array: ByteArray = ByteArray::from(vec![0x00, 0x02]);
|
let shifted_array: ByteArray = ByteArray(vec![0x00, 0x02]);
|
||||||
byte_array.left_shift("xex");
|
byte_array.left_shift("xex").unwrap();
|
||||||
|
|
||||||
assert_eq!(byte_array.vector, shifted_array.vector);
|
assert_eq!(byte_array.0, shifted_array.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_byte_array_shift2() {
|
fn test_byte_array_shift2() {
|
||||||
let mut byte_array: ByteArray = ByteArray::from(vec![0xFF, 0x00]);
|
let mut byte_array: ByteArray = ByteArray(vec![0xFF, 0x00]);
|
||||||
let shifted_array: ByteArray = ByteArray::from(vec![0xFE, 0x01]);
|
let shifted_array: ByteArray = ByteArray(vec![0xFE, 0x01]);
|
||||||
byte_array.left_shift("xex");
|
byte_array.left_shift("xex").unwrap();
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
byte_array.vector, shifted_array.vector,
|
byte_array.0, shifted_array.0,
|
||||||
"Failure: Shifted array was: {:?}",
|
"Failure: Shifted array was: {:?}",
|
||||||
byte_array.vector
|
byte_array.0
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_byte_array_shift1_gcm() {
|
fn test_byte_array_shift1_gcm() {
|
||||||
let mut byte_array: ByteArray = ByteArray::from(vec![0xFF, 0x00]);
|
let mut byte_array: ByteArray = ByteArray(vec![0xFF, 0x00]);
|
||||||
let shifted_array: ByteArray = ByteArray::from(vec![0x7F, 0x80]);
|
let shifted_array: ByteArray = ByteArray(vec![0x7F, 0x80]);
|
||||||
byte_array.left_shift("gcm");
|
byte_array.left_shift("gcm").unwrap();
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
byte_array.vector, shifted_array.vector,
|
byte_array.0, shifted_array.0,
|
||||||
"Failure: Shifted array was: {:02X?}",
|
"Failure: Shifted array was: {:02X?}",
|
||||||
byte_array.vector
|
byte_array.0
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_byte_array_shift1_right_gcm() {
|
fn test_byte_array_shift1_right_gcm() {
|
||||||
let mut byte_array: ByteArray = ByteArray::from(vec![0xFF, 0x00]);
|
let mut byte_array: ByteArray = ByteArray(vec![0xFF, 0x00]);
|
||||||
let shifted_array: ByteArray = ByteArray::from(vec![0xFE, 0x00]);
|
let shifted_array: ByteArray = ByteArray(vec![0xFE, 0x00]);
|
||||||
byte_array.right_shift("gcm");
|
byte_array.right_shift("gcm").unwrap();
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
byte_array.vector, shifted_array.vector,
|
byte_array.0, shifted_array.0,
|
||||||
"Failure: Shifted array was: {:02X?}",
|
"Failure: Shifted array was: {:02X?}",
|
||||||
byte_array.vector
|
byte_array.0
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_byte_array_shift_right() {
|
fn test_byte_array_shift_right() {
|
||||||
let mut byte_array: ByteArray = ByteArray::from(vec![0x02]);
|
let mut byte_array: ByteArray = ByteArray(vec![0x02]);
|
||||||
let shifted_array: ByteArray = ByteArray::from(vec![0x01]);
|
let shifted_array: ByteArray = ByteArray(vec![0x01]);
|
||||||
byte_array.right_shift("xex");
|
byte_array.right_shift("xex").unwrap();
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
byte_array.vector, shifted_array.vector,
|
byte_array.0, shifted_array.0,
|
||||||
"Failure: Shifted array was: {:?}",
|
"Failure: Shifted array was: {:?}",
|
||||||
byte_array.vector
|
byte_array.0
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_lsb_one() {
|
fn test_lsb_one() {
|
||||||
let byte_array: ByteArray = ByteArray(vec![0x00, 0xFF]);
|
let byte_array: ByteArray = ByteArray(vec![0x00, 0xFF]);
|
||||||
assert!(!byte_array.lsb_is_one());
|
assert!(!byte_array.LSB_is_one());
|
||||||
|
|
||||||
let byte_array2: ByteArray = ByteArray(vec![0x02, 0xFF]);
|
let byte_array2: ByteArray = ByteArray(vec![0x02, 0xFF]);
|
||||||
assert!(!byte_array2.lsb_is_one());
|
assert!(!byte_array2.LSB_is_one());
|
||||||
|
|
||||||
let byte_array3: ByteArray = ByteArray(vec![0xFF, 0x00]);
|
let byte_array3: ByteArray = ByteArray(vec![0xFF, 0x00]);
|
||||||
assert!(byte_array3.lsb_is_one());
|
assert!(byte_array3.LSB_is_one());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_byte_xor() {
|
fn test_byte_xor() {
|
||||||
let mut byte_array: ByteArray = ByteArray::from(vec![0x25, 0x25]);
|
let mut byte_array: ByteArray = ByteArray(vec![0x25, 0x25]);
|
||||||
let byte_array2: ByteArray = ByteArray::from(vec![0x55, 0x55]);
|
let byte_array2: ByteArray = ByteArray(vec![0x55, 0x55]);
|
||||||
|
|
||||||
byte_array.xor_byte_arrays(&byte_array2);
|
byte_array.xor_byte_arrays(&byte_array2);
|
||||||
|
|
||||||
assert_eq!(byte_array.vector, vec![0x70, 0x70]);
|
assert_eq!(byte_array.0, vec![0x70, 0x70]);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_byte_xor2() {
|
fn test_byte_xor2() {
|
||||||
let mut byte_array: ByteArray = ByteArray::from(vec![0x00, 0x00]);
|
let mut byte_array: ByteArray = ByteArray(vec![0x00, 0x00]);
|
||||||
let byte_array2: ByteArray = ByteArray::from(vec![0x55, 0x55]);
|
let byte_array2: ByteArray = ByteArray(vec![0x55, 0x55]);
|
||||||
|
|
||||||
byte_array.xor_byte_arrays(&byte_array2);
|
byte_array.xor_byte_arrays(&byte_array2);
|
||||||
|
|
||||||
assert_eq!(byte_array.vector, vec![0x55, 0x55]);
|
assert_eq!(byte_array.0, vec![0x55, 0x55]);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_field_add_01() {
|
||||||
|
let element1: FieldElement =
|
||||||
|
FieldElement::new(BASE64_STANDARD.decode("NeverGonnaGiveYouUpAAA==").unwrap());
|
||||||
|
let element2: FieldElement =
|
||||||
|
FieldElement::new(BASE64_STANDARD.decode("KryptoanalyseAAAAAAAAA==").unwrap());
|
||||||
|
let sum = element2 + element1;
|
||||||
|
|
||||||
|
assert_eq!(sum.to_b64(), "H1d3GuyA9/0OxeYouUpAAA==");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_field_add_02() {
|
||||||
|
let element1: FieldElement =
|
||||||
|
FieldElement::new(BASE64_STANDARD.decode("NeverGonnaLetYouDownAA==").unwrap());
|
||||||
|
let element2: FieldElement =
|
||||||
|
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==");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
use anyhow::{Ok, Result};
|
use anyhow::{Ok, Result};
|
||||||
|
|
||||||
|
|
||||||
pub fn xor_bytes(vec1: &Vec<u8>, mut vec2: Vec<u8>) -> Result<Vec<u8>> {
|
pub fn xor_bytes(vec1: &Vec<u8>, mut vec2: Vec<u8>) -> Result<Vec<u8>> {
|
||||||
for (byte1, byte2) in vec1.iter().zip(vec2.iter_mut()) {
|
for (byte1, byte2) in vec1.iter().zip(vec2.iter_mut()) {
|
||||||
*byte2 ^= byte1;
|
*byte2 ^= byte1;
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,9 @@
|
||||||
pub mod ciphers;
|
pub mod ciphers;
|
||||||
|
pub mod dff;
|
||||||
|
pub mod edf;
|
||||||
pub mod field;
|
pub mod field;
|
||||||
pub mod math;
|
pub mod math;
|
||||||
|
pub mod net;
|
||||||
pub mod parse;
|
pub mod parse;
|
||||||
pub mod poly;
|
pub mod poly;
|
||||||
|
pub mod sff;
|
||||||
|
|
|
||||||
1
src/utils/net.rs
Normal file
1
src/utils/net.rs
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
|
||||||
|
|
@ -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>,
|
||||||
}
|
}
|
||||||
|
|
@ -28,8 +28,6 @@ pub fn parse_json(json: String) -> Result<Testcases> {
|
||||||
mod tests {
|
mod tests {
|
||||||
use std::fs;
|
use std::fs;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// 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::*;
|
||||||
|
|
||||||
|
|
|
||||||
1259
src/utils/poly.rs
1259
src/utils/poly.rs
File diff suppressed because it is too large
Load diff
92
src/utils/sff.rs
Normal file
92
src/utils/sff.rs
Normal file
|
|
@ -0,0 +1,92 @@
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
|
use crate::utils::{
|
||||||
|
field::FieldElement,
|
||||||
|
poly::{gcd, polynomial_2_block},
|
||||||
|
};
|
||||||
|
|
||||||
|
use super::poly::Polynomial;
|
||||||
|
|
||||||
|
#[derive(Debug, Serialize, Deserialize)]
|
||||||
|
pub struct Factors {
|
||||||
|
pub factor: Vec<String>,
|
||||||
|
pub exponent: u128,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn sff(mut f: Polynomial) -> Vec<(Polynomial, u128)> {
|
||||||
|
let mut c = gcd(&f, &f.clone().diff());
|
||||||
|
f = f.div(&c).0;
|
||||||
|
let mut z: Vec<(Polynomial, u128)> = vec![];
|
||||||
|
let mut e: u128 = 1;
|
||||||
|
|
||||||
|
let one_element = Polynomial::new(vec![FieldElement::new(
|
||||||
|
polynomial_2_block(vec![0], "gcm").unwrap(),
|
||||||
|
)]);
|
||||||
|
|
||||||
|
while f != one_element {
|
||||||
|
let y = gcd(&f, &c);
|
||||||
|
if f != y {
|
||||||
|
z.push(((f.div(&y).0), e));
|
||||||
|
}
|
||||||
|
|
||||||
|
f = y.clone();
|
||||||
|
c = c.div(&y).0;
|
||||||
|
e += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if c != one_element {
|
||||||
|
let r = sff(c.sqrt());
|
||||||
|
for (f_star, e_star) in r {
|
||||||
|
z.push((f_star, 2 * e_star));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
z
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
|
||||||
|
use serde_json::json;
|
||||||
|
// Note this useful idiom: importing names from outer (for mod tests) scope.
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn byte_indices_0x01() {
|
||||||
|
let json_f = json!([
|
||||||
|
"vL77UwAAAAAAAAAAAAAAAA==",
|
||||||
|
"mEHchYAAAAAAAAAAAAAAAA==",
|
||||||
|
"9WJa0MAAAAAAAAAAAAAAAA==",
|
||||||
|
"akHfwWAAAAAAAAAAAAAAAA==",
|
||||||
|
"E12o/QAAAAAAAAAAAAAAAA==",
|
||||||
|
"vKJ/FgAAAAAAAAAAAAAAAA==",
|
||||||
|
"yctWwAAAAAAAAAAAAAAAAA==",
|
||||||
|
"c1BXYAAAAAAAAAAAAAAAAA==",
|
||||||
|
"o0AtAAAAAAAAAAAAAAAAAA==",
|
||||||
|
"AbP2AAAAAAAAAAAAAAAAAA==",
|
||||||
|
"k2YAAAAAAAAAAAAAAAAAAA==",
|
||||||
|
"vBYAAAAAAAAAAAAAAAAAAA==",
|
||||||
|
"dSAAAAAAAAAAAAAAAAAAAA==",
|
||||||
|
"69gAAAAAAAAAAAAAAAAAAA==",
|
||||||
|
"VkAAAAAAAAAAAAAAAAAAAA==",
|
||||||
|
"a4AAAAAAAAAAAAAAAAAAAA==",
|
||||||
|
"gAAAAAAAAAAAAAAAAAAAAA=="
|
||||||
|
]);
|
||||||
|
let poly_f = Polynomial::from_c_array(&json_f);
|
||||||
|
|
||||||
|
let mut factors = sff(poly_f);
|
||||||
|
factors.sort();
|
||||||
|
let mut result: Vec<Factors> = vec![];
|
||||||
|
|
||||||
|
for (factor, exponent) in factors {
|
||||||
|
result.push(Factors {
|
||||||
|
factor: factor.to_c_array(),
|
||||||
|
exponent,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
println!("{:?}", result);
|
||||||
|
let _bit_indices: Vec<u8> = vec![0];
|
||||||
|
assert!(false)
|
||||||
|
}
|
||||||
|
}
|
||||||
14
test_json/gcm_decrypt_aes.json
Normal file
14
test_json/gcm_decrypt_aes.json
Normal file
|
|
@ -0,0 +1,14 @@
|
||||||
|
{
|
||||||
|
"testcases": {
|
||||||
|
"b856d760-023d-4b00-bad2-15d2b6da22fe": {
|
||||||
|
"action": "gcm_decrypt",
|
||||||
|
"arguments": {
|
||||||
|
"algorithm": "aes128",
|
||||||
|
"nonce": "4gF+BtR3ku/PUQci",
|
||||||
|
"key": "Xjq/GkpTSWoe3ZH0F+tjrQ==",
|
||||||
|
"ciphertext": "ET3RmvH/Hbuxba63EuPRrw==",
|
||||||
|
"ad": "QUQtRGF0ZW4=",
|
||||||
|
"tag": "Mp0APJb/ZIURRwQlMgNN/w=="
|
||||||
|
} }
|
||||||
|
}
|
||||||
|
}
|
||||||
14
test_json/gcm_decrypt_sea.json
Normal file
14
test_json/gcm_decrypt_sea.json
Normal file
|
|
@ -0,0 +1,14 @@
|
||||||
|
{
|
||||||
|
"testcases": {
|
||||||
|
"b856d760-023d-4b00-bad2-15d2b6da22fe": {
|
||||||
|
"action": "gcm_decrypt",
|
||||||
|
"arguments": {
|
||||||
|
"algorithm": "sea128",
|
||||||
|
"nonce": "4gF+BtR3ku/PUQci",
|
||||||
|
"key": "Xjq/GkpTSWoe3ZH0F+tjrQ==",
|
||||||
|
"ciphertext": "0cI/Wg4R3URfrVFZ0hw/vg==",
|
||||||
|
"ad": "QUQtRGF0ZW4=",
|
||||||
|
"tag": "ysDdzOSnqLH0MQ+Mkb23gw=="
|
||||||
|
} }
|
||||||
|
}
|
||||||
|
}
|
||||||
14
test_json/gcm_encrypt.json
Normal file
14
test_json/gcm_encrypt.json
Normal file
|
|
@ -0,0 +1,14 @@
|
||||||
|
{
|
||||||
|
"testcases": {
|
||||||
|
"b856d760-023d-4b00-bad2-15d2b6da22fe": {
|
||||||
|
"action": "gcm_encrypt",
|
||||||
|
"arguments": {
|
||||||
|
"algorithm": "aes128",
|
||||||
|
"nonce": "4gF+BtR3ku/PUQci",
|
||||||
|
"key": "Xjq/GkpTSWoe3ZH0F+tjrQ==",
|
||||||
|
"plaintext": "RGFzIGlzdCBlaW4gVGVzdA==",
|
||||||
|
"ad": "QUQtRGF0ZW4="
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
14
test_json/gcm_encrypt_sea.json
Normal file
14
test_json/gcm_encrypt_sea.json
Normal file
|
|
@ -0,0 +1,14 @@
|
||||||
|
{
|
||||||
|
"testcases": {
|
||||||
|
"b856d760-023d-4b00-bad2-15d2b6da22fe": {
|
||||||
|
"action": "gcm_encrypt",
|
||||||
|
"arguments": {
|
||||||
|
"algorithm": "sea128",
|
||||||
|
"nonce": "4gF+BtR3ku/PUQci",
|
||||||
|
"key": "Xjq/GkpTSWoe3ZH0F+tjrQ==",
|
||||||
|
"plaintext": "RGFzIGlzdCBlaW4gVGVzdA==",
|
||||||
|
"ad": "QUQtRGF0ZW4="
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
1203
test_json/padding_long.json
Normal file
1203
test_json/padding_long.json
Normal file
File diff suppressed because it is too large
Load diff
12015
test_json/padding_oracle.json
Normal file
12015
test_json/padding_oracle.json
Normal file
File diff suppressed because it is too large
Load diff
98
test_json/pfmath_tests.json
Normal file
98
test_json/pfmath_tests.json
Normal file
|
|
@ -0,0 +1,98 @@
|
||||||
|
{
|
||||||
|
"testcases": {
|
||||||
|
"gfpoly_add": {
|
||||||
|
"action": "gfpoly_add",
|
||||||
|
"arguments": {
|
||||||
|
"A": [
|
||||||
|
"NeverGonnaGiveYouUpAAA==",
|
||||||
|
"NeverGonnaLetYouDownAA==",
|
||||||
|
"NeverGonnaRunAroundAAA==",
|
||||||
|
"AndDesertYouAAAAAAAAAA=="
|
||||||
|
],
|
||||||
|
"B": [
|
||||||
|
"KryptoanalyseAAAAAAAAA==",
|
||||||
|
"DHBWMannheimAAAAAAAAAA=="
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"gfpoly_mul": {
|
||||||
|
"action": "gfpoly_mul",
|
||||||
|
"arguments": {
|
||||||
|
"A": [
|
||||||
|
"JAAAAAAAAAAAAAAAAAAAAA==",
|
||||||
|
"wAAAAAAAAAAAAAAAAAAAAA==",
|
||||||
|
"ACAAAAAAAAAAAAAAAAAAAA=="
|
||||||
|
],
|
||||||
|
"B": [
|
||||||
|
"0AAAAAAAAAAAAAAAAAAAAA==",
|
||||||
|
"IQAAAAAAAAAAAAAAAAAAAA=="
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"gfpoly_mul_10": {
|
||||||
|
"action": "gfpoly_mul",
|
||||||
|
"arguments": {
|
||||||
|
"A": [
|
||||||
|
"JAAAAAAAAAAAAAAAAAAAAA==",
|
||||||
|
"wAAAAAAAAAAAAAAAAAAAAA==",
|
||||||
|
"ACAAAAAAAAAAAAAAAAAAAA=="
|
||||||
|
],
|
||||||
|
"B": [
|
||||||
|
"AAAAAAAAAAAAAAAAAAAAAA=="
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"gfpoly_mul_01": {
|
||||||
|
"action": "gfpoly_mul",
|
||||||
|
"arguments": {
|
||||||
|
"A": [
|
||||||
|
"AAAAAAAAAAAAAAAAAAAAAA=="
|
||||||
|
],
|
||||||
|
"B": [
|
||||||
|
"0AAAAAAAAAAAAAAAAAAAAA==",
|
||||||
|
"IQAAAAAAAAAAAAAAAAAAAA=="
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"gfpoly_pow": {
|
||||||
|
"action": "gfpoly_pow",
|
||||||
|
"arguments": {
|
||||||
|
"A": [
|
||||||
|
"JAAAAAAAAAAAAAAAAAAAAA==",
|
||||||
|
"wAAAAAAAAAAAAAAAAAAAAA==",
|
||||||
|
"ACAAAAAAAAAAAAAAAAAAAA=="
|
||||||
|
],
|
||||||
|
"k": 3
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"gfpoly_pow_k0": {
|
||||||
|
"action": "gfpoly_pow",
|
||||||
|
"arguments": {
|
||||||
|
"A": [
|
||||||
|
"JAAAAAAAAAAAAAAAAAAAAA==",
|
||||||
|
"wAAAAAAAAAAAAAAAAAAAAA==",
|
||||||
|
"ACAAAAAAAAAAAAAAAAAAAA=="
|
||||||
|
],
|
||||||
|
"k": 0
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"gfpoly_pow_k1": {
|
||||||
|
"action": "gfpoly_pow",
|
||||||
|
"arguments": {
|
||||||
|
"A": [
|
||||||
|
"JAAAAAAAAAAAAAAAAAAAAA==",
|
||||||
|
"wAAAAAAAAAAAAAAAAAAAAA==",
|
||||||
|
"ACAAAAAAAAAAAAAAAAAAAA=="
|
||||||
|
],
|
||||||
|
"k": 1
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"gfdiv": {
|
||||||
|
"action": "gfdiv",
|
||||||
|
"arguments": {
|
||||||
|
"a": "JAAAAAAAAAAAAAAAAAAAAA==",
|
||||||
|
"b": "wAAAAAAAAAAAAAAAAAAAAA=="
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
29
test_json/poly_algs.json
Normal file
29
test_json/poly_algs.json
Normal file
|
|
@ -0,0 +1,29 @@
|
||||||
|
{
|
||||||
|
"testcases": {
|
||||||
|
"b856d760-023d-4b00-bad2-15d2b6da22fe": {
|
||||||
|
|
||||||
|
"action": "gfpoly_sort",
|
||||||
|
"arguments": {
|
||||||
|
"polys": [
|
||||||
|
[
|
||||||
|
"NeverGonnaGiveYouUpAAA==",
|
||||||
|
"NeverGonnaLetYouDownAA==",
|
||||||
|
"NeverGonnaRunAroundAAA==",
|
||||||
|
"AndDesertYouAAAAAAAAAA=="
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"WereNoStrangersToLoveA==",
|
||||||
|
"YouKnowTheRulesAAAAAAA==",
|
||||||
|
"AndSoDoIAAAAAAAAAAAAAA=="
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"NeverGonnaMakeYouCryAA==",
|
||||||
|
"NeverGonnaSayGoodbyeAA==",
|
||||||
|
"NeverGonnaTellALieAAAA==",
|
||||||
|
"AndHurtYouAAAAAAAAAAAA=="
|
||||||
|
]
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
29
test_json/sandbox.json
Normal file
29
test_json/sandbox.json
Normal file
|
|
@ -0,0 +1,29 @@
|
||||||
|
{
|
||||||
|
"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": ""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue