Merge branch 'final-version-AC'

This commit is contained in:
pGerhart 2025-09-11 10:58:02 -04:00
commit fbe7894767
10 changed files with 635 additions and 470 deletions

1
.gitignore vendored
View File

@ -2,3 +2,4 @@ target
.code
req
req1
.DS_Store

View File

@ -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

View File

@ -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

View File

@ -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

5
benchmarks/encrypt.json Normal file
View File

@ -0,0 +1,5 @@
{
"username": "alice",
"password": "correct horse battery staple",
"data": "hello ophe"
}

7
benchmarks/test_enc.sh Executable file
View 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
View File

@ -0,0 +1 @@
{"c1":"dhRKjCIEfNfL+CgN4OfvzBkaOif+1wJC2CBT62ihz8ZQQHAouwSW3oO9/616LgYs7b4ygw1TdfgNHQ3fAoKUfw==","c2":"o/yGK+mh5eMDYSKhOCI85ShMcLsRxnhkWarx9lgX/4+xICd4d4dxcpBrFvYDU8qWb0tYk4lvLey2BLGmSIX4mg==","n":"gUoDnQNPXGGnHuJSLRmtim0PCnRfPvWxWPYK5LnHbmk="}

View File

@ -1,91 +1,88 @@
use ark_bls12_381::Bls12_381;
use ark_groth16::PreparedVerifyingKey;
use ark_groth16::ProvingKey;
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,
ps: Scalar,
pw: String
p0: G2Projective,
pw: String,
}
impl ServerState {
fn new(username: &String, password: &String,pk: &ProvingKey<Bls12_381>) -> (ServerState,Vec<u8>){
fn new(username: &String, password: &String) -> ServerState {
let r = utils::random_scalar();
let n = utils::random_scalar();
let (hash_scalar,hash_proof) = proofs::generate_hash_proof(username, password, &n, &r, pk);
let p = G2Affine::generator() * hash_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,ps:hash_scalar,pw: password.to_owned()},hash_proof)
let username = username.to_owned();
let to_be_hashed = username + password;
let tempr = utils::hash_string_to_scalar(to_be_hashed);
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,pk: &ProvingKey<Bls12_381>) -> (ServerState,Vec<u8>){
fn from_nonce(username: &String, password: &String, nonce: &Scalar) -> ServerState {
let r = utils::random_scalar();
let (hash_scalar,hash_proof) = proofs::generate_hash_proof(username, password, &nonce, &r, pk);
let p = G2Affine::generator() * hash_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 username = username.to_owned();
let to_be_hashed = username + password;
let tempr = utils::hash_string_to_scalar(to_be_hashed);
let p0 = G2Affine::generator() * tempr;
let p = p0 * r;
(ServerState{r,n: nonce.clone(),p,ps:hash_scalar,pw: password.to_owned()},hash_proof)
}
ServerState {
r,
n: nonce.clone(),
p,
p0,
pw: password.to_owned(),
}
}
}
#[serde_as]
#[derive(Serialize, Deserialize, JsonSchema,Clone,Debug)]
pub struct RatelimiterRequest{
#[derive(Serialize, Deserialize, JsonSchema, Clone, Copy, Debug)]
pub struct RatelimiterRequest {
#[serde_as(as = "serializers::SerializeScalar")]
#[schemars(with = "String")]
n: Scalar,
#[serde_as(as = "serializers::SerializeG2")]
#[schemars(with = "String")]
p: G2Projective,
#[serde_as(as = "serializers::SerializeScalar")]
#[schemars(with = "String")]
ps: Scalar,
#[serde_as(as = "serde_with::base64::Base64")]
#[schemars(with = "String")]
hash_proof: Vec<u8>
}
#[serde_as]
#[derive(Serialize, Deserialize, JsonSchema)]
pub struct RatelimiterResponse{
pub struct RatelimiterResponse {
proof: proofs::SameDLogProof,
#[serde_as(as = "serializers::SerializeGt")]
#[schemars(with = "String")]
@ -94,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,
@ -102,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,
@ -111,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],
@ -128,76 +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,pk: &ProvingKey<Bls12_381>) -> (ServerState,RatelimiterRequest){
let (ss,hash_proof) = ServerState::new(username,password,pk);
let rr = RatelimiterRequest{n:ss.n,p:ss.p,hash_proof,ps:ss.ps};
return (ss,rr)
return (ss, rr);
}
pub fn phe_init_decrypt(username: &String, password: &String,n: &Scalar,pk: &ProvingKey<Bls12_381>) -> (ServerState,RatelimiterRequest){
let (ss,hash_proof) = ServerState::from_nonce(username,password,n,pk);
let rr = RatelimiterRequest{n:ss.n,p:ss.p,hash_proof,ps:ss.ps};
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,pvk: &PreparedVerifyingKey<Bls12_381>) -> Result<RatelimiterResponse,String> {
// check if request.p = G2Affine::generator() * hash_proof
if (G2Affine::generator() * request.ps) != request.p{
return Err("Invalid hash proof. Hash scalar and Point not matching.".to_string());
}
//verify hash proof
let result = proofs::validate_hash_proof(&request.ps,&request.hash_proof,&pvk);
if !result{
return Err("Invalid hash proof.".to_string());
}
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);
Ok(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(
&[
@ -210,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(
@ -246,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(
&[
@ -284,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(
&[
@ -317,40 +377,56 @@ 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);
//test_core_k(32,8);
}
#[test]
fn t1est_core_test() {
rayon::ThreadPoolBuilder::new()
.num_threads(1)
.build_global()
.unwrap();
test_core_t(10, 10);
}
#[test]
fn test_speed_operations() {
@ -364,208 +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 = &gt1 + &gt2;
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 = &gtres + &gt2;
}
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 = &gtres * s1;
}
println!(" {:.2?} gt exp ",start.elapsed()/1000);
println!(" {:.2?} gt exp ", start.elapsed() / 1000);
}
#[test]
fn t1est_core_test()
{
rayon::ThreadPoolBuilder::new().num_threads(1).build_global().unwrap();
test_core_t(10,10);
}
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");
let (pk,vk,pvk) = proofs::setup_hash_proof();
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(),&pk);
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],&pvk).unwrap();
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, &pk);
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],&pvk).unwrap();
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 resdec = 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!(resdec.unwrap(),msg);
// test invalid password
let (ss,request) = phe_init(&"test".to_string(),&"test2".to_string(),&pk);
let responses = (0..t as usize).into_par_iter().map(|i|{
let response = phe_ratelimiter(&rlkeys[i],&request,&pps[i],&pvk).unwrap();
response
}).collect::<Vec<_>>();
let err_res = phe_dec_finish_t(&res,&pps,&responses,&ss,n);
assert!(err_res.is_err());
// test corrupted ciphertext
let mut res2 = res.clone();
res2.c1[0] = res2.c1[0] ^ 1;
let err_res = phe_dec_finish_t(&res2,&pps,&responses,&ss,n);
assert!(err_res.is_err());
// test changed real key
let real_key2 = utils::random_scalar();
let rlkeys2 = shamir::gen_shares_scalar(real_key2,n,t);
let pps2 = rlkeys2.iter().map(|x|PublicParameters{
gt_gen: generator,
ratelimiter_public_key: generator*x
}).collect::<Vec<_>>();
let pp_keys2 = pps2.iter().map(|x|{x.ratelimiter_public_key}).collect::<Vec<_>>();
let pp_key2 = shamir::recover_shares(&pp_keys2, n as i64);
assert_eq!(pp_key2,generator*real_key2,"Public keys do not match");
let (ss,request) = phe_init(&"test".to_string(),&"test".to_string(),&pk);
let responses = (0..t as usize).into_par_iter().map(|i|{
let response = phe_ratelimiter(&rlkeys2[i],&request,&pps2[i],&pvk).unwrap();
response
}).collect::<Vec<_>>();
let err_res = phe_dec_finish_t(&res,&pps2,&responses,&ss,n);
assert!(err_res.is_err());
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 (pk,vk,pvk) = proofs::setup_hash_proof();
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();
let (ss,request) = phe_init(&"test".to_string(),&"test".to_string(),&pk);
println!("{:.2?} phe_init",start.elapsed());
let response = phe_ratelimiter(&key,&request,&pp,&pvk).unwrap();
let start = Instant::now();
for _i in 0..100{
let response = phe_ratelimiter(&key,&request,&pp,&pvk).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();
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();
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, &pk);
println!("{:.2?} phe_enc_finish", start.elapsed() / 1000);
let response = phe_ratelimiter(&key,&request,&pp,&pvk).unwrap();
let (ss, request) = phe_init_decrypt(&"test".to_string(), &"test".to_string(), &ciphertext.n);
let expected = phe_dec_finish_simple(&ciphertext,&pp,&response,&ss).unwrap();
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();
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);
}

View File

@ -1,92 +1,84 @@
#[macro_use] extern crate rocket;
#[macro_use]
extern crate rocket;
extern crate bls12_381;
extern crate rand;
use std::sync::RwLock;
use ark_bls12_381::Bls12_381;
use ark_groth16::PreparedVerifyingKey;
use bls12_381::pairing;
use bls12_381::G2Affine;
use ophe::proofs;
use ophe::proofs::HashProof;
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};
let mut rng = OsRng::default();
let test: HashProof = HashProof {
pw_point: None,
nonce_point: None,
random_r: None,
let pp = core::PublicParameters {
ratelimiter_public_key: public_key,
gt_gen: generator,
};
let (pk, vk,pvk) = proofs::setup_hash_proof();
CryptoserviceState{key,pp,hashproof_pvk:pvk}
CryptoserviceState { key, pp }
}
struct CryptoserviceState {
key: Scalar,
pp: core::PublicParameters,
hashproof_pvk: PreparedVerifyingKey<Bls12_381>,
}
type CryptoserviceStatePointer = Arc<RwLock<CryptoserviceState>>;
use rand_core::{RngCore, OsRng};
#[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),
@ -94,46 +86,53 @@ async fn main() {
}
#[openapi()]
#[post("/phe_help",format = "json", data = "<request>")]
fn phe_help(request: Json<RatelimiterRequest>,c_state: &State<CryptoserviceStatePointer>) -> Result<Json<RatelimiterResponse>,String> {
let (key,pp,pvk) = {
#[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.hashproof_pvk.clone())
(c_state.key.clone(), c_state.pp.clone())
};
Ok(Json(core::phe_ratelimiter(&key,&request,&pp,&pvk)?))
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)
}

View File

@ -1,36 +1,35 @@
#[macro_use] extern crate rocket;
#[macro_use]
extern crate rocket;
extern crate bls12_381;
extern crate rand;
use ark_bls12_381::Bls12_381;
use ark_groth16::PreparedVerifyingKey;
use ark_groth16::ProvingKey;
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 ophe::proofs;
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;
@ -47,101 +46,131 @@ struct OpheState {
n: i64,
t: i64,
pk: Gt,
hash_proof_vk: ProvingKey<Bls12_381>,
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() {
rayon::ThreadPoolBuilder::new().num_threads(1).build_global().unwrap();
let cryptoservice_urls = vec!["http://localhost:9001"];
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 hash_proof_setup = proofs::setup_hash_proof();
let o_state = OpheState{pps,n: n as i64,t: t as i64, pk: pp_key, hash_proof_vk: hash_proof_setup.0};
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),
@ -149,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,&o_state.hash_proof_vk);
#[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,&o_state.hash_proof_vk);
#[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()
}
}