diff --git a/rust-src/concordium_base/CHANGELOG.md b/rust-src/concordium_base/CHANGELOG.md index 64736becf..28e1b58c8 100644 --- a/rust-src/concordium_base/CHANGELOG.md +++ b/rust-src/concordium_base/CHANGELOG.md @@ -10,6 +10,7 @@ - Add `From<&AccountKeys>` instance for AccountAccessStructure. - Add `verify_data_signature` function to verify a signature with account keys on arbitrary data. +- Update notation of sigma protocols to better match the literature and the bluepaper. ## 2.0.0 (2023-06-16) diff --git a/rust-src/concordium_base/Cargo.toml b/rust-src/concordium_base/Cargo.toml index c4b238d28..bff866930 100644 --- a/rust-src/concordium_base/Cargo.toml +++ b/rust-src/concordium_base/Cargo.toml @@ -114,7 +114,7 @@ name = "verify_cdi" harness = false [[bench]] -name = "aggr_dlog_commit_point" +name = "aggr_dlog_commit_message" harness = false [[bench]] diff --git a/rust-src/concordium_base/benches/aggr_dlog_commit_point.rs b/rust-src/concordium_base/benches/aggr_dlog_commit_message.rs similarity index 78% rename from rust-src/concordium_base/benches/aggr_dlog_commit_point.rs rename to rust-src/concordium_base/benches/aggr_dlog_commit_message.rs index 190fe7df4..ad7e81623 100644 --- a/rust-src/concordium_base/benches/aggr_dlog_commit_point.rs +++ b/rust-src/concordium_base/benches/aggr_dlog_commit_message.rs @@ -7,7 +7,7 @@ use pairing::bls12_381::G1; use rand::*; /// Benchmark the aggregate dlog sigma protocol -fn bench_aggr_dlog_commit_point(c: &mut Criterion) { +fn bench_aggr_dlog_commit_message(c: &mut Criterion) { let mut csprng = thread_rng(); let number_of_coeffs = 42; let mut coeffs = Vec::with_capacity(number_of_coeffs); @@ -19,10 +19,10 @@ fn bench_aggr_dlog_commit_point(c: &mut Criterion) { public: public_key, coeff: coeffs, }; - c.bench_function("Aggregate dlog commit point", move |b| { - b.iter(|| dlog.commit_point(&mut csprng)) + c.bench_function("Aggregate dlog commit message", move |b| { + b.iter(|| dlog.compute_commit_message(&mut csprng)) }); } -criterion_group!(commit_point_benchmarks, bench_aggr_dlog_commit_point); +criterion_group!(commit_point_benchmarks, bench_aggr_dlog_commit_message); criterion_main!(commit_point_benchmarks); diff --git a/rust-src/concordium_base/src/aggregate_sig/mod.rs b/rust-src/concordium_base/src/aggregate_sig/mod.rs index 5ea14c20e..5fbbe1753 100644 --- a/rust-src/concordium_base/src/aggregate_sig/mod.rs +++ b/rust-src/concordium_base/src/aggregate_sig/mod.rs @@ -136,7 +136,7 @@ impl PartialEq for Signature

{ } /// A proof of knowledge of a secretkey -pub type Proof

= SigmaProof::G2>>; +pub type Proof

= SigmaProof::G2>>; /// Verifies an aggregate signature on pairs `(messages m_i, PK_i)` `for i=1..n` /// by checking `pairing(sig, g_2) == product_{i=0}^n ( diff --git a/rust-src/concordium_base/src/eddsa_ed25519/dlog_ed25519.rs b/rust-src/concordium_base/src/eddsa_ed25519/dlog_ed25519.rs index c1fe47b2e..3e5753f6a 100644 --- a/rust-src/concordium_base/src/eddsa_ed25519/dlog_ed25519.rs +++ b/rust-src/concordium_base/src/eddsa_ed25519/dlog_ed25519.rs @@ -1,3 +1,7 @@ +//! This module provides the implementation of the `dlog` sigma protocol for +//! curve25519 (cf. "Proof of Knowledge of Discrete Logarithm" Section 9.2.1, +//! Bluepaper v1.2.5) which enables one to prove knowledge of the discrete +//! logarithm without revealing it. use crate::{common::*, random_oracle::RandomOracle}; use anyhow::bail; use curve25519_dalek::{ @@ -13,14 +17,14 @@ use thiserror::Error; #[derive(Clone, Copy, Debug, Eq, PartialEq, SerdeBase16Serialize)] pub struct Ed25519DlogProof { challenge: Scalar, - witness: Scalar, + response: Scalar, } impl Serial for Ed25519DlogProof { fn serial(&self, out: &mut B) { out.write_all(self.challenge.as_bytes()) .expect("Writing to buffer should succeed."); - out.write_all(self.witness.as_bytes()) + out.write_all(self.response.as_bytes()) .expect("Writing to buffer should succeed."); } } @@ -31,10 +35,13 @@ impl Deserial for Ed25519DlogProof { source.read_exact(&mut buf)?; if let Some(challenge) = Scalar::from_canonical_bytes(buf) { source.read_exact(&mut buf)?; - if let Some(witness) = Scalar::from_canonical_bytes(buf) { - Ok(Ed25519DlogProof { challenge, witness }) + if let Some(response) = Scalar::from_canonical_bytes(buf) { + Ok(Ed25519DlogProof { + challenge, + response, + }) } else { - bail!("Not a valid witness.") + bail!("Not a valid response.") } } else { bail!("Not a valid scalar.") @@ -102,7 +109,7 @@ pub fn prove_dlog_ed25519( let challenge = Scalar::from_bytes_mod_order(array); Ed25519DlogProof { challenge, - witness: rand_scalar - challenge * secret, + response: rand_scalar - challenge * secret, } } @@ -115,7 +122,7 @@ pub fn verify_dlog_ed25519( None => false, Some(public) => { let randomised_point = - public * proof.challenge + &proof.witness * &constants::ED25519_BASEPOINT_TABLE; + public * proof.challenge + &proof.response * &constants::ED25519_BASEPOINT_TABLE; ro.append_message(b"dlog_ed25519", public_key); ro.append_message(b"randomised_point", &randomised_point.compress().to_bytes()); diff --git a/rust-src/concordium_base/src/encrypted_transfers/proofs/dlogaggequal.rs b/rust-src/concordium_base/src/encrypted_transfers/proofs/dlogaggequal.rs index e227a8b7c..5aaef91ff 100644 --- a/rust-src/concordium_base/src/encrypted_transfers/proofs/dlogaggequal.rs +++ b/rust-src/concordium_base/src/encrypted_transfers/proofs/dlogaggequal.rs @@ -4,7 +4,7 @@ //! NB: //! This module is currently not used, and is only here as a reference. -//! When using the code needs to be thouroughly reviewed. +//! When using the code needs to be thoroughly reviewed. use crate::{ common::*, @@ -22,10 +22,10 @@ pub struct DlogAndAggregateDlogsEqual { } #[derive(Debug, Serialize)] -pub struct Witness { +pub struct Response { #[size_length = 4] - witnesses: Vec>, - witness_common: C::Scalar, // For equality + responses: Vec>, + response_common: C::Scalar, // For equality } #[allow(clippy::type_complexity)] @@ -33,7 +33,7 @@ impl SigmaProtocol for DlogAndAggregateDlogsEqual { type CommitMessage = (C, Vec); type ProtocolChallenge = C::Scalar; type ProverState = (C::Scalar, Vec>); - type ProverWitness = Witness; + type Response = Response; type SecretData = (Rc, Vec>>); fn public(&self, ro: &mut RandomOracle) { @@ -45,7 +45,7 @@ impl SigmaProtocol for DlogAndAggregateDlogsEqual { C::scalar_from_bytes(challenge) } - fn commit_point( + fn compute_commit_message( &self, csprng: &mut R, ) -> Option<(Self::CommitMessage, Self::ProverState)> { @@ -82,51 +82,51 @@ impl SigmaProtocol for DlogAndAggregateDlogsEqual { Some((commit, rand)) } - fn generate_witness( + fn compute_response( &self, secret: Self::SecretData, state: Self::ProverState, challenge: &Self::ProtocolChallenge, - ) -> Option { - let mut witness_common = *challenge; - witness_common.mul_assign(&secret.0); - witness_common.negate(); // According to Bluepaper, we negate here. Shouldn't matter. - witness_common.add_assign(&state.0); - let mut witnesses = vec![]; + ) -> Option { + let mut response_common = *challenge; + response_common.mul_assign(&secret.0); + response_common.negate(); // According to Bluepaper, we negate here. Shouldn't matter. + response_common.add_assign(&state.0); + let mut responses = vec![]; for (secret_vec, state_vec) in izip!(secret.1, state.1) { - let mut witness = vec![]; + let mut response = vec![]; for (ref s, ref r) in izip!(secret_vec, state_vec) { - let mut wit = *challenge; - wit.mul_assign(s); - wit.negate(); - wit.add_assign(r); - witness.push(wit); + let mut res = *challenge; + res.mul_assign(s); + res.negate(); + res.add_assign(r); + response.push(res); } - witnesses.push(witness); + responses.push(response); } - Some(Witness { - witnesses, - witness_common, + Some(Response { + responses, + response_common, }) } - fn extract_point( + fn extract_commit_message( &self, challenge: &Self::ProtocolChallenge, - witness: &Self::ProverWitness, + response: &Self::Response, ) -> Option { let dlog_point = self .dlog .coeff - .mul_by_scalar(&witness.witness_common) + .mul_by_scalar(&response.response_common) .plus_point(&self.dlog.public.mul_by_scalar(challenge)); let mut agg_points = vec![]; - for (aggregate_dlog, w) in izip!(&self.aggregate_dlogs, &witness.witnesses) { + for (aggregate_dlog, w) in izip!(&self.aggregate_dlogs, &response.responses) { if w.len() + 1 != aggregate_dlog.coeff.len() { return None; } let mut point = aggregate_dlog.public.mul_by_scalar(challenge); - let mut exps = vec![witness.witness_common]; + let mut exps = vec![response.response_common]; exps.extend_from_slice(w); let product = multiexp(&aggregate_dlog.coeff, &exps); point = point.plus_point(&product); diff --git a/rust-src/concordium_base/src/encrypted_transfers/proofs/dlogeq.rs b/rust-src/concordium_base/src/encrypted_transfers/proofs/dlogeq.rs index c53fbe65c..60c22467b 100644 --- a/rust-src/concordium_base/src/encrypted_transfers/proofs/dlogeq.rs +++ b/rust-src/concordium_base/src/encrypted_transfers/proofs/dlogeq.rs @@ -8,7 +8,7 @@ use crate::{ curve_arithmetic::Curve, id::sigma_protocols::{ common::*, - dlog::{Witness as DlogWitness, *}, + dlog::{Response as DlogResponse, *}, }, random_oracle::{Challenge, RandomOracle}, }; @@ -22,7 +22,7 @@ impl SigmaProtocol for DlogEqual { type CommitMessage = (C, C); type ProtocolChallenge = C::Scalar; type ProverState = C::Scalar; - type ProverWitness = DlogWitness; + type Response = DlogResponse; type SecretData = DlogSecret; fn public(&self, ro: &mut RandomOracle) { @@ -34,7 +34,7 @@ impl SigmaProtocol for DlogEqual { C::scalar_from_bytes(challenge) } - fn commit_point( + fn compute_commit_message( &self, csprng: &mut R, ) -> Option<(Self::CommitMessage, Self::ProverState)> { @@ -45,23 +45,23 @@ impl SigmaProtocol for DlogEqual { Some((commit, rand_scalar)) } - fn generate_witness( + fn compute_response( &self, secret: Self::SecretData, state: Self::ProverState, challenge: &Self::ProtocolChallenge, - ) -> Option { - let w1 = self.dlog1.generate_witness(secret, state, challenge)?; + ) -> Option { + let w1 = self.dlog1.compute_response(secret, state, challenge)?; Some(w1) } - fn extract_point( + fn extract_commit_message( &self, challenge: &Self::ProtocolChallenge, - witness: &Self::ProverWitness, + response: &Self::Response, ) -> Option { - let p1 = self.dlog1.extract_point(challenge, witness)?; - let p2 = self.dlog2.extract_point(challenge, witness)?; + let p1 = self.dlog1.extract_commit_message(challenge, response)?; + let p2 = self.dlog2.extract_commit_message(challenge, response)?; Some((p1, p2)) } diff --git a/rust-src/concordium_base/src/encrypted_transfers/proofs/enc_trans.rs b/rust-src/concordium_base/src/encrypted_transfers/proofs/enc_trans.rs index 07088e97b..285905f55 100644 --- a/rust-src/concordium_base/src/encrypted_transfers/proofs/enc_trans.rs +++ b/rust-src/concordium_base/src/encrypted_transfers/proofs/enc_trans.rs @@ -12,10 +12,11 @@ //! //! This is done using the subprotocols Dlog, Elgdec and EncExp (EncExp is //! basically just several ComEq's (can be found in -//! sigma_protocols in the id crate)) as described in Id Layer Bluepaper, see -//! genEncTransProofInfo and genEncTrans. The resulting sigma protocol is -//! contructed using the sigma protocols for equality and linear relations -//! described in the Cryptoprim Bluepaper. +//! sigma_protocols in the id crate)) as described in the Bluepaper, see +//! genEncTransProofInfo and genEncTrans in "Encrypted Transfers" Section +//! 18.2.2. The resulting sigma protocol is constructed using the sigma +//! protocols for equality and linear relations described in the Bluepaper, +//! "Instantiations of Sigma Protocols" Section 9.2 //! //! Proving knowledge of (a_i, r_i) such that c_{i,1} = g^{r_i} and c_{i,2} = //! h^{a_i} pk_receiver^{r_i} is done using the ComEq sigma protocol in the @@ -30,14 +31,14 @@ //! //! Ensuring that the same secret is known in the dlog proof and the elg-dec //! proof is done by ensuring that the same randomness alpha and challenge c is -//! used in the dlog proof and in the elg-dec proof (see the Cryptoprim -//! bluepaper). +//! used in the dlog proof and in the elg-dec proof (see also "Combining Sigma +//! Protocols" Section 9.4.2 in the Bluepaper). //! //! Proving the relation //! s = \sum_{j=1}^t 2^{(chunk_size)*(j-1)} (a_j) //! +\sum_{j=1}^(t') 2^{(chunk_size)*(j-1)} s_j' s' -//! is done using the protocol 10.1.4 in the Cryptoprim bluepaper for proving -//! linear relations of preimages of homomorphisms. The homomorphism in question +//! is done using the protocol `com-lin` for proving +//! linear relations of preimages of homomorphisms (see "Linear Relationship of Committed Values" Section 9.2.11, Bluepaper). The homomorphism in question //! is the one that maps the amounts in chunks to the encrypted amounts. //! //! The trait SigmaProtocol is @@ -52,7 +53,7 @@ use crate::{ curve_arithmetic::{multiexp, Curve}, elgamal::ChunkSize, id::sigma_protocols::{ - com_eq::{ComEq, ComEqSecret, CommittedPoints, Witness as ComEqWitness}, + com_eq::{ComEq, ComEqSecret, CommittedMessages, Response as ComEqResponse}, common::*, dlog::*, }, @@ -92,24 +93,24 @@ pub struct EncTrans { pub encexp2: Vec>, } -/// Witness for the [EncTrans] protocol. +/// Response for the [EncTrans] protocol. /// -/// The elc_dec protocol actually has two witnesses, one involving sk and one +/// The elc_dec protocol actually has two responses, one involving sk and one /// involving s, but since sk is also the secret for the dlog, and since /// s is a linear combination of the secrets for the EncExp/ComEq's, -/// we calculate the same linear combination, but of the witnesses, in -/// the extract_point function. We do therefore not need to transfer/send -/// those witnesses, since they are determined by the ones below. +/// we calculate the same linear combination, but of the responses, in +/// the extract_commit_message function. We do therefore not need to +/// transfer/send those responses, since they are determined by the ones below. #[derive(Debug, Serialize, Clone)] -pub struct EncTransWitness { - /// The common witness for both dlog and elc-dec - witness_common: C::Scalar, +pub struct EncTransResponse { + /// The common response for both dlog and elc-dec + response_common: C::Scalar, /// For EncExp/ComEq's involving a_i #[size_length = 4] - witness_encexp1: Vec>, + response_encexp1: Vec>, /// For EncExp/ComEq's involving s_i' #[size_length = 4] - witness_encexp2: Vec>, + response_encexp2: Vec>, } /// Secret values which the [EncTrans] proof talks about. For constructing @@ -129,19 +130,19 @@ pub struct EncTransSecret { /// after the prover has committed to all the values they wish to prove /// statements about. This is then used in the computation of the challenge. pub struct EncTransCommit { - /// Commitmessage for dlog + /// Commit message for dlog dlog: C, - /// Commitmessage for elg_dec + /// Commit message for elg_dec elg_dec: C, - /// Commitmessages for EncExp/ComEq's involving a_i + /// Commit messages for EncExp/ComEq's involving a_i #[size_length = 4] - encexp1: Vec>, - /// Commitmessages for EncExp/ComEq's involving s_i' + encexp1: Vec>, + /// Commit messages for EncExp/ComEq's involving s_i' #[size_length = 4] - encexp2: Vec>, + encexp2: Vec>, } -/// As for the witness, we don't need the state for elg_dec +/// As for the response, we don't need the state for elg_dec #[derive(Debug, Serialize)] pub struct EncTransState { /// Randomness used for dlog @@ -177,7 +178,7 @@ impl SigmaProtocol for EncTrans { type CommitMessage = EncTransCommit; type ProtocolChallenge = C::Scalar; type ProverState = EncTransState; - type ProverWitness = EncTransWitness; + type Response = EncTransResponse; type SecretData = EncTransSecret; fn public(&self, ro: &mut RandomOracle) { @@ -191,7 +192,7 @@ impl SigmaProtocol for EncTrans { C::scalar_from_bytes(challenge) } - fn commit_point( + fn compute_commit_message( &self, csprng: &mut R, ) -> Option<(Self::CommitMessage, Self::ProverState)> { @@ -203,7 +204,7 @@ impl SigmaProtocol for EncTrans { let mut Rs_a = vec![]; let mut Rs_s_prime = vec![]; for comeq in &self.encexp1 { - match comeq.commit_point(csprng) { + match comeq.compute_commit_message(csprng) { Some((comm_point, (alpha, R_i))) => { rands_encexp_1.push((alpha, R_i.clone())); commit_encexp_1.push(comm_point); @@ -213,7 +214,7 @@ impl SigmaProtocol for EncTrans { }; } for comeq in &self.encexp2 { - match comeq.commit_point(csprng) { + match comeq.compute_commit_message(csprng) { Some((comm_point, (alpha, R_s))) => { rands_encexp_2.push((alpha, R_s.clone())); commit_encexp_2.push(comm_point); @@ -246,19 +247,19 @@ impl SigmaProtocol for EncTrans { Some((commit, rand)) } - fn generate_witness( + fn compute_response( &self, secret: Self::SecretData, state: Self::ProverState, challenge: &Self::ProtocolChallenge, - ) -> Option { - let mut witness_common = *challenge; - witness_common.mul_assign(&secret.dlog_secret); - witness_common.negate(); - witness_common.add_assign(&state.dlog); + ) -> Option { + let mut response_common = *challenge; + response_common.mul_assign(&secret.dlog_secret); + response_common.negate(); + response_common.add_assign(&state.dlog); // For encexps: - let mut witness_encexp1 = Vec::with_capacity(secret.encexp1_secrets.len()); - let mut witness_encexp2 = Vec::with_capacity(secret.encexp2_secrets.len()); + let mut response_encexp1 = Vec::with_capacity(secret.encexp1_secrets.len()); + let mut response_encexp2 = Vec::with_capacity(secret.encexp2_secrets.len()); if secret.encexp1_secrets.len() != state.encexp1.len() { return None; } @@ -267,8 +268,8 @@ impl SigmaProtocol for EncTrans { state.encexp1.iter(), self.encexp1.iter() ) { - match comeq1.generate_witness(sec, (*encexp1).clone(), challenge) { - Some(w) => witness_encexp1.push(w), + match comeq1.compute_response(sec, (*encexp1).clone(), challenge) { + Some(w) => response_encexp1.push(w), None => return None, } } @@ -280,28 +281,28 @@ impl SigmaProtocol for EncTrans { state.encexp2.iter(), self.encexp2.iter() ) { - match comeq2.generate_witness(sec, (*encexp2).clone(), challenge) { - Some(w) => witness_encexp2.push(w), + match comeq2.compute_response(sec, (*encexp2).clone(), challenge) { + Some(w) => response_encexp2.push(w), None => return None, } } - Some(EncTransWitness { - witness_common, - witness_encexp1, - witness_encexp2, + Some(EncTransResponse { + response_common, + response_encexp1, + response_encexp2, }) } - fn extract_point( + fn extract_commit_message( &self, challenge: &Self::ProtocolChallenge, - witness: &Self::ProverWitness, + response: &Self::Response, ) -> Option { - if self.encexp1.len() != witness.witness_encexp1.len() { + if self.encexp1.len() != response.response_encexp1.len() { return None; } - if self.encexp2.len() != witness.witness_encexp2.len() { + if self.encexp2.len() != response.response_encexp2.len() { return None; } // For enc_exps: @@ -309,20 +310,20 @@ impl SigmaProtocol for EncTrans { let mut commit_encexp2 = Vec::with_capacity(self.encexp2.len()); let mut w_a_vec = Vec::with_capacity(self.encexp1.len()); let mut w_s_prime_vec = Vec::with_capacity(self.encexp2.len()); - for (comeq, witness) in izip!(&self.encexp1, &witness.witness_encexp1) { - match comeq.extract_point(challenge, witness) { + for (comeq, response) in izip!(&self.encexp1, &response.response_encexp1) { + match comeq.extract_commit_message(challenge, response) { Some(m) => { commit_encexp1.push(m); - w_a_vec.push(witness.witness.1); + w_a_vec.push(response.response.1); } None => return None, } } - for (comeq, witness) in izip!(&self.encexp2, &witness.witness_encexp2) { - match comeq.extract_point(challenge, witness) { + for (comeq, response) in izip!(&self.encexp2, &response.response_encexp2) { + match comeq.extract_commit_message(challenge, response) { Some(m) => { commit_encexp2.push(m); - w_s_prime_vec.push(witness.witness.1); + w_s_prime_vec.push(response.response.1); } None => return None, } @@ -336,10 +337,10 @@ impl SigmaProtocol for EncTrans { let dlog_point = self .dlog .coeff - .mul_by_scalar(&witness.witness_common) + .mul_by_scalar(&response.response_common) .plus_point(&self.dlog.public.mul_by_scalar(challenge)); let mut point = self.elg_dec.public.mul_by_scalar(challenge); - let exps = vec![witness.witness_common, w_lin]; + let exps = vec![response.response_common, w_lin]; let product = multiexp(&self.elg_dec.coeff, &exps); point = point.plus_point(&product); Some(EncTransCommit { diff --git a/rust-src/concordium_base/src/encrypted_transfers/types.rs b/rust-src/concordium_base/src/encrypted_transfers/types.rs index 34c500ad7..79276a414 100644 --- a/rust-src/concordium_base/src/encrypted_transfers/types.rs +++ b/rust-src/concordium_base/src/encrypted_transfers/types.rs @@ -131,7 +131,7 @@ pub struct AggregatedDecryptedAmount { pub struct EncryptedAmountTransferProof { /// Proof that accounting is done correctly, i.e., remaining + transfer is /// the original amount. - pub accounting: SigmaProof>, + pub accounting: SigmaProof>, /// Proof that the transfered amount is correctly encrypted, i.e., chunks /// are small enough. pub transfer_amount_correct_encryption: RangeProof, @@ -145,7 +145,7 @@ pub struct EncryptedAmountTransferProof { pub struct SecToPubAmountTransferProof { /// Proof that accounting is done correctly, i.e., remaining + transfer is /// the original amount. - pub accounting: SigmaProof>, + pub accounting: SigmaProof>, /// Proof that the remaining amount is correctly encrypted, i.e, chunks /// small enough. pub remaining_amount_correct_encryption: RangeProof, diff --git a/rust-src/concordium_base/src/id/account_holder.rs b/rust-src/concordium_base/src/id/account_holder.rs index 7023b2a2f..7c0893e46 100644 --- a/rust-src/concordium_base/src/id/account_holder.rs +++ b/rust-src/concordium_base/src/id/account_holder.rs @@ -148,21 +148,21 @@ pub fn generate_pio>( let ip_ar_data = ip_ar_data .iter() - .zip(proof.witness.w1.w2.witnesses.into_iter()) + .zip(proof.response.r1.r2.responses.into_iter()) .map(|((ar_id, f), w)| (*ar_id, f(w))) .collect::>(); // Returning the version 0 pre-identity object. let poks_common = CommonPioProofFields { challenge: proof.challenge, - id_cred_sec_witness: proof.witness.w1.w1.w1.w1, - commitments_same_proof: proof.witness.w1.w1.w1.w2, - commitments_prf_same: proof.witness.w1.w1.w2, + id_cred_sec_response: proof.response.r1.r1.r1.r1, + commitments_same_proof: proof.response.r1.r1.r1.r2, + commitments_prf_same: proof.response.r1.r1.r2, bulletproofs, }; let poks = PreIdentityProof { common_proof_fields: poks_common, - prf_regid_proof: proof.witness.w2, + prf_regid_proof: proof.response.r2, proof_acc_sk, }; let pio = PreIdentityObject { @@ -222,16 +222,16 @@ pub fn generate_pio_v1>( let ip_ar_data = ip_ar_data .iter() - .zip(proof.witness.w2.witnesses.into_iter()) + .zip(proof.response.r2.responses.into_iter()) .map(|((ar_id, f), w)| (*ar_id, f(w))) .collect::>(); // Returning the version 1 pre-identity object. let poks = CommonPioProofFields { challenge: proof.challenge, - id_cred_sec_witness: proof.witness.w1.w1.w1, - commitments_same_proof: proof.witness.w1.w1.w2, - commitments_prf_same: proof.witness.w1.w2, + id_cred_sec_response: proof.response.r1.r1.r1, + commitments_same_proof: proof.response.r1.r1.r2, + commitments_prf_same: proof.response.r1.r2, bulletproofs, }; let pio = PreIdentityObjectV1 { @@ -261,7 +261,7 @@ type CommonPioProverType = AndAdapter< type IpArDataClosures<'a, C> = Vec<( ArIdentity, - Box) -> IpArData + 'a>, + Box) -> IpArData + 'a>, )>; /// Various data returned by `generate_pio_common` needed by both @@ -317,7 +317,7 @@ fn generate_pio_common<'a, P: Pairing, C: Curve, R: ran // We now construct all the zero-knowledge proofs. // Since all proofs must be bound together, we // first construct inputs to all the proofs, and only at the end - // do we produce all the different witnesses. + // do we produce all the different responses. // First the proof that we know id_cred_sec. let id_cred_pub = context @@ -435,7 +435,7 @@ fn generate_pio_common<'a, P: Pairing, C: Curve, R: ran replicated_provers.push(item_prover); replicated_secrets.push(secret); let encrypted_share = item.encrypted_share; - let closure: Box) -> IpArData + 'a> = + let closure: Box) -> IpArData + 'a> = Box::new(move |proof_com_enc_eq| IpArData { enc_prf_key_share: encrypted_share, proof_com_enc_eq, @@ -939,10 +939,10 @@ where challenge: proof.challenge, proof_id_cred_pub: id_cred_pub_share_numbers .into_iter() - .zip(proof.witness.w2.witnesses) + .zip(proof.response.r2.responses) .collect(), - proof_reg_id: proof.witness.w1.w1, - proof_ip_sig: proof.witness.w1.w2, + proof_reg_id: proof.response.r1.r1, + proof_ip_sig: proof.response.r1.r2, cred_counter_less_than_max_accounts, }; @@ -1192,13 +1192,13 @@ fn compute_pok_reg_id( Commitment(reg_id), cmm_one, ]; - // finally the secret keys are derived from actual commited values + // finally the secret keys are derived from actual committed values // and the randomness. let mut k = C::scalar_from_u64(u64::from(cred_counter)); k.add_assign(&prf_key); - // combine the two randomness witnesses + // combine the two random values let mut rand_1 = C::Scalar::zero(); rand_1.add_assign(prf_rand); rand_1.add_assign(cred_counter_rand); diff --git a/rust-src/concordium_base/src/id/chain.rs b/rust-src/concordium_base/src/id/chain.rs index 1a5896fdd..e90b139a5 100644 --- a/rust-src/concordium_base/src/id/chain.rs +++ b/rust-src/concordium_base/src/id/chain.rs @@ -99,7 +99,7 @@ pub fn verify_cdi< cmm_key: on_chain_commitment_key, }; // FIXME: Figure out a pattern to get rid of these clone's. - let witness_reg_id = cdi.proofs.id_proofs.proof_reg_id.clone(); + let response_reg_id = cdi.proofs.id_proofs.proof_reg_id.clone(); let cdv = &cdi.values; let proofs = &cdi.proofs; @@ -123,9 +123,9 @@ pub fn verify_cdi< return Err(CdiVerificationError::Signature); }; - let witness_sig = cdi.proofs.id_proofs.proof_ip_sig.clone(); + let response_sig = cdi.proofs.id_proofs.proof_ip_sig.clone(); - let (id_cred_pub_verifier, id_cred_pub_witnesses) = id_cred_pub_verifier( + let (id_cred_pub_verifier, id_cred_pub_responses) = id_cred_pub_verifier( &on_chain_commitment_key, known_ars, &cdi.values.ar_data, @@ -138,16 +138,16 @@ pub fn verify_cdi< second: verifier_sig, }; let verifier = verifier.add_prover(id_cred_pub_verifier); - let witness = AndWitness { - w1: AndWitness { - w1: witness_reg_id, - w2: witness_sig, + let response = AndResponse { + r1: AndResponse { + r1: response_reg_id, + r2: response_sig, }, - w2: id_cred_pub_witnesses, + r2: id_cred_pub_responses, }; let proof = SigmaProof { challenge: cdi.proofs.id_proofs.challenge, - witness, + response, }; if !verify(&mut ro, &verifier, &proof) { @@ -214,10 +214,10 @@ fn id_cred_pub_verifier>( known_ars: &BTreeMap, chain_ar_data: &BTreeMap>, cmm_sharing_coeff: &[Commitment], - proof_id_cred_pub: &BTreeMap>, + proof_id_cred_pub: &BTreeMap>, ) -> Result, CdiVerificationError> { let mut provers = Vec::with_capacity(proof_id_cred_pub.len()); - let mut witnesses = Vec::with_capacity(proof_id_cred_pub.len()); + let mut responses = Vec::with_capacity(proof_id_cred_pub.len()); // The encryptions and the proofs have to match. if chain_ar_data.len() != proof_id_cred_pub.len() { @@ -226,7 +226,8 @@ fn id_cred_pub_verifier>( // The following relies on the fact that iterators over BTreeMap are // over sorted values. - for ((ar_id, ar_data), (ar_id_1, witness)) in chain_ar_data.iter().zip(proof_id_cred_pub.iter()) + for ((ar_id, ar_data), (ar_id_1, response)) in + chain_ar_data.iter().zip(proof_id_cred_pub.iter()) { if ar_id != ar_id_1 { return Err(CdiVerificationError::IdCredPub); @@ -245,11 +246,13 @@ fn id_cred_pub_verifier>( encryption_in_exponent_generator: ar_info.get_public_key().generator, }; provers.push(item_prover); - witnesses.push(witness.clone()); + responses.push(response.clone()); } - Ok((ReplicateAdapter { protocols: provers }, ReplicateWitness { - witnesses, - })) + Ok( + (ReplicateAdapter { protocols: provers }, ReplicateResponse { + responses, + }), + ) } /// Verify a policy. This currently does not do anything since diff --git a/rust-src/concordium_base/src/id/id_proof_types.rs b/rust-src/concordium_base/src/id/id_proof_types.rs index a89b16770..1552a50e6 100644 --- a/rust-src/concordium_base/src/id/id_proof_types.rs +++ b/rust-src/concordium_base/src/id/id_proof_types.rs @@ -5,7 +5,7 @@ //! Given the statement and relevant secret data (being the attribute value and //! the commitment randomness), the user can construct a proof of the statement //! (if the statement is true). -use super::{constants::AttributeKind, sigma_protocols::dlog::Witness as DlogWitness, types::*}; +use super::{constants::AttributeKind, sigma_protocols::dlog::Response as DlogResponse, types::*}; use crate::{ bulletproofs::{ range_proof::RangeProof, set_membership_proof::SetMembershipProof, @@ -225,7 +225,7 @@ pub enum AtomicProof> { RevealAttribute { attribute: AttributeType, /* The verifier has to learn this, so it is sent together with * the proof. */ - proof: super::sigma_protocols::common::SigmaProof>, + proof: super::sigma_protocols::common::SigmaProof>, }, /// A proof that an attribute is in a range AttributeInRange { diff --git a/rust-src/concordium_base/src/id/identity_provider.rs b/rust-src/concordium_base/src/id/identity_provider.rs index ffd80cb2c..97ea5b9fc 100644 --- a/rust-src/concordium_base/src/id/identity_provider.rs +++ b/rust-src/concordium_base/src/id/identity_provider.rs @@ -54,7 +54,7 @@ impl std::fmt::Display for Reason { /// The validation of the two versions of identity object requests are very /// similar, and therefore the common validation parts of the two flows are /// factored out in the function `validate_request_common`. It produces the -/// common sigma protocol verifier and witnesses that are used in both +/// common sigma protocol verifier and responses that are used in both /// `validate_request` and `validate_request_v1`: /// * In the version 0 flow, the common verifier is AND'ed with a verifier /// checking that RegID = PRF(key_PRF, 0) @@ -87,7 +87,7 @@ pub fn validate_request>( let mut transcript = RandomOracle::domain("PreIdentityProof"); // Construct the common verifier and verify the range proof - let (verifier, witness) = validate_request_common( + let (verifier, response) = validate_request_common( &mut transcript, id_cred_pub, pre_id_obj.get_common_pio_fields(), @@ -102,18 +102,18 @@ pub fn validate_request>( g: pub_info_for_ip.reg_id, cmm_key: verifier.first.second.cmm_key_1, }; - let prf_regid_witness = pre_id_obj.poks.prf_regid_proof.clone(); + let prf_regid_response = pre_id_obj.poks.prf_regid_proof.clone(); let verifier = verifier.add_prover(verifier_prf_regid); - // Construct the witness consisting of the common witness and the - // prf_regid_witness above. - let witness = AndWitness { - w1: witness, - w2: prf_regid_witness, + // Construct the response consisting of the common response and the + // prf_regid_response above. + let response = AndResponse { + r1: response, + r2: prf_regid_response, }; let proof = SigmaProof { challenge: poks_common.challenge, - witness, + response, }; // Verify the sigma protocol proof @@ -136,7 +136,7 @@ pub fn validate_request_v1>( let mut transcript = RandomOracle::domain("PreIdentityProof"); // Construct the common verifier and verify the range proof - let (verifier, witness) = validate_request_common( + let (verifier, response) = validate_request_common( &mut transcript, id_cred_pub, common_fields, @@ -145,7 +145,7 @@ pub fn validate_request_v1>( )?; let proof = SigmaProof { challenge: poks_common.challenge, - witness, + response, }; // Verify the sigma protocol proof if verify(&mut transcript, &verifier, &proof) { @@ -165,18 +165,18 @@ type CommonPioVerifierType = AndAdapter< ReplicateAdapter>, >; -type CommonVerifierWithWitness = ( +type CommonVerifierWithResponse = ( CommonPioVerifierType, - as SigmaProtocol>::ProverWitness, + as SigmaProtocol>::Response, ); /// This is used by both `validate_request` and `validate_request_v1` to -/// construct the sigma protocol verifier and witness used by both of these +/// construct the sigma protocol verifier and response used by both of these /// functions. The inputs are /// - transcript - the RandomOracle used in the protocol. /// - id_cred_pub - the IdCredPub of the user behind the identity. /// - common_fields - relevant information used to verify proofs. -/// - poks_common - the challenge, the common sigma protocol witnesses together +/// - poks_common - the challenge, the common sigma protocol responses together /// with the range proof. /// - context - the identity provider context fn validate_request_common>( @@ -185,7 +185,7 @@ fn validate_request_common>( common_fields: CommonPioFields, poks_common: &CommonPioProofFields, context: IpContext, -) -> Result, Reason> { +) -> Result, Reason> { // Verify proof: let ip_info = &context.ip_info; let commitment_key_sc = CommitmentKey { @@ -209,7 +209,7 @@ fn validate_request_common>( public: *id_cred_pub, coeff: context.global_context.on_chain_commitment_key.g, }; - let id_cred_sec_witness = poks_common.id_cred_sec_witness; + let id_cred_sec_response = poks_common.id_cred_sec_response; // Verify that id_cred_sec is the same both in id_cred_pub and in cmm_sc let id_cred_sec_eq_verifier = com_eq::ComEq { @@ -220,7 +220,7 @@ fn validate_request_common>( }; // TODO: Figure out whether we can somehow get rid of this clone. - let id_cred_sec_eq_witness = poks_common.commitments_same_proof.clone(); + let id_cred_sec_eq_response = poks_common.commitments_same_proof.clone(); let choice_ar_handles = common_fields.choice_ar_parameters.ar_identities.clone(); let revocation_threshold = common_fields.choice_ar_parameters.threshold; @@ -280,7 +280,7 @@ fn validate_request_common>( cmm_key_1: commitment_key_prf, cmm_key_2: *ar_ck, }; - let witness_prf_same = poks_common.commitments_prf_same; + let response_prf_same = poks_common.commitments_prf_same; let h_in_exponent = *context.global_context.encryption_in_exponent_generator(); let prf_verification = compute_prf_sharing_verifier( @@ -290,7 +290,7 @@ fn validate_request_common>( context.ars_infos, &h_in_exponent, ); - let (prf_sharing_verifier, prf_sharing_witness) = match prf_verification { + let (prf_sharing_verifier, prf_sharing_response) = match prf_verification { Some(v) => v, None => return Err(Reason::WrongArParameters), }; @@ -337,17 +337,17 @@ fn validate_request_common>( } transcript.append_message(b"bulletproofs", &poks_common.bulletproofs); - let witness = AndWitness { - w1: AndWitness { - w1: AndWitness { - w1: id_cred_sec_witness, - w2: id_cred_sec_eq_witness, + let response = AndResponse { + r1: AndResponse { + r1: AndResponse { + r1: id_cred_sec_response, + r2: id_cred_sec_eq_response, }, - w2: witness_prf_same, + r2: response_prf_same, }, - w2: prf_sharing_witness, + r2: prf_sharing_response, }; - Ok((verifier, witness)) + Ok((verifier, response)) } /// Sign the given pre-identity-object to produce a version 0 identity object. @@ -440,7 +440,7 @@ fn compute_prf_sharing_verifier( encryption_in_exponent_generator: &C, ) -> Option> { let mut verifiers = Vec::with_capacity(ip_ar_data.len()); - let mut witnesses = Vec::with_capacity(ip_ar_data.len()); + let mut responses = Vec::with_capacity(ip_ar_data.len()); for (ar_id, ar_data) in ip_ar_data.iter() { let cmm_share = utils::commitment_to_share(&ar_id.to_scalar::(), cmm_sharing_coeff); @@ -468,13 +468,13 @@ fn compute_prf_sharing_verifier( }; verifiers.push(verifier); // TODO: Figure out whether we can somehow get rid of this clone. - witnesses.push(ar_data.proof_com_enc_eq.clone()) + responses.push(ar_data.proof_com_enc_eq.clone()) } Some(( ReplicateAdapter { protocols: verifiers, }, - ReplicateWitness { witnesses }, + ReplicateResponse { responses }, )) } diff --git a/rust-src/concordium_base/src/id/sigma_protocols/aggregate_dlog.rs b/rust-src/concordium_base/src/id/sigma_protocols/aggregate_dlog.rs index 07b93e61a..2190c81fd 100644 --- a/rust-src/concordium_base/src/id/sigma_protocols/aggregate_dlog.rs +++ b/rust-src/concordium_base/src/id/sigma_protocols/aggregate_dlog.rs @@ -1,7 +1,8 @@ -//! The module provides the implementation of the `aggregate_dlog` sigma -//! protocol. This protocol enables one to prove knowledge of discrete -//! logarithms $a_1 ... a_n$ public values $ y = \prod G_i^{a_i} $. -//! This is a specialization of `com_eq` protocol where we do not require +//! The module provides the implementation of the `agg-dlog` sigma +//! protocol (cf. "Proof of Knowledge for Aggregate Discrete Logarithms" Section +//! 9.2.2, Bluepaper v1.2.5). This protocol enables one to prove knowledge of +//! discrete logarithms $a_1 ... a_n$ for the public value $ y = \prod G_i^{a_i} +//! $. This is a specialization of `com_eq` protocol where we do not require //! commitments. use super::common::*; use crate::{ @@ -20,21 +21,21 @@ pub struct AggregateDlog { pub coeff: Vec, } -/// Aggregate dlog witness. We deliberately make it opaque. +/// Aggregate dlog response. We deliberately make it opaque. #[derive(Debug, Serialize)] -pub struct Witness { +pub struct Response { #[size_length = 4] - witness: Vec, + response: Vec, } /// Convenient alias for aggregate dlog proof -pub type Proof = SigmaProof>; +pub type Proof = SigmaProof>; impl SigmaProtocol for AggregateDlog { type CommitMessage = C; type ProtocolChallenge = C::Scalar; type ProverState = Vec; - type ProverWitness = Witness; + type Response = Response; type SecretData = Vec>; fn public(&self, ro: &mut RandomOracle) { @@ -42,11 +43,7 @@ impl SigmaProtocol for AggregateDlog { ro.extend_from(b"coeff", &self.coeff) } - fn get_challenge(&self, challenge: &Challenge) -> Self::ProtocolChallenge { - C::scalar_from_bytes(challenge) - } - - fn commit_point( + fn compute_commit_message( &self, csprng: &mut R, ) -> Option<(Self::CommitMessage, Self::ProverState)> { @@ -60,40 +57,44 @@ impl SigmaProtocol for AggregateDlog { Some((multiexp(&self.coeff, &rands), rands)) } - fn generate_witness( + fn get_challenge(&self, challenge: &Challenge) -> Self::ProtocolChallenge { + C::scalar_from_bytes(challenge) + } + + fn compute_response( &self, secret: Self::SecretData, state: Self::ProverState, challenge: &Self::ProtocolChallenge, - ) -> Option { + ) -> Option { let n = secret.len(); if state.len() != n { return None; } - let mut witness = Vec::with_capacity(n); + let mut response = Vec::with_capacity(n); for (ref s, ref r) in izip!(secret, state) { - let mut wit = *challenge; - wit.mul_assign(s); - wit.negate(); - wit.add_assign(r); - witness.push(wit); + let mut res = *challenge; + res.mul_assign(s); + res.negate(); + res.add_assign(r); + response.push(res); } - Some(Witness { witness }) + Some(Response { response }) } - fn extract_point( + fn extract_commit_message( &self, challenge: &Self::ProtocolChallenge, - witness: &Self::ProverWitness, + response: &Self::Response, ) -> Option { - if witness.witness.len() != self.coeff.len() { + if response.response.len() != self.coeff.len() { return None; } - let mut point = self.public.mul_by_scalar(challenge); - for (w, g) in izip!(witness.witness.iter(), self.coeff.iter()) { - point = point.plus_point(&g.mul_by_scalar(w)); + let mut commit_message = self.public.mul_by_scalar(challenge); + for (w, g) in izip!(response.response.iter(), self.coeff.iter()) { + commit_message = commit_message.plus_point(&g.mul_by_scalar(w)); } - Some(point) + Some(commit_message) } #[cfg(test)] diff --git a/rust-src/concordium_base/src/id/sigma_protocols/com_enc_eq.rs b/rust-src/concordium_base/src/id/sigma_protocols/com_enc_eq.rs index 1b0172414..378561d67 100644 --- a/rust-src/concordium_base/src/id/sigma_protocols/com_enc_eq.rs +++ b/rust-src/concordium_base/src/id/sigma_protocols/com_enc_eq.rs @@ -1,6 +1,8 @@ -//! Implementation of the `com_enc_eq` sigma protocol. -//! This protocol is used to prove that the encrypted value (encrypted via -//! ElGamal) is the same as the value commited to via the Pedersen commitment. +//! Implementation of the `com_enc_eq` sigma protocol (cf. "Proof of Equality +//! for Committed Value and ElGamal Encrypted Value" Section 9.2.7, +//! Bluepaper v1.2.5). This protocol is used to prove that the encrypted value +//! (encrypted via ElGamal) is the same as the value committed to via the +//! Pedersen commitment. use super::common::*; use crate::{ @@ -23,7 +25,7 @@ pub struct ComEncEqSecret { } #[derive(Clone, Debug, Eq, PartialEq, Serialize, SerdeBase16Serialize)] -pub struct Witness { +pub struct Response { /// The values /// * $\alpha - c R$ /// * $\beta - c x$ @@ -33,7 +35,7 @@ pub struct Witness { /// * R is the ElGamal randomness /// * r is the Pedersen randomness /// * x is the encrypted/commited value - witness: (T::Scalar, T::Scalar, T::Scalar), + response: (T::Scalar, T::Scalar, T::Scalar), } pub struct ComEncEq { @@ -55,7 +57,7 @@ impl SigmaProtocol for ComEncEq { type ProtocolChallenge = C::Scalar; // (beta, alpha, gamma) type ProverState = (Value, ElgamalRandomness, PedersenRandomness); - type ProverWitness = Witness; + type Response = Response; type SecretData = ComEncEqSecret; #[inline] @@ -67,15 +69,7 @@ impl SigmaProtocol for ComEncEq { } #[inline] - fn get_challenge( - &self, - challenge: &crate::random_oracle::Challenge, - ) -> Self::ProtocolChallenge { - C::scalar_from_bytes(challenge) - } - - #[inline] - fn commit_point( + fn compute_commit_message( &self, csprng: &mut R, ) -> Option<(Self::CommitMessage, Self::ProverState)> { @@ -90,12 +84,20 @@ impl SigmaProtocol for ComEncEq { } #[inline] - fn generate_witness( + fn get_challenge( + &self, + challenge: &crate::random_oracle::Challenge, + ) -> Self::ProtocolChallenge { + C::scalar_from_bytes(challenge) + } + + #[inline] + fn compute_response( &self, secret: Self::SecretData, state: Self::ProverState, challenge: &Self::ProtocolChallenge, - ) -> Option { + ) -> Option { let x = &secret.value; let cR = &secret.elgamal_rand; let r = &secret.pedersen_rand; @@ -114,16 +116,16 @@ impl SigmaProtocol for ComEncEq { z_3.negate(); z_3.mul_assign(r); z_3.add_assign(&gamma); - Some(Witness { - witness: (z_1, z_2, z_3), + Some(Response { + response: (z_1, z_2, z_3), }) } #[inline] - fn extract_point( + fn extract_commit_message( &self, challenge: &Self::ProtocolChallenge, - witness: &Self::ProverWitness, + response: &Self::Response, ) -> Option { let g_1 = self.pub_key.generator; let h_1 = self.pub_key.key; @@ -131,9 +133,9 @@ impl SigmaProtocol for ComEncEq { let h = self.cmm_key.h; let h_in_exponent = self.encryption_in_exponent_generator; - let z_1 = witness.witness.0; - let z_2 = witness.witness.1; - let z_3 = witness.witness.2; + let z_1 = response.response.0; + let z_2 = response.response.1; + let z_3 = response.response.2; let e_1 = self.cipher.0; let e_2 = self.cipher.1; diff --git a/rust-src/concordium_base/src/id/sigma_protocols/com_eq.rs b/rust-src/concordium_base/src/id/sigma_protocols/com_eq.rs index c8b709d04..22c4b069e 100644 --- a/rust-src/concordium_base/src/id/sigma_protocols/com_eq.rs +++ b/rust-src/concordium_base/src/id/sigma_protocols/com_eq.rs @@ -1,10 +1,12 @@ -//! The module provides the implementation of the `com_eq` sigma protocol. -//! This protocol enables one to prove knowledge of discrete logarithm $a_1$ -//! together with randomnesses $r_1$ corresponding to the public value -//! $ y = \prod G_i^{a_i} $ and commitment $C = commit(a_1, r_1)$. -//! The product y and commitments can be in different groups, but they have to -//! be of the same prime order, and for the implementation the field of scalars -//! must be the same type for both groups. +//! The module provides the implementation of the `com-dlog-eq` sigma protocol +//! for the special case of one commitment (cf. "Proof of Equality for +//! Aggregated Discrete Logarithms and Commitments" Section 9.2.5, Bluepaper +//! v1.2.5). This protocol enables one to prove knowledge of discrete logarithm +//! $a_1$ together with randomnesses $r_1$ corresponding to the public value $ y +//! = \prod G_i^{a_i} $ and the commitment $C = commit(a_1, r_1)$. The product y +//! and commitments can be in different groups, but they have to be of the same +//! prime order, and for the implementation the field of scalars must be the +//! same type for both groups. use super::common::*; use crate::{ @@ -16,17 +18,17 @@ use crate::{ use ff::Field; #[derive(Clone, Debug, Eq, PartialEq, Serialize, SerdeBase16Serialize)] -pub struct Witness { +pub struct Response { /// The pair $(s, t)$ where /// * $s = \alpha - c a$ /// * $t = R - c r$ /// where $c$ is the challenge and $\alpha$ and $R$ are prover chosen /// random scalars. - pub witness: (T::Scalar, T::Scalar), + pub response: (T::Scalar, T::Scalar), } #[derive(Debug, Serialize)] -pub struct CommittedPoints { +pub struct CommittedMessages { pub u: C, pub v: Commitment, } @@ -50,11 +52,11 @@ pub struct ComEqSecret { #[allow(non_snake_case)] impl> SigmaProtocol for ComEq { - type CommitMessage = CommittedPoints; + type CommitMessage = CommittedMessages; type ProtocolChallenge = C::Scalar; // Vector of pairs (alpha_i, R_i). type ProverState = (Value, Randomness); - type ProverWitness = Witness; + type Response = Response; type SecretData = ComEqSecret; fn public(&self, ro: &mut RandomOracle) { @@ -64,7 +66,7 @@ impl> SigmaProtocol for ComEq { ro.append_message("g", &self.g) } - fn commit_point( + fn compute_commit_message( &self, csprng: &mut R, ) -> Option<(Self::CommitMessage, Self::ProverState)> { @@ -74,7 +76,7 @@ impl> SigmaProtocol for ComEq { // This cR_i is R_i from the specification. let (v, cR) = self.cmm_key.commit(&alpha, csprng); u = u.plus_point(&self.g.mul_by_scalar(&alpha)); - Some((CommittedPoints { u, v }, (alpha, cR))) + Some((CommittedMessages { u, v }, (alpha, cR))) } fn get_challenge( @@ -84,12 +86,12 @@ impl> SigmaProtocol for ComEq { C::scalar_from_bytes(challenge) } - fn generate_witness( + fn compute_response( &self, secret: Self::SecretData, state: Self::ProverState, challenge: &Self::ProtocolChallenge, - ) -> Option { + ) -> Option { let (ref alpha, ref cR) = state; // compute alpha_i - a_i * c let mut s = *challenge; @@ -101,26 +103,26 @@ impl> SigmaProtocol for ComEq { t.mul_assign(&secret.r); t.negate(); t.add_assign(cR); - Some(Witness { witness: (s, t) }) + Some(Response { response: (s, t) }) } - fn extract_point( + fn extract_commit_message( &self, challenge: &Self::ProtocolChallenge, - witness: &Self::ProverWitness, + response: &Self::Response, ) -> Option { // let mut u = self.y.mul_by_scalar(challenge); // FIXME: Could benefit from multiexponentiation - // u = u.plus_point(&self.g.mul_by_scalar(&witness.witness.0)); + // u = u.plus_point(&self.g.mul_by_scalar(&response.response.0)); - let u = multiexp(&[self.y, self.g], &[*challenge, witness.witness.0]); + let u = multiexp(&[self.y, self.g], &[*challenge, response.response.0]); let v = self.commitment.mul_by_scalar(challenge).plus_point( &self .cmm_key - .hide_worker(&witness.witness.0, &witness.witness.1), + .hide_worker(&response.response.0, &response.response.1), ); - Some(CommittedPoints { + Some(CommittedMessages { u, v: Commitment(v), }) diff --git a/rust-src/concordium_base/src/id/sigma_protocols/com_eq_different_groups.rs b/rust-src/concordium_base/src/id/sigma_protocols/com_eq_different_groups.rs index 9771a2fa3..c3706740f 100644 --- a/rust-src/concordium_base/src/id/sigma_protocols/com_eq_different_groups.rs +++ b/rust-src/concordium_base/src/id/sigma_protocols/com_eq_different_groups.rs @@ -1,7 +1,8 @@ -//! The module provides the implementation of the `com_eq_diff_groups` sigma -//! protocol. This protocol enables one to prove that the value committed to in -//! two commitments $C_1$ and $C_2$ in (potentially) two different groups (of -//! the same order) is the same. +//! The module provides the implementation of the `com-com-eq` sigma +//! protocol (cf. "Proof of Equality for Commitments in Different Groups" +//! Section 9.2.9, Bluepaper v1.2.5). This protocol enables one to prove that +//! the value committed to in two commitments $C_1$ and $C_2$ in (potentially) +//! two different groups (of the same order) is the same. use super::common::*; use crate::{ common::*, @@ -20,14 +21,13 @@ pub struct ComEqDiffGroupsSecret> { } #[derive(Clone, Debug, Eq, PartialEq, Copy, Serialize, SerdeBase16Serialize)] -pub struct Witness> { +pub struct Response> { /// The triple (s_1, s_2, t). - witness: (C1::Scalar, C1::Scalar, C2::Scalar), + response: (C1::Scalar, C1::Scalar, C2::Scalar), } pub struct ComEqDiffGroups { - /// A pair of commitments to the same value in different - /// groups. + /// A pair of commitments to the same value in different groups. pub commitment_1: Commitment, pub commitment_2: Commitment, /// A pair of commitment keys (for the first and second @@ -42,7 +42,7 @@ impl> SigmaProtocol for ComEqDiffGroup type ProtocolChallenge = C1::Scalar; // The triple alpha_1, alpha_2, R type ProverState = (Value, Randomness, Randomness); - type ProverWitness = Witness; + type Response = Response; type SecretData = ComEqDiffGroupsSecret; #[inline] @@ -54,15 +54,7 @@ impl> SigmaProtocol for ComEqDiffGroup } #[inline] - fn get_challenge( - &self, - challenge: &crate::random_oracle::Challenge, - ) -> Self::ProtocolChallenge { - C1::scalar_from_bytes(challenge) - } - - #[inline] - fn commit_point( + fn compute_commit_message( &self, csprng: &mut R, ) -> Option<(Self::CommitMessage, Self::ProverState)> { @@ -73,12 +65,20 @@ impl> SigmaProtocol for ComEqDiffGroup } #[inline] - fn generate_witness( + fn get_challenge( + &self, + challenge: &crate::random_oracle::Challenge, + ) -> Self::ProtocolChallenge { + C1::scalar_from_bytes(challenge) + } + + #[inline] + fn compute_response( &self, secret: Self::SecretData, state: Self::ProverState, challenge: &Self::ProtocolChallenge, - ) -> Option { + ) -> Option { let mut s_1 = *challenge; s_1.mul_assign(&secret.value); s_1.negate(); @@ -93,17 +93,17 @@ impl> SigmaProtocol for ComEqDiffGroup t.mul_assign(&secret.rand_cmm_2); t.negate(); t.add_assign(&state.2); - Some(Witness { - witness: (s_1, s_2, t), + Some(Response { + response: (s_1, s_2, t), }) } #[inline] #[allow(clippy::many_single_char_names)] - fn extract_point( + fn extract_commit_message( &self, challenge: &Self::ProtocolChallenge, - witness: &Self::ProverWitness, + response: &Self::Response, ) -> Option { let y = self.commitment_1; let cC = self.commitment_2; @@ -111,7 +111,7 @@ impl> SigmaProtocol for ComEqDiffGroup let CommitmentKey { g: cG1, h: cG2 } = self.cmm_key_1; let CommitmentKey { g, h } = self.cmm_key_2; - let (s_1, s_2, t) = witness.witness; + let (s_1, s_2, t) = response.response; let u = { let bases = [y.0, cG1, cG2]; diff --git a/rust-src/concordium_base/src/id/sigma_protocols/com_eq_sig.rs b/rust-src/concordium_base/src/id/sigma_protocols/com_eq_sig.rs index 46352420b..744826f12 100644 --- a/rust-src/concordium_base/src/id/sigma_protocols/com_eq_sig.rs +++ b/rust-src/concordium_base/src/id/sigma_protocols/com_eq_sig.rs @@ -1,8 +1,11 @@ //! This module implements the proof of knowledge of signature sigma protocol. -//! This protocol allows a user to prove knowledge of a signature without +//! This protocol allows a user to prove knowledge of a PS signature without //! revealing the original signature, or the message, but they have to reveal //! the blinded version of the signature, and commitments to the values that -//! were signed. +//! were signed. The protocol is a essentially `com-dlog-eq` from "Proof of +//! Equality for Aggregated Discrete Logarithms and Commitments" Section 9.2.5, +//! Bluepaper v1.2.5 where the blinded signature is the aggregated dlog (cf. +//! "Proof of Knowledge of a Signature" Section 5.3.5, Bluepaper v1.2.5") use super::common::*; use crate::{ @@ -17,14 +20,14 @@ use itertools::izip; use rand::*; #[derive(Clone, Debug, Serialize)] -pub struct Witness> { - /// The witness that the prover knows $r'$ (see specification) - witness_rho: P::ScalarField, - /// List of witnesses $(w_i, R_i)$ that the user knows the messages m_i and - /// randomness R_i that combine to commitments and the public randomized - /// signature. +pub struct Response> { + /// The response that the prover knows $r'$ (see specification) + response_rho: P::ScalarField, + /// List of responses $(res_m_i, res_R_i)$ that the user knows the messages + /// m_i and randomness R_i that combine to commitments and the public + /// randomized signature. #[size_length = 4] - witness_commit: Vec<(P::ScalarField, C::Scalar)>, + response_commit: Vec<(P::ScalarField, C::Scalar)>, } pub struct ComEqSig> { @@ -57,7 +60,7 @@ impl> SigmaProtocol for ComEqSig

; - type ProverWitness = Witness; + type Response = Response; type SecretData = ComEqSigSecret; #[inline] @@ -77,7 +80,7 @@ impl> SigmaProtocol for ComEqSig

( + fn compute_commit_message( &self, csprng: &mut R, ) -> Option<(Self::CommitMessage, Self::ProverState)> { @@ -93,7 +96,7 @@ impl> SigmaProtocol for ComEqSig

> SigmaProtocol for ComEqSig

Option { + ) -> Option { if secret.values_and_rands.len() != state.mus_and_rs.len() { return None; } @@ -151,37 +154,37 @@ impl> SigmaProtocol for ComEqSig

Option { let g_tilda = self.ps_pub_key.g_tilda; let a_hat = self.blinded_sig.sig.0; @@ -192,7 +195,7 @@ impl> SigmaProtocol for ComEqSig

cY_tildas.len() { @@ -203,24 +206,21 @@ impl> SigmaProtocol for ComEqSig

{ - // The witness consists of a com_mult witness and a commitment. - com_mult_witness: SigmaProof>, - aux_com: Commitment, +pub struct Response { + // The response consists of a com_mult response and a commitment. + com_mult_response: SigmaProof>, + aux_com: Commitment, } /// Function for proving that a committed value `value` is different from @@ -43,7 +43,7 @@ pub fn prove_com_ineq( value_tilde: &Randomness, pub_value: C::Scalar, csprng: &mut R, -) -> Option> { +) -> Option> { let mut transcript = RandomOracle::domain(b"InequalityProof"); let c = com_key.hide(&value, value_tilde); @@ -84,9 +84,9 @@ pub fn prove_com_ineq( }; let partial_proof = sigma_prove(&mut transcript, &prover, secret, csprng)?; - Some(Witness { - com_mult_witness: partial_proof, - aux_com: cmm_2, + Some(Response { + com_mult_response: partial_proof, + aux_com: cmm_2, }) } @@ -104,10 +104,10 @@ pub fn verify_com_ineq( com_key: &CommitmentKey, c: &Commitment, pub_value: C::Scalar, - proof: &Witness, + proof: &Response, ) -> bool { - let Witness { - com_mult_witness, + let Response { + com_mult_response, aux_com, } = proof; let mut transcript = RandomOracle::domain(b"InequalityProof"); @@ -127,7 +127,7 @@ pub fn verify_com_ineq( cmms: [Commitment(cmm_1), *aux_com, cmm_3], cmm_key: *com_key, }; - sigma_verify(&mut transcript, &com_mult, com_mult_witness) + sigma_verify(&mut transcript, &com_mult, com_mult_response) } #[cfg(test)] @@ -169,9 +169,9 @@ mod tests { // Make the proof invalid by changing parameters let wrong_com_key = CommitmentKey::::generate(&mut csprng); let wrong_pub_value = Fr::from_str("20000102").unwrap(); - let wrong_proof = Witness { - aux_com: Commitment(G1::generate(&mut csprng)), - com_mult_witness: proof.com_mult_witness.clone(), + let wrong_proof = Response { + aux_com: Commitment(G1::generate(&mut csprng)), + com_mult_response: proof.com_mult_response.clone(), }; // Verify failure for invalid parameters diff --git a/rust-src/concordium_base/src/id/sigma_protocols/com_lin.rs b/rust-src/concordium_base/src/id/sigma_protocols/com_lin.rs index 6e4eba1e2..89d5dc866 100644 --- a/rust-src/concordium_base/src/id/sigma_protocols/com_lin.rs +++ b/rust-src/concordium_base/src/id/sigma_protocols/com_lin.rs @@ -1,6 +1,7 @@ -//! This module implements the com-lin sigma protocol, which allows -//! the prover to prove knowledge of pairs (s_i, r_i) and (s, r) such that -//! \sum_{i} u_i * s_i = u * s for some public constants u_i and u. +//! This module implements the `com-lin` sigma protocol (cf. "Linear +//! Relationship of Committed Values" Section 9.2.11, Bluepaper v1.2.5). This +//! protocol enables the prover to prove knowledge of pairs (s_i, r_i) and (s, +//! r) such that \sum_{i} u_i * s_i = u * s for some public constants u_i and u. //! The r's are randomness in commitments to s_i's and s'. use super::common::*; @@ -37,7 +38,7 @@ pub struct ComLin { // TODO: What if u = 0? #[derive(Debug, Clone, Eq, PartialEq, Serialize)] -pub struct Witness { +pub struct Response { /// Randomized s_i's #[size_length = 4] /// Randomized r_i's. @@ -52,7 +53,7 @@ impl SigmaProtocol for ComLin { type CommitMessage = (Vec>, Commitment); type ProtocolChallenge = C::Scalar; type ProverState = (Vec>, Vec>, Randomness); - type ProverWitness = Witness; + type Response = Response; type SecretData = ComLinSecret; fn public(&self, ro: &mut RandomOracle) { @@ -66,7 +67,7 @@ impl SigmaProtocol for ComLin { C::scalar_from_bytes(challenge) } - fn commit_point( + fn compute_commit_message( &self, csprng: &mut R, ) -> Option<(Self::CommitMessage, Self::ProverState)> { @@ -103,12 +104,12 @@ impl SigmaProtocol for ComLin { Some((cm, ps)) } - fn generate_witness( + fn compute_response( &self, secret: Self::SecretData, state: Self::ProverState, challenge: &Self::ProtocolChallenge, - ) -> Option { + ) -> Option { let (alphas, r_i_tildes, r_tilde) = state; let n = alphas.len(); if self.cmms.len() != n @@ -138,19 +139,19 @@ impl SigmaProtocol for ComLin { s.mul_assign(&secret.r); s.negate(); s.add_assign(&r_tilde); - let witness = Witness { zs, ss, s }; - Some(witness) + let response = Response { zs, ss, s }; + Some(response) } #[allow(non_snake_case)] #[allow(clippy::many_single_char_names)] - fn extract_point( + fn extract_commit_message( &self, challenge: &Self::ProtocolChallenge, - witness: &Self::ProverWitness, + response: &Self::Response, ) -> Option { - let zs = &witness.zs; - let ss = &witness.ss; + let zs = &response.zs; + let ss = &response.ss; let c = *challenge; let n = zs.len(); if ss.len() != n || self.us.len() != n || self.cmms.len() != n { @@ -170,7 +171,7 @@ impl SigmaProtocol for ComLin { } // TODO: The g, h are the same in this, and the loop above. // We could partially precompute the table to speed-up the multiexp - let a = Commitment(multiexp(&[g, h, self.cmm.0], &[sum, witness.s, c])); + let a = Commitment(multiexp(&[g, h, self.cmm.0], &[sum, response.s, c])); let cm = (ais, a); Some(cm) } diff --git a/rust-src/concordium_base/src/id/sigma_protocols/com_mult.rs b/rust-src/concordium_base/src/id/sigma_protocols/com_mult.rs index 6283041af..5f784c345 100644 --- a/rust-src/concordium_base/src/id/sigma_protocols/com_mult.rs +++ b/rust-src/concordium_base/src/id/sigma_protocols/com_mult.rs @@ -1,7 +1,8 @@ -//! The module provides the implementation of the `com_mult` sigma protocol. -//! This protocol enables one to prove that the the product of two commited -//! values is equal to the third commited value, without revealing the values -//! themselves. +//! The module provides the implementation of the `com-mult` sigma protocol (cf. +//! "Proof of Multiplicative Relation on Commitments" Section 9.2.10, Bluepaper +//! v1.2.5). This protocol enables one to prove that the the product of two +//! committed values is equal to the third committed value, without revealing +//! the values themselves. use super::common::*; use crate::{ common::*, @@ -28,8 +29,8 @@ pub struct ComMult { } #[derive(Debug, Clone, Eq, PartialEq, Serialize)] -pub struct Witness { - /// The witness, expanded using the same notation as in the specification. +pub struct Response { + /// The response, expanded using the same notation as in the specification. ss: [C::Scalar; 2], ts: [C::Scalar; 2], t: C::Scalar, @@ -41,7 +42,7 @@ impl SigmaProtocol for ComMult { type ProtocolChallenge = C::Scalar; // alpha's, R_i's, R's type ProverState = ([Value; 2], [Randomness; 2], Randomness); - type ProverWitness = Witness; + type Response = Response; type SecretData = ComMultSecret; #[inline] @@ -51,12 +52,7 @@ impl SigmaProtocol for ComMult { } #[inline] - fn get_challenge(&self, challenge: &Challenge) -> Self::ProtocolChallenge { - C::scalar_from_bytes(challenge) - } - - #[inline] - fn commit_point( + fn compute_commit_message( &self, csprng: &mut R, ) -> Option<(Self::CommitMessage, Self::ProverState)> { @@ -75,12 +71,17 @@ impl SigmaProtocol for ComMult { } #[inline] - fn generate_witness( + fn get_challenge(&self, challenge: &Challenge) -> Self::ProtocolChallenge { + C::scalar_from_bytes(challenge) + } + + #[inline] + fn compute_response( &self, secret: Self::SecretData, state: Self::ProverState, challenge: &Self::ProtocolChallenge, - ) -> Option { + ) -> Option { let mut ss = [*challenge; 2]; let mut ts = [*challenge; 2]; @@ -109,17 +110,17 @@ impl SigmaProtocol for ComMult { t.negate(); t.add_assign(&cR); - Some(Witness { ss, ts, t }) + Some(Response { ss, ts, t }) } #[inline] - fn extract_point( + fn extract_commit_message( &self, challenge: &Self::ProtocolChallenge, - witness: &Self::ProverWitness, + response: &Self::Response, ) -> Option { let mut points = [Commitment(C::zero_point()); 2]; - for (i, (s_i, t_i)) in izip!(witness.ss.iter(), witness.ts.iter()).enumerate() { + for (i, (s_i, t_i)) in izip!(response.ss.iter(), response.ts.iter()).enumerate() { points[i] = { let bases = [self.cmms[i].0, self.cmm_key.g, self.cmm_key.h]; let powers = [*challenge, *s_i, *t_i]; @@ -128,12 +129,12 @@ impl SigmaProtocol for ComMult { } } let h = &self.cmm_key.h; - let s_2 = &witness.ss[1]; + let s_2 = &response.ss[1]; let cC_3 = self.cmms[2]; let cC_1 = self.cmms[0]; let v = { let bases = [cC_1.0, *h, cC_3.0]; - let powers = [*s_2, witness.t, *challenge]; + let powers = [*s_2, response.t, *challenge]; multiexp(&bases, &powers) // C_1^s_2 * h^t * C_3^c }; Some((points, Commitment(v))) diff --git a/rust-src/concordium_base/src/id/sigma_protocols/common.rs b/rust-src/concordium_base/src/id/sigma_protocols/common.rs index 0c3c30890..77ff80eb2 100644 --- a/rust-src/concordium_base/src/id/sigma_protocols/common.rs +++ b/rust-src/concordium_base/src/id/sigma_protocols/common.rs @@ -4,66 +4,69 @@ use itertools::izip; /// The common data known to the prover and verifier, i.e., public values and /// coefficients. pub trait SigmaProtocol: Sized { - /// Prover's commit message. + /// The first message of the prover. type CommitMessage: Serial; - /// Prover's witness. - type ProverWitness: Serialize; - /// Inherent challenge type. This needs to be convertible from the Challenge - /// type above. + /// The second message in the sigma protocol sent by the verifier to the + /// prover. type ProtocolChallenge; + /// The third message in the sigma protocol sent by the prover in response + /// to the challenge. + type Response: Serialize; /// Prover's state after the first message. Essentially any randomness /// they've chosen to generate the commit message. type ProverState; - /// The prover's secret data. + /// The prover's secret data. This corresponds to what is usually called + /// "witness". type SecretData; /// Given a random oracle, feed it all of the public input of this instance. fn public(&self, ro: &mut RandomOracle); - fn get_challenge(&self, challenge: &Challenge) -> Self::ProtocolChallenge; - - /// First message generated by the prover. We allow this function + /// Compute the first message of the prover. We allow this function /// to return 'None' if the inputs are inconsistent. /// The arguments are /// - self -- the prover's public and secret data /// - secret -- secret data known to the prover only /// - csprng -- a cryptographically secure random number generator - fn commit_point( + fn compute_commit_message( &self, csprng: &mut R, ) -> Option<(Self::CommitMessage, Self::ProverState)>; + /// Convert a random_oracle Challenge to a ProtocolChallenge + fn get_challenge(&self, challenge: &Challenge) -> Self::ProtocolChallenge; + /// Third message generated by the prover. We allow this function to return /// 'None' if the inputs are inconsistent. /// - self -- the prover's public and secret data /// - secret -- secret data known to the prover only - /// - state -- the state returned from the 'commit_point' call + /// - state -- the state returned from the 'compute_commit_message' call /// - challenge -- computed challenge /// This function is pure and deterministic. - fn generate_witness( + fn compute_response( &self, secret: Self::SecretData, state: Self::ProverState, challenge: &Self::ProtocolChallenge, - ) -> Option; + ) -> Option; /// Combine the public outputs from the third message with the challenge - /// and produce a commitment for verification. + /// and produce a CommitMessage for verification. /// - challenge -- computed challenge /// - self -- the verifier's public data /// This function is pure and deterministic. /// It is allowed to return 'None' if some of the input data is malformed, /// e.g., vectors of inconsistent lengths. - fn extract_point( + fn extract_commit_message( &self, challenge: &Self::ProtocolChallenge, - witness: &Self::ProverWitness, + response: &Self::Response, ) -> Option; #[cfg(test)] - /// Function used for testing. Generated valid input for this sigma proof. - /// The 'data_size' parameter can be used to adjust the size of generated - /// data. + /// Function used for testing. Generates valid input for this sigma proof. + /// The 'data_size' parameter can be used to adjust the size of the + /// generated data. fn with_valid_data( data_size: usize, csprng: &mut R, @@ -73,15 +76,15 @@ pub trait SigmaProtocol: Sized { #[derive(Debug, Serialize, Eq, PartialEq, SerdeBase16Serialize, Clone)] /// Generic structure to contain a single sigma proof. -pub struct SigmaProof { +pub struct SigmaProof { pub challenge: Challenge, - pub witness: W, + pub response: R, } #[derive(Serialize)] -pub struct AndWitness { - pub w1: W1, - pub w2: W2, +pub struct AndResponse { + pub r1: R1, + pub r2: R2, } /// An adapter to combine multiple provers or multiple verifiers. @@ -99,7 +102,7 @@ impl SigmaProtocol for AndAdapter // this is a minor inefficiency. type ProtocolChallenge = (P1::ProtocolChallenge, P2::ProtocolChallenge); type ProverState = (P1::ProverState, P2::ProverState); - type ProverWitness = AndWitness; + type Response = AndResponse; type SecretData = (P1::SecretData, P2::SecretData); fn public(&self, ro: &mut RandomOracle) { @@ -107,6 +110,15 @@ impl SigmaProtocol for AndAdapter self.second.public(ro) } + fn compute_commit_message( + &self, + csprng: &mut R, + ) -> Option<(Self::CommitMessage, Self::ProverState)> { + let (m1, s1) = self.first.compute_commit_message(csprng)?; + let (m2, s2) = self.second.compute_commit_message(csprng)?; + Some(((m1, m2), (s1, s2))) + } + fn get_challenge(&self, challenge: &Challenge) -> Self::ProtocolChallenge { ( self.first.get_challenge(challenge), @@ -114,37 +126,32 @@ impl SigmaProtocol for AndAdapter ) } - fn commit_point( - &self, - csprng: &mut R, - ) -> Option<(Self::CommitMessage, Self::ProverState)> { - let (m1, s1) = self.first.commit_point(csprng)?; - let (m2, s2) = self.second.commit_point(csprng)?; - Some(((m1, m2), (s1, s2))) - } - - fn generate_witness( + fn compute_response( &self, secret: Self::SecretData, state: Self::ProverState, challenge: &Self::ProtocolChallenge, - ) -> Option { - let w1 = self + ) -> Option { + let r1 = self .first - .generate_witness(secret.0, state.0, &challenge.0)?; - let w2 = self + .compute_response(secret.0, state.0, &challenge.0)?; + let r2 = self .second - .generate_witness(secret.1, state.1, &challenge.1)?; - Some(AndWitness { w1, w2 }) + .compute_response(secret.1, state.1, &challenge.1)?; + Some(AndResponse { r1, r2 }) } - fn extract_point( + fn extract_commit_message( &self, challenge: &Self::ProtocolChallenge, - witness: &Self::ProverWitness, + response: &Self::Response, ) -> Option { - let p1 = self.first.extract_point(&challenge.0, &witness.w1)?; - let p2 = self.second.extract_point(&challenge.1, &witness.w2)?; + let p1 = self + .first + .extract_commit_message(&challenge.0, &response.r1)?; + let p2 = self + .second + .extract_commit_message(&challenge.1, &response.r2)?; Some((p1, p2)) } @@ -178,9 +185,9 @@ impl AndAdapter { /// ## This section provides an and-like adapter, but where we combine /// multiple proofs of the same kind, only with different parameters. #[derive(Serialize)] -pub struct ReplicateWitness { +pub struct ReplicateResponse { #[size_length = 4] - pub witnesses: Vec, + pub responses: Vec, } /// An adapter to combine multiple provers or multiple verifiers. @@ -202,7 +209,7 @@ impl SigmaProtocol for ReplicateAdapter

{ // We assume that all protocols use the same challenge map. type ProtocolChallenge = P::ProtocolChallenge; type ProverState = Vec; - type ProverWitness = ReplicateWitness; + type Response = ReplicateResponse; type SecretData = Vec; fn public(&self, ro: &mut RandomOracle) { @@ -210,15 +217,7 @@ impl SigmaProtocol for ReplicateAdapter

{ self.protocols.iter().for_each(|p| p.public(ro)) } - fn get_challenge(&self, challenge: &Challenge) -> Self::ProtocolChallenge { - // FIXME: This relies on the replicate adapter precondition. - self.protocols - .first() - .expect("Protocols is non-empty.") - .get_challenge(challenge) - } - - fn commit_point( + fn compute_commit_message( &self, csprng: &mut R, ) -> Option<(Self::CommitMessage, Self::ProverState)> { @@ -226,19 +225,27 @@ impl SigmaProtocol for ReplicateAdapter

{ let mut ms = Vec::with_capacity(n); let mut ss = Vec::with_capacity(n); for p in self.protocols.iter() { - let (m, s) = p.commit_point(csprng)?; + let (m, s) = p.compute_commit_message(csprng)?; ms.push(m); ss.push(s); } Some((ReplicatePoints { points: ms }, ss)) } - fn generate_witness( + fn get_challenge(&self, challenge: &Challenge) -> Self::ProtocolChallenge { + // FIXME: This relies on the replicate adapter precondition. + self.protocols + .first() + .expect("Protocols is non-empty.") + .get_challenge(challenge) + } + + fn compute_response( &self, secret: Self::SecretData, state: Self::ProverState, challenge: &Self::ProtocolChallenge, - ) -> Option { + ) -> Option { let n = self.protocols.len(); if secret.len() != n { return None; @@ -246,25 +253,25 @@ impl SigmaProtocol for ReplicateAdapter

{ if state.len() != n { return None; } - let mut ws = Vec::with_capacity(n); + let mut rs: Vec<

::Response> = Vec::with_capacity(n); for (p, sec, state) in izip!(self.protocols.iter(), secret, state) { - ws.push(p.generate_witness(sec, state, challenge)?); + rs.push(p.compute_response(sec, state, challenge)?); } - Some(ReplicateWitness { witnesses: ws }) + Some(ReplicateResponse { responses: rs }) } - fn extract_point( + fn extract_commit_message( &self, challenge: &Self::ProtocolChallenge, - witness: &Self::ProverWitness, + response: &Self::Response, ) -> Option { let n = self.protocols.len(); - if witness.witnesses.len() != n { + if response.responses.len() != n { return None; } let mut points = Vec::with_capacity(n); - for (p, wit) in izip!(self.protocols.iter(), witness.witnesses.iter()) { - points.push(p.extract_point(challenge, wit)?); + for (p, res) in izip!(self.protocols.iter(), response.responses.iter()) { + points.push(p.extract_commit_message(challenge, res)?); } Some(ReplicatePoints { points }) } @@ -294,16 +301,18 @@ pub fn prove( prover: &D, secret: D::SecretData, csprng: &mut R, -) -> Option> { - let (point, state) = prover.commit_point(csprng)?; +) -> Option> { + let (commit_message, state) = prover.compute_commit_message(csprng)?; prover.public(ro); - ro.append_message("point", &point); + // For legacy reasons the label `point` is used when adding the commit message + // to the RO + ro.append_message("point", &commit_message); let challenge_bytes = ro.split().get_challenge(); let challenge = prover.get_challenge(&challenge_bytes); - let witness = prover.generate_witness(secret, state, &challenge)?; + let response = prover.compute_response(secret, state, &challenge)?; Some(SigmaProof { challenge: challenge_bytes, - witness, + response, }) } @@ -312,10 +321,10 @@ pub fn prove( pub fn verify( ro: &mut RandomOracle, verifier: &D, - proof: &SigmaProof, + proof: &SigmaProof, ) -> bool { let challenge = verifier.get_challenge(&proof.challenge); - match verifier.extract_point(&challenge, &proof.witness) { + match verifier.extract_commit_message(&challenge, &proof.response) { None => false, Some(ref point) => { verifier.public(ro); @@ -327,6 +336,7 @@ pub fn verify( } #[cfg(test)] +/// Generate a random challenge prefix of random length used for testing. pub fn generate_challenge_prefix(csprng: &mut R) -> Vec { // length of the challenge let l = csprng.gen_range(0, 1000); diff --git a/rust-src/concordium_base/src/id/sigma_protocols/dlog.rs b/rust-src/concordium_base/src/id/sigma_protocols/dlog.rs index 182dc9122..0ed2070f1 100644 --- a/rust-src/concordium_base/src/id/sigma_protocols/dlog.rs +++ b/rust-src/concordium_base/src/id/sigma_protocols/dlog.rs @@ -1,6 +1,7 @@ -//! This module provides the implementation of the discrete log sigma protocol -//! which enables one to prove knowledge of the discrete logarithm without -//! revealing it. +//! This module provides the implementation of the `dlog` sigma protocol +//! (cf. "Proof of Knowledge of Discrete Logarithm" Section 9.2.1, Bluepaper +//! v1.2.5) which enables one to prove knowledge of the discrete logarithm +//! without revealing it. use super::common::*; use crate::{ common::*, @@ -20,21 +21,21 @@ pub struct DlogSecret { pub secret: Value, } -/// Dlog witness. We deliberately make it opaque. +/// Response for Dlog proof. We deliberately make it opaque. /// We implement Copy to make the interface easier to use. #[derive(Debug, Serialize, Clone, Copy, Eq, PartialEq)] -pub struct Witness { - witness: C::Scalar, +pub struct Response { + response: C::Scalar, } /// Convenient alias for aggregate dlog proof -pub type Proof = SigmaProof>; +pub type Proof = SigmaProof>; impl SigmaProtocol for Dlog { type CommitMessage = C; type ProtocolChallenge = C::Scalar; type ProverState = C::Scalar; - type ProverWitness = Witness; + type Response = Response; type SecretData = DlogSecret; fn public(&self, ro: &mut RandomOracle) { @@ -42,41 +43,41 @@ impl SigmaProtocol for Dlog { ro.append_message("coeff", &self.coeff) } - fn get_challenge(&self, challenge: &Challenge) -> Self::ProtocolChallenge { - C::scalar_from_bytes(challenge) - } - - fn commit_point( + fn compute_commit_message( &self, csprng: &mut R, ) -> Option<(Self::CommitMessage, Self::ProverState)> { let rand_scalar = C::generate_non_zero_scalar(csprng); - let randomised_point = self.coeff.mul_by_scalar(&rand_scalar); - Some((randomised_point, rand_scalar)) + let commit_message = self.coeff.mul_by_scalar(&rand_scalar); + Some((commit_message, rand_scalar)) + } + + fn get_challenge(&self, challenge: &Challenge) -> Self::ProtocolChallenge { + C::scalar_from_bytes(challenge) } - fn generate_witness( + fn compute_response( &self, secret: Self::SecretData, state: Self::ProverState, challenge: &Self::ProtocolChallenge, - ) -> Option { + ) -> Option { // If the challenge is zero, the proof is not going to be valid unless alpha // (randomised point) is also zero. - let mut witness = *challenge; - witness.mul_assign(&secret.secret); - witness.add_assign(&state); - Some(Witness { witness }) + let mut response = *challenge; + response.mul_assign(&secret.secret); + response.add_assign(&state); + Some(Response { response }) } - fn extract_point( + fn extract_commit_message( &self, challenge: &Self::ProtocolChallenge, - witness: &Self::ProverWitness, + response: &Self::Response, ) -> Option { let randomised_point = self .coeff - .mul_by_scalar(&witness.witness) + .mul_by_scalar(&response.response) .minus_point(&self.public.mul_by_scalar(challenge)); Some(randomised_point) } @@ -138,9 +139,9 @@ mod tests { .get_challenge(), ..proof }; - let wrong_proof_witness = SigmaProof { - witness: Witness { - witness: G1::generate_scalar(csprng), + let wrong_proof_response = SigmaProof { + response: Response { + response: G1::generate_scalar(csprng), }, ..proof }; @@ -160,7 +161,7 @@ mod tests { assert!(!verify(&mut ro.split(), &dlog_wrong_base, &proof)); assert!(!verify(&mut ro.split(), &dlog_wrong_public, &proof)); assert!(!verify(&mut ro.split(), &dlog, &wrong_proof_challenge)); - assert!(!verify(&mut ro, &dlog, &wrong_proof_witness)); + assert!(!verify(&mut ro, &dlog, &wrong_proof_response)); }) } } diff --git a/rust-src/concordium_base/src/id/sigma_protocols/vcom_eq.rs b/rust-src/concordium_base/src/id/sigma_protocols/vcom_eq.rs index 2edc17156..2bf219327 100644 --- a/rust-src/concordium_base/src/id/sigma_protocols/vcom_eq.rs +++ b/rust-src/concordium_base/src/id/sigma_protocols/vcom_eq.rs @@ -1,7 +1,8 @@ -//! The module provides the implementation of the `vcom_eq` sigma -//! protocol. This protocol enables one to prove knowledge of -//! $x_1, ..., x_n, r, (r_i)_{i\in I}$ such that $ C = h^r \prod_{i=1}^n -//! g_i^{x_i}$ and $C_i = \bar{g}^{x_i} \bar{h}^{r_i}$ for $i\in I$. +//! The module provides the implementation of the `Vcom-com-eq` sigma +//! protocol (cf. "Proof of Equality for Vector Pedersen Commitment and Pedersen Commitments" Section 9.7.1, Bluepaper v1.2.5). This protocol enables one to +//! prove knowledge of $x_1, ..., x_n, r, (r_i)_{i\in I}$ such that $ C = h^r +//! \prod_{i=1}^n g_i^{x_i}$ and $C_i = \bar{g}^{x_i} \bar{h}^{r_i}$ for $i\in +//! I$. use super::common::*; use crate::{ common::*, @@ -36,9 +37,9 @@ pub struct VecComEq { pub h_bar: C, } -/// `VecComEq` witness. We deliberately make it opaque. +/// Response for `VecComEq` proof. We deliberately make it opaque. #[derive(Clone, Debug, Serialize)] -pub struct Witness { +pub struct Response { #[size_length = 2] sis: Vec, t: C::Scalar, @@ -47,13 +48,13 @@ pub struct Witness { } /// Convenient alias -pub type Proof = SigmaProof>; +pub type Proof = SigmaProof>; impl SigmaProtocol for VecComEq { type CommitMessage = (C, Vec); type ProtocolChallenge = C::Scalar; type ProverState = (Vec, C::Scalar, BTreeMap); - type ProverWitness = Witness; + type Response = Response; type SecretData = (Vec, Value, BTreeMap>); fn public(&self, ro: &mut RandomOracle) { @@ -65,11 +66,7 @@ impl SigmaProtocol for VecComEq { ro.append_message("g_bar", &self.g_bar) } - fn get_challenge(&self, challenge: &Challenge) -> Self::ProtocolChallenge { - C::scalar_from_bytes(challenge) - } - - fn commit_point( + fn compute_commit_message( &self, csprng: &mut R, ) -> Option<(Self::CommitMessage, Self::ProverState)> { @@ -98,12 +95,16 @@ impl SigmaProtocol for VecComEq { Some(((a, ais), (alphas, rtilde, rtildes))) } - fn generate_witness( + fn get_challenge(&self, challenge: &Challenge) -> Self::ProtocolChallenge { + C::scalar_from_bytes(challenge) + } + + fn compute_response( &self, secret: Self::SecretData, state: Self::ProverState, challenge: &Self::ProtocolChallenge, - ) -> Option { + ) -> Option { let (alphas, rtilde, rtildes) = state; let (xis, r, ris) = secret; let n = xis.len(); @@ -131,15 +132,15 @@ impl SigmaProtocol for VecComEq { t.mul_assign(&r); t.negate(); t.add_assign(&rtilde); - Some(Witness { sis, t, tis }) + Some(Response { sis, t, tis }) } - fn extract_point( + fn extract_commit_message( &self, challenge: &Self::ProtocolChallenge, - witness: &Self::ProverWitness, + response: &Self::Response, ) -> Option { - let Witness { sis, t, tis } = witness; + let Response { sis, t, tis } = response; if sis.is_empty() { return None; } diff --git a/rust-src/concordium_base/src/id/types.rs b/rust-src/concordium_base/src/id/types.rs index 733894277..6fabf6710 100644 --- a/rust-src/concordium_base/src/id/types.rs +++ b/rust-src/concordium_base/src/id/types.rs @@ -4,7 +4,7 @@ use super::{ secret_sharing::Threshold, sigma_protocols::{ com_enc_eq, com_eq, com_eq_different_groups, com_eq_sig, com_mult, - common::{ReplicateAdapter, ReplicateWitness}, + common::{ReplicateAdapter, ReplicateResponse}, dlog, }, }; @@ -643,12 +643,12 @@ pub struct IpArData { deserialize_with = "base16_decode" )] pub enc_prf_key_share: [Cipher; 8], - /// Witness to the proof that the computed commitment to the share + /// Response in the proof that the computed commitment to the share /// contains the same value as the encryption /// the commitment to the share is not sent but computed from /// the commitments to the sharing coefficients #[serde(rename = "proofComEncEq")] - pub proof_com_enc_eq: com_enc_eq::Witness, + pub proof_com_enc_eq: com_enc_eq::Response, } /// Data structure for when a anonymity revoker decrypts its encrypted share @@ -713,8 +713,8 @@ pub struct ChoiceArParameters { #[derive(Debug, Clone)] pub struct PreIdentityProof> { pub common_proof_fields: CommonPioProofFields, - /// Witness to the proof that reg_id = PRF(prf_key, 0) - pub prf_regid_proof: com_eq::Witness, + /// Response in the proof that reg_id = PRF(prf_key, 0) + pub prf_regid_proof: com_eq::Response, /// Signature on the public information for the IP from the account holder pub proof_acc_sk: AccountOwnershipProof, } @@ -722,7 +722,7 @@ pub struct PreIdentityProof> { impl> Serial for PreIdentityProof { fn serial(&self, out: &mut B) { out.put(&self.common_proof_fields.challenge); - out.put(&self.common_proof_fields.id_cred_sec_witness); + out.put(&self.common_proof_fields.id_cred_sec_response); out.put(&self.common_proof_fields.commitments_same_proof); out.put(&self.common_proof_fields.commitments_prf_same); out.put(&self.prf_regid_proof); @@ -734,15 +734,15 @@ impl> Serial for PreIdentityProof< impl> Deserial for PreIdentityProof { fn deserial(source: &mut R) -> ParseResult { let challenge: Challenge = source.get()?; - let id_cred_sec_witness: dlog::Witness = source.get()?; - let commitments_same_proof: com_eq::Witness = source.get()?; - let commitments_prf_same: com_eq_different_groups::Witness = source.get()?; - let prf_regid_proof: com_eq::Witness = source.get()?; + let id_cred_sec_response: dlog::Response = source.get()?; + let commitments_same_proof: com_eq::Response = source.get()?; + let commitments_prf_same: com_eq_different_groups::Response = source.get()?; + let prf_regid_proof: com_eq::Response = source.get()?; let proof_acc_sk: AccountOwnershipProof = source.get()?; let bulletproofs: Vec> = source.get()?; let common_proof_fields = CommonPioProofFields { challenge, - id_cred_sec_witness, + id_cred_sec_response, commitments_same_proof, commitments_prf_same, bulletproofs, @@ -762,15 +762,15 @@ pub struct CommonPioProofFields> { /// Challenge for the combined proof. This includes the three proofs below, /// and additionally also the proofs in IpArData. pub challenge: Challenge, - /// Witness to the proof of knowledge of IdCredSec. - pub id_cred_sec_witness: dlog::Witness, - /// Witness to the proof that cmm_sc and id_cred_pub + /// Response in the proof of knowledge of IdCredSec. + pub id_cred_sec_response: dlog::Response, + /// Response in the proof that cmm_sc and id_cred_pub /// are hiding the same id_cred_sec. - pub commitments_same_proof: com_eq::Witness, - /// Witness to the proof that cmm_prf and the + pub commitments_same_proof: com_eq::Response, + /// Response in the proof that cmm_prf and the /// second commitment to the prf key (hidden in cmm_prf_sharing_coeff) /// are hiding the same value. - pub commitments_prf_same: com_eq_different_groups::Witness, + pub commitments_prf_same: com_eq_different_groups::Response, /// Bulletproofs for showing that chunks are small so that encryption /// of the prf key can be decrypted pub bulletproofs: Vec>, @@ -780,7 +780,7 @@ pub struct CommonPioProofFields> { /// IdCredPub. pub type IdCredPubVerifiers = ( ReplicateAdapter>, - ReplicateWitness>, + ReplicateResponse>, ); /// Information sent from the account holder to the identity provider. @@ -1293,14 +1293,14 @@ pub struct IdOwnershipProofs> { deserialize_with = "base16_decode" )] pub challenge: Challenge, - /// Witnesses to the proof that the computed commitment to the share + /// Responses in the proof that the computed commitment to the share /// contains the same value as the encryption /// the commitment to the share is not sent but computed from /// the commitments to the sharing coefficients #[serde(rename = "proofIdCredPub")] #[map_size_length = 4] - pub proof_id_cred_pub: BTreeMap>, - /// Witnesses for proof of knowledge of signature of Identity Provider on + pub proof_id_cred_pub: BTreeMap>, + /// Responses in the proof of knowledge of signature of Identity Provider on /// the list /// ```(idCredSec, prfKey, attributes[0], attributes[1],..., attributes[n], /// AR[1], ..., AR[m])``` @@ -1309,7 +1309,7 @@ pub struct IdOwnershipProofs> { serialize_with = "base16_encode", deserialize_with = "base16_decode" )] - pub proof_ip_sig: com_eq_sig::Witness, + pub proof_ip_sig: com_eq_sig::Response, /// Proof that reg_id = prf_K(x). Also establishes that reg_id is computed /// from the prf key signed by the identity provider. #[serde( @@ -1317,7 +1317,7 @@ pub struct IdOwnershipProofs> { serialize_with = "base16_encode", deserialize_with = "base16_decode" )] - pub proof_reg_id: com_mult::Witness, + pub proof_reg_id: com_mult::Response, /// Proof that cred_counter is less than or equal to max_accounts #[serde( rename = "credCounterLessThanMaxAccounts", diff --git a/rust-src/concordium_base/src/id/utils.rs b/rust-src/concordium_base/src/id/utils.rs index d53dca856..1d7e0f6ba 100644 --- a/rust-src/concordium_base/src/id/utils.rs +++ b/rust-src/concordium_base/src/id/utils.rs @@ -239,7 +239,9 @@ pub fn verify_account_ownership_proof( // - all keys are distinct // - at least one key is provided // - there are the same number of proofs and keys - let Ok(num_proofs) = proof_acc_sk.num_proofs() else { return false }; + let Ok(num_proofs) = proof_acc_sk.num_proofs() else { + return false; + }; if num_proofs < threshold || keys.len() > 255 || keys.is_empty()