Added new mimc hash with calculation proof.
This commit is contained in:
parent
ab1e399768
commit
0fbfc57a9a
712
Cargo.lock
generated
712
Cargo.lock
generated
File diff suppressed because it is too large
Load Diff
15
Cargo.toml
15
Cargo.toml
@ -28,6 +28,21 @@ futures = "*"
|
||||
reqwest ={ version = "*", features = ["json"]}
|
||||
|
||||
rocket_okapi = { version = "0.8.0-alpha-1", features = ["swagger", "rapidoc"] }
|
||||
arkworks-mimc = { version = "0.3.0", features = ["mimc-7-91-bls12-381","r1cs"] }
|
||||
ark-ff = { version = "^0.3.0", default-features = false }
|
||||
ark-bls12-381 = "0.3.0"
|
||||
ark-bls12-377 = "0.3.0"
|
||||
ark-crypto-primitives = "0.3.0"
|
||||
ark-std = "0.3.0"
|
||||
ark-relations = "0.3.0"
|
||||
ark-r1cs-std = "0.3.0"
|
||||
ark-groth16 = "0.3.0"
|
||||
ark-serialize = "0.3.0"
|
||||
ark-ec = "0.3.0"
|
||||
subtle = "*"
|
||||
|
||||
# Fixes compilation on windows
|
||||
tokio = "1.28.0"
|
||||
|
||||
[[bin]]
|
||||
name = "cryptoservice"
|
||||
|
||||
101
src/core.rs
101
src/core.rs
@ -1,3 +1,6 @@
|
||||
use ark_bls12_381::Bls12_381;
|
||||
use ark_groth16::PreparedVerifyingKey;
|
||||
use ark_groth16::ProvingKey;
|
||||
use bls12_381::*;
|
||||
use group::Group;
|
||||
use crate::utils;
|
||||
@ -28,35 +31,43 @@ pub struct ServerState{
|
||||
r: Scalar,
|
||||
pub n: Scalar,
|
||||
p: G2Projective,
|
||||
pw: String,
|
||||
ps: Scalar,
|
||||
pw: String
|
||||
}
|
||||
|
||||
impl ServerState {
|
||||
fn new(username: &String, password: &String) -> ServerState{
|
||||
fn new(username: &String, password: &String,pk: &ProvingKey<Bls12_381>) -> (ServerState,Vec<u8>){
|
||||
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 (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)
|
||||
}
|
||||
|
||||
fn from_nonce(username: &String, password: &String, nonce: &Scalar) -> ServerState{
|
||||
fn from_nonce(username: &String, password: &String, nonce: &Scalar,pk: &ProvingKey<Bls12_381>) -> (ServerState,Vec<u8>){
|
||||
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;
|
||||
|
||||
ServerState{r,n: nonce.clone(),p,pw: password.to_owned()}
|
||||
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;
|
||||
|
||||
(ServerState{r,n: nonce.clone(),p,ps:hash_scalar,pw: password.to_owned()},hash_proof)
|
||||
}
|
||||
}
|
||||
|
||||
#[serde_as]
|
||||
#[derive(Serialize, Deserialize, JsonSchema,Clone,Copy,Debug)]
|
||||
#[derive(Serialize, Deserialize, JsonSchema,Clone,Debug)]
|
||||
pub struct RatelimiterRequest{
|
||||
#[serde_as(as = "serializers::SerializeScalar")]
|
||||
#[schemars(with = "String")]
|
||||
@ -64,6 +75,12 @@ pub struct RatelimiterRequest{
|
||||
#[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]
|
||||
@ -118,28 +135,42 @@ pub struct SetKeyHelper{
|
||||
}
|
||||
|
||||
|
||||
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)
|
||||
}
|
||||
|
||||
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,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};
|
||||
|
||||
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,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());
|
||||
}
|
||||
|
||||
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}
|
||||
|
||||
|
||||
Ok(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>{
|
||||
@ -421,12 +452,14 @@ fn test_core_t(n:i64,t:i64){
|
||||
|
||||
assert_eq!(pp_key,generator*realkey,"Public keys do not match");
|
||||
|
||||
let (pk,vk,pvk) = proofs::setup_hash_proof();
|
||||
|
||||
let start = Instant::now();
|
||||
let (ss,request) = phe_init(&"test".to_string(),&"test".to_string());
|
||||
let (ss,request) = phe_init(&"test".to_string(),&"test".to_string(),&pk);
|
||||
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]);
|
||||
let response = phe_ratelimiter(&rlkeys[i],&request,&pps[i],&pvk).unwrap();
|
||||
response
|
||||
}).collect::<Vec<_>>();
|
||||
|
||||
@ -434,10 +467,10 @@ fn test_core_t(n:i64,t:i64){
|
||||
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 (ss,request) = phe_init_decrypt(&"test".to_string(),&"test".to_string(),&request.n, &pk);
|
||||
|
||||
let responses = (0..t as usize).into_par_iter().map(|i|{
|
||||
let response = phe_ratelimiter(&rlkeys[i],&request,&pps[i]);
|
||||
let response = phe_ratelimiter(&rlkeys[i],&request,&pps[i],&pvk).unwrap();
|
||||
response
|
||||
}).collect::<Vec<_>>();
|
||||
|
||||
@ -459,14 +492,16 @@ fn test_core_k() {
|
||||
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());
|
||||
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);
|
||||
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);
|
||||
let response = phe_ratelimiter(&key,&request,&pp,&pvk).unwrap();
|
||||
}
|
||||
println!("{:.2?} phe_ratelimiter",start.elapsed()/1000);
|
||||
|
||||
@ -477,9 +512,9 @@ fn test_core_k() {
|
||||
}
|
||||
println!("{:.2?} phe_enc_finish",start.elapsed()/1000);
|
||||
|
||||
let (ss,request) = phe_init_decrypt(&"test".to_string(),&"test".to_string(),&ciphertext.n);
|
||||
let (ss,request) = phe_init_decrypt(&"test".to_string(),&"test".to_string(),&ciphertext.n, &pk);
|
||||
|
||||
let response = phe_ratelimiter(&key,&request,&pp);
|
||||
let response = phe_ratelimiter(&key,&request,&pp,&pvk).unwrap();
|
||||
|
||||
let expected = phe_dec_finish_simple(&ciphertext,&pp,&response,&ss).unwrap();
|
||||
let start = Instant::now();
|
||||
|
||||
@ -4,9 +4,12 @@ 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 std::sync::Mutex;
|
||||
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::*};
|
||||
@ -22,23 +25,35 @@ use bls12_381::Scalar;
|
||||
use bls12_381::G1Affine;
|
||||
|
||||
|
||||
|
||||
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 mut rng = OsRng::default();
|
||||
|
||||
let test: HashProof = HashProof {
|
||||
pw_point: None,
|
||||
nonce_point: None,
|
||||
random_r: None,
|
||||
};
|
||||
|
||||
let (pk, vk,pvk) = proofs::setup_hash_proof();
|
||||
|
||||
CryptoserviceState{key,pp,hashproof_pvk:pvk}
|
||||
}
|
||||
|
||||
|
||||
|
||||
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() {
|
||||
@ -80,15 +95,14 @@ async fn main() {
|
||||
|
||||
#[openapi()]
|
||||
#[post("/phe_help",format = "json", data = "<request>")]
|
||||
fn phe_help(request: Json<RatelimiterRequest>,c_state: &State<CryptoserviceStatePointer>) -> Json<RatelimiterResponse> {
|
||||
fn phe_help(request: Json<RatelimiterRequest>,c_state: &State<CryptoserviceStatePointer>) -> Result<Json<RatelimiterResponse>,String> {
|
||||
|
||||
let (key,pp) = {
|
||||
let (key,pp,pvk) = {
|
||||
let c_state = c_state.read().unwrap();
|
||||
(c_state.key.clone(),c_state.pp.clone())
|
||||
(c_state.key.clone(),c_state.pp.clone(),c_state.hashproof_pvk.clone())
|
||||
};
|
||||
|
||||
|
||||
Json(core::phe_ratelimiter(&key,&request,&pp))
|
||||
Ok(Json(core::phe_ratelimiter(&key,&request,&pp,&pvk)?))
|
||||
}
|
||||
|
||||
#[openapi()]
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
#![allow(dead_code)]
|
||||
mod proofs;
|
||||
pub mod proofs;
|
||||
pub mod utils;
|
||||
pub mod shamir;
|
||||
pub mod core;
|
||||
|
||||
15
src/ophe.rs
15
src/ophe.rs
@ -3,11 +3,15 @@
|
||||
extern crate bls12_381;
|
||||
extern crate rand;
|
||||
|
||||
use ark_bls12_381::Bls12_381;
|
||||
use ark_groth16::PreparedVerifyingKey;
|
||||
use ark_groth16::ProvingKey;
|
||||
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;
|
||||
@ -43,6 +47,7 @@ struct OpheState {
|
||||
n: i64,
|
||||
t: i64,
|
||||
pk: Gt,
|
||||
hash_proof_vk: ProvingKey<Bls12_381>,
|
||||
}
|
||||
|
||||
#[derive(Serialize,Deserialize,JsonSchema)]
|
||||
@ -77,7 +82,7 @@ fn serialize_failed(_req: &Request) -> String {
|
||||
|
||||
#[rocket::main]
|
||||
async fn main() {
|
||||
let cryptoservice_urls = vec!["http://localhost:9001","http://localhost:9002","http://localhost:9003"];
|
||||
let cryptoservice_urls = vec!["http://localhost:9001","http://localhost:9002"];
|
||||
let n = cryptoservice_urls.len();
|
||||
let t = n;
|
||||
let rl_key = ophe::utils::random_scalar();
|
||||
@ -102,7 +107,9 @@ async fn main() {
|
||||
|
||||
assert_eq!(pp_key,rl_public_key,"Public keys do not match");
|
||||
|
||||
let o_state = OpheState{pps,n: n as i64,t: t as i64, pk: pp_key};
|
||||
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};
|
||||
|
||||
|
||||
println!("Received public parameters from crytoservice");
|
||||
@ -143,7 +150,7 @@ 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);
|
||||
let (ss,request1) = core::phe_init(&request.username,&request.password,&o_state.hash_proof_vk);
|
||||
|
||||
let mut msg = request.data.clone().into_bytes();
|
||||
|
||||
@ -165,7 +172,7 @@ async fn encrypt(request: Json<EncryptRequest>,o_state: &State<OpheState>) -> Re
|
||||
#[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);
|
||||
let (ss,request1) = core::phe_init_decrypt(&request.username,&request.password,&request.ciphertext.n,&o_state.hash_proof_vk);
|
||||
|
||||
let responses = get_ratelimiter_reponses(&request1,&o_state.pps).await.map_err(|x| {(Status::InternalServerError,Json("Decryption failed: ".to_string()+&x))})?;
|
||||
|
||||
|
||||
414
src/proofs.rs
414
src/proofs.rs
@ -1,23 +1,48 @@
|
||||
use bls12_381::*;
|
||||
use crate::utils;
|
||||
use std::convert::TryInto;
|
||||
use std::time::Instant;
|
||||
|
||||
use crate::serializers;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use rocket_okapi::okapi::schemars;
|
||||
use rocket_okapi::okapi::schemars::JsonSchema;
|
||||
use serde_with::serde_as;
|
||||
use crate::utils;
|
||||
use ark_bls12_381::Bls12_381;
|
||||
use ark_crypto_primitives::CircuitSpecificSetupSNARK;
|
||||
use ark_crypto_primitives::SNARK;
|
||||
use ark_ff::BigInteger;
|
||||
use ark_ff::Fp2;
|
||||
use ark_ff::Fp384;
|
||||
use ark_ff::Fp384Parameters;
|
||||
use ark_groth16::PreparedVerifyingKey;
|
||||
use ark_groth16::Proof;
|
||||
use ark_groth16::ProvingKey;
|
||||
use ark_groth16::VerifyingKey;
|
||||
use ark_groth16::prepare_verifying_key;
|
||||
use ark_groth16::Groth16;
|
||||
use ark_r1cs_std::alloc::AllocationMode;
|
||||
use ark_r1cs_std::eq::EqGadget;
|
||||
use ark_r1cs_std::fields::FieldVar;
|
||||
use ark_relations::lc;
|
||||
use ark_relations::r1cs::ConstraintSynthesizer;
|
||||
use ark_relations::r1cs::ConstraintSystem;
|
||||
use ark_relations::r1cs::ConstraintSystemRef;
|
||||
use ark_relations::r1cs::SynthesisError;
|
||||
use ark_serialize::CanonicalSerializeWithFlags;
|
||||
use arkworks_mimc::constraints::MiMCVar;
|
||||
use bls12_381::*;
|
||||
#[cfg(test)]
|
||||
use group::Group;
|
||||
|
||||
|
||||
use rand_core::OsRng;
|
||||
use rocket_okapi::okapi::schemars;
|
||||
use rocket_okapi::okapi::schemars::JsonSchema;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use serde_with::serde_as;
|
||||
|
||||
pub struct SameDLogProofPublic {
|
||||
pub g: Gt,
|
||||
pub h: Gt,
|
||||
pub y1: Gt,
|
||||
pub y2: Gt,
|
||||
pub g: Gt,
|
||||
pub h: Gt,
|
||||
pub y1: Gt,
|
||||
pub y2: Gt,
|
||||
}
|
||||
|
||||
impl SameDLogProofPublic{
|
||||
impl SameDLogProofPublic {
|
||||
pub fn new(g: Gt, h: Gt, x: Scalar) -> Self {
|
||||
SameDLogProofPublic {
|
||||
g,
|
||||
@ -27,7 +52,7 @@ impl SameDLogProofPublic{
|
||||
}
|
||||
}
|
||||
|
||||
pub fn proof(&self,x: &Scalar) -> SameDLogProof{
|
||||
pub fn proof(&self, x: &Scalar) -> SameDLogProof {
|
||||
let r = utils::random_scalar();
|
||||
let c = utils::hash_gt_to_scalar(&[&self.g, &self.h, &self.y1, &self.y2]);
|
||||
let t = r - x * c;
|
||||
@ -39,9 +64,8 @@ impl SameDLogProofPublic{
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#[serde_as]
|
||||
#[derive(Eq,PartialEq,Debug,Serialize,Deserialize,JsonSchema)]
|
||||
#[derive(Eq, PartialEq, Debug, Serialize, Deserialize, JsonSchema)]
|
||||
pub struct SameDLogProof {
|
||||
#[serde_as(as = "serializers::SerializeGt")]
|
||||
#[schemars(with = "String")]
|
||||
@ -54,15 +78,13 @@ pub struct SameDLogProof {
|
||||
t: Scalar,
|
||||
}
|
||||
|
||||
|
||||
impl SameDLogProof {
|
||||
pub fn verify(&self,pp: &SameDLogProofPublic) -> bool{
|
||||
pub fn verify(&self, pp: &SameDLogProofPublic) -> bool {
|
||||
let c = utils::hash_gt_to_scalar(&[&pp.g, &pp.h, &pp.y1, &pp.y2]);
|
||||
self.a == (pp.g * self.t) + (pp.y1 * c) && self.b == (pp.h * self.t) + (pp.y2 * c)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#[test]
|
||||
fn test_proof_correct() {
|
||||
let x = utils::random_scalar();
|
||||
@ -83,7 +105,6 @@ fn test_proof_incorrect() {
|
||||
assert!(!proof.verify(&pp));
|
||||
}
|
||||
|
||||
|
||||
#[test]
|
||||
fn test_proof_serialize() {
|
||||
let x = utils::random_scalar();
|
||||
@ -94,4 +115,355 @@ fn test_proof_serialize() {
|
||||
let serialized = serde_json::to_string(&proof).unwrap();
|
||||
let proof2: SameDLogProof = serde_json::from_str(&serialized).unwrap();
|
||||
assert_eq!(proof, proof2);
|
||||
}
|
||||
}
|
||||
|
||||
use arkworks_mimc::params::mimc_7_91_bls12_381::{
|
||||
MIMC_7_91_BLS12_381_PARAMS, MIMC_7_91_BLS12_381_ROUND_KEYS,
|
||||
};
|
||||
use arkworks_mimc::params::round_keys_contants_to_vec;
|
||||
use arkworks_mimc::MiMC;
|
||||
//mimc-7-91-bls12-381
|
||||
use ark_bls12_381::Fr;
|
||||
use ark_bls12_381::Fq;
|
||||
use ark_ff::Field;
|
||||
use ark_ff::PrimeField;
|
||||
use ark_ff::Zero;
|
||||
use bls12_381::*;
|
||||
|
||||
#[test]
|
||||
fn test_mimc_hash() {
|
||||
let mimc = MiMC::<Fr, MIMC_7_91_BLS12_381_PARAMS>::new(
|
||||
1,
|
||||
Fr::zero(),
|
||||
round_keys_contants_to_vec(&MIMC_7_91_BLS12_381_ROUND_KEYS),
|
||||
);
|
||||
println!(
|
||||
"mimc hash: {:?}",
|
||||
mimc.permute_non_feistel(vec![Fr::zero()])
|
||||
);
|
||||
}
|
||||
|
||||
// nizk for p2,pw,n,r prove that p2 = r * mimc(pw,n) which is g2/str to g2 where p2 is public
|
||||
|
||||
use ark_std;
|
||||
|
||||
use arkworks_mimc::{
|
||||
constraints::{MiMCFeistelCRHGadget},
|
||||
MiMCFeistelCRH
|
||||
};
|
||||
|
||||
use ark_crypto_primitives::{
|
||||
crh::{TwoToOneCRH, TwoToOneCRHGadget},
|
||||
CRH as CRHTrait,
|
||||
};
|
||||
use ark_ff::to_bytes;
|
||||
|
||||
use ark_r1cs_std::{
|
||||
fields::fp::FpVar,
|
||||
prelude::{AllocVar},
|
||||
R1CSVar, ToBytesGadget,
|
||||
};
|
||||
|
||||
use ark_serialize::{CanonicalSerialize, CanonicalDeserialize};
|
||||
use ark_std::io::{Read, Write};
|
||||
use sha2::Digest;
|
||||
use std::ops::MulAssign;
|
||||
use ark_serialize::SerializationError;
|
||||
|
||||
|
||||
//TODO Type conversion
|
||||
//TODO add to server
|
||||
//TODO add to client
|
||||
//TODO 32 bytes?
|
||||
|
||||
pub fn setup_hash_proof() -> (ProvingKey<Bls12_381>, VerifyingKey<Bls12_381>, PreparedVerifyingKey<Bls12_381>) {
|
||||
let a = Fr::from(20); // No idea why this is needed // TODO remove once fixed
|
||||
|
||||
let test: HashProof = HashProof {
|
||||
pw_point: Some(a),
|
||||
nonce_point: Some(a),
|
||||
random_r: Some(a),
|
||||
};
|
||||
|
||||
let mut rng = OsRng::default();
|
||||
let (pk, vk) = Groth16::<Bls12_381>::setup(test.clone(), &mut rng).unwrap();
|
||||
let pvk = prepare_verifying_key::<Bls12_381>(&vk);
|
||||
(pk, vk, pvk)
|
||||
}
|
||||
|
||||
pub fn generate_hash_proof(username: &String, password: &String, nonce: &Scalar,random: &Scalar,pk: &ProvingKey<Bls12_381>)-> (Scalar,Vec<u8>){
|
||||
// hash the password and nonce to Fr
|
||||
let n_fr = Fr::from_le_bytes_mod_order(&nonce.to_bytes());
|
||||
//use sha256
|
||||
let mut hasher = sha2::Sha256::new();
|
||||
hasher.update(username.as_bytes());
|
||||
hasher.update(password.as_bytes());
|
||||
let hash = hasher.finalize();
|
||||
let hash_fr = Fr::from_le_bytes_mod_order(&hash);
|
||||
// hash the two Fr to Fr
|
||||
let random_fr = Fr::from_le_bytes_mod_order(&random.to_bytes());
|
||||
let mimc = MiMC::<Fr, MIMC_7_91_BLS12_381_PARAMS>::new(
|
||||
1,
|
||||
Fr::zero(),
|
||||
round_keys_contants_to_vec(&MIMC_7_91_BLS12_381_ROUND_KEYS),
|
||||
);
|
||||
let hashed = <MiMCFeistelCRH<Fr, _> as TwoToOneCRH>::evaluate(
|
||||
&mimc,
|
||||
&to_bytes!(hash_fr).unwrap(),
|
||||
&to_bytes!(n_fr).unwrap(),
|
||||
).unwrap();
|
||||
|
||||
let result_fr = random_fr * hashed;
|
||||
let mut result_vec = Vec::new();
|
||||
result_fr.serialize(&mut result_vec).unwrap();
|
||||
// convert to &[u8; 32]
|
||||
let result_arr = result_vec.as_slice().try_into().unwrap();
|
||||
let result_scalar = Scalar::from_bytes(result_arr).unwrap();
|
||||
let proof = HashProof {
|
||||
pw_point: Some(hash_fr),
|
||||
nonce_point: Some(n_fr),
|
||||
random_r: Some(random_fr),
|
||||
};
|
||||
let proof = Groth16::<Bls12_381>::prove(
|
||||
&pk,
|
||||
proof,
|
||||
&mut ark_std::test_rng(),
|
||||
).unwrap();
|
||||
|
||||
let mut proof_serialized = Vec::<u8>::new();
|
||||
proof.serialize(&mut proof_serialized).unwrap();
|
||||
|
||||
(result_scalar,proof_serialized)
|
||||
}
|
||||
|
||||
pub fn validate_hash_proof(scalar: &Scalar, proof: &Vec<u8>, vk: &PreparedVerifyingKey<Bls12_381>) -> bool {
|
||||
match Proof::<Bls12_381>::deserialize(&proof[..]) {
|
||||
Ok(proof) => {
|
||||
let g2_fr = Fr::from_le_bytes_mod_order(&scalar.to_bytes());
|
||||
match Groth16::<Bls12_381>::verify_with_processed_vk(&vk, &[g2_fr], &proof) {
|
||||
Ok(result) => result,
|
||||
Err(_) => false,
|
||||
}
|
||||
}
|
||||
Err(_) => false,
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Hash,CanonicalSerialize, CanonicalDeserialize)]
|
||||
pub struct HashProof {
|
||||
pub pw_point: Option<Fr>,
|
||||
pub nonce_point: Option<Fr>,
|
||||
pub random_r: Option<Fr>,
|
||||
}
|
||||
|
||||
impl ConstraintSynthesizer<Fr> for HashProof {
|
||||
fn generate_constraints(self, cs: ConstraintSystemRef<Fr>) -> Result<(), SynthesisError> {
|
||||
|
||||
let mimc = MiMC::<Fr, MIMC_7_91_BLS12_381_PARAMS>::new(
|
||||
1,
|
||||
Fr::zero(),
|
||||
round_keys_contants_to_vec(&MIMC_7_91_BLS12_381_ROUND_KEYS),
|
||||
);
|
||||
|
||||
let x_l = self.pw_point.ok_or(SynthesisError::AssignmentMissing)?;
|
||||
let x_r = self.nonce_point.ok_or(SynthesisError::AssignmentMissing)?;
|
||||
let c_r = self.random_r.ok_or(SynthesisError::AssignmentMissing)?;
|
||||
|
||||
let x_l_var = FpVar::new_witness(cs.clone(), || Ok(x_l) )?;
|
||||
let x_r_var = FpVar::new_witness(cs.clone(), || Ok(x_r) )?;
|
||||
let c_r_var = FpVar::new_witness(cs.clone(), || Ok(c_r) )?;
|
||||
let k_var = FpVar::new_constant(cs.clone(), &mimc.k)?;
|
||||
|
||||
let round_keys = Vec::<FpVar<_>>::new_constant(cs.clone(), mimc.round_keys)?;
|
||||
let mimc_var = MiMCVar::<_, _>::new(1, k_var, round_keys);
|
||||
|
||||
let hashed_var =
|
||||
<MiMCFeistelCRHGadget<_, MIMC_7_91_BLS12_381_PARAMS> as TwoToOneCRHGadget<
|
||||
MiMCFeistelCRH<_, _>,
|
||||
_,
|
||||
>>::evaluate(&mimc_var, &x_l_var.to_bytes()?, &x_r_var.to_bytes()?)
|
||||
.unwrap();
|
||||
|
||||
// mult c and hashed_var
|
||||
let result = FpVar::new_input(cs.clone(), || {
|
||||
let mut res = c_r_var.value()?;
|
||||
res.mul_assign(&hashed_var.value()?);
|
||||
Ok(res)
|
||||
})?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#[test]
|
||||
fn test_type_conversion() {
|
||||
|
||||
let usename = String::from("username");
|
||||
let password = String::from("password");
|
||||
let nonce = utils::random_scalar();
|
||||
let random = utils::random_scalar();
|
||||
let (pk, vk, pvk) = setup_hash_proof();
|
||||
let (sclar1, proof) = generate_hash_proof(&usename, &password, &nonce, &random, &pk);
|
||||
let res = validate_hash_proof(&sclar1, &proof, &pvk);
|
||||
assert!(res);
|
||||
// change g2 and test for inequality
|
||||
let mut scalar2 = sclar1;
|
||||
scalar2 *= utils::random_scalar();
|
||||
let res = validate_hash_proof(&scalar2, &proof, &pvk);
|
||||
assert!(!res);
|
||||
// change proof and test for inequality
|
||||
let mut proof2 = proof;
|
||||
proof2[0] = 0;
|
||||
let res = validate_hash_proof(&sclar1, &proof2, &pvk);
|
||||
assert!(!res);
|
||||
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_groth16() {
|
||||
let mut rng = &mut ark_std::test_rng();
|
||||
let mimc = MiMC::<Fr, MIMC_7_91_BLS12_381_PARAMS>::new(
|
||||
1,
|
||||
Fr::zero(),
|
||||
round_keys_contants_to_vec(&MIMC_7_91_BLS12_381_ROUND_KEYS),
|
||||
);
|
||||
|
||||
let a = Fr::from(20);
|
||||
let b = Fr::from(200);
|
||||
let c = Fr::from(10);
|
||||
|
||||
let d = c * <MiMCFeistelCRH<Fr, _> as TwoToOneCRH>::evaluate(
|
||||
&mimc,
|
||||
&to_bytes!(a).unwrap(),
|
||||
&to_bytes!(b).unwrap(),
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
// instantce g2
|
||||
let mut bytes = Vec::<u8>::new();
|
||||
d.serialize(&mut bytes).unwrap();
|
||||
|
||||
let mut buf = [0u8; 32];
|
||||
(&mut buf[0..32]).copy_from_slice(&bytes[..]);
|
||||
|
||||
let scalar = Scalar::from_bytes(&buf).unwrap();
|
||||
let point = G2Affine::generator() * scalar;
|
||||
println!("point: {:?}", point);
|
||||
|
||||
|
||||
let test: HashProof = HashProof {
|
||||
pw_point: Some(a),
|
||||
nonce_point: Some(b),
|
||||
random_r: Some(c), };
|
||||
|
||||
let (pk, vk) = Groth16::<Bls12_381>::setup(test.clone(), &mut rng).unwrap();
|
||||
|
||||
let pvk = prepare_verifying_key::<Bls12_381>(&vk);
|
||||
|
||||
let proof = Groth16::<Bls12_381>::prove(
|
||||
&pk,
|
||||
HashProof {
|
||||
pw_point: Some(a),
|
||||
nonce_point: Some(b),
|
||||
random_r: Some(c),
|
||||
},
|
||||
&mut rng,
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let start = Instant::now();
|
||||
for _i in 0..100{
|
||||
let proof = Groth16::<Bls12_381>::prove(
|
||||
&pk,
|
||||
HashProof {
|
||||
pw_point: Some(a),
|
||||
nonce_point: Some(b),
|
||||
random_r: Some(c),
|
||||
},
|
||||
&mut rng,
|
||||
)
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
println!("{:.2?} Groth16::<Bls12_381>::prove(", start.elapsed()/100);
|
||||
|
||||
let res = Groth16::<Bls12_381>::verify_with_processed_vk(&pvk, &[d], &proof);
|
||||
|
||||
// let start = Instant::now();
|
||||
// for _i in 0..100{
|
||||
// let res = Groth16::<Bls12_381>::verify_with_processed_vk(&pvk, &[a,b,Fr::from(1)], &proof);
|
||||
// }
|
||||
|
||||
println!("{:.2?} verify_with_processed_vk", start.elapsed()/100);
|
||||
|
||||
println!("res: {:?}", res.unwrap());
|
||||
|
||||
//serialization test
|
||||
|
||||
let mut compressed_proof = Vec::new();
|
||||
proof.serialize(&mut compressed_proof).unwrap();
|
||||
let proof2 = Proof::<Bls12_381>::deserialize(&compressed_proof[..]).unwrap();
|
||||
assert_eq!(proof, proof2);
|
||||
|
||||
let mut compressed_pvk = Vec::new();
|
||||
vk.serialize(&mut compressed_pvk).unwrap();
|
||||
let vk2 = VerifyingKey::<Bls12_381>::deserialize(&compressed_pvk[..]).unwrap();
|
||||
assert_eq!(vk, vk2);
|
||||
let pk2 = prepare_verifying_key(&vk2);
|
||||
assert_eq!(pvk, pk2);
|
||||
|
||||
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_constraint() -> Result<(), ark_relations::r1cs::SynthesisError> {
|
||||
let rng = &mut ark_std::test_rng();
|
||||
let cs = ConstraintSystem::<Fr>::new_ref();
|
||||
let mimc = MiMC::<Fr, MIMC_7_91_BLS12_381_PARAMS>::new(
|
||||
1,
|
||||
Fr::zero(),
|
||||
round_keys_contants_to_vec(&MIMC_7_91_BLS12_381_ROUND_KEYS),
|
||||
);
|
||||
|
||||
let x_l = Fr::from(20);
|
||||
let x_r = Fr::from(200);
|
||||
let hashed = <MiMCFeistelCRH<Fr, _> as TwoToOneCRH>::evaluate(
|
||||
&mimc,
|
||||
&to_bytes!(x_l).unwrap(),
|
||||
&to_bytes!(x_r).unwrap(),
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let x_l_var = FpVar::new_witness(cs.clone(), || Ok(x_l))?;
|
||||
let x_r_var = FpVar::new_witness(cs.clone(), || Ok(x_r))?;
|
||||
let k_var = FpVar::new_input(cs.clone(), || Ok(mimc.k))?;
|
||||
|
||||
let round_keys = Vec::<FpVar<Fr>>::new_constant(cs.clone(), mimc.round_keys)?;
|
||||
let mimc_var = MiMCVar::<_, _>::new(1, k_var, round_keys);
|
||||
let hashed_var = <MiMCFeistelCRHGadget<_, MIMC_7_91_BLS12_381_PARAMS> as TwoToOneCRHGadget<
|
||||
MiMCFeistelCRH<_, _>,
|
||||
_,
|
||||
>>::evaluate(&mimc_var, &x_l_var.to_bytes()?, &x_r_var.to_bytes()?)
|
||||
.unwrap();
|
||||
|
||||
assert!(FpVar::constant(hashed).is_eq(&hashed_var)?.value()?);
|
||||
|
||||
let additional_input = FpVar::new_input(cs.clone(), || Ok(Fr::from(10)))?;
|
||||
|
||||
// make input additional_input * hashed
|
||||
|
||||
let hashed_var2 = hashed_var.clone() * additional_input;
|
||||
|
||||
println!("hashed: {:?}", hashed_var2.value()?);
|
||||
|
||||
cs.is_satisfied()?;
|
||||
|
||||
println!("constraints: {}", cs.clone().num_constraints());
|
||||
println!("inputs: {}", cs.clone().num_instance_variables());
|
||||
println!("aux: {}", cs.clone().num_witness_variables());
|
||||
|
||||
// try building a circurit for the nizk
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user