From f7da97c89675aa34dbcf7e0cb9c4c8c351e3b5de Mon Sep 17 00:00:00 2001 From: pGerhart Date: Thu, 11 Sep 2025 10:32:09 -0400 Subject: [PATCH 1/3] update for AC --- benchmarks/decrypt.json | 1 + benchmarks/decrypt_request.json | 9 + benchmarks/encrypt.json | 5 + benchmarks/test_enc.sh | 7 + ct.json | 1 + src/core.rs | 516 +++++++++++++++++++------------- src/cryptoservice.rs | 131 ++++---- src/ophe.rs | 326 +++++++++++++------- 8 files changed, 627 insertions(+), 369 deletions(-) create mode 100644 benchmarks/decrypt.json create mode 100644 benchmarks/decrypt_request.json create mode 100644 benchmarks/encrypt.json create mode 100755 benchmarks/test_enc.sh create mode 100644 ct.json diff --git a/benchmarks/decrypt.json b/benchmarks/decrypt.json new file mode 100644 index 0000000..b79c6eb --- /dev/null +++ b/benchmarks/decrypt.json @@ -0,0 +1 @@ +{"c1":"Kg7PO4cAz5MEvfW2PNsWeYgIqPp+sFuyEJylelukYEMlaf2xJbP1EFpIt6/Prr5QKUKuf90Vp9qeEpNNjD+Hbw==","c2":"/cEpryemTCOMxhBdfqkuHFtG69/+rBpngUnb4aBeh3ZKTKbwyEMA8KPikl8xaGPO4xj0SC82kuqD/LkZvb00hA==","n":"0RrSr35GyOUJiyg/rsm1CSSnHjj9bJx6LwxY7fC7Ty4="} \ No newline at end of file diff --git a/benchmarks/decrypt_request.json b/benchmarks/decrypt_request.json new file mode 100644 index 0000000..30d9e27 --- /dev/null +++ b/benchmarks/decrypt_request.json @@ -0,0 +1,9 @@ +{ + "username": "alice", + "password": "correct horse battery staple", + "ciphertext": { + "c1": "XTLVdSI41jrdYZoy3yMObpUa6ZKE2p7eXEJyxNJGupq92ArGpIKZAIrHj0W69MNuaZDOXYQ4rNNetwaPfRKoYw==", + "c2": "W/3NHpAN07IlktQgc8vTGPtSDUkqm2RJqH+ovtRbbRmeTOSqDelzshZPLubeeiiBWZ2eYqcwhyvBGq4zN77lFw==", + "n": "KPeQdFyKETghj/5qj70MkSTD1rQ6TLcFiprzTnA+xwo=" + } +} diff --git a/benchmarks/encrypt.json b/benchmarks/encrypt.json new file mode 100644 index 0000000..d32782a --- /dev/null +++ b/benchmarks/encrypt.json @@ -0,0 +1,5 @@ +{ + "username": "alice", + "password": "correct horse battery staple", + "data": "hello ophe" +} diff --git a/benchmarks/test_enc.sh b/benchmarks/test_enc.sh new file mode 100755 index 0000000..d0b3dad --- /dev/null +++ b/benchmarks/test_enc.sh @@ -0,0 +1,7 @@ +curl -sS -X POST http://127.0.0.1:8000/encrypt \ + -H "Content-Type: application/json" \ + --data-binary @encrypt.json \ +| tee decrypt.json \ +| jq -n --arg u "alice" --arg p "correct horse battery staple" --argfile ciphertext /dev/stdin \ + '{username:$u, password:$p, ciphertext:$ciphertext}' \ +| curl -sS -X POST http://127.0.0.1:8000/decrypt -H "Content-Type: application/json" --data-binary @- diff --git a/ct.json b/ct.json new file mode 100644 index 0000000..14726b2 --- /dev/null +++ b/ct.json @@ -0,0 +1 @@ +{"c1":"dhRKjCIEfNfL+CgN4OfvzBkaOif+1wJC2CBT62ihz8ZQQHAouwSW3oO9/616LgYs7b4ygw1TdfgNHQ3fAoKUfw==","c2":"o/yGK+mh5eMDYSKhOCI85ShMcLsRxnhkWarx9lgX/4+xICd4d4dxcpBrFvYDU8qWb0tYk4lvLey2BLGmSIX4mg==","n":"gUoDnQNPXGGnHuJSLRmtim0PCnRfPvWxWPYK5LnHbmk="} \ No newline at end of file diff --git a/src/core.rs b/src/core.rs index 60b41af..ecbc447 100644 --- a/src/core.rs +++ b/src/core.rs @@ -1,63 +1,77 @@ -use bls12_381::*; -use group::Group; -use crate::utils; use crate::proofs; use crate::shamir; -use std::time::Instant; +use crate::utils; +use bls12_381::*; +use group::Group; use rayon::prelude::*; -use serde::{Deserialize, Serialize}; use rocket_okapi::okapi::schemars; use rocket_okapi::okapi::schemars::JsonSchema; +use serde::{Deserialize, Serialize}; +use std::time::Instant; use crate::serializers; use serde_with::serde_as; #[serde_as] -#[derive(Deserialize, Serialize,JsonSchema,Clone,Copy)] -pub struct PublicParameters{ +#[derive(Deserialize, Serialize, JsonSchema, Clone, Copy)] +pub struct PublicParameters { #[serde_as(as = "serializers::SerializeGt")] #[schemars(with = "String")] pub gt_gen: Gt, #[serde_as(as = "serializers::SerializeGt")] #[schemars(with = "String")] - pub ratelimiter_public_key: Gt + pub ratelimiter_public_key: Gt, } - -pub struct ServerState{ +pub struct ServerState { r: Scalar, pub n: Scalar, p: G2Projective, + p0: G2Projective, pw: String, } impl ServerState { - fn new(username: &String, password: &String) -> ServerState{ + fn new(username: &String, password: &String) -> ServerState { let r = utils::random_scalar(); let n = utils::random_scalar(); - + let username = username.to_owned(); let to_be_hashed = username + password; let tempr = utils::hash_string_to_scalar(to_be_hashed); - let p = G2Affine::generator() * tempr * r; - ServerState{r,n,p,pw: password.to_owned()} + let p0 = G2Affine::generator() * tempr; + let p = p0 * r; + ServerState { + r, + n, + p, + p0, + pw: password.to_owned(), + } } - fn from_nonce(username: &String, password: &String, nonce: &Scalar) -> ServerState{ + fn from_nonce(username: &String, password: &String, nonce: &Scalar) -> ServerState { let r = utils::random_scalar(); - + let username = username.to_owned(); let to_be_hashed = username + password; let tempr = utils::hash_string_to_scalar(to_be_hashed); - let p = G2Affine::generator() * tempr * r; + let p0 = G2Affine::generator() * tempr; + let p = p0 * r; - ServerState{r,n: nonce.clone(),p,pw: password.to_owned()} - } + ServerState { + r, + n: nonce.clone(), + p, + p0, + pw: password.to_owned(), + } + } } #[serde_as] -#[derive(Serialize, Deserialize, JsonSchema,Clone,Copy,Debug)] -pub struct RatelimiterRequest{ +#[derive(Serialize, Deserialize, JsonSchema, Clone, Copy, Debug)] +pub struct RatelimiterRequest { #[serde_as(as = "serializers::SerializeScalar")] #[schemars(with = "String")] n: Scalar, @@ -68,7 +82,7 @@ pub struct RatelimiterRequest{ #[serde_as] #[derive(Serialize, Deserialize, JsonSchema)] -pub struct RatelimiterResponse{ +pub struct RatelimiterResponse { proof: proofs::SameDLogProof, #[serde_as(as = "serializers::SerializeGt")] #[schemars(with = "String")] @@ -77,7 +91,7 @@ pub struct RatelimiterResponse{ #[serde_as] #[derive(Serialize, Deserialize, JsonSchema)] -pub struct RatelimiterRotateRequest{ +pub struct RatelimiterRotateRequest { #[serde_as(as = "serializers::SerializeScalar")] #[schemars(with = "String")] pub s: Scalar, @@ -85,7 +99,7 @@ pub struct RatelimiterRotateRequest{ #[serde_as] #[derive(Serialize, Deserialize, JsonSchema)] -pub struct RatelimiterRotateResponse{ +pub struct RatelimiterRotateResponse { #[serde_as(as = "serializers::SerializeScalar")] #[schemars(with = "String")] pub n: Scalar, @@ -94,10 +108,9 @@ pub struct RatelimiterRotateResponse{ pub pk_new: Gt, } - #[serde_as] #[derive(Serialize, Deserialize, JsonSchema, Clone)] -pub struct EncryptedMessage{ +pub struct EncryptedMessage { #[serde_as(as = "serde_with::base64::Base64")] #[schemars(with = "String")] pub c1: [u8; 64], @@ -111,62 +124,100 @@ pub struct EncryptedMessage{ #[serde_as] #[derive(Serialize, Deserialize, JsonSchema)] -pub struct SetKeyHelper{ +pub struct SetKeyHelper { #[serde_as(as = "serializers::SerializeScalar")] #[schemars(with = "String")] pub key: Scalar, } +pub fn phe_init(username: &String, password: &String) -> (ServerState, RatelimiterRequest) { + let ss = ServerState::new(username, password); + let rr = RatelimiterRequest { n: ss.n, p: ss.p }; -pub fn phe_init(username: &String, password: &String) -> (ServerState,RatelimiterRequest){ - let ss = ServerState::new(username,password); - let rr = RatelimiterRequest{n:ss.n,p:ss.p}; - - return (ss,rr) + return (ss, rr); } -pub fn phe_init_decrypt(username: &String, password: &String,n: &Scalar) -> (ServerState,RatelimiterRequest){ - let ss = ServerState::from_nonce(username,password,n); - let rr = RatelimiterRequest{n:ss.n,p:ss.p}; +pub fn phe_init_decrypt( + username: &String, + password: &String, + n: &Scalar, +) -> (ServerState, RatelimiterRequest) { + let ss = ServerState::from_nonce(username, password, n); + let rr = RatelimiterRequest { n: ss.n, p: ss.p }; - return (ss,rr) + return (ss, rr); } - - -pub fn phe_ratelimiter(private_key: &Scalar, request: &RatelimiterRequest,pp: &PublicParameters) -> RatelimiterResponse { +pub fn phe_ratelimiter( + private_key: &Scalar, + request: &RatelimiterRequest, + pp: &PublicParameters, +) -> RatelimiterResponse { let n = request.n; - let u = pairing(&G1Affine::from(G1Affine::generator() * n) , &G2Affine::from(request.p)); - let value = u*private_key; - let proof = proofs::SameDLogProofPublic{g:pp.gt_gen,h:u,y1:pp.ratelimiter_public_key,y2:value}.proof(&private_key); - RatelimiterResponse{proof,u:value} + let u = pairing( + &G1Affine::from(G1Affine::generator() * n), + &G2Affine::from(request.p), + ); + let value = u * private_key; + let proof = proofs::SameDLogProofPublic { + g: pp.gt_gen, + h: u, + y1: pp.ratelimiter_public_key, + y2: value, + } + .proof(&private_key); + RatelimiterResponse { proof, u: value } } -pub fn phe_enc_finish_t(msg: &Vec,pp: &Vec,response: &Vec,ss:&ServerState,n: i64) -> Result{ - let h = pairing(&G1Affine::from(G1Affine::generator() * ss.n), &G2Affine::from(ss.p)); +pub fn phe_enc_finish_t( + msg: &Vec, + pp: &Vec, + response: &Vec, + ss: &ServerState, + n: i64, + server_sk: &Scalar, +) -> Result { + let h = pairing( + &G1Affine::from(G1Affine::generator() * ss.n), + &G2Affine::from(ss.p0), + ); let r_inv = ss.r.invert().unwrap(); - let proofok = response.par_iter().zip(pp).map(|(r,p)| r.proof.verify(&proofs::SameDLogProofPublic{g:p.gt_gen,h:h ,y1:p.ratelimiter_public_key,y2:r.u})).collect::>().iter().all(|x| *x); - if !proofok{ + let proofok = response + .par_iter() + .zip(pp) + .map(|(r, p)| { + r.proof.verify(&proofs::SameDLogProofPublic { + g: p.gt_gen, + h: h, + y1: p.ratelimiter_public_key, + y2: r.u, + }) + }) + .collect::>() + .iter() + .all(|x| *x); + if !proofok { return Err("Proofs not ok".to_string()); } - let split_message = utils::vec_to_msg(msg); let uvec = response.iter().map(|r| r.u).collect::>(); let u = shamir::recover_shares(&uvec, n); - let ut = u * r_inv; - - let c1 = utils::hash_data( // H3([u]t 1/r, pw, id, ns, nr) + M //id is username, ns is nonce - &[ - &&"3".to_string(), - &&ut, - &&ss.pw, - &&ss.n, - //&response.iter().map(|r| &r.n).collect::>(), - ]); + let ut = u * r_inv + (h * server_sk); + + let c1 = utils::hash_data( + // H3([u]t 1/r, pw, id, ns, nr) + M //id is username, ns is nonce + &[ + &&"3".to_string(), + &&ut, + &&ss.pw, + &&ss.n, + //&response.iter().map(|r| &r.n).collect::>(), + ], + ); let c2 =// H3([u]t 1/r, M, pw, id, ns, nr) utils::hash_data( &[ @@ -179,30 +230,55 @@ pub fn phe_enc_finish_t(msg: &Vec,pp: &Vec,response: &Vec< ], ); let c1 = utils::xor(&c1, &split_message); - Ok(EncryptedMessage{c1,c2,n:ss.n}) + Ok(EncryptedMessage { c1, c2, n: ss.n }) } -pub fn phe_dec_finish_t(ciphertext: &EncryptedMessage,pp: &Vec,response: &Vec,ss:&ServerState,n: i64) -> Result,String>{ - let h = pairing(&G1Affine::from(G1Affine::generator() * ss.n), &G2Affine::from(ss.p)); +pub fn phe_dec_finish_t( + ciphertext: &EncryptedMessage, + pp: &Vec, + response: &Vec, + ss: &ServerState, + n: i64, + server_sk: &Scalar, +) -> Result, String> { + let h = pairing( + &G1Affine::from(G1Affine::generator() * ss.n), + &G2Affine::from(ss.p0), + ); let r_inv = ss.r.invert().unwrap(); - - let proofok = response.par_iter().zip(pp).map(|(r,p)| r.proof.verify(&proofs::SameDLogProofPublic{g:p.gt_gen,h:h,y1:p.ratelimiter_public_key,y2:r.u})).collect::>().iter().all(|x| *x); - if !proofok{ + + let proofok = response + .par_iter() + .zip(pp) + .map(|(r, p)| { + r.proof.verify(&proofs::SameDLogProofPublic { + g: p.gt_gen, + h: h, + y1: p.ratelimiter_public_key, + y2: r.u, + }) + }) + .collect::>() + .iter() + .all(|x| *x); + if !proofok { return Err("Proofs not ok".to_string()); } let uvec = response.iter().map(|r| r.u).collect::>(); let u = shamir::recover_shares(&uvec, n); - - let ut = u * r_inv; - let c1 = utils::hash_data( // H3([u]t 1/r, pw, id, ns, nr) + M //id is username, ns is nonce - &[ - &&"3".to_string(), - &&ut, - &&ss.pw, - &&ss.n, - //&response.iter().map(|r| &r.n).collect::>(), - ]); + let ut = u * r_inv + (h * server_sk); + + let c1 = utils::hash_data( + // H3([u]t 1/r, pw, id, ns, nr) + M //id is username, ns is nonce + &[ + &&"3".to_string(), + &&ut, + &&ss.pw, + &&ss.n, + //&response.iter().map(|r| &r.n).collect::>(), + ], + ); let c1 = utils::xor(&c1, &ciphertext.c1); let c2 =// H3([u]t 1/r, M, pw, id, ns, nr) utils::hash_data( @@ -215,34 +291,41 @@ pub fn phe_dec_finish_t(ciphertext: &EncryptedMessage,pp: &Vec //&response.iter().map(|r| &r.n).collect::>(), ], ); - - if c2 == ciphertext.c2{ + + if c2 == ciphertext.c2 { Ok(c1.to_vec()) - }else{ + } else { Err("Invalid ciphertext".to_string()) } } - - -pub fn phe_enc_finish(msg: &Vec,pp: &PublicParameters,response: &RatelimiterResponse,ss:&ServerState) -> Result{ +pub fn phe_enc_finish( + msg: &Vec, + pp: &PublicParameters, + response: &RatelimiterResponse, + ss: &ServerState, +) -> Result { let split_message = utils::vec_to_msg(msg); - let u = pairing(&G1Affine::from(G1Affine::generator() * ss.n) , &G2Affine::from(ss.p)); + let u = pairing( + &G1Affine::from(G1Affine::generator() * ss.n), + &G2Affine::from(ss.p), + ); let r_inv = ss.r.invert().unwrap(); - if !response.proof.verify(&proofs::SameDLogProofPublic{g:pp.gt_gen,h:u,y1:pp.ratelimiter_public_key,y2:response.u}){ + if !response.proof.verify(&proofs::SameDLogProofPublic { + g: pp.gt_gen, + h: u, + y1: pp.ratelimiter_public_key, + y2: response.u, + }) { Err("Invalid Proof ENC".to_string()) - }else{ + } else { let ut = response.u * r_inv; - let c1 = utils::hash_data( // H3([u]t 1/r, pw, id, ns, nr) + M //id is username, ns is nonce - &[ - &&"3".to_string(), - &&ut, - &&ss.pw, - &&ss.n - ] + let c1 = utils::hash_data( + // H3([u]t 1/r, pw, id, ns, nr) + M //id is username, ns is nonce + &[&&"3".to_string(), &&ut, &&ss.pw, &&ss.n], ); - let c1 = utils::xor(&c1,&split_message); + let c1 = utils::xor(&c1, &split_message); let c2 = // H3([u]t 1/r, M, pw, id, ns, nr) utils::hash_data( &[ @@ -253,27 +336,35 @@ pub fn phe_enc_finish(msg: &Vec,pp: &PublicParameters,response: &Ratelimiter &&ss.n ] ); - Ok(EncryptedMessage{c1,c2,n:ss.n}) + Ok(EncryptedMessage { c1, c2, n: ss.n }) } } -pub fn phe_dec_finish_simple(ciphertext: &EncryptedMessage,pp: &PublicParameters,response: &RatelimiterResponse,ss:&ServerState) -> Result,String>{ - let u = pairing(&G1Affine::from(G1Affine::generator() * ss.n) , &G2Affine::from(ss.p)); +pub fn phe_dec_finish_simple( + ciphertext: &EncryptedMessage, + pp: &PublicParameters, + response: &RatelimiterResponse, + ss: &ServerState, +) -> Result, String> { + let u = pairing( + &G1Affine::from(G1Affine::generator() * ss.n), + &G2Affine::from(ss.p), + ); let r_inv = ss.r.invert().unwrap(); - if !response.proof.verify(&proofs::SameDLogProofPublic{g:pp.gt_gen,h:u,y1:pp.ratelimiter_public_key,y2:response.u}){ + if !response.proof.verify(&proofs::SameDLogProofPublic { + g: pp.gt_gen, + h: u, + y1: pp.ratelimiter_public_key, + y2: response.u, + }) { Err("Invalid Proof".to_string()) - }else{ - - let ut = response.u * r_inv; - let c1 = utils::hash_data( // H3([u]t 1/r, pw, id, ns, nr) + M //id is username, ns is nonce - &[ - &&"3".to_string(), - &&ut, - &&ss.pw, - &&ss.n - ] + } else { + let ut = response.u * r_inv; + let c1 = utils::hash_data( + // H3([u]t 1/r, pw, id, ns, nr) + M //id is username, ns is nonce + &[&&"3".to_string(), &&ut, &&ss.pw, &&ss.n], ); - let split_message = utils::xor(&ciphertext.c1,&c1); + let split_message = utils::xor(&ciphertext.c1, &c1); let c2 = // H3([u]t 1/r, M, pw, id, ns, nr) utils::hash_data( &[ @@ -286,31 +377,42 @@ pub fn phe_dec_finish_simple(ciphertext: &EncryptedMessage,pp: &PublicParameters ); if ciphertext.c2 == c2 { Ok(split_message.to_vec()) - }else{ + } else { Err("Invalid C2".to_string()) } } } - - -pub fn phe_roate_ratelimiter(private_key: &Scalar, s: &Scalar) -> (RatelimiterRotateResponse, Scalar){ +pub fn phe_roate_ratelimiter( + private_key: &Scalar, + s: &Scalar, +) -> (RatelimiterRotateResponse, Scalar) { let k_new = private_key + s; let pk_i = Gt::generator() * k_new; let n_i = utils::random_scalar(); - (RatelimiterRotateResponse{n: n_i, pk_new: pk_i}, k_new) + ( + RatelimiterRotateResponse { + n: n_i, + pk_new: pk_i, + }, + k_new, + ) } -pub fn find_set(public_key: &Gt, public_key_shares: &Vec, n: &i64) -> Vec{ +pub fn find_set(public_key: &Gt, public_key_shares: &Vec, n: &i64) -> Vec { let test_pk = shamir::recover_shares(public_key_shares, *n); - assert_eq!(public_key.clone(), test_pk, "Find Set: Public keys do not match"); + assert_eq!( + public_key.clone(), + test_pk, + "Find Set: Public keys do not match" + ); return public_key_shares.clone(); } #[test] -fn test_core(){ +fn test_core() { //rayon::ThreadPoolBuilder::new().num_threads(8).build_global().unwrap(); test_core_k(); //test_core_k(32,4); @@ -318,14 +420,14 @@ fn test_core(){ } #[test] -fn t1est_core_test() -{ - rayon::ThreadPoolBuilder::new().num_threads(1).build_global().unwrap(); - test_core_t(10,10); +fn t1est_core_test() { + rayon::ThreadPoolBuilder::new() + .num_threads(1) + .build_global() + .unwrap(); + test_core_t(10, 10); } - - #[test] fn test_speed_operations() { let mut s1 = utils::random_scalar(); @@ -338,156 +440,162 @@ fn test_speed_operations() { let g21p = G2Affine::generator() * s1; let g22 = G2Affine::from(G2Affine::generator() * s2); let g22p = G2Affine::generator() * s2; - let mut gt1 = pairing(&g11,&g21); - let gt2 = pairing(&g12,&g22); + let mut gt1 = pairing(&g11, &g21); + let gt2 = pairing(&g12, &g22); let mut g1res = &g11p + &g12p; let mut g2res = &g21p + &g22p; let mut gtres = >1 + >2; let start = Instant::now(); - for _i in 0..100000{ + for _i in 0..100000 { s1 = s1 * s2; } - println!(" {:.2?} scalar *",start.elapsed()/100000); + println!(" {:.2?} scalar *", start.elapsed() / 100000); let start = Instant::now(); - for _i in 0..100000{ + for _i in 0..100000 { s1 = s1 + s2; } - println!(" {:.2?} scalar +",start.elapsed()/100000); + println!(" {:.2?} scalar +", start.elapsed() / 100000); let start = Instant::now(); - for _i in 0..1000{ - gt1 = pairing(&g11,&g21); + for _i in 0..1000 { + gt1 = pairing(&g11, &g21); } - println!(" {:.2?} pairing ",start.elapsed()/1000); - + println!(" {:.2?} pairing ", start.elapsed() / 1000); let start = Instant::now(); - for _i in 0..1000000{ + for _i in 0..1000000 { g1res = &g1res + &g12p; } - println!(" {:.2?} g1 + ",start.elapsed()/1000000); - + println!(" {:.2?} g1 + ", start.elapsed() / 1000000); let start = Instant::now(); - for _i in 0..1000000{ + for _i in 0..1000000 { g2res = &g2res + &g22p; } - println!(" {:.2?} g2 + ",start.elapsed()/1000000); + println!(" {:.2?} g2 + ", start.elapsed() / 1000000); let start = Instant::now(); - for _i in 0..1000000{ + for _i in 0..1000000 { gtres = >res + >2; } - println!(" {:.2?} gt + ",start.elapsed()/1000000); - + println!(" {:.2?} gt + ", start.elapsed() / 1000000); let start = Instant::now(); - for _i in 0..10000{ + for _i in 0..10000 { g1res = &g1res * s1; } - println!(" {:.2?} g1 exp ",start.elapsed()/10000); - + println!(" {:.2?} g1 exp ", start.elapsed() / 10000); let start = Instant::now(); - for _i in 0..1000{ + for _i in 0..1000 { g2res = &g2res * s1; } - println!(" {:.2?} g2 exp ",start.elapsed()/1000); + println!(" {:.2?} g2 exp ", start.elapsed() / 1000); let start = Instant::now(); - for _i in 0..1000{ + for _i in 0..1000 { gtres = >res * s1; } - println!(" {:.2?} gt exp ",start.elapsed()/1000); + println!(" {:.2?} gt exp ", start.elapsed() / 1000); } -fn test_core_t(n:i64,t:i64){ - let msg = (0..64).map(|x|(x) as u8).collect::>(); - let generator = pairing(&G1Affine::generator(),&G2Affine::generator()); +fn test_core_t(n: i64, t: i64) { + let msg = (0..64).map(|x| (x) as u8).collect::>(); + let generator = pairing(&G1Affine::generator(), &G2Affine::generator()); let realkey = utils::random_scalar(); + let server_sk = utils::random_scalar(); - let rlkeys = shamir::gen_shares_scalar(realkey,n,t); - let pps = rlkeys.iter().map(|x|PublicParameters{ - gt_gen: generator, - ratelimiter_public_key: generator*x - }).collect::>(); + let rlkeys = shamir::gen_shares_scalar(realkey, n, t); + let pps = rlkeys + .iter() + .map(|x| PublicParameters { + gt_gen: generator, + ratelimiter_public_key: generator * x, + }) + .collect::>(); - - let pp_keys = pps.iter().map(|x|{x.ratelimiter_public_key}).collect::>(); + let pp_keys = pps + .iter() + .map(|x| x.ratelimiter_public_key) + .collect::>(); let pp_key = shamir::recover_shares(&pp_keys, n as i64); - assert_eq!(pp_key,generator*realkey,"Public keys do not match"); + assert_eq!(pp_key, generator * realkey, "Public keys do not match"); let start = Instant::now(); - let (ss,request) = phe_init(&"test".to_string(),&"test".to_string()); - println!("{:.2?} phe_init",start.elapsed()); + let (ss, request) = phe_init(&"test".to_string(), &"test".to_string()); + println!("{:.2?} phe_init", start.elapsed()); - let responses = (0..t as usize).into_par_iter().map(|i|{ - let response = phe_ratelimiter(&rlkeys[i],&request,&pps[i]); - response - }).collect::>(); + let responses = (0..t as usize) + .into_par_iter() + .map(|i| { + let response = phe_ratelimiter(&rlkeys[i], &request, &pps[i]); + response + }) + .collect::>(); let start = Instant::now(); - let res = phe_enc_finish_t(&msg,&pps,&responses,&ss,n).unwrap(); - println!("{:.2?} phe_enc_finish_t",start.elapsed()); + let res = phe_enc_finish_t(&msg, &pps, &responses, &ss, n, &server_sk).unwrap(); + println!("{:.2?} phe_enc_finish_t", start.elapsed()); - let (ss,request) = phe_init_decrypt(&"test".to_string(),&"test".to_string(),&request.n); + let (ss, request) = phe_init_decrypt(&"test".to_string(), &"test".to_string(), &request.n); - let responses = (0..t as usize).into_par_iter().map(|i|{ - let response = phe_ratelimiter(&rlkeys[i],&request,&pps[i]); - response - }).collect::>(); + let responses = (0..t as usize) + .into_par_iter() + .map(|i| { + let response = phe_ratelimiter(&rlkeys[i], &request, &pps[i]); + response + }) + .collect::>(); let start = Instant::now(); - let res = phe_dec_finish_t(&res,&pps,&responses,&ss,n); - println!("{:.2?} phe_dec_finish_t",start.elapsed()); + let res = phe_dec_finish_t(&res, &pps, &responses, &ss, n, &server_sk); + println!("{:.2?} phe_dec_finish_t", start.elapsed()); - assert_eq!(res.unwrap(),msg); + assert_eq!(res.unwrap(), msg); } - fn test_core_k() { - let msg = (0..64).map(|x|(x) as u8).collect::>(); + let msg = (0..64).map(|x| (x) as u8).collect::>(); let generator = utils::random_gt(); let key = utils::random_scalar(); - let public_key = generator*key; - let pp = PublicParameters{ + let public_key = generator * key; + let pp = PublicParameters { gt_gen: generator, - ratelimiter_public_key: public_key + ratelimiter_public_key: public_key, }; let start = Instant::now(); - - let (ss,request) = phe_init(&"test".to_string(),&"test".to_string()); - println!("{:.2?} phe_init",start.elapsed()); - let response = phe_ratelimiter(&key,&request,&pp); - let start = Instant::now(); - for _i in 0..100{ - let response = phe_ratelimiter(&key,&request,&pp); - } - println!("{:.2?} phe_ratelimiter",start.elapsed()/1000); - - let ciphertext = phe_enc_finish(&msg,&pp,&response,&ss).unwrap(); - let start = Instant::now(); - for _i in 0..100{ - let ciphertext = phe_enc_finish(&msg,&pp,&response,&ss).unwrap(); - } - println!("{:.2?} phe_enc_finish",start.elapsed()/1000); - - let (ss,request) = phe_init_decrypt(&"test".to_string(),&"test".to_string(),&ciphertext.n); - let response = phe_ratelimiter(&key,&request,&pp); - - let expected = phe_dec_finish_simple(&ciphertext,&pp,&response,&ss).unwrap(); + let (ss, request) = phe_init(&"test".to_string(), &"test".to_string()); + println!("{:.2?} phe_init", start.elapsed()); + let response = phe_ratelimiter(&key, &request, &pp); let start = Instant::now(); - for _i in 0..100{ - let expected = phe_dec_finish_simple(&ciphertext,&pp,&response,&ss).unwrap(); + for _i in 0..100 { + let response = phe_ratelimiter(&key, &request, &pp); + } + println!("{:.2?} phe_ratelimiter", start.elapsed() / 1000); + + let ciphertext = phe_enc_finish(&msg, &pp, &response, &ss).unwrap(); + let start = Instant::now(); + for _i in 0..100 { + let ciphertext = phe_enc_finish(&msg, &pp, &response, &ss).unwrap(); + } + println!("{:.2?} phe_enc_finish", start.elapsed() / 1000); + + let (ss, request) = phe_init_decrypt(&"test".to_string(), &"test".to_string(), &ciphertext.n); + + let response = phe_ratelimiter(&key, &request, &pp); + + let expected = phe_dec_finish_simple(&ciphertext, &pp, &response, &ss).unwrap(); + let start = Instant::now(); + for _i in 0..100 { + let expected = phe_dec_finish_simple(&ciphertext, &pp, &response, &ss).unwrap(); } - println!("{:.2?} phe_dec_finish_simple", start.elapsed()/1000); - assert_eq!(expected,msg); - -} \ No newline at end of file + println!("{:.2?} phe_dec_finish_simple", start.elapsed() / 1000); + assert_eq!(expected, msg); +} diff --git a/src/cryptoservice.rs b/src/cryptoservice.rs index bf6ac65..6846d6a 100644 --- a/src/cryptoservice.rs +++ b/src/cryptoservice.rs @@ -1,37 +1,40 @@ - -#[macro_use] extern crate rocket; +#[macro_use] +extern crate rocket; extern crate bls12_381; extern crate rand; -use std::sync::RwLock; use bls12_381::pairing; use bls12_381::G2Affine; -use std::sync::Mutex; -use std::sync::Arc; -use rocket_okapi::settings::UrlObject; -use rocket_okapi::{openapi, openapi_get_routes, rapidoc::*, swagger_ui::*}; use rocket::serde::json::Json; use rocket::Request; +use rocket_okapi::settings::UrlObject; +use rocket_okapi::{openapi, openapi_get_routes, rapidoc::*, swagger_ui::*}; +use std::sync::Arc; +use std::sync::Mutex; +use std::sync::RwLock; -use ophe::core::{RatelimiterRequest,RatelimiterResponse,SetKeyHelper, RatelimiterRotateRequest, RatelimiterRotateResponse}; use ophe::core; +use ophe::core::{ + RatelimiterRequest, RatelimiterResponse, RatelimiterRotateRequest, RatelimiterRotateResponse, + SetKeyHelper, +}; +use bls12_381::G1Affine; +use bls12_381::Scalar; use ophe::utils; use rocket::State; -use bls12_381::Scalar; -use bls12_381::G1Affine; - - -fn make_public_parameters(key: Scalar) -> CryptoserviceState{ +fn make_public_parameters(key: Scalar) -> CryptoserviceState { let generator = pairing(&G1Affine::generator(), &G2Affine::generator()); let public_key = generator * key; - let pp = core::PublicParameters{ratelimiter_public_key:public_key,gt_gen:generator}; - CryptoserviceState{key,pp} + let pp = core::PublicParameters { + ratelimiter_public_key: public_key, + gt_gen: generator, + }; + CryptoserviceState { key, pp } } - struct CryptoserviceState { key: Scalar, pp: core::PublicParameters, @@ -39,39 +42,43 @@ struct CryptoserviceState { type CryptoserviceStatePointer = Arc>; - #[rocket::main] async fn main() { let c = make_public_parameters(utils::random_scalar()); - let c_p:CryptoserviceStatePointer = Arc::new(RwLock::new(c)); + let c_p: CryptoserviceStatePointer = Arc::new(RwLock::new(c)); + let figment = rocket::Config::figment().merge(("port", 8081)); - let launch_result = rocket::build() - .manage(c_p) - .mount("/", openapi_get_routes![phe_help,get_public_parameters,set_key, rotate_key]) - .mount( - "/swagger-ui/", - make_swagger_ui(&SwaggerUIConfig { - url: "../openapi.json".to_owned(), - ..Default::default() - }), - ) .mount( - "/rapidoc/", - make_rapidoc(&RapiDocConfig { - general: GeneralConfig { - spec_urls: vec![UrlObject::new("General", "../openapi.json")], + let launch_result = rocket::custom(figment) + .manage(c_p) + .mount( + "/", + openapi_get_routes![phe_help, get_public_parameters, set_key, rotate_key], + ) + .mount( + "/swagger-ui/", + make_swagger_ui(&SwaggerUIConfig { + url: "../openapi.json".to_owned(), ..Default::default() - }, - hide_show: HideShowConfig { - allow_spec_url_load: false, - allow_spec_file_load: false, + }), + ) + .mount( + "/rapidoc/", + make_rapidoc(&RapiDocConfig { + general: GeneralConfig { + spec_urls: vec![UrlObject::new("General", "../openapi.json")], + ..Default::default() + }, + hide_show: HideShowConfig { + allow_spec_url_load: false, + allow_spec_file_load: false, + ..Default::default() + }, ..Default::default() - }, - ..Default::default() - }), - ) - .register("/",catchers![serialize_failed]) - .launch() - .await; + }), + ) + .register("/", catchers![serialize_failed]) + .launch() + .await; match launch_result { Ok(_) => println!("Rocket shut down gracefully."), Err(err) => println!("Rocket had an error: {}", err), @@ -79,47 +86,53 @@ async fn main() { } #[openapi()] -#[post("/phe_help",format = "json", data = "")] -fn phe_help(request: Json,c_state: &State) -> Json { - - let (key,pp) = { +#[post("/phe_help", format = "json", data = "")] +fn phe_help( + request: Json, + c_state: &State, +) -> Json { + let (key, pp) = { let c_state = c_state.read().unwrap(); - (c_state.key.clone(),c_state.pp.clone()) + (c_state.key.clone(), c_state.pp.clone()) }; - - Json(core::phe_ratelimiter(&key,&request,&pp)) + Json(core::phe_ratelimiter(&key, &request, &pp)) } #[openapi()] #[get("/get_public_parameters")] -fn get_public_parameters(c_state: &State) -> Json{ +fn get_public_parameters( + c_state: &State, +) -> Json { let pp = c_state.read().unwrap().pp.clone(); Json(pp) } - #[openapi()] -#[post("/set_key",format = "json", data = "")] -fn set_key(request: Json,c_state: &State) -> Json { +#[post("/set_key", format = "json", data = "")] +fn set_key( + request: Json, + c_state: &State, +) -> Json { let new_c = make_public_parameters(request.key); let mut c_state = c_state.write().unwrap(); c_state.key = new_c.key; c_state.pp = new_c.pp; - Json(new_c.pp) } - #[openapi()] -#[post("/rotate_key",format = "json", data = "")] -fn rotate_key(request: Json,c_state: &State) -> Json { +#[post("/rotate_key", format = "json", data = "")] +fn rotate_key( + request: Json, + c_state: &State, +) -> Json { let mut c_state = c_state.write().unwrap(); let (response, k_new) = core::phe_roate_ratelimiter(&c_state.key, &request.s); c_state.key = k_new; - + Json(response) } diff --git a/src/ophe.rs b/src/ophe.rs index e8e0f84..1cd54d0 100644 --- a/src/ophe.rs +++ b/src/ophe.rs @@ -1,32 +1,35 @@ - -#[macro_use] extern crate rocket; +#[macro_use] +extern crate rocket; extern crate bls12_381; extern crate rand; +use crate::core::EncryptedMessage; +use bls12_381::pairing; +use bls12_381::G1Affine; use bls12_381::G2Affine; use bls12_381::Gt; use bls12_381::Scalar; -use bls12_381::pairing; -use bls12_381::G1Affine; use rocket::request; -use std::time::Duration; -use crate::core::EncryptedMessage; -use rocket_okapi::settings::UrlObject; -use rocket_okapi::{openapi, openapi_get_routes, rapidoc::*, swagger_ui::*}; use rocket::serde::json::Json; use rocket::Request; +use rocket_okapi::settings::UrlObject; +use rocket_okapi::{openapi, openapi_get_routes, rapidoc::*, swagger_ui::*}; +use std::time::Duration; -use ophe::core::{PublicParameters,RatelimiterRequest,RatelimiterResponse,RatelimiterRotateRequest,RatelimiterRotateResponse}; use ophe::core; -use ophe::utils::random_scalar; +use ophe::core::{ + PublicParameters, RatelimiterRequest, RatelimiterResponse, RatelimiterRotateRequest, + RatelimiterRotateResponse, +}; use ophe::shamir; +use ophe::utils::random_scalar; +use futures::future::join_all; use rocket::State; -use serde::{Deserialize, Serialize}; use rocket_okapi::okapi::schemars; use rocket_okapi::okapi::schemars::JsonSchema; +use serde::{Deserialize, Serialize}; use serde_with::serde_as; -use futures::future::join_all; use rocket::http::Status; @@ -43,97 +46,131 @@ struct OpheState { n: i64, t: i64, pk: Gt, + secret_key: Scalar, } -#[derive(Serialize,Deserialize,JsonSchema)] -struct EncryptRequest { - username: String, - password: String, - /// # data - /// data to be encrypted - data:String -} - -#[serde_as] #[derive(Serialize, Deserialize, JsonSchema)] -pub struct DecryptRequest{ +struct EncryptRequest { username: String, password: String, - ciphertext: EncryptedMessage + /// # data + /// data to be encrypted + data: String, } #[serde_as] #[derive(Serialize, Deserialize, JsonSchema)] -pub struct RotateRequest{ - ciphertext: EncryptedMessage +pub struct DecryptRequest { + username: String, + password: String, + ciphertext: EncryptedMessage, } +#[serde_as] +#[derive(Serialize, Deserialize, JsonSchema)] +pub struct RotateRequest { + ciphertext: EncryptedMessage, +} #[catch(422)] fn serialize_failed(_req: &Request) -> String { format!("Malformed Request") } - #[rocket::main] async fn main() { - let cryptoservice_urls = vec!["http://localhost:9001","http://localhost:9002","http://localhost:9003"]; + let cryptoservice_urls = vec!["http://localhost:8081"]; //,"http://localhost:9002","http://localhost:9003"]; let n = cryptoservice_urls.len(); let t = n; let rl_key = ophe::utils::random_scalar(); - let rl_public_key = pairing(&G1Affine::generator(), &G2Affine::generator()) * rl_key; - println!("Generated public key: {:?}",rl_public_key); - let keys = ophe::shamir::gen_shares_scalar(rl_key, n as i64,t as i64); + // we now also have server keys + let s_key = ophe::utils::random_scalar(); + + let rl_public_key = pairing(&G1Affine::generator(), &G2Affine::generator()) * rl_key; + println!("Generated public key: {:?}", rl_public_key); + let keys = ophe::shamir::gen_shares_scalar(rl_key, n as i64, t as i64); + + let pps = keys + .iter() + .zip(cryptoservice_urls) + .map(|(k, url)| async move { + let client = reqwest::ClientBuilder::new() + .tcp_keepalive(Some(Duration::from_secs(60))) + .build() + .unwrap(); + let set_key_request = core::SetKeyHelper { key: k.clone() }; + let res = client + .post(&format!("{}/set_key", url)) + .json(&set_key_request) + .send() + .await + .map_err(|x| format!("Cryptoservice not reachable: {}", x)) + .unwrap() + .text() + .await + .unwrap(); + let pp: PublicParameters = serde_json::from_str(&res) + .map_err(|x| format!("Cryptoservice not reachable: {}", x)) + .unwrap(); + RlState { + pp, + url: url.to_string(), + client, + s: Scalar::zero(), + } + }) + .collect::>(); - let pps = keys.iter().zip(cryptoservice_urls).map( |(k,url)| async move{ - let client = reqwest::ClientBuilder::new().tcp_keepalive(Some(Duration::from_secs(60))).build().unwrap(); - let set_key_request = core::SetKeyHelper{key:k.clone()}; - let res = client.post(&format!("{}/set_key",url)).json(&set_key_request).send() - .await.map_err(|x|{format!("Cryptoservice not reachable: {}",x)}).unwrap().text().await.unwrap(); - let pp: PublicParameters = serde_json::from_str(&res).map_err(|x|{format!("Cryptoservice not reachable: {}",x)}).unwrap(); - RlState{pp,url:url.to_string(),client,s: Scalar::zero()} - }).collect::>(); - let pps = join_all(pps).await; - let pp_keys = pps.iter().map(|x|{x.pp.ratelimiter_public_key}).collect::>(); + let pp_keys = pps + .iter() + .map(|x| x.pp.ratelimiter_public_key) + .collect::>(); let pp_key = ophe::shamir::recover_shares(&pp_keys, n as i64); - assert_eq!(pp_key,rl_public_key,"Public keys do not match"); - - let o_state = OpheState{pps,n: n as i64,t: t as i64, pk: pp_key}; + assert_eq!(pp_key, rl_public_key, "Public keys do not match"); + let o_state = OpheState { + pps, + n: n as i64, + t: t as i64, + pk: pp_key, + secret_key: s_key, + }; println!("Received public parameters from crytoservice"); - let launch_result = rocket::build().mount("/", openapi_get_routes![encrypt,decrypt,rotate]) - .manage(o_state) - .mount( - "/swagger-ui/", - make_swagger_ui(&SwaggerUIConfig { - url: "../openapi.json".to_owned(), - ..Default::default() - }), - ) .mount( - "/rapidoc/", - make_rapidoc(&RapiDocConfig { - general: GeneralConfig { - spec_urls: vec![UrlObject::new("General", "../openapi.json")], + let launch_result = rocket::build() + .mount("/", openapi_get_routes![encrypt, decrypt, rotate]) + .manage(o_state) + .mount( + "/swagger-ui/", + make_swagger_ui(&SwaggerUIConfig { + url: "../openapi.json".to_owned(), ..Default::default() - }, - hide_show: HideShowConfig { - allow_spec_url_load: false, - allow_spec_file_load: false, + }), + ) + .mount( + "/rapidoc/", + make_rapidoc(&RapiDocConfig { + general: GeneralConfig { + spec_urls: vec![UrlObject::new("General", "../openapi.json")], + ..Default::default() + }, + hide_show: HideShowConfig { + allow_spec_url_load: false, + allow_spec_file_load: false, + ..Default::default() + }, ..Default::default() - }, - ..Default::default() - }), - ) - .register("/",catchers![serialize_failed]) - .launch() - .await; - + }), + ) + .register("/", catchers![serialize_failed]) + .launch() + .await; + match launch_result { Ok(_) => println!("Rocket shut down gracefully."), Err(err) => println!("Rocket had an error: {}", err), @@ -141,87 +178,164 @@ async fn main() { } #[openapi()] -#[post("/encrypt",format = "json", data = "")] -async fn encrypt(request: Json,o_state: &State) -> Result,(Status, Json)> { - let (ss,request1) = core::phe_init(&request.username,&request.password); +#[post("/encrypt", format = "json", data = "")] +async fn encrypt( + request: Json, + o_state: &State, +) -> Result, (Status, Json)> { + let (ss, request1) = core::phe_init(&request.username, &request.password); let mut msg = request.data.clone().into_bytes(); if msg.len() > 64 { - return Err((Status::BadRequest,Json("Data too long.".to_string()))) + return Err((Status::BadRequest, Json("Data too long.".to_string()))); } // pad to 64 bytes - msg.resize(64,0); + msg.resize(64, 0); let pps = o_state.pps.iter().map(|x| x.pp).collect::>(); - let responses = get_ratelimiter_reponses(&request1,&o_state.pps).await.map_err(|x| {(Status::InternalServerError,Json("Decryption failed: ".to_string()+&x))})?; + let responses = get_ratelimiter_reponses(&request1, &o_state.pps) + .await + .map_err(|x| { + ( + Status::InternalServerError, + Json("Decryption failed: ".to_string() + &x), + ) + })?; - let ciphertext = core::phe_enc_finish_t(&msg,&pps,&responses,&ss,o_state.n).map_err(|x| {(Status::InternalServerError,Json("Decryption failed.".to_string()+&x))})?; + let ciphertext = + core::phe_enc_finish_t(&msg, &pps, &responses, &ss, o_state.n, &o_state.secret_key) + .map_err(|x| { + ( + Status::InternalServerError, + Json("Decryption failed.".to_string() + &x), + ) + })?; Ok(Json(ciphertext)) } #[openapi()] -#[post("/decrypt",format = "json", data = "")] -async fn decrypt(request: Json,o_state: &State) -> Result,(Status, Json)> { - let (ss,request1) = core::phe_init_decrypt(&request.username,&request.password,&request.ciphertext.n); +#[post("/decrypt", format = "json", data = "")] +async fn decrypt( + request: Json, + o_state: &State, +) -> Result, (Status, Json)> { + let (ss, request1) = + core::phe_init_decrypt(&request.username, &request.password, &request.ciphertext.n); - let responses = get_ratelimiter_reponses(&request1,&o_state.pps).await.map_err(|x| {(Status::InternalServerError,Json("Decryption failed: ".to_string()+&x))})?; + let responses = get_ratelimiter_reponses(&request1, &o_state.pps) + .await + .map_err(|x| { + ( + Status::InternalServerError, + Json("Decryption failed: ".to_string() + &x), + ) + })?; let pps = o_state.pps.iter().map(|x| x.pp).collect::>(); - let res = core::phe_dec_finish_t(&request.ciphertext,&pps,&responses,&ss,o_state.n).map_err(|x| {(Status::InternalServerError,Json("Decryption failed: ".to_string()+&x))})?; + let res = core::phe_dec_finish_t( + &request.ciphertext, + &pps, + &responses, + &ss, + o_state.n, + &o_state.secret_key, + ) + .map_err(|x| { + ( + Status::InternalServerError, + Json("Decryption failed: ".to_string() + &x), + ) + })?; - Ok(Json(String::from_utf8(res).map_err(|_x| {(Status::InternalServerError,Json("Decryption failed. Utf8".to_string()))})?.trim_end_matches(char::from(0)).to_string())) + Ok(Json( + String::from_utf8(res) + .map_err(|_x| { + ( + Status::InternalServerError, + Json("Decryption failed. Utf8".to_string()), + ) + })? + .trim_end_matches(char::from(0)) + .to_string(), + )) } - #[openapi()] -#[post("/rotate",format = "json", data = "")] -async fn rotate(request: Json,o_state: &State) -> Result,(Status, Json)> { +#[post("/rotate", format = "json", data = "")] +async fn rotate( + request: Json, + o_state: &State, +) -> Result, (Status, Json)> { let sk_new = random_scalar(); let shares = shamir::gen_shares_scalar(Scalar::zero(), o_state.n, o_state.t); let ct_new = request.ciphertext.clone(); - let responses = get_ratelimiter_rotate_reponses(&shares, &o_state.pps).await.map_err(|x| {(Status::InternalServerError,Json("Rotation failed: ".to_string()+&x))})?; + let responses = get_ratelimiter_rotate_reponses(&shares, &o_state.pps) + .await + .map_err(|x| { + ( + Status::InternalServerError, + Json("Rotation failed: ".to_string() + &x), + ) + })?; Ok(Json(ct_new)) } -async fn get_ratelimiter_reponses(request: &RatelimiterRequest, urls: &Vec) -> Result,String> { +async fn get_ratelimiter_reponses( + request: &RatelimiterRequest, + urls: &Vec, +) -> Result, String> { let responses = urls.iter().map(|x| async move { - let res = x.client.post(&format!("{}/phe_help",x.url)) - .json(&request) - .send() - .await.map_err(|_x| {format!("Cryptoserice unreachable.")})?.text().await.map_err(|_x| {format!("Cryptoserice unreachable.")})?; - let rs = serde_json::from_str(&res).map_err(|_x| {format!("Invalid cryptoservice response.")})?; - Ok::<_,String>(rs) - + let res = x + .client + .post(&format!("{}/phe_help", x.url)) + .json(&request) + .send() + .await + .map_err(|_x| format!("Cryptoserice unreachable."))? + .text() + .await + .map_err(|_x| format!("Cryptoserice unreachable."))?; + let rs = + serde_json::from_str(&res).map_err(|_x| format!("Invalid cryptoservice response."))?; + Ok::<_, String>(rs) }); join_all(responses).await.into_iter().flatten().collect() } - - -async fn get_ratelimiter_rotate_reponses(shares: &Vec, urls: &Vec) -> Result,String> { +async fn get_ratelimiter_rotate_reponses( + shares: &Vec, + urls: &Vec, +) -> Result, String> { // insert shares to ratelimiter state let mut requests = Vec::new(); for (index, item) in urls.iter().enumerate() { - let mut tmp_state:RlState = item.clone(); + let mut tmp_state: RlState = item.clone(); tmp_state.s = shares[index]; requests.push(tmp_state); } let responses = requests.iter().map(|x| async move { - let request = RatelimiterRotateRequest{s:x.s}; - let res = x.client.post(&format!("{}/rotate_key",x.url)) - .json(&request) - .send() - .await.map_err(|_x| {format!("Cryptoserice unreachable.")})?.text().await.map_err(|_x| {format!("Cryptoserice unreachable.")})?; - let rs = serde_json::from_str(&res).map_err(|_x| {format!("Invalid cryptoservice response.")})?; - Ok::<_,String>(rs) + let request = RatelimiterRotateRequest { s: x.s }; + let res = x + .client + .post(&format!("{}/rotate_key", x.url)) + .json(&request) + .send() + .await + .map_err(|_x| format!("Cryptoserice unreachable."))? + .text() + .await + .map_err(|_x| format!("Cryptoserice unreachable."))?; + let rs = + serde_json::from_str(&res).map_err(|_x| format!("Invalid cryptoservice response."))?; + Ok::<_, String>(rs) }); join_all(responses).await.into_iter().flatten().collect() -} +} From 7add711e05684de85e83b13c51acd44813b38a8b Mon Sep 17 00:00:00 2001 From: pGerhart Date: Thu, 11 Sep 2025 10:39:21 -0400 Subject: [PATCH 2/3] benchmark scripts --- benchmarks/benchmark_decrypt.sh | 4 ++++ benchmarks/benchmark_encrypt.sh | 4 ++++ benchmarks/create_decrypt_request.sh | 8 ++++++++ benchmarks/decrypt_request.json | 6 +++--- 4 files changed, 19 insertions(+), 3 deletions(-) create mode 100755 benchmarks/benchmark_decrypt.sh create mode 100755 benchmarks/benchmark_encrypt.sh create mode 100755 benchmarks/create_decrypt_request.sh diff --git a/benchmarks/benchmark_decrypt.sh b/benchmarks/benchmark_decrypt.sh new file mode 100755 index 0000000..44f0d08 --- /dev/null +++ b/benchmarks/benchmark_decrypt.sh @@ -0,0 +1,4 @@ +ab -k -n 2000 -c 64 \ + -p decrypt_request.json -T application/json \ + http://127.0.0.1:8000/decrypt \ +> ab_decrypt.txt diff --git a/benchmarks/benchmark_encrypt.sh b/benchmarks/benchmark_encrypt.sh new file mode 100755 index 0000000..04488de --- /dev/null +++ b/benchmarks/benchmark_encrypt.sh @@ -0,0 +1,4 @@ +ab -k -n 200 -c 64 \ + -p encrypt.json -T application/json \ + http://127.0.0.1:8000/encrypt \ +> ab_encrypt.txt diff --git a/benchmarks/create_decrypt_request.sh b/benchmarks/create_decrypt_request.sh new file mode 100755 index 0000000..8b38fee --- /dev/null +++ b/benchmarks/create_decrypt_request.sh @@ -0,0 +1,8 @@ +curl -sS http://127.0.0.1:8000/encrypt \ + -H "Content-Type: application/json" \ + --data-binary @encrypt.json \ +| jq -n --argfile ciphertext /dev/stdin \ + --arg u "alice" \ + --arg p "correct horse battery staple" \ + '{username:$u, password:$p, ciphertext:$ciphertext}' \ +> decrypt_request.json diff --git a/benchmarks/decrypt_request.json b/benchmarks/decrypt_request.json index 30d9e27..efb6aee 100644 --- a/benchmarks/decrypt_request.json +++ b/benchmarks/decrypt_request.json @@ -2,8 +2,8 @@ "username": "alice", "password": "correct horse battery staple", "ciphertext": { - "c1": "XTLVdSI41jrdYZoy3yMObpUa6ZKE2p7eXEJyxNJGupq92ArGpIKZAIrHj0W69MNuaZDOXYQ4rNNetwaPfRKoYw==", - "c2": "W/3NHpAN07IlktQgc8vTGPtSDUkqm2RJqH+ovtRbbRmeTOSqDelzshZPLubeeiiBWZ2eYqcwhyvBGq4zN77lFw==", - "n": "KPeQdFyKETghj/5qj70MkSTD1rQ6TLcFiprzTnA+xwo=" + "c1": "0vfnHCz6t0/R5okIAorA7T20lgjpjO8/f8QDGXuICGV73lAL5NSbZcGEQE2mxTMCXYZdDYIdOYBEikSBvNFPbg==", + "c2": "vrT0ECeHsn20CtnjnqhcYQv44hzihdNsmtZ+XU9urxKz3EMPeYZtHc61ucBPb/rq8co9hRyjYfZrBaWyFBlSxQ==", + "n": "ec4lhew4AdybrXXmEhOW1uggPm2oqc2bVQzKUsuZhD0=" } } From d70d97f0c512271c7f01f6fab25c4544a578465d Mon Sep 17 00:00:00 2001 From: pGerhart Date: Thu, 11 Sep 2025 10:57:33 -0400 Subject: [PATCH 3/3] clean up --- .gitignore | 1 + benchmarks/decrypt.json | 1 - benchmarks/decrypt_request.json | 9 --------- 3 files changed, 1 insertion(+), 10 deletions(-) delete mode 100644 benchmarks/decrypt.json delete mode 100644 benchmarks/decrypt_request.json diff --git a/.gitignore b/.gitignore index 75faea8..110cc90 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,4 @@ target .code req req1 +.DS_Store diff --git a/benchmarks/decrypt.json b/benchmarks/decrypt.json deleted file mode 100644 index b79c6eb..0000000 --- a/benchmarks/decrypt.json +++ /dev/null @@ -1 +0,0 @@ -{"c1":"Kg7PO4cAz5MEvfW2PNsWeYgIqPp+sFuyEJylelukYEMlaf2xJbP1EFpIt6/Prr5QKUKuf90Vp9qeEpNNjD+Hbw==","c2":"/cEpryemTCOMxhBdfqkuHFtG69/+rBpngUnb4aBeh3ZKTKbwyEMA8KPikl8xaGPO4xj0SC82kuqD/LkZvb00hA==","n":"0RrSr35GyOUJiyg/rsm1CSSnHjj9bJx6LwxY7fC7Ty4="} \ No newline at end of file diff --git a/benchmarks/decrypt_request.json b/benchmarks/decrypt_request.json deleted file mode 100644 index efb6aee..0000000 --- a/benchmarks/decrypt_request.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "username": "alice", - "password": "correct horse battery staple", - "ciphertext": { - "c1": "0vfnHCz6t0/R5okIAorA7T20lgjpjO8/f8QDGXuICGV73lAL5NSbZcGEQE2mxTMCXYZdDYIdOYBEikSBvNFPbg==", - "c2": "vrT0ECeHsn20CtnjnqhcYQv44hzihdNsmtZ+XU9urxKz3EMPeYZtHc61ucBPb/rq8co9hRyjYfZrBaWyFBlSxQ==", - "n": "ec4lhew4AdybrXXmEhOW1uggPm2oqc2bVQzKUsuZhD0=" - } -}