From b538f74bbd5044c50039ca74e9e142c611c4dc43 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?zkdream=20=E2=98=81=EF=B8=8F=20she/them?= Date: Tue, 12 Mar 2024 16:40:42 +0000 Subject: [PATCH] pushed the file pushed the file --- file.rs | 199 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 199 insertions(+) create mode 100644 file.rs diff --git a/file.rs b/file.rs new file mode 100644 index 0000000..bb417be --- /dev/null +++ b/file.rs @@ -0,0 +1,199 @@ +#![no_std] +use ark_ec::CurveGroup; +use ark_ff::{fields::PrimeField, UniformRand}; +use ark_serialize::{CanonicalSerialize, SerializationError}; +use ark_std::{marker::PhantomData, rand::Rng, vec::Vec}; +use sha3::{ + digest::{ExtendableOutput, Update, XofReader}, + Shake128, +}; +pub type Commitment = C; + +pub struct Ciphertext { + c1: C::Affine, + c2: C::Affine, +} + +#[derive(Debug)] +pub enum Error { + SerializationError, +} + +impl Ciphertext { + fn serialize_compressed(&self) -> Result<(Vec, Vec), SerializationError> { + let mut c1_bytes = Vec::new(); + let mut c2_bytes = Vec::new(); + + self.c1.serialize_compressed(&mut c1_bytes)?; + self.c2.serialize_compressed(&mut c2_bytes)?; + + Ok((c1_bytes, c2_bytes)) + } +} + +pub struct PoK { + pub t: C, + pub a: C, + pub z: C::ScalarField, +} + +#[derive(Clone, Debug)] +pub struct Params { + pub g: C, + pub h: C, +} + +pub struct ElGamalSigmaProtocol { + _c: PhantomData, +} + +impl ElGamalSigmaProtocol { + pub fn prove( + s: C::ScalarField, + params: Params, + mut rng: R, + ) -> (Commitment, Ciphertext, PoK) { + let r = C::ScalarField::rand(&mut rng); + let c1 = params.g * r; + let c2 = params.h * (s * r); + + let ct: Ciphertext = Ciphertext { + c1: c1.into(), + c2: c2.into(), + }; + let c: Commitment = params.g * s + params.h * s; + + let k = C::ScalarField::rand(&mut rng); + let t = params.g * k; + let a = params.h * k; + + let mut t_bytes = Vec::new(); + let mut a_bytes = Vec::new(); + t.serialize_compressed(&mut t_bytes) + .expect("group element should exist"); + a.serialize_compressed(&mut a_bytes) + .expect("group element should exist"); + + let mut inputs = Vec::new(); + inputs.push(t_bytes); + inputs.push(a_bytes); + let (c1_bytes, c2_bytes) = ct + .serialize_compressed() + .expect("group elements should exist"); + inputs.push(c1_bytes); + inputs.push(c2_bytes); + + let challenge: C::ScalarField = + C::ScalarField::from_be_bytes_mod_order(&shake128(inputs.as_ref())); + let z = k + challenge * s; + (c, ct, PoK { t, a, z }) + } + pub fn verify( + commitment: Commitment, + ciphertext: Ciphertext, + proof: PoK, + params: Params, + ) -> bool { + let mut t_bytes = Vec::new(); + let mut a_bytes = Vec::new(); + proof + .t + .serialize_compressed(&mut t_bytes) + .expect("group element should exist"); + proof + .a + .serialize_compressed(&mut a_bytes) + .expect("group element should exist"); + + let mut inputs = Vec::new(); + inputs.push(t_bytes); + inputs.push(a_bytes); + let (c1_bytes, c2_bytes) = ciphertext + .serialize_compressed() + .expect("group element should exist"); + inputs.push(c1_bytes); + inputs.push(c2_bytes); + + let challenge: C::ScalarField = + C::ScalarField::from_be_bytes_mod_order(&shake128(inputs.as_ref())); + + let zg = params.g * proof.z; + let zh = params.h * proof.z; + + zg + zh == proof.t + proof.a + commitment * challenge + } +} + +fn shake128(input: &[Vec]) -> [u8; 32] { + let mut h = Shake128::default(); + for item in input.iter() { + h.update(item); + } + let mut o = [0u8; 32]; + h.finalize_xof().read(&mut o); + o +} + +#[cfg(test)] +mod test { + + use super::*; + use ark_ec::Group; + use ark_ed_on_bls12_381::EdwardsProjective as JubJub; + use ark_std::{ops::Mul, test_rng}; + + #[test] + pub fn prove_and_verify() { + let mut rng = test_rng(); + let x = ::ScalarField::rand(&mut rng); + let g: JubJub = JubJub::generator().into(); + let h: JubJub = g.mul(x).into(); + + let params = Params { g, h }; + + let (commitment, ciphertext, proof) = + ElGamalSigmaProtocol::prove(x, params.clone(), test_rng()); + let result = ElGamalSigmaProtocol::verify(commitment, ciphertext, proof, params); + assert_eq!(result, true); + } + + #[test] + pub fn verify_fails_with_invalid_proof() { + let mut rng = test_rng(); + let x = ::ScalarField::rand(&mut rng); + let g: JubJub = JubJub::generator().into(); + let h: JubJub = g.mul(x).into(); + + let j = ::ScalarField::rand(&mut rng); + let bad_proof = PoK { + t: g.mul(j).into(), + a: g.mul(j).into(), + z: j, + }; + + let params = Params { g, h }; + + let (commitment, ciphertext, _proof) = + ElGamalSigmaProtocol::prove(x, params.clone(), test_rng()); + let result = ElGamalSigmaProtocol::verify(commitment, ciphertext, bad_proof, params); + assert_eq!(result, false); + } + + #[test] + pub fn verify_fails_with_invalid_commitment() { + let mut rng = test_rng(); + let x = ::ScalarField::rand(&mut rng); + let g: JubJub = JubJub::generator().into(); + let h: JubJub = g.mul(x).into(); + + let j = ::ScalarField::rand(&mut rng); + let bad_commitment = g.mul(j).into(); + + let params = Params { g, h }; + + let (_commitment, ciphertext, proof) = + ElGamalSigmaProtocol::prove(x, params.clone(), test_rng()); + let result = ElGamalSigmaProtocol::verify(bad_commitment, ciphertext, proof, params); + assert_eq!(result, false); + } +}