implement rotation

This commit is contained in:
Paul Gerhart 2023-07-23 16:12:00 +02:00
parent 6fb0dcd867
commit ab1e399768
3 changed files with 104 additions and 8 deletions

View File

@ -1,4 +1,5 @@
use bls12_381::*;
use group::Group;
use crate::utils;
use crate::proofs;
use crate::shamir;
@ -74,9 +75,28 @@ pub struct RatelimiterResponse{
u: Gt,
}
#[serde_as]
#[derive(Serialize, Deserialize, JsonSchema)]
pub struct RatelimiterRotateRequest{
#[serde_as(as = "serializers::SerializeScalar")]
#[schemars(with = "String")]
pub s: Scalar,
}
#[serde_as]
#[derive(Serialize, Deserialize, JsonSchema)]
pub struct RatelimiterRotateResponse{
#[serde_as(as = "serializers::SerializeScalar")]
#[schemars(with = "String")]
pub n: Scalar,
#[serde_as(as = "serializers::SerializeGt")]
#[schemars(with = "String")]
pub pk_new: Gt,
}
#[serde_as]
#[derive(Serialize, Deserialize, JsonSchema, Clone)]
pub struct EncryptedMessage{
#[serde_as(as = "serde_with::base64::Base64")]
#[schemars(with = "String")]
@ -273,6 +293,22 @@ pub fn phe_dec_finish_simple(ciphertext: &EncryptedMessage,pp: &PublicParameters
}
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)
}
pub fn find_set(public_key: &Gt, public_key_shares: &Vec<Gt>, n: &i64) -> Vec<Gt>{
let test_pk = shamir::recover_shares(public_key_shares, *n);
assert_eq!(public_key.clone(), test_pk, "Find Set: Public keys do not match");
return public_key_shares.clone();
}
#[test]
fn test_core(){
//rayon::ThreadPoolBuilder::new().num_threads(8).build_global().unwrap();

View File

@ -13,8 +13,9 @@ use rocket_okapi::{openapi, openapi_get_routes, rapidoc::*, swagger_ui::*};
use rocket::serde::json::Json;
use rocket::Request;
use ophe::core::{RatelimiterRequest,RatelimiterResponse,SetKeyHelper};
use ophe::core::{RatelimiterRequest,RatelimiterResponse,SetKeyHelper, RatelimiterRotateRequest, RatelimiterRotateResponse};
use ophe::core;
use ophe::utils;
use rocket::State;
use bls12_381::Scalar;
@ -46,7 +47,7 @@ async fn main() {
let launch_result = rocket::build()
.manage(c_p)
.mount("/", openapi_get_routes![phe_help,get_public_parameters,set_key])
.mount("/", openapi_get_routes![phe_help,get_public_parameters,set_key, rotate_key])
.mount(
"/swagger-ui/",
make_swagger_ui(&SwaggerUIConfig {
@ -111,6 +112,17 @@ fn set_key(request: Json<SetKeyHelper>,c_state: &State<CryptoserviceStatePointer
Json(new_c.pp)
}
#[openapi()]
#[post("/rotate_key",format = "json", data = "<request>")]
fn rotate_key(request: Json<RatelimiterRotateRequest>,c_state: &State<CryptoserviceStatePointer>) -> Json<RatelimiterRotateResponse> {
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)
}
#[catch(422)]
fn serialize_failed(_req: &Request) -> String {
format!("Malformed Request")

View File

@ -4,8 +4,11 @@ extern crate bls12_381;
extern crate rand;
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;
@ -13,8 +16,10 @@ use rocket_okapi::{openapi, openapi_get_routes, rapidoc::*, swagger_ui::*};
use rocket::serde::json::Json;
use rocket::Request;
use ophe::core::{PublicParameters,RatelimiterRequest,RatelimiterResponse};
use ophe::core::{PublicParameters,RatelimiterRequest,RatelimiterResponse,RatelimiterRotateRequest,RatelimiterRotateResponse};
use ophe::core;
use ophe::utils::random_scalar;
use ophe::shamir;
use rocket::State;
use serde::{Deserialize, Serialize};
@ -25,17 +30,19 @@ use futures::future::join_all;
use rocket::http::Status;
#[derive(Clone)]
struct RlState {
pp: PublicParameters,
url: String,
client: reqwest::Client
client: reqwest::Client,
s: Scalar,
}
struct OpheState {
pps: Vec<RlState>,
n: i64,
t: i64,
pk: Gt,
}
#[derive(Serialize,Deserialize,JsonSchema)]
@ -55,6 +62,12 @@ pub struct DecryptRequest{
ciphertext: EncryptedMessage
}
#[serde_as]
#[derive(Serialize, Deserialize, JsonSchema)]
pub struct RotateRequest{
ciphertext: EncryptedMessage
}
#[catch(422)]
fn serialize_failed(_req: &Request) -> String {
@ -78,7 +91,7 @@ async fn main() {
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}
RlState{pp,url:url.to_string(),client,s: Scalar::zero()}
}).collect::<Vec<_>>();
let pps = join_all(pps).await;
@ -89,12 +102,12 @@ async fn main() {
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 o_state = OpheState{pps,n: n as i64,t: t as i64, pk: pp_key};
println!("Received public parameters from crytoservice");
let launch_result = rocket::build().mount("/", openapi_get_routes![encrypt,decrypt])
let launch_result = rocket::build().mount("/", openapi_get_routes![encrypt,decrypt,rotate])
.manage(o_state)
.mount(
"/swagger-ui/",
@ -163,6 +176,18 @@ async fn decrypt(request: Json<DecryptRequest>,o_state: &State<OpheState>) -> Re
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 = "<request>")]
async fn rotate(request: Json<RotateRequest>,o_state: &State<OpheState>) -> Result<Json<EncryptedMessage>,(Status, Json<String>)> {
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))})?;
Ok(Json(ct_new))
}
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))
@ -177,3 +202,26 @@ async fn get_ratelimiter_reponses(request: &RatelimiterRequest, urls: &Vec<RlSta
join_all(responses).await.into_iter().flatten().collect()
}
async fn get_ratelimiter_rotate_reponses(shares: &Vec<Scalar>, urls: &Vec<RlState>) -> Result<Vec<RatelimiterRotateResponse>,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();
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)
});
join_all(responses).await.into_iter().flatten().collect()
}