update for AC
This commit is contained in:
parent
ab1e399768
commit
f7da97c896
1
benchmarks/decrypt.json
Normal file
1
benchmarks/decrypt.json
Normal file
@ -0,0 +1 @@
|
||||
{"c1":"Kg7PO4cAz5MEvfW2PNsWeYgIqPp+sFuyEJylelukYEMlaf2xJbP1EFpIt6/Prr5QKUKuf90Vp9qeEpNNjD+Hbw==","c2":"/cEpryemTCOMxhBdfqkuHFtG69/+rBpngUnb4aBeh3ZKTKbwyEMA8KPikl8xaGPO4xj0SC82kuqD/LkZvb00hA==","n":"0RrSr35GyOUJiyg/rsm1CSSnHjj9bJx6LwxY7fC7Ty4="}
|
||||
9
benchmarks/decrypt_request.json
Normal file
9
benchmarks/decrypt_request.json
Normal file
@ -0,0 +1,9 @@
|
||||
{
|
||||
"username": "alice",
|
||||
"password": "correct horse battery staple",
|
||||
"ciphertext": {
|
||||
"c1": "XTLVdSI41jrdYZoy3yMObpUa6ZKE2p7eXEJyxNJGupq92ArGpIKZAIrHj0W69MNuaZDOXYQ4rNNetwaPfRKoYw==",
|
||||
"c2": "W/3NHpAN07IlktQgc8vTGPtSDUkqm2RJqH+ovtRbbRmeTOSqDelzshZPLubeeiiBWZ2eYqcwhyvBGq4zN77lFw==",
|
||||
"n": "KPeQdFyKETghj/5qj70MkSTD1rQ6TLcFiprzTnA+xwo="
|
||||
}
|
||||
}
|
||||
5
benchmarks/encrypt.json
Normal file
5
benchmarks/encrypt.json
Normal file
@ -0,0 +1,5 @@
|
||||
{
|
||||
"username": "alice",
|
||||
"password": "correct horse battery staple",
|
||||
"data": "hello ophe"
|
||||
}
|
||||
7
benchmarks/test_enc.sh
Executable file
7
benchmarks/test_enc.sh
Executable file
@ -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 @-
|
||||
1
ct.json
Normal file
1
ct.json
Normal file
@ -0,0 +1 @@
|
||||
{"c1":"dhRKjCIEfNfL+CgN4OfvzBkaOif+1wJC2CBT62ihz8ZQQHAouwSW3oO9/616LgYs7b4ygw1TdfgNHQ3fAoKUfw==","c2":"o/yGK+mh5eMDYSKhOCI85ShMcLsRxnhkWarx9lgX/4+xICd4d4dxcpBrFvYDU8qWb0tYk4lvLey2BLGmSIX4mg==","n":"gUoDnQNPXGGnHuJSLRmtim0PCnRfPvWxWPYK5LnHbmk="}
|
||||
516
src/core.rs
516
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<u8>,pp: &Vec<PublicParameters>,response: &Vec<RatelimiterResponse>,ss:&ServerState,n: i64) -> Result<EncryptedMessage,String>{
|
||||
let h = pairing(&G1Affine::from(G1Affine::generator() * ss.n), &G2Affine::from(ss.p));
|
||||
pub fn phe_enc_finish_t(
|
||||
msg: &Vec<u8>,
|
||||
pp: &Vec<PublicParameters>,
|
||||
response: &Vec<RatelimiterResponse>,
|
||||
ss: &ServerState,
|
||||
n: i64,
|
||||
server_sk: &Scalar,
|
||||
) -> Result<EncryptedMessage, 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::<Vec<bool>>().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::<Vec<bool>>()
|
||||
.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::<Vec<Gt>>();
|
||||
|
||||
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::<Vec<&Scalar>>(),
|
||||
]);
|
||||
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::<Vec<&Scalar>>(),
|
||||
],
|
||||
);
|
||||
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<u8>,pp: &Vec<PublicParameters>,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<PublicParameters>,response: &Vec<RatelimiterResponse>,ss:&ServerState,n: i64) -> Result<Vec<u8>,String>{
|
||||
let h = pairing(&G1Affine::from(G1Affine::generator() * ss.n), &G2Affine::from(ss.p));
|
||||
pub fn phe_dec_finish_t(
|
||||
ciphertext: &EncryptedMessage,
|
||||
pp: &Vec<PublicParameters>,
|
||||
response: &Vec<RatelimiterResponse>,
|
||||
ss: &ServerState,
|
||||
n: i64,
|
||||
server_sk: &Scalar,
|
||||
) -> Result<Vec<u8>, 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::<Vec<bool>>().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::<Vec<bool>>()
|
||||
.iter()
|
||||
.all(|x| *x);
|
||||
if !proofok {
|
||||
return Err("Proofs not ok".to_string());
|
||||
}
|
||||
let uvec = response.iter().map(|r| r.u).collect::<Vec<Gt>>();
|
||||
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::<Vec<&Scalar>>(),
|
||||
]);
|
||||
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::<Vec<&Scalar>>(),
|
||||
],
|
||||
);
|
||||
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<PublicParameters>
|
||||
//&response.iter().map(|r| &r.n).collect::<Vec<&Scalar>>(),
|
||||
],
|
||||
);
|
||||
|
||||
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<u8>,pp: &PublicParameters,response: &RatelimiterResponse,ss:&ServerState) -> Result<EncryptedMessage,String>{
|
||||
pub fn phe_enc_finish(
|
||||
msg: &Vec<u8>,
|
||||
pp: &PublicParameters,
|
||||
response: &RatelimiterResponse,
|
||||
ss: &ServerState,
|
||||
) -> Result<EncryptedMessage, String> {
|
||||
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<u8>,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<Vec<u8>,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<Vec<u8>, 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<Gt>, n: &i64) -> Vec<Gt>{
|
||||
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");
|
||||
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::<Vec<_>>();
|
||||
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::<Vec<_>>();
|
||||
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::<Vec<_>>();
|
||||
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::<Vec<_>>();
|
||||
|
||||
|
||||
let pp_keys = pps.iter().map(|x|{x.ratelimiter_public_key}).collect::<Vec<_>>();
|
||||
let pp_keys = pps
|
||||
.iter()
|
||||
.map(|x| x.ratelimiter_public_key)
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
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::<Vec<_>>();
|
||||
let responses = (0..t as usize)
|
||||
.into_par_iter()
|
||||
.map(|i| {
|
||||
let response = phe_ratelimiter(&rlkeys[i], &request, &pps[i]);
|
||||
response
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
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::<Vec<_>>();
|
||||
let responses = (0..t as usize)
|
||||
.into_par_iter()
|
||||
.map(|i| {
|
||||
let response = phe_ratelimiter(&rlkeys[i], &request, &pps[i]);
|
||||
response
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
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::<Vec<_>>();
|
||||
let msg = (0..64).map(|x| (x) as u8).collect::<Vec<_>>();
|
||||
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);
|
||||
|
||||
}
|
||||
println!("{:.2?} phe_dec_finish_simple", start.elapsed() / 1000);
|
||||
assert_eq!(expected, msg);
|
||||
}
|
||||
|
||||
@ -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<RwLock<CryptoserviceState>>;
|
||||
|
||||
|
||||
#[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 = "<request>")]
|
||||
fn phe_help(request: Json<RatelimiterRequest>,c_state: &State<CryptoserviceStatePointer>) -> Json<RatelimiterResponse> {
|
||||
|
||||
let (key,pp) = {
|
||||
#[post("/phe_help", format = "json", data = "<request>")]
|
||||
fn phe_help(
|
||||
request: Json<RatelimiterRequest>,
|
||||
c_state: &State<CryptoserviceStatePointer>,
|
||||
) -> Json<RatelimiterResponse> {
|
||||
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<CryptoserviceStatePointer>) -> Json<core::PublicParameters>{
|
||||
fn get_public_parameters(
|
||||
c_state: &State<CryptoserviceStatePointer>,
|
||||
) -> Json<core::PublicParameters> {
|
||||
let pp = c_state.read().unwrap().pp.clone();
|
||||
Json(pp)
|
||||
}
|
||||
|
||||
|
||||
#[openapi()]
|
||||
#[post("/set_key",format = "json", data = "<request>")]
|
||||
fn set_key(request: Json<SetKeyHelper>,c_state: &State<CryptoserviceStatePointer>) -> Json<core::PublicParameters> {
|
||||
#[post("/set_key", format = "json", data = "<request>")]
|
||||
fn set_key(
|
||||
request: Json<SetKeyHelper>,
|
||||
c_state: &State<CryptoserviceStatePointer>,
|
||||
) -> Json<core::PublicParameters> {
|
||||
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 = "<request>")]
|
||||
fn rotate_key(request: Json<RatelimiterRotateRequest>,c_state: &State<CryptoserviceStatePointer>) -> Json<RatelimiterRotateResponse> {
|
||||
#[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)
|
||||
}
|
||||
|
||||
|
||||
326
src/ophe.rs
326
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::<Vec<_>>();
|
||||
|
||||
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::<Vec<_>>();
|
||||
|
||||
let pps = join_all(pps).await;
|
||||
|
||||
let pp_keys = pps.iter().map(|x|{x.pp.ratelimiter_public_key}).collect::<Vec<_>>();
|
||||
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, 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 = "<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);
|
||||
#[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 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::<Vec<_>>();
|
||||
|
||||
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 = "<request>")]
|
||||
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);
|
||||
#[post("/decrypt", format = "json", data = "<request>")]
|
||||
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 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::<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))})?;
|
||||
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 = "<request>")]
|
||||
async fn rotate(request: Json<RotateRequest>,o_state: &State<OpheState>) -> Result<Json<EncryptedMessage>,(Status, Json<String>)> {
|
||||
#[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))})?;
|
||||
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> {
|
||||
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)
|
||||
|
||||
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<Scalar>, urls: &Vec<RlState>) -> Result<Vec<RatelimiterRotateResponse>,String> {
|
||||
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();
|
||||
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()
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user