Updated to t-variant and new protocol

This commit is contained in:
Fritz Schmid
2023-03-06 19:10:03 +01:00
parent a11a92d3d7
commit 6fb0dcd867
10 changed files with 514 additions and 337 deletions
+106 -86
View File
@@ -3,40 +3,99 @@
extern crate bls12_381;
extern crate rand;
use bls12_381::G2Affine;
use bls12_381::pairing;
use bls12_381::G1Affine;
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 ophe::core::{RatelimiterResponse,PublicParameters};
use ophe::core::{PublicParameters,RatelimiterRequest,RatelimiterResponse};
use ophe::core;
use rocket::State;
use serde::{Deserialize, Serialize};
use rocket_okapi::okapi::schemars;
use rocket_okapi::okapi::schemars::JsonSchema;
use bls12_381::Scalar;
use bls12_381::Gt;
use ophe::serializers;
use serde_with::serde_as;
use futures::future::join_all;
use rocket::http::Status;
struct RlState {
pp: PublicParameters,
url: String,
client: reqwest::Client
}
struct OpheState {
pps: Vec<RlState>,
n: i64,
t: i64,
}
#[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{
username: String,
password: String,
ciphertext: EncryptedMessage
}
#[catch(422)]
fn serialize_failed(_req: &Request) -> String {
format!("Malformed Request")
}
#[rocket::main]
async fn main() {
let client = reqwest::Client::new();
let res = client.get("http://localhost:9999/get_public_parameters").send()
.await.map_err(|x|{format!("Cryptoservice not reachable: {}",x)}).unwrap().text().await.unwrap();
let cryptoservice_urls = vec!["http://localhost:9001","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);
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}
}).collect::<Vec<_>>();
let pps = join_all(pps).await;
let pp_keys = pps.iter().map(|x|{x.pp.ratelimiter_public_key}).collect::<Vec<_>>();
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};
let pp: PublicParameters = serde_json::from_str(&res).map_err(|x|{format!("Cryptoservice not reachable: {}",x)}).unwrap();
println!("Received public parameters from crytoservice");
let launch_result = rocket::build().mount("/", openapi_get_routes![make_request,decrypt])
.manage(pp)
let launch_result = rocket::build().mount("/", openapi_get_routes![encrypt,decrypt])
.manage(o_state)
.mount(
"/swagger-ui/",
make_swagger_ui(&SwaggerUIConfig {
@@ -61,99 +120,60 @@ async fn main() {
.register("/",catchers![serialize_failed])
.launch()
.await;
match launch_result {
Ok(_) => println!("Rocket shut down gracefully."),
Err(err) => println!("Rocket had an error: {}", err),
};
}
#[derive(Serialize,Deserialize,JsonSchema)]
struct UsernamePw{
username: String,
password: String
}
#[catch(422)]
fn serialize_failed(_req: &Request) -> String {
format!("Malformed Request")
}
#[serde_as]
#[derive(Serialize, Deserialize, JsonSchema)]
pub struct EnrollResponse{
#[serde_as(as = "serializers::SerializeScalar")]
#[schemars(with = "String")]
n: Scalar,
#[serde_as(as = "Vec<serializers::SerializeGt>")]
#[schemars(with = "Vec<String>")]
ciphertext: Vec<Gt>
match launch_result {
Ok(_) => println!("Rocket shut down gracefully."),
Err(err) => println!("Rocket had an error: {}", err),
};
}
#[openapi()]
#[post("/make_request",format = "json", data = "<request>")]
async fn make_request(request: Json<UsernamePw>,pp: &State<core::PublicParameters>) -> Result<Json<EnrollResponse>,(Status, Json<String>)> {
#[post("/encrypt",format = "json", data = "<request>")]
async fn encrypt(request: Json<EncryptRequest>,o_state: &State<OpheState>) -> Result<Json<EncryptedMessage>,(Status, Json<String>)> {
let (ss,request1) = core::phe_init(&request.username,&request.password);
let client = reqwest::Client::new();
let mut msg = request.data.clone().into_bytes();
let res = client.post("http://localhost:9999/phe_help")
.json(&request1)
.send()
.await.map_err(|_x| {(Status::InternalServerError,Json("Cryptoserice unreachable.".to_string()))})?.text().await.map_err(|_x| {(Status::InternalServerError,Json("Cryptoserice unreachable.".to_string()))})?;
let response: RatelimiterResponse = serde_json::from_str(&res).map_err(|_x| {(Status::InternalServerError,Json("Invalid cryptoservice response.".to_string()))})?;
let mut msg = Vec::new();
for _x in 0..32{
msg.push(0u8);
if msg.len() > 64 {
return Err((Status::BadRequest,Json("Data too long.".to_string())))
}
let ciphertext = core::phe_enc_finish(&msg,&pp,&response,&ss).map_err(|x| {(Status::InternalServerError,Json("Decryption failed.".to_string()+&x))})?;
// pad to 64 bytes
msg.resize(64,0);
Ok(Json(EnrollResponse{n:ss.n,ciphertext}))
}
let pps = o_state.pps.iter().map(|x| x.pp).collect::<Vec<_>>();
let responses = get_ratelimiter_reponses(&request1,&o_state.pps).await.map_err(|x| {(Status::InternalServerError,Json("Decryption failed: ".to_string()+&x))})?;
#[serde_as]
#[derive(Serialize, Deserialize, JsonSchema)]
pub struct DecryptRequest{
#[serde_as(as = "serializers::SerializeScalar")]
#[schemars(with = "String")]
n: Scalar,
username: String,
password: String,
#[serde_as(as = "Vec<serializers::SerializeGt>")]
#[schemars(with = "Vec<String>")]
ciphertext: Vec<Gt>
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))})?;
Ok(Json(ciphertext))
}
#[openapi()]
#[post("/decrypt",format = "json", data = "<request>")]
async fn decrypt(request: Json<DecryptRequest>,pp: &State<core::PublicParameters>) -> Result<Json<bool>,(Status, Json<String>)>{
async fn decrypt(request: Json<DecryptRequest>,o_state: &State<OpheState>) -> Result<Json<String>,(Status, Json<String>)> {
let (ss,request1) = core::phe_init_decrypt(&request.username,&request.password,&request.ciphertext.n);
let res = decrypt_err(request,pp).await;
let responses = get_ratelimiter_reponses(&request1,&o_state.pps).await.map_err(|x| {(Status::InternalServerError,Json("Decryption failed: ".to_string()+&x))})?;
res
let pps = o_state.pps.iter().map(|x| x.pp).collect::<Vec<_>>();
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))})?;
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()))
}
async fn get_ratelimiter_reponses(request: &RatelimiterRequest, urls: &Vec<RlState>) -> Result<Vec<RatelimiterResponse>,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)
});
async fn decrypt_err(request: Json<DecryptRequest>,pp: &State<core::PublicParameters>) -> Result<Json<bool>,(Status, Json<String>)> {
let (ss,request1) = core::phe_init_decrypt(&request.username,&request.password,&request.n);
let client = reqwest::Client::new();
let res = client.post("http://localhost:9999/phe_help")
.json(&request1)
.send()
.await.map_err(|_x| {(Status::InternalServerError,Json("Cryptoserice unreachable.".to_string()))})?.text().await.map_err(|_x| {(Status::InternalServerError,Json("Internal Error.".to_string()))})?;
let response: RatelimiterResponse = serde_json::from_str(&res).map_err(|_x| {(Status::InternalServerError,Json("Invalid cryptoservice response.".to_string()))})?;
let mut msg = Vec::new();
for _x in 0..32{
msg.push(0u8);
}
let expected = core::phe_dec_finish_simple(&request.ciphertext,&pp,&response,&ss).map_err(|x| {(Status::InternalServerError,Json("Decryption failed.".to_string()+&x))})?;
println!("{:?}",expected);
Ok(Json(true))
join_all(responses).await.into_iter().flatten().collect()
}