pub(crate) fn construct(
        params: &Parameters,
        pub_key: &elgamal::PublicKey,
        ephemeral_keys: &[elgamal::EphemeralKey],
        commitment: &G1Projective,
        blinding_factor: &Scalar,
        private_attributes: &[Attribute],
        public_attributes: &[Attribute],
    ) -> Self {
        // note: this is only called from `prepare_blind_sign` that already checks
        // whether private attributes are non-empty and whether we don't have too many
        // attributes in total to sign.
        // we also know, due to the single call place, that ephemeral_keys.len() == private_attributes.len()

        // witness creation

        let witness_blinder = params.random_scalar();
        let witness_keys = params.n_random_scalars(ephemeral_keys.len());
        let witness_attributes =
            params.n_random_scalars(private_attributes.len() + public_attributes.len());

        // make h
        let h = hash_g1(commitment.to_bytes());

        // witnesses commitments
        let g1 = params.gen1();
        let hs_bytes = params
            .gen_hs()
            .iter()
            .map(|h| h.to_bytes())
            .collect::<Vec<_>>();

        // TODO NAMING: Aw, Bw, Cw.... ?
        // Aw[i] = (wk[i] * g1)
        let commitment_keys1_bytes = witness_keys
            .iter()
            .map(|wk_i| g1 * wk_i)
            .map(|witness| witness.to_bytes())
            .collect::<Vec<_>>();

        // Bw[i] = (wm[i] * h) + (wk[i] * gamma)
        let commitment_keys2_bytes = witness_keys
            .iter()
            .zip(witness_attributes.iter())
            .map(|(wk_i, wm_i)| pub_key * wk_i + h * wm_i)
            .map(|witness| witness.to_bytes())
            .collect::<Vec<_>>();

        // Cw = (wr * g1) + (wm[0] * hs[0]) + ... + (wm[i] * hs[i])
        let commitment_attributes = g1 * witness_blinder
            + witness_attributes
                .iter()
                .zip(params.gen_hs().iter())
                .map(|(wm_i, hs_i)| hs_i * wm_i)
                .sum::<G1Projective>();

        // challenge ([g1, g2, cm, h, Cw]+hs+Aw+Bw)
        let challenge = compute_challenge::<ChallengeDigest, _, _>(
            std::iter::once(params.gen1().to_bytes().as_ref())
                .chain(std::iter::once(params.gen2().to_bytes().as_ref()))
                .chain(std::iter::once(commitment.to_bytes().as_ref()))
                .chain(std::iter::once(h.to_bytes().as_ref()))
                .chain(std::iter::once(commitment_attributes.to_bytes().as_ref()))
                .chain(hs_bytes.iter().map(|hs| hs.as_ref()))
                .chain(commitment_keys1_bytes.iter().map(|aw| aw.as_ref()))
                .chain(commitment_keys2_bytes.iter().map(|bw| bw.as_ref())),
        );

        // responses
        let response_blinder = produce_response(&witness_blinder, &challenge, &blinding_factor);

        // TODO: maybe make `produce_responses` take an iterator instead?
        let response_keys = produce_responses(&witness_keys, &challenge, ephemeral_keys);
        let response_attributes = produce_responses(
            &witness_attributes,
            &challenge,
            &private_attributes
                .iter()
                .chain(public_attributes.iter())
                .collect::<Vec<_>>(),
        );

        ProofCmCs {
            challenge,
            response_random: response_blinder,
            response_keys,
            response_attributes,
        }
    }
/// Construct non-interactive zero-knowledge proof of correctness of the ciphertexts and the commitment.
Construct non-interactive zero-knowledge proof of correctness of the ciphertexts and the commitment.
Construct non - interactive zero - knowledge proof of correctness of the ciphertexts and the commitment .
pub(crate) fn construct(
        params: &Parameters,
        pub_key: &elgamal::PublicKey,
        ephemeral_keys: &[elgamal::EphemeralKey],
        commitment: &G1Projective,
        blinding_factor: &Scalar,
        private_attributes: &[Attribute],
        public_attributes: &[Attribute],
    ) -> Self {
        // note: this is only called from `prepare_blind_sign` that already checks
        // whether private attributes are non-empty and whether we don't have too many
        // attributes in total to sign.
        // we also know, due to the single call place, that ephemeral_keys.len() == private_attributes.len()
        // witness creation
        let witness_blinder = params.random_scalar();
        let witness_keys = params.n_random_scalars(ephemeral_keys.len());
        let witness_attributes =
            params.n_random_scalars(private_attributes.len() + public_attributes.len());
        // make h
        let h = hash_g1(commitment.to_bytes());
        // witnesses commitments
        let g1 = params.gen1();
        let hs_bytes = params
            .gen_hs()
            .iter()
            .map(|h| h.to_bytes())
            .collect::<Vec<_>>();
        // TODO NAMING: Aw, Bw, Cw.... ?
        // Aw[i] = (wk[i] * g1)
        let commitment_keys1_bytes = witness_keys
            .iter()
            .map(|wk_i| g1 * wk_i)
            .map(|witness| witness.to_bytes())
            .collect::<Vec<_>>();
        // Bw[i] = (wm[i] * h) + (wk[i] * gamma)
        let commitment_keys2_bytes = witness_keys
            .iter()
            .zip(witness_attributes.iter())
            .map(|(wk_i, wm_i)| pub_key * wk_i + h * wm_i)
            .map(|witness| witness.to_bytes())
            .collect::<Vec<_>>();
        // Cw = (wr * g1) + (wm[0] * hs[0]) + ... + (wm[i] * hs[i])
        let commitment_attributes = g1 * witness_blinder
            + witness_attributes
                .iter()
                .zip(params.gen_hs().iter())
                .map(|(wm_i, hs_i)| hs_i * wm_i)
                .sum::<G1Projective>();
        // challenge ([g1, g2, cm, h, Cw]+hs+Aw+Bw)
        let challenge = compute_challenge::<ChallengeDigest, _, _>(
            std::iter::once(params.gen1().to_bytes().as_ref())
                .chain(std::iter::once(params.gen2().to_bytes().as_ref()))
                .chain(std::iter::once(commitment.to_bytes().as_ref()))
                .chain(std::iter::once(h.to_bytes().as_ref()))
                .chain(std::iter::once(commitment_attributes.to_bytes().as_ref()))
                .chain(hs_bytes.iter().map(|hs| hs.as_ref()))
                .chain(commitment_keys1_bytes.iter().map(|aw| aw.as_ref()))
                .chain(commitment_keys2_bytes.iter().map(|bw| bw.as_ref())),
        );
        // responses
        let response_blinder = produce_response(&witness_blinder, &challenge, &blinding_factor);
        // TODO: maybe make `produce_responses` take an iterator instead?
        let response_keys = produce_responses(&witness_keys, &challenge, ephemeral_keys);
        let response_attributes = produce_responses(
            &witness_attributes,
            &challenge,
            &private_attributes
                .iter()
                .chain(public_attributes.iter())
                .collect::<Vec<_>>(),
        );
        ProofCmCs {
            challenge,
            response_random: response_blinder,
            response_keys,
            response_attributes,
        }
    }
pub ( crate ) fn construct ( params : & Parameters , pub_key : & elgamal :: PublicKey , ephemeral_keys : & [ elgamal :: EphemeralKey ] , commitment : & G1Projective , blinding_factor : & Scalar , private_attributes : & [ Attribute ] , public_attributes : & [ Attribute ] , ) -> Self { // note: this is only called from `prepare_blind_sign` that already checks // whether private attributes are non-empty and whether we don't have too many // attributes in total to sign. // we also know, due to the single call place, that ephemeral_keys.len() == private_attributes.len() // witness creation let witness_blinder = params . random_scalar ( ) ; let witness_keys = params . n_random_scalars ( ephemeral_keys . len ( ) ) ; let witness_attributes = params . n_random_scalars ( private_attributes . len ( ) + public_attributes . len ( ) ) ; // make h let h = hash_g1 ( commitment . to_bytes ( ) ) ; // witnesses commitments let g1 = params . gen1 ( ) ; let hs_bytes = params . gen_hs ( ) . iter ( ) . map ( | h | h . to_bytes ( ) ) . collect :: < Vec < _ > > ( ) ; // TODO NAMING: Aw, Bw, Cw.... ? // Aw[i] = (wk[i] * g1) let commitment_keys1_bytes = witness_keys . iter ( ) . map ( | wk_i | g1 * wk_i ) . map ( | witness | witness . to_bytes ( ) ) . collect :: < Vec < _ > > ( ) ; // Bw[i] = (wm[i] * h) + (wk[i] * gamma) let commitment_keys2_bytes = witness_keys . iter ( ) . zip ( witness_attributes . iter ( ) ) . map ( | ( wk_i , wm_i ) | pub_key * wk_i + h * wm_i ) . map ( | witness | witness . to_bytes ( ) ) . collect :: < Vec < _ > > ( ) ; // Cw = (wr * g1) + (wm[0] * hs[0]) + ... + (wm[i] * hs[i]) let commitment_attributes = g1 * witness_blinder + witness_attributes . iter ( ) . zip ( params . gen_hs ( ) . iter ( ) ) . map ( | ( wm_i , hs_i ) | hs_i * wm_i ) . sum :: < G1Projective > ( ) ; // challenge ([g1, g2, cm, h, Cw]+hs+Aw+Bw) let challenge = compute_challenge :: < ChallengeDigest , _ , _ > ( std :: iter :: once ( params . gen1 ( ) . to_bytes ( ) . as_ref ( ) ) . chain ( std :: iter :: once ( params . gen2 ( ) . to_bytes ( ) . as_ref ( ) ) ) . chain ( std :: iter :: once ( commitment . to_bytes ( ) . as_ref ( ) ) ) . chain ( std :: iter :: once ( h . to_bytes ( ) . as_ref ( ) ) ) . chain ( std :: iter :: once ( commitment_attributes . to_bytes ( ) . as_ref ( ) ) ) . chain ( hs_bytes . iter ( ) . map ( | hs | hs . as_ref ( ) ) ) . chain ( commitment_keys1_bytes . iter ( ) . map ( | aw | aw . as_ref ( ) ) ) . chain ( commitment_keys2_bytes . iter ( ) . map ( | bw | bw . as_ref ( ) ) ) , ) ; // responses let response_blinder = produce_response ( & witness_blinder , & challenge , & blinding_factor ) ; // TODO: maybe make `produce_responses` take an iterator instead? let response_keys = produce_responses ( & witness_keys , & challenge , ephemeral_keys ) ; let response_attributes = produce_responses ( & witness_attributes , & challenge , & private_attributes . iter ( ) . chain ( public_attributes . iter ( ) ) . collect :: < Vec < _ > > ( ) , ) ; ProofCmCs { challenge , response_random : response_blinder , response_keys , response_attributes , } }
Construct non-interactive zero-knowledge proof of correctness of the ciphertexts and the commitment.
Construct non - interactive zero - knowledge proof of correctness of the ciphertexts and the commitment .
params
&Parameters
pub_key
&elgamal::PublicKey
ephemeral_keys
&[elgamal::EphemeralKey]
commitment
&G1Projective
blinding_factor
&Scalar
private_attributes
&[Attribute]
public_attributes
&[Attribute]