Updated to t-variant and new protocol
This commit is contained in:
parent
a11a92d3d7
commit
6fb0dcd867
2
.cargo/config.toml
Normal file
2
.cargo/config.toml
Normal file
@ -0,0 +1,2 @@
|
||||
[build]
|
||||
rustflags = ["-C", "target-cpu=native"]
|
||||
2
.gitignore
vendored
2
.gitignore
vendored
@ -1,2 +1,4 @@
|
||||
target
|
||||
.code
|
||||
req
|
||||
req1
|
||||
|
||||
2
Cargo.lock
generated
2
Cargo.lock
generated
@ -977,6 +977,7 @@ dependencies = [
|
||||
"bit-vec",
|
||||
"bitvec 0.22.0",
|
||||
"bls12_381",
|
||||
"futures",
|
||||
"group",
|
||||
"lazy_static",
|
||||
"rand",
|
||||
@ -1550,6 +1551,7 @@ version = "1.14.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "678b5a069e50bf00ecd22d0cd8ddf7c236f68581b03db652061ed5eb13a312ff"
|
||||
dependencies = [
|
||||
"base64",
|
||||
"serde",
|
||||
"serde_with_macros",
|
||||
]
|
||||
|
||||
@ -23,7 +23,8 @@ time = "*"
|
||||
rocket = "0.5.0-rc.1"
|
||||
rayon = "*"
|
||||
base64 = "*"
|
||||
serde_with = "*"
|
||||
serde_with = { version = "*", features = ["base64","default"] }
|
||||
futures = "*"
|
||||
reqwest ={ version = "*", features = ["json"]}
|
||||
|
||||
rocket_okapi = { version = "0.8.0-alpha-1", features = ["swagger", "rapidoc"] }
|
||||
|
||||
346
src/core.rs
346
src/core.rs
@ -1,7 +1,7 @@
|
||||
use bls12_381::*;
|
||||
use crate::utils;
|
||||
use crate::proofs;
|
||||
use std::collections::HashMap;
|
||||
use crate::shamir;
|
||||
use std::time::Instant;
|
||||
use rayon::prelude::*;
|
||||
use serde::{Deserialize, Serialize};
|
||||
@ -12,25 +12,22 @@ use crate::serializers;
|
||||
use serde_with::serde_as;
|
||||
|
||||
#[serde_as]
|
||||
#[derive(Deserialize, Serialize,JsonSchema)]
|
||||
#[derive(Deserialize, Serialize,JsonSchema,Clone,Copy)]
|
||||
pub struct PublicParameters{
|
||||
#[serde_as(as = "Vec<serializers::SerializeScalar>")]
|
||||
#[schemars(with = "Vec::<String>")]
|
||||
pub space: Vec<Scalar>,
|
||||
pub k: usize,
|
||||
#[serde_as(as = "serializers::SerializeGt")]
|
||||
#[schemars(with = "String")]
|
||||
pub gt_gen: Gt,
|
||||
#[serde_as(as = "Vec<serializers::SerializeGt>")]
|
||||
#[schemars(with = "Vec::<String>")]
|
||||
pub ratelimiter_public_keys: Vec<Gt>
|
||||
#[serde_as(as = "serializers::SerializeGt")]
|
||||
#[schemars(with = "String")]
|
||||
pub ratelimiter_public_key: Gt
|
||||
}
|
||||
|
||||
|
||||
pub struct ServerState{
|
||||
r: Scalar,
|
||||
pub n: Scalar,
|
||||
p: G2Projective
|
||||
p: G2Projective,
|
||||
pw: String,
|
||||
}
|
||||
|
||||
impl ServerState {
|
||||
@ -40,9 +37,9 @@ impl ServerState {
|
||||
|
||||
let username = username.to_owned();
|
||||
let to_be_hashed = username + password;
|
||||
let h2 = G2Affine::generator() * utils::hash_string_to_scalar(to_be_hashed);
|
||||
let p = h2 * r;
|
||||
ServerState{r,n,p}
|
||||
let tempr = utils::hash_string_to_scalar(to_be_hashed);
|
||||
let p = G2Affine::generator() * tempr * r;
|
||||
ServerState{r,n,p,pw: password.to_owned()}
|
||||
}
|
||||
|
||||
fn from_nonce(username: &String, password: &String, nonce: &Scalar) -> ServerState{
|
||||
@ -50,14 +47,15 @@ impl ServerState {
|
||||
|
||||
let username = username.to_owned();
|
||||
let to_be_hashed = username + password;
|
||||
let h2 = G2Affine::generator() * utils::hash_string_to_scalar(to_be_hashed);
|
||||
let p = h2 * r;
|
||||
ServerState{r,n: nonce.clone(),p}
|
||||
let tempr = utils::hash_string_to_scalar(to_be_hashed);
|
||||
let p = G2Affine::generator() * tempr * r;
|
||||
|
||||
ServerState{r,n: nonce.clone(),p,pw: password.to_owned()}
|
||||
}
|
||||
}
|
||||
|
||||
#[serde_as]
|
||||
#[derive(Serialize, Deserialize, JsonSchema)]
|
||||
#[derive(Serialize, Deserialize, JsonSchema,Clone,Copy,Debug)]
|
||||
pub struct RatelimiterRequest{
|
||||
#[serde_as(as = "serializers::SerializeScalar")]
|
||||
#[schemars(with = "String")]
|
||||
@ -70,18 +68,36 @@ pub struct RatelimiterRequest{
|
||||
#[serde_as]
|
||||
#[derive(Serialize, Deserialize, JsonSchema)]
|
||||
pub struct RatelimiterResponse{
|
||||
elements: Vec<RatelimiterResponseElement>
|
||||
proof: proofs::SameDLogProof,
|
||||
#[serde_as(as = "serializers::SerializeGt")]
|
||||
#[schemars(with = "String")]
|
||||
u: Gt,
|
||||
}
|
||||
|
||||
|
||||
#[serde_as]
|
||||
#[derive(Serialize, Deserialize, JsonSchema)]
|
||||
pub struct EncryptedMessage{
|
||||
#[serde_as(as = "serde_with::base64::Base64")]
|
||||
#[schemars(with = "String")]
|
||||
pub c1: [u8; 64],
|
||||
#[serde_as(as = "serde_with::base64::Base64")]
|
||||
#[schemars(with = "String")]
|
||||
pub c2: [u8; 64],
|
||||
#[serde_as(as = "serializers::SerializeScalar")]
|
||||
#[schemars(with = "String")]
|
||||
pub n: Scalar,
|
||||
}
|
||||
|
||||
#[serde_as]
|
||||
#[derive(Serialize, Deserialize, JsonSchema)]
|
||||
pub struct RatelimiterResponseElement{
|
||||
proof: proofs::SameDLogProof,
|
||||
#[serde_as(as = "serializers::SerializeGt")]
|
||||
pub struct SetKeyHelper{
|
||||
#[serde_as(as = "serializers::SerializeScalar")]
|
||||
#[schemars(with = "String")]
|
||||
p: Gt
|
||||
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};
|
||||
@ -96,71 +112,184 @@ pub fn phe_init_decrypt(username: &String, password: &String,n: &Scalar) -> (Ser
|
||||
return (ss,rr)
|
||||
}
|
||||
|
||||
pub fn phe_ratelimiter(private_keys: &Vec<Scalar>, request: &RatelimiterRequest,pp: &PublicParameters) -> RatelimiterResponse {
|
||||
let u = pairing(&G1Affine::from(G1Affine::generator() * request.n) , &G2Affine::from(request.p));
|
||||
let results = private_keys.par_iter().zip(&pp.ratelimiter_public_keys).map(|(private_key,public_key)| {
|
||||
let value = u*private_key;
|
||||
let proof = proofs::SameDLogProofPublic{g:pp.gt_gen,h:u,y1:*public_key,y2:value}.proof(&private_key);
|
||||
RatelimiterResponseElement{proof,p:value}
|
||||
}).collect::<Vec<_>>();
|
||||
RatelimiterResponse{elements:results}
|
||||
|
||||
|
||||
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}
|
||||
}
|
||||
|
||||
pub fn phe_enc_finish(msg: &Vec<u8>,pp: &PublicParameters,response: &RatelimiterResponse,ss:&ServerState) -> Result<Vec<Gt>,String>{
|
||||
let split_message = utils::split_message_into_space(msg,&pp.space,pp.k);
|
||||
assert_eq!(split_message.len(),pp.ratelimiter_public_keys.len(),"key length {} and msglength {} do not match",pp.ratelimiter_public_keys.len(),split_message.len());
|
||||
let u = 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) -> Result<EncryptedMessage,String>{
|
||||
let h = pairing(&G1Affine::from(G1Affine::generator() * ss.n), &G2Affine::from(ss.p));
|
||||
let r_inv = ss.r.invert().unwrap();
|
||||
let values = pp.ratelimiter_public_keys.par_iter().zip(&response.elements).zip(&split_message).map(|((public_key,x),msg)|{
|
||||
if !x.proof.verify(&proofs::SameDLogProofPublic{g:pp.gt_gen,h:u,y1:*public_key,y2:x.p}){
|
||||
Err("Invalid Proof".to_string())
|
||||
}else{
|
||||
Ok(x.p * r_inv * msg)
|
||||
}
|
||||
}).collect::<Result<Vec<_>,String>>();
|
||||
|
||||
values
|
||||
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 c2 =// H3([u]t 1/r, M, pw, id, ns, nr)
|
||||
utils::hash_data(
|
||||
&[
|
||||
&&"3".to_string(),
|
||||
&&ut,
|
||||
&&split_message,
|
||||
&&ss.pw,
|
||||
&&ss.n,
|
||||
//&response.iter().map(|r| &r.n).collect::<Vec<&Scalar>>(),
|
||||
],
|
||||
);
|
||||
let c1 = utils::xor(&c1, &split_message);
|
||||
Ok(EncryptedMessage{c1,c2,n:ss.n})
|
||||
}
|
||||
|
||||
pub fn phe_dec_finish_simple(ciphertext: &Vec<Gt>,pp: &PublicParameters,response: &RatelimiterResponse,ss:&ServerState) -> Result<Vec<u8>,String>{
|
||||
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));
|
||||
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{
|
||||
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 c1 = utils::xor(&c1, &ciphertext.c1);
|
||||
let c2 =// H3([u]t 1/r, M, pw, id, ns, nr)
|
||||
utils::hash_data(
|
||||
&[
|
||||
&&"3".to_string(),
|
||||
&&ut,
|
||||
&&c1,
|
||||
&&ss.pw,
|
||||
&&ss.n,
|
||||
//&response.iter().map(|r| &r.n).collect::<Vec<&Scalar>>(),
|
||||
],
|
||||
);
|
||||
|
||||
if c2 == ciphertext.c2{
|
||||
Ok(c1.to_vec())
|
||||
}else{
|
||||
Err("Invalid ciphertext".to_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 r_inv = ss.r.invert().unwrap();
|
||||
|
||||
let values = pp.ratelimiter_public_keys.par_iter().zip(&response.elements).map(|(public_key,x)|{
|
||||
if !x.proof.verify(&proofs::SameDLogProofPublic{g:pp.gt_gen,h:u,y1:*public_key,y2:x.p}){
|
||||
Err("Invalid Proof".to_string())
|
||||
}else{
|
||||
Ok(x.p * r_inv)
|
||||
}
|
||||
}).collect::<Result<Vec<_>,String>>()?;
|
||||
|
||||
return Ok(utils::solve_dlog(&values, ciphertext, &pp.space, pp.k)?);
|
||||
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{
|
||||
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::xor(&c1,&split_message);
|
||||
let c2 = // H3([u]t 1/r, M, pw, id, ns, nr)
|
||||
utils::hash_data(
|
||||
&[
|
||||
&&"3".to_string(),
|
||||
&&ut,
|
||||
&&split_message,
|
||||
&&ss.pw,
|
||||
&&ss.n
|
||||
]
|
||||
);
|
||||
Ok(EncryptedMessage{c1,c2,n:ss.n})
|
||||
}
|
||||
}
|
||||
|
||||
fn phe_dec_finish_preparedspace(pp: &PublicParameters,response: &RatelimiterResponse,ss:&ServerState,preparedspace: &Vec<HashMap<[u8;288],usize>>) -> Result<Vec<u8>,String>{
|
||||
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}){
|
||||
Err("Invalid Proof".to_string())
|
||||
}else{
|
||||
|
||||
let values = pp.ratelimiter_public_keys.par_iter().zip(&response.elements).map(|(public_key,x)|{
|
||||
if !x.proof.verify(&proofs::SameDLogProofPublic{g:pp.gt_gen,h:u,y1:*public_key,y2:x.p}){
|
||||
Err("Invalid Proof".to_string())
|
||||
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 c2 = // H3([u]t 1/r, M, pw, id, ns, nr)
|
||||
utils::hash_data(
|
||||
&[
|
||||
&&"3".to_string(),
|
||||
&&ut,
|
||||
&&split_message,
|
||||
&&ss.pw,
|
||||
&&ss.n
|
||||
]
|
||||
);
|
||||
if ciphertext.c2 == c2 {
|
||||
Ok(split_message.to_vec())
|
||||
}else{
|
||||
Ok(x.p * r_inv)
|
||||
Err("Invalid C2".to_string())
|
||||
}
|
||||
}).collect::<Result<Vec<_>,String>>()?;
|
||||
|
||||
return Ok(utils::find_in_precomputed_space(&values, &pp.space,preparedspace, pp.k));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#[test]
|
||||
fn test_core(){
|
||||
rayon::ThreadPoolBuilder::new().num_threads(1).build_global().unwrap();
|
||||
test_core_k(32,2);
|
||||
//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() {
|
||||
let mut s1 = utils::random_scalar();
|
||||
@ -238,42 +367,91 @@ fn test_speed_operations() {
|
||||
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());
|
||||
let realkey = 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<_>>();
|
||||
|
||||
|
||||
fn test_core_k(bytes:usize, k:usize) {
|
||||
let pp_keys = pps.iter().map(|x|{x.ratelimiter_public_key}).collect::<Vec<_>>();
|
||||
|
||||
let keysize = bytes*8/k; //in bytes
|
||||
let msg = (0..keysize/8*k).map(|x|(255*x/(keysize/8*k-1)) as u8).collect::<Vec<_>>();
|
||||
let generator = utils::random_gt();
|
||||
let keys = (0..keysize).map(|_|utils::random_scalar()).collect::<Vec<_>>();
|
||||
let public_keys = keys.iter().map(|x|generator*x).collect::<Vec<_>>();
|
||||
let space = utils::prepare_messages_to_space(k);
|
||||
let pp = PublicParameters{space, ratelimiter_public_keys:public_keys,gt_gen:generator,k};
|
||||
let pp_key = shamir::recover_shares(&pp_keys, n as i64);
|
||||
|
||||
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!("k: {} {:.2?} phe_init", k,start.elapsed());
|
||||
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 start = Instant::now();
|
||||
let response = phe_ratelimiter(&keys,&request,&pp);
|
||||
println!("k: {} {:.2?} phe_ratelimiter", k,start.elapsed());
|
||||
let res = phe_enc_finish_t(&msg,&pps,&responses,&ss,n).unwrap();
|
||||
println!("{:.2?} phe_enc_finish_t",start.elapsed());
|
||||
|
||||
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 start = Instant::now();
|
||||
let res = phe_dec_finish_t(&res,&pps,&responses,&ss,n);
|
||||
println!("{:.2?} phe_dec_finish_t",start.elapsed());
|
||||
|
||||
assert_eq!(res.unwrap(),msg);
|
||||
}
|
||||
|
||||
|
||||
fn test_core_k() {
|
||||
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{
|
||||
gt_gen: generator,
|
||||
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();
|
||||
println!("k: {} {:.2?} phe_enc_finish", k,start.elapsed());
|
||||
|
||||
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();
|
||||
println!("k: {} {:.2?} phe_dec_finish_simple", k,start.elapsed());
|
||||
assert_eq!(expected,msg);
|
||||
|
||||
let start = Instant::now();
|
||||
let prepared_space = ciphertext.iter().map(|x|utils::prepare_messages_to_precomputed_space(&pp.space, x)).collect::<Vec<_>>();
|
||||
println!("k: {} {:.2?} prepare_messages_to_precomputed_space", k,start.elapsed());
|
||||
for _i in 0..100{
|
||||
let expected = phe_dec_finish_simple(&ciphertext,&pp,&response,&ss).unwrap();
|
||||
}
|
||||
|
||||
let start = Instant::now();
|
||||
|
||||
let expected = phe_dec_finish_preparedspace(&pp, &response, &ss, &prepared_space).unwrap();
|
||||
println!("k: {} {:.2?} phe_dec_finish_preparedspace", k,start.elapsed());
|
||||
println!("{:.2?} phe_dec_finish_simple", start.elapsed()/1000);
|
||||
assert_eq!(expected,msg);
|
||||
|
||||
}
|
||||
@ -3,40 +3,50 @@
|
||||
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 ophe::core::{RatelimiterRequest,RatelimiterResponse};
|
||||
use ophe::core::{RatelimiterRequest,RatelimiterResponse,SetKeyHelper};
|
||||
use ophe::core;
|
||||
use ophe::utils;
|
||||
use rocket::State;
|
||||
use bls12_381::Scalar;
|
||||
use bls12_381::G1Affine;
|
||||
|
||||
|
||||
|
||||
fn make_public_parameters() -> (Vec<Scalar>,core::PublicParameters){
|
||||
let bytes = 32;
|
||||
let k = 2;
|
||||
let keysize = bytes*8/k;
|
||||
let generator = utils::random_gt();
|
||||
let keys = (0..keysize).map(|_|utils::random_scalar()).collect::<Vec<_>>();
|
||||
let public_keys = keys.iter().map(|x|generator*x).collect::<Vec<_>>();
|
||||
let space = utils::prepare_messages_to_space(k);
|
||||
fn make_public_parameters(key: Scalar) -> CryptoserviceState{
|
||||
let generator = pairing(&G1Affine::generator(), &G2Affine::generator());
|
||||
let public_key = generator * key;
|
||||
|
||||
(keys,core::PublicParameters{space, ratelimiter_public_keys:public_keys,gt_gen:generator,k})
|
||||
let pp = core::PublicParameters{ratelimiter_public_key:public_key,gt_gen:generator};
|
||||
CryptoserviceState{key,pp}
|
||||
}
|
||||
|
||||
|
||||
struct CryptoserviceState {
|
||||
key: Scalar,
|
||||
pp: core::PublicParameters,
|
||||
}
|
||||
|
||||
type CryptoserviceStatePointer = Arc<RwLock<CryptoserviceState>>;
|
||||
|
||||
|
||||
#[rocket::main]
|
||||
async fn main() {
|
||||
let (keys,pp) = make_public_parameters();
|
||||
let c = make_public_parameters(utils::random_scalar());
|
||||
let c_p:CryptoserviceStatePointer = Arc::new(RwLock::new(c));
|
||||
|
||||
let launch_result = rocket::build()
|
||||
.manage(pp)
|
||||
.manage(keys)
|
||||
.mount("/", openapi_get_routes![phe_help,get_public_parameters])
|
||||
.manage(c_p)
|
||||
.mount("/", openapi_get_routes![phe_help,get_public_parameters,set_key])
|
||||
.mount(
|
||||
"/swagger-ui/",
|
||||
make_swagger_ui(&SwaggerUIConfig {
|
||||
@ -69,16 +79,38 @@ async fn main() {
|
||||
|
||||
#[openapi()]
|
||||
#[post("/phe_help",format = "json", data = "<request>")]
|
||||
fn phe_help(request: Json<RatelimiterRequest>,pp: &State<core::PublicParameters>,keys: &State<Vec<Scalar>>) -> Json<RatelimiterResponse> {
|
||||
Json(core::phe_ratelimiter(keys,&request,pp))
|
||||
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())
|
||||
};
|
||||
|
||||
|
||||
Json(core::phe_ratelimiter(&key,&request,&pp))
|
||||
}
|
||||
|
||||
#[openapi()]
|
||||
#[get("/get_public_parameters")]
|
||||
fn get_public_parameters(pp: &State<core::PublicParameters>) -> 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> {
|
||||
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)
|
||||
}
|
||||
|
||||
#[catch(422)]
|
||||
fn serialize_failed(_req: &Request) -> String {
|
||||
format!("Malformed Request")
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
#![allow(dead_code)]
|
||||
mod proofs;
|
||||
pub mod utils;
|
||||
mod shamir;
|
||||
pub mod shamir;
|
||||
pub mod core;
|
||||
pub mod serializers;
|
||||
192
src/ophe.rs
192
src/ophe.rs
@ -3,40 +3,99 @@
|
||||
extern crate bls12_381;
|
||||
extern crate rand;
|
||||
|
||||
use bls12_381::G2Affine;
|
||||
use bls12_381::pairing;
|
||||
use bls12_381::G1Affine;
|
||||
use std::time::Duration;
|
||||
use crate::core::EncryptedMessage;
|
||||
use rocket_okapi::settings::UrlObject;
|
||||
use rocket_okapi::{openapi, openapi_get_routes, rapidoc::*, swagger_ui::*};
|
||||
use rocket::serde::json::Json;
|
||||
use rocket::Request;
|
||||
|
||||
use ophe::core::{RatelimiterResponse,PublicParameters};
|
||||
use ophe::core::{PublicParameters,RatelimiterRequest,RatelimiterResponse};
|
||||
use ophe::core;
|
||||
|
||||
use rocket::State;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use rocket_okapi::okapi::schemars;
|
||||
use rocket_okapi::okapi::schemars::JsonSchema;
|
||||
use bls12_381::Scalar;
|
||||
use bls12_381::Gt;
|
||||
use ophe::serializers;
|
||||
use serde_with::serde_as;
|
||||
|
||||
use futures::future::join_all;
|
||||
|
||||
use rocket::http::Status;
|
||||
|
||||
|
||||
struct RlState {
|
||||
pp: PublicParameters,
|
||||
url: String,
|
||||
client: reqwest::Client
|
||||
}
|
||||
|
||||
struct OpheState {
|
||||
pps: Vec<RlState>,
|
||||
n: i64,
|
||||
t: i64,
|
||||
}
|
||||
|
||||
#[derive(Serialize,Deserialize,JsonSchema)]
|
||||
struct EncryptRequest {
|
||||
username: String,
|
||||
password: String,
|
||||
/// # data
|
||||
/// data to be encrypted
|
||||
data:String
|
||||
}
|
||||
|
||||
#[serde_as]
|
||||
#[derive(Serialize, Deserialize, JsonSchema)]
|
||||
pub struct DecryptRequest{
|
||||
username: String,
|
||||
password: String,
|
||||
ciphertext: EncryptedMessage
|
||||
}
|
||||
|
||||
|
||||
#[catch(422)]
|
||||
fn serialize_failed(_req: &Request) -> String {
|
||||
format!("Malformed Request")
|
||||
}
|
||||
|
||||
|
||||
#[rocket::main]
|
||||
async fn main() {
|
||||
let client = reqwest::Client::new();
|
||||
let res = client.get("http://localhost:9999/get_public_parameters").send()
|
||||
.await.map_err(|x|{format!("Cryptoservice not reachable: {}",x)}).unwrap().text().await.unwrap();
|
||||
let cryptoservice_urls = vec!["http://localhost:9001","http://localhost:9002","http://localhost:9003"];
|
||||
let n = cryptoservice_urls.len();
|
||||
let t = n;
|
||||
let rl_key = ophe::utils::random_scalar();
|
||||
let rl_public_key = pairing(&G1Affine::generator(), &G2Affine::generator()) * rl_key;
|
||||
println!("Generated public key: {:?}",rl_public_key);
|
||||
let keys = ophe::shamir::gen_shares_scalar(rl_key, n as i64,t as i64);
|
||||
|
||||
let pps = keys.iter().zip(cryptoservice_urls).map( |(k,url)| async move{
|
||||
let client = reqwest::ClientBuilder::new().tcp_keepalive(Some(Duration::from_secs(60))).build().unwrap();
|
||||
let set_key_request = core::SetKeyHelper{key:k.clone()};
|
||||
let res = client.post(&format!("{}/set_key",url)).json(&set_key_request).send()
|
||||
.await.map_err(|x|{format!("Cryptoservice not reachable: {}",x)}).unwrap().text().await.unwrap();
|
||||
let pp: PublicParameters = serde_json::from_str(&res).map_err(|x|{format!("Cryptoservice not reachable: {}",x)}).unwrap();
|
||||
RlState{pp,url:url.to_string(),client}
|
||||
}).collect::<Vec<_>>();
|
||||
|
||||
let pps = join_all(pps).await;
|
||||
|
||||
let pp_keys = pps.iter().map(|x|{x.pp.ratelimiter_public_key}).collect::<Vec<_>>();
|
||||
|
||||
let pp_key = ophe::shamir::recover_shares(&pp_keys, n as i64);
|
||||
|
||||
assert_eq!(pp_key,rl_public_key,"Public keys do not match");
|
||||
|
||||
let o_state = OpheState{pps,n: n as i64,t: t as i64};
|
||||
|
||||
let pp: PublicParameters = serde_json::from_str(&res).map_err(|x|{format!("Cryptoservice not reachable: {}",x)}).unwrap();
|
||||
|
||||
println!("Received public parameters from crytoservice");
|
||||
|
||||
let launch_result = rocket::build().mount("/", openapi_get_routes![make_request,decrypt])
|
||||
.manage(pp)
|
||||
let launch_result = rocket::build().mount("/", openapi_get_routes![encrypt,decrypt])
|
||||
.manage(o_state)
|
||||
.mount(
|
||||
"/swagger-ui/",
|
||||
make_swagger_ui(&SwaggerUIConfig {
|
||||
@ -61,99 +120,60 @@ async fn main() {
|
||||
.register("/",catchers![serialize_failed])
|
||||
.launch()
|
||||
.await;
|
||||
match launch_result {
|
||||
Ok(_) => println!("Rocket shut down gracefully."),
|
||||
Err(err) => println!("Rocket had an error: {}", err),
|
||||
};
|
||||
}
|
||||
|
||||
#[derive(Serialize,Deserialize,JsonSchema)]
|
||||
struct UsernamePw{
|
||||
username: String,
|
||||
password: String
|
||||
}
|
||||
|
||||
#[catch(422)]
|
||||
fn serialize_failed(_req: &Request) -> String {
|
||||
format!("Malformed Request")
|
||||
}
|
||||
|
||||
#[serde_as]
|
||||
#[derive(Serialize, Deserialize, JsonSchema)]
|
||||
pub struct EnrollResponse{
|
||||
#[serde_as(as = "serializers::SerializeScalar")]
|
||||
#[schemars(with = "String")]
|
||||
n: Scalar,
|
||||
#[serde_as(as = "Vec<serializers::SerializeGt>")]
|
||||
#[schemars(with = "Vec<String>")]
|
||||
ciphertext: Vec<Gt>
|
||||
|
||||
match launch_result {
|
||||
Ok(_) => println!("Rocket shut down gracefully."),
|
||||
Err(err) => println!("Rocket had an error: {}", err),
|
||||
};
|
||||
}
|
||||
|
||||
#[openapi()]
|
||||
#[post("/make_request",format = "json", data = "<request>")]
|
||||
async fn make_request(request: Json<UsernamePw>,pp: &State<core::PublicParameters>) -> Result<Json<EnrollResponse>,(Status, Json<String>)> {
|
||||
#[post("/encrypt",format = "json", data = "<request>")]
|
||||
async fn encrypt(request: Json<EncryptRequest>,o_state: &State<OpheState>) -> Result<Json<EncryptedMessage>,(Status, Json<String>)> {
|
||||
let (ss,request1) = core::phe_init(&request.username,&request.password);
|
||||
|
||||
let client = reqwest::Client::new();
|
||||
let mut msg = request.data.clone().into_bytes();
|
||||
|
||||
let res = client.post("http://localhost:9999/phe_help")
|
||||
.json(&request1)
|
||||
.send()
|
||||
.await.map_err(|_x| {(Status::InternalServerError,Json("Cryptoserice unreachable.".to_string()))})?.text().await.map_err(|_x| {(Status::InternalServerError,Json("Cryptoserice unreachable.".to_string()))})?;
|
||||
|
||||
let response: RatelimiterResponse = serde_json::from_str(&res).map_err(|_x| {(Status::InternalServerError,Json("Invalid cryptoservice response.".to_string()))})?;
|
||||
|
||||
let mut msg = Vec::new();
|
||||
for _x in 0..32{
|
||||
msg.push(0u8);
|
||||
if msg.len() > 64 {
|
||||
return Err((Status::BadRequest,Json("Data too long.".to_string())))
|
||||
}
|
||||
let ciphertext = core::phe_enc_finish(&msg,&pp,&response,&ss).map_err(|x| {(Status::InternalServerError,Json("Decryption failed.".to_string()+&x))})?;
|
||||
// pad to 64 bytes
|
||||
msg.resize(64,0);
|
||||
|
||||
Ok(Json(EnrollResponse{n:ss.n,ciphertext}))
|
||||
}
|
||||
let pps = o_state.pps.iter().map(|x| x.pp).collect::<Vec<_>>();
|
||||
|
||||
let responses = get_ratelimiter_reponses(&request1,&o_state.pps).await.map_err(|x| {(Status::InternalServerError,Json("Decryption failed: ".to_string()+&x))})?;
|
||||
|
||||
#[serde_as]
|
||||
#[derive(Serialize, Deserialize, JsonSchema)]
|
||||
pub struct DecryptRequest{
|
||||
#[serde_as(as = "serializers::SerializeScalar")]
|
||||
#[schemars(with = "String")]
|
||||
n: Scalar,
|
||||
username: String,
|
||||
password: String,
|
||||
#[serde_as(as = "Vec<serializers::SerializeGt>")]
|
||||
#[schemars(with = "Vec<String>")]
|
||||
ciphertext: Vec<Gt>
|
||||
let ciphertext = core::phe_enc_finish_t(&msg,&pps,&responses,&ss,o_state.n).map_err(|x| {(Status::InternalServerError,Json("Decryption failed.".to_string()+&x))})?;
|
||||
|
||||
Ok(Json(ciphertext))
|
||||
}
|
||||
|
||||
#[openapi()]
|
||||
#[post("/decrypt",format = "json", data = "<request>")]
|
||||
async fn decrypt(request: Json<DecryptRequest>,pp: &State<core::PublicParameters>) -> Result<Json<bool>,(Status, Json<String>)>{
|
||||
async fn decrypt(request: Json<DecryptRequest>,o_state: &State<OpheState>) -> Result<Json<String>,(Status, Json<String>)> {
|
||||
let (ss,request1) = core::phe_init_decrypt(&request.username,&request.password,&request.ciphertext.n);
|
||||
|
||||
let res = decrypt_err(request,pp).await;
|
||||
let responses = get_ratelimiter_reponses(&request1,&o_state.pps).await.map_err(|x| {(Status::InternalServerError,Json("Decryption failed: ".to_string()+&x))})?;
|
||||
|
||||
res
|
||||
let pps = o_state.pps.iter().map(|x| x.pp).collect::<Vec<_>>();
|
||||
|
||||
let res = core::phe_dec_finish_t(&request.ciphertext,&pps,&responses,&ss,o_state.n).map_err(|x| {(Status::InternalServerError,Json("Decryption failed: ".to_string()+&x))})?;
|
||||
|
||||
Ok(Json(String::from_utf8(res).map_err(|_x| {(Status::InternalServerError,Json("Decryption failed. Utf8".to_string()))})?.trim_end_matches(char::from(0)).to_string()))
|
||||
}
|
||||
|
||||
async fn get_ratelimiter_reponses(request: &RatelimiterRequest, urls: &Vec<RlState>) -> Result<Vec<RatelimiterResponse>,String> {
|
||||
let responses = urls.iter().map(|x| async move {
|
||||
let res = x.client.post(&format!("{}/phe_help",x.url))
|
||||
.json(&request)
|
||||
.send()
|
||||
.await.map_err(|_x| {format!("Cryptoserice unreachable.")})?.text().await.map_err(|_x| {format!("Cryptoserice unreachable.")})?;
|
||||
let rs = serde_json::from_str(&res).map_err(|_x| {format!("Invalid cryptoservice response.")})?;
|
||||
Ok::<_,String>(rs)
|
||||
|
||||
});
|
||||
|
||||
async fn decrypt_err(request: Json<DecryptRequest>,pp: &State<core::PublicParameters>) -> Result<Json<bool>,(Status, Json<String>)> {
|
||||
let (ss,request1) = core::phe_init_decrypt(&request.username,&request.password,&request.n);
|
||||
|
||||
let client = reqwest::Client::new();
|
||||
|
||||
let res = client.post("http://localhost:9999/phe_help")
|
||||
.json(&request1)
|
||||
.send()
|
||||
.await.map_err(|_x| {(Status::InternalServerError,Json("Cryptoserice unreachable.".to_string()))})?.text().await.map_err(|_x| {(Status::InternalServerError,Json("Internal Error.".to_string()))})?;
|
||||
|
||||
let response: RatelimiterResponse = serde_json::from_str(&res).map_err(|_x| {(Status::InternalServerError,Json("Invalid cryptoservice response.".to_string()))})?;
|
||||
|
||||
let mut msg = Vec::new();
|
||||
for _x in 0..32{
|
||||
msg.push(0u8);
|
||||
}
|
||||
let expected = core::phe_dec_finish_simple(&request.ciphertext,&pp,&response,&ss).map_err(|x| {(Status::InternalServerError,Json("Decryption failed.".to_string()+&x))})?;
|
||||
println!("{:?}",expected);
|
||||
Ok(Json(true))
|
||||
join_all(responses).await.into_iter().flatten().collect()
|
||||
}
|
||||
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
use bls12_381::*;
|
||||
use rayon::prelude::*;
|
||||
use crate::utils;
|
||||
|
||||
fn lambda(i: i64, shares: i64) -> (Scalar, bool) {
|
||||
@ -19,17 +20,15 @@ fn lambda(i: i64, shares: i64) -> (Scalar, bool) {
|
||||
}
|
||||
}
|
||||
|
||||
fn recover_shares(shares: &Vec<Gt>, n: i64) -> Gt {
|
||||
let mut target = Gt::identity();
|
||||
for i in 0..shares.len() {
|
||||
pub fn recover_shares(shares: &Vec<Gt>, n: i64) -> Gt {
|
||||
shares.par_iter().enumerate().map(|(i, share)| {
|
||||
let (l, b) = lambda((i + 1) as i64, n);
|
||||
let mut temp = shares[i] * l;
|
||||
let mut temp = share * l;
|
||||
if b {
|
||||
temp = -temp
|
||||
}
|
||||
target = target + temp;
|
||||
}
|
||||
return target;
|
||||
temp
|
||||
}).reduce(|| Gt::identity(), |a, b| a + b)
|
||||
}
|
||||
|
||||
fn recover_shares_scalar(shares: &Vec<Scalar>, n: i64) -> Scalar {
|
||||
@ -61,7 +60,7 @@ fn eval_at_scalar(poly: &Vec<Scalar>, x: i64) -> Scalar {
|
||||
return y;
|
||||
}
|
||||
|
||||
fn gen_shares(secret: Gt, n: i64, t: i64) -> Vec<Gt> {
|
||||
pub fn gen_shares(secret: Gt, n: i64, t: i64) -> Vec<Gt> {
|
||||
assert!(t > 0);
|
||||
assert!(n >= t);
|
||||
assert!(t <= n);
|
||||
@ -77,7 +76,7 @@ fn gen_shares(secret: Gt, n: i64, t: i64) -> Vec<Gt> {
|
||||
return shares;
|
||||
}
|
||||
|
||||
fn gen_shares_scalar(secret: Scalar, n: i64, t: i64) -> Vec<Scalar> {
|
||||
pub fn gen_shares_scalar(secret: Scalar, n: i64, t: i64) -> Vec<Scalar> {
|
||||
assert!(t > 0);
|
||||
assert!(n >= t);
|
||||
assert!(t <= n);
|
||||
|
||||
219
src/utils.rs
219
src/utils.rs
@ -4,11 +4,6 @@ use sha2::{Digest, Sha512};
|
||||
use std::convert::TryInto;
|
||||
use bls12_381::*;
|
||||
use rand_core::{OsRng,RngCore};
|
||||
use std::collections::HashMap;
|
||||
use rayon::prelude::*;
|
||||
#[cfg(test)]
|
||||
use std::time::Instant;
|
||||
|
||||
|
||||
pub fn random_scalar() -> Scalar {
|
||||
let mut buf = [0u8; 64];
|
||||
@ -20,6 +15,71 @@ pub fn random_gt() -> Gt{
|
||||
Gt::random(OsRng)
|
||||
}
|
||||
|
||||
pub trait HashData {
|
||||
fn hash_data(&self) -> Vec<u8>;
|
||||
}
|
||||
|
||||
impl HashData for &Gt {
|
||||
fn hash_data(&self) -> Vec<u8> {
|
||||
self.to_compressed().to_vec()
|
||||
}
|
||||
}
|
||||
|
||||
impl HashData for &G2Affine {
|
||||
fn hash_data(&self) -> Vec<u8> {
|
||||
self.to_compressed().to_vec()
|
||||
}
|
||||
}
|
||||
|
||||
impl HashData for &G1Affine {
|
||||
fn hash_data(&self) -> Vec<u8> {
|
||||
self.to_compressed().to_vec()
|
||||
}
|
||||
}
|
||||
|
||||
impl HashData for &Scalar {
|
||||
fn hash_data(&self) -> Vec<u8> {
|
||||
self.to_bytes().to_vec()
|
||||
}
|
||||
}
|
||||
|
||||
impl HashData for &String {
|
||||
fn hash_data(&self) -> Vec<u8> {
|
||||
self.as_bytes().to_vec()
|
||||
}
|
||||
}
|
||||
|
||||
impl HashData for &[u8; 64] {
|
||||
fn hash_data(&self) -> Vec<u8> {
|
||||
self.to_vec()
|
||||
}
|
||||
}
|
||||
|
||||
impl HashData for &Vec<&dyn HashData> {
|
||||
fn hash_data(&self) -> Vec<u8> {
|
||||
self.iter().map(|x| x.hash_data()).flatten().collect()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
pub fn hash_data(elements: &[&dyn HashData]) -> [u8; 64] {
|
||||
let buf:[u8; 64];
|
||||
let mut hasher = Sha512::new();
|
||||
for x in elements {
|
||||
hasher.update(x.hash_data());
|
||||
}
|
||||
let result = hasher.finalize();
|
||||
buf = result.as_slice().try_into().expect("Wrong length");
|
||||
|
||||
buf
|
||||
}
|
||||
|
||||
pub fn hash_to_scalar(elements: &[&dyn HashData]) -> Scalar {
|
||||
let buf = hash_data(elements);
|
||||
Scalar::from_bytes_wide(&buf)
|
||||
}
|
||||
|
||||
|
||||
pub fn hash_string_to_scalar(element: String) -> Scalar {
|
||||
let buf:[u8; 64];
|
||||
let mut hasher = Sha512::new();
|
||||
@ -44,144 +104,25 @@ pub fn hash_gt_to_scalar(elements: &[&Gt]) -> Scalar {
|
||||
Scalar::from_bytes_wide(&buf)
|
||||
}
|
||||
|
||||
pub fn prepare_messages_to_space(k: usize) -> Vec<Scalar>{
|
||||
let mut m = Vec::new();
|
||||
for _j in 0..1 << k {
|
||||
//let current_m = Scalar::from_raw([(j + 1) as u64, 0, 0, 0]);
|
||||
let current_m = random_scalar();
|
||||
m.push(current_m);
|
||||
pub fn convert_64_bytes_to_scalar(bytes: &[u8]) -> Result<Scalar, &'static str> {
|
||||
if bytes.len() != 64 {
|
||||
return Err("Wrong length");
|
||||
}
|
||||
m
|
||||
let mut buf = [0u8; 64];
|
||||
buf.copy_from_slice(bytes);
|
||||
Ok(Scalar::from_bytes_wide(&buf))
|
||||
}
|
||||
|
||||
|
||||
pub fn prepare_messages_to_precomputed_space(space: &Vec<Scalar>,cipher: &Gt) -> HashMap<[u8;288],usize>{
|
||||
let mapped = space.par_iter().map(|x|(cipher * x.invert().unwrap()).to_compressed()).collect::<Vec<_>>();
|
||||
let mut m = HashMap::new();
|
||||
(0..space.len()).for_each(|i| {
|
||||
m.insert( mapped[i],i);
|
||||
});
|
||||
m
|
||||
pub fn vec_to_msg(vec: &Vec<u8>) -> [u8; 64] {
|
||||
let mut buf = [0u8; 64];
|
||||
buf.copy_from_slice(vec);
|
||||
buf
|
||||
}
|
||||
|
||||
pub fn find_in_precomputed_space(ciphertext: &Vec<Gt>,_space: &Vec<Scalar>,maps: &Vec<HashMap<[u8;288],usize>>,k:usize) -> Vec<u8>{
|
||||
let mut prep = Vec::new();
|
||||
for i in 0..ciphertext.len() {
|
||||
let index = maps[i][&ciphertext[i].to_compressed()];
|
||||
for z in 0..k{
|
||||
prep.push((index>>z)&1);
|
||||
}
|
||||
pub fn xor(a: &[u8], b: &[u8]) -> [u8; 64] {
|
||||
let mut buf = [0u8; 64];
|
||||
for i in 0..64 {
|
||||
buf[i] = a[i] ^ b[i];
|
||||
}
|
||||
let mut result = Vec::new();
|
||||
for i in 0..prep.len()/8{
|
||||
let mut x = 0u8;
|
||||
for j in 0..8{
|
||||
x = x + (prep[i*8+j]<<j) as u8;
|
||||
|
||||
}
|
||||
result.push(x as u8);
|
||||
}
|
||||
result
|
||||
}
|
||||
|
||||
pub fn split_message_into_space(msg: &Vec<u8>,space: &Vec<Scalar>,k: usize) -> Vec<Scalar> {
|
||||
let mut preparedmsg = Vec::new();
|
||||
for i in 0..msg.len() {
|
||||
for j in 0..8{
|
||||
preparedmsg.push((msg[i]&(1<<j))>>j);
|
||||
}
|
||||
}
|
||||
let msgsize = preparedmsg.len(); // size of msg in bits
|
||||
assert!(msgsize%k==0,"Msg must be aligned to space"); //TODO extend msg with size and padding
|
||||
let steps = msgsize / k;
|
||||
let mut result = Vec::new();
|
||||
for i in 0..steps{
|
||||
let mut x = 0;
|
||||
for j in 0..k{
|
||||
x = x + ((preparedmsg[i*k+j] as usize)<<j);
|
||||
}
|
||||
result.push(space[x]);
|
||||
}
|
||||
result
|
||||
}
|
||||
|
||||
pub fn solve_dlog(target: &Vec<Gt>,ciphertext: &Vec<Gt>,space:& Vec<Scalar>,k: usize) -> Result<Vec<u8>,String>{
|
||||
let mut prep = Vec::new();
|
||||
let spacesize = space.len();
|
||||
|
||||
let t = target.par_iter().map(|x|space.iter().map(|y|x*y).collect::<Vec<_>>()).collect::<Vec<_>>();
|
||||
|
||||
for i in 0..target.len() {
|
||||
let mut found = false;
|
||||
for j in 0..spacesize{
|
||||
if t[i][j] == ciphertext[i]{
|
||||
found = true;
|
||||
for z in 0..k{
|
||||
prep.push((j>>z)&1);
|
||||
}
|
||||
}
|
||||
}
|
||||
if !found {
|
||||
return Err("Decryption failed.".to_string())
|
||||
}
|
||||
}
|
||||
let mut result = Vec::new();
|
||||
for i in 0..prep.len()/8{
|
||||
let mut x = 0u8;
|
||||
for j in 0..8{
|
||||
x = x | (prep[i*8+j]<<j) as u8;
|
||||
|
||||
}
|
||||
result.push(x as u8);
|
||||
}
|
||||
Ok(result)
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
fn test_msg_space_k(k: usize){
|
||||
|
||||
let start = Instant::now();
|
||||
let space= prepare_messages_to_space(k);
|
||||
|
||||
println!("k: {} {:.2?} preparing message space", k,start.elapsed());
|
||||
|
||||
let msg =[1,2,3,4,255,128,127,151,16,15,127,200,0,13,15,16];
|
||||
let start = Instant::now();
|
||||
let split = split_message_into_space(&msg.to_vec(),&space,k);
|
||||
|
||||
println!("k: {} {:.2?} spliting into message space", k,start.elapsed());
|
||||
|
||||
let gt = random_gt();
|
||||
let gts = (&split).into_iter().map(|_x|gt).collect::<Vec<Gt>>();
|
||||
let test = (&split).into_iter().map(|x|gt*x).collect::<Vec<Gt>>();
|
||||
|
||||
let start = Instant::now();
|
||||
let solved = solve_dlog(>s, &test, &space, k).unwrap();
|
||||
|
||||
println!("k: {} {:.2?} solve dlog ", k,start.elapsed());
|
||||
|
||||
assert_eq!(msg.to_vec(),solved);
|
||||
let start = Instant::now();
|
||||
let prepared_space= (&test).into_iter().map(|x|prepare_messages_to_precomputed_space(&space, x)).collect::<Vec<HashMap<[u8;288],usize>>>();
|
||||
|
||||
|
||||
println!("k: {} {:.2?} precomputing message space", k,start.elapsed());
|
||||
|
||||
let start = Instant::now();
|
||||
let prepared_solved = find_in_precomputed_space(>s,&space,&prepared_space, k);
|
||||
|
||||
println!("k: {} {:.2?} lookup in prepared message space", k,start.elapsed());
|
||||
|
||||
assert_eq!(msg.to_vec(),prepared_solved);
|
||||
|
||||
}
|
||||
|
||||
|
||||
#[test]
|
||||
fn test_msg_space() {
|
||||
//rayon::ThreadPoolBuilder::new().num_threads(1).build_global().unwrap();
|
||||
test_msg_space_k(2);
|
||||
test_msg_space_k(4);
|
||||
test_msg_space_k(8);
|
||||
//test_msg_space_k(16);
|
||||
buf
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user