VYPR
Moderate severityNVD Advisory· Published Jan 16, 2024· Updated Jun 16, 2025

Ursa CL-Signatures Revocation allows verifiers to generate unique identifiers for holders

CVE-2024-22192

Description

Ursa is a cryptographic library for use with blockchains. The revocation scheme that is part of the Ursa CL-Signatures implementations has a flaw that could impact the privacy guarantees defined by the AnonCreds verifiable credential model. Notably, a malicious verifier may be able to generate a unique identifier for a holder providing a verifiable presentation that includes a Non-Revocation proof. The impact of the flaw is that a malicious verifier may be able to determine a unique identifier for a holder presenting a Non-Revocation proof. Ursa has moved to end-of-life status and no fix is expected.

Affected packages

Versions sourced from the GitHub Security Advisory.

PackageAffected versionsPatched versions
ursacrates.io
<= 0.3.7
anoncreds-clsignaturescrates.io
< 0.1.00.1.0

Affected products

1

Patches

1
1e55780c890b

remove separate m2^ value from non-revocation proof

7 files changed · +249 68
  • src/amcl.rs+14 13 modified
    @@ -22,6 +22,7 @@ use rand::prelude::*;
     #[cfg(test)]
     use std::cell::RefCell;
     
    +use crate::bn::BigNumber;
     use crate::error::Result as ClResult;
     
     const ORDER: BIG = BIG { w: CURVE_ORDER };
    @@ -396,6 +397,13 @@ impl GroupOrderElement {
             Ok(GroupOrderElement { bn: BIG::new() })
         }
     
    +    pub fn order() -> ClResult<BigNumber> {
    +        let mut buf = [0u8; Self::BYTES_REPR_SIZE];
    +        let mut order = BIG::new_ints(&CURVE_ORDER);
    +        order.tobytes(&mut buf);
    +        BigNumber::from_bytes(&buf)
    +    }
    +
         pub fn is_zero(&self) -> bool {
             self.bn.iszilch()
         }
    @@ -486,19 +494,12 @@ impl GroupOrderElement {
             if b.len() > Self::BYTES_REPR_SIZE {
                 return Err(err_msg!("Invalid byte length for GroupOrderElement"));
             }
    -        let mut vec = b.to_vec();
    -        let len = vec.len();
    -        if len < MODBYTES {
    -            let diff = MODBYTES - len;
    -            let mut result = vec![0; diff];
    -            result.append(&mut vec);
    -            return Ok(GroupOrderElement {
    -                bn: BIG::frombytes(&result),
    -            });
    -        }
    -        Ok(GroupOrderElement {
    -            bn: BIG::frombytes(b),
    -        })
    +        let mut buf = [0u8; Self::BYTES_REPR_SIZE];
    +        buf[(Self::BYTES_REPR_SIZE - b.len())..].copy_from_slice(&b);
    +        let mut bn = BIG::frombytes(&buf);
    +        bn.rmod(&BIG::new_ints(&CURVE_ORDER));
    +        bn.norm();
    +        Ok(GroupOrderElement { bn })
         }
     }
     
    
  • src/constants.rs+1 0 modified
    @@ -11,6 +11,7 @@ pub const LARGE_ETILDE: usize = 456;
     pub const LARGE_VTILDE: usize = 3060;
     pub const LARGE_UTILDE: usize = 592;
     pub const LARGE_MTILDE: usize = 593;
    +pub const LARGE_M2TILDE: usize = 2432;
     pub const LARGE_VPRIME_TILDE: usize = 673;
     pub const LARGE_RTILDE: usize = 672;
     pub const ITERATION: usize = 4;
    
  • src/helpers.rs+15 5 modified
    @@ -319,11 +319,11 @@ pub fn calc_teq<S: ::std::hash::BuildHasher>(
         e: &BigNumber,
         v: &BigNumber,
         m_tilde: &HashMap<String, BigNumber, S>,
    -    m2tilde: &BigNumber,
    +    m2_tilde: &BigNumber,
         unrevealed_attrs: &HashSet<String, S>,
     ) -> ClResult<BigNumber> {
    -    trace!("Helpers::calc_teq: >>> p_pub_key: {:?}, p_pub_key: {:?}, e: {:?}, v: {:?}, m_tilde: {:?}, m2tilde: {:?}, \
    -    unrevealed_attrs: {:?}", p_pub_key, a_prime, e, v, m_tilde, m2tilde, unrevealed_attrs);
    +    trace!("Helpers::calc_teq: >>> p_pub_key: {:?}, p_pub_key: {:?}, e: {:?}, v: {:?}, m_tilde: {:?}, m2_tilde: {:?}, \
    +    unrevealed_attrs: {:?}", p_pub_key, a_prime, e, v, m_tilde, m2_tilde, unrevealed_attrs);
     
         let mut ctx = BigNumber::new_context()?;
         // a_prime^e % p_pub_key.n
    @@ -351,7 +351,7 @@ pub fn calc_teq<S: ::std::hash::BuildHasher>(
     
         result = p_pub_key
             .rctxt
    -        .mod_exp(m2tilde, &p_pub_key.n, Some(&mut ctx))?
    +        .mod_exp(m2_tilde, &p_pub_key.n, Some(&mut ctx))?
             .mod_mul(&result, &p_pub_key.n, Some(&mut ctx))?;
     
         trace!("Helpers::calc_teq: <<< t: {:?}", result);
    @@ -524,6 +524,15 @@ pub fn bignum_to_group_element(num: &BigNumber) -> ClResult<GroupOrderElement> {
         GroupOrderElement::from_bytes(&num.to_bytes()?)
     }
     
    +#[inline(always)]
    +pub fn bignum_to_group_element_reduce(
    +    num: &BigNumber,
    +    ctx: Option<&mut BigNumberContext>,
    +) -> ClResult<GroupOrderElement> {
    +    let reduced = num.modulus(&GroupOrderElement::order()?, ctx)?;
    +    GroupOrderElement::from_bytes(&reduced.to_bytes()?)
    +}
    +
     pub fn create_tau_list_expected_values(
         r_pub_key: &CredentialRevocationPublicKey,
         rev_reg: &RevocationRegistry,
    @@ -577,6 +586,7 @@ pub fn create_tau_list_values(
         rev_reg: &RevocationRegistry,
         params: &NonRevocProofXList,
         proof_c: &NonRevocProofCList,
    +    m2: &GroupOrderElement,
     ) -> ClResult<NonRevocProofTauList> {
         trace!("Helpers::create_tau_list_values: >>> r_pub_key: {:?}, rev_reg: {:?}, params: {:?}, proof_c: {:?}",
                r_pub_key, rev_reg, params, proof_c);
    @@ -598,7 +608,7 @@ pub fn create_tau_list_values(
                 .a
                 .mul(&params.c)?
                 .add(&r_pub_key.htilde.mul(&params.r.sub_mod(&params.m)?)?)?
    -            .sub(&r_pub_key.h1.mul(&params.m2)?)?
    +            .sub(&r_pub_key.h1.mul(&m2)?)?
                 .sub(&r_pub_key.h2.mul(&params.s)?)?,
             &r_pub_key.h_cap,
             &r_pub_key.htilde.mul(&params.rho)?.neg()?,
    
  • src/issuer.rs+1 1 modified
    @@ -1345,7 +1345,7 @@ impl Issuer {
     
             let vr_prime_prime = GroupOrderElement::new()?;
             let c = GroupOrderElement::new()?;
    -        let m2 = GroupOrderElement::from_bytes(&cred_context.to_bytes()?)?;
    +        let m2 = bignum_to_group_element_reduce(&cred_context, None)?;
     
             let gamma_i = Tail::index_pow(rev_idx, &rev_key_priv.gamma)?;
             let g_i = r_pub_key.g.mul(&gamma_i)?;
    
  • src/prover.rs+200 36 modified
    @@ -933,20 +933,19 @@ impl ProofBuilder {
             )?;
     
             let mut non_revoc_init_proof = None;
    -        let mut m2_tilde: Option<BigNumber> = None;
    +        let m2_tilde: BigNumber = bn_rand(LARGE_M2TILDE)?;
     
             if let (&Some(ref r_cred), &Some(r_reg), &Some(ref r_pub_key), &Some(witness)) = (
                 &credential_signature.r_credential,
                 &rev_reg,
                 &credential_pub_key.r_key,
                 &witness,
             ) {
    -            let proof =
    -                ProofBuilder::_init_non_revocation_proof(r_cred, r_reg, r_pub_key, witness)?;
    -
    +            let proof = ProofBuilder::_init_non_revocation_proof(
    +                r_cred, r_reg, r_pub_key, witness, &m2_tilde,
    +            )?;
                 self.c_list.extend_from_slice(&proof.as_c_list()?);
                 self.tau_list.extend_from_slice(&proof.as_tau_list()?);
    -            m2_tilde = Some(group_element_to_bignum(&proof.tau_list_params.m2)?);
                 non_revoc_init_proof = Some(proof);
             }
     
    @@ -958,7 +957,7 @@ impl ProofBuilder {
                 credential_schema,
                 non_credential_schema,
                 sub_proof_request,
    -            m2_tilde,
    +            &m2_tilde,
             )?;
     
             self.c_list
    @@ -1179,7 +1178,7 @@ impl ProofBuilder {
             cred_schema: &CredentialSchema,
             non_cred_schema_elems: &NonCredentialSchema,
             sub_proof_request: &SubProofRequest,
    -        m2_t: Option<BigNumber>,
    +        m2_tilde: &BigNumber,
         ) -> ClResult<PrimaryInitProof> {
             trace!(
                 "ProofBuilder::_init_primary_proof: >>> common_attributes: {:?}, \
    @@ -1189,15 +1188,15 @@ impl ProofBuilder {
                  cred_schema: {:?}, \
                  non_cred_schema_elems: {:?}, \
                  sub_proof_request: {:?}, \
    -             m2_t: {:?}",
    +             m2_tilde: {:?}",
                 common_attributes,
                 issuer_pub_key,
                 c1,
                 cred_values,
                 cred_schema,
                 non_cred_schema_elems,
                 sub_proof_request,
    -            m2_t
    +            m2_tilde,
             );
     
             let eq_proof = ProofBuilder::_init_eq_proof(
    @@ -1207,7 +1206,7 @@ impl ProofBuilder {
                 cred_schema,
                 non_cred_schema_elems,
                 sub_proof_request,
    -            m2_t,
    +            m2_tilde,
             )?;
     
             let mut ne_proofs: Vec<PrimaryPredicateInequalityInitProof> = Vec::new();
    @@ -1239,17 +1238,19 @@ impl ProofBuilder {
             rev_reg: &RevocationRegistry,
             cred_rev_pub_key: &CredentialRevocationPublicKey,
             witness: &Witness,
    +        m2_tilde: &BigNumber,
         ) -> ClResult<NonRevocInitProof> {
    -        trace!("ProofBuilder::_init_non_revocation_proof: >>> r_cred: {:?}, rev_reg: {:?}, cred_rev_pub_key: {:?}, witness: {:?}",
    -               r_cred, rev_reg, cred_rev_pub_key, witness);
    +        trace!("ProofBuilder::_init_non_revocation_proof: >>> r_cred: {:?}, rev_reg: {:?}, cred_rev_pub_key: {:?}, witness: {:?}, m2_tilde: {:?}",
    +               r_cred, rev_reg, cred_rev_pub_key, witness, m2_tilde);
     
             let c_list_params = ProofBuilder::_gen_c_list_params(r_cred)?;
             let c_list =
                 ProofBuilder::_create_c_list_values(r_cred, &c_list_params, cred_rev_pub_key, witness)?;
     
             let tau_list_params = ProofBuilder::_gen_tau_list_params()?;
    +        let m2 = bignum_to_group_element_reduce(&m2_tilde, None)?;
             let tau_list =
    -            create_tau_list_values(cred_rev_pub_key, rev_reg, &tau_list_params, &c_list)?;
    +            create_tau_list_values(cred_rev_pub_key, rev_reg, &tau_list_params, &c_list, &m2)?;
     
             let r_init_proof = NonRevocInitProof {
                 c_list_params,
    @@ -1273,7 +1274,7 @@ impl ProofBuilder {
             cred_schema: &CredentialSchema,
             non_cred_schema_elems: &NonCredentialSchema,
             sub_proof_request: &SubProofRequest,
    -        m2_t: Option<BigNumber>,
    +        m2_tilde: &BigNumber,
         ) -> ClResult<PrimaryEqualInitProof> {
             trace!(
                 "ProofBuilder::_init_eq_proof: >>> cred_pub_key: {:?}, \
    @@ -1287,13 +1288,11 @@ impl ProofBuilder {
                 cred_schema,
                 non_cred_schema_elems,
                 sub_proof_request,
    -            m2_t
    +            m2_tilde,
             );
     
             let mut ctx = BigNumber::new_context()?;
     
    -        let m2_tilde = m2_t.unwrap_or(bn_rand(LARGE_MVECT)?);
    -
             let r = bn_rand(LARGE_VPRIME)?;
             let e_tilde = bn_rand(LARGE_ETILDE)?;
             let v_tilde = bn_rand(LARGE_VTILDE)?;
    @@ -1527,7 +1526,7 @@ impl ProofBuilder {
                 m_hat.insert(k.clone(), val);
             }
     
    -        let m2 = challenge
    +        let m2_hat = challenge
                 .mul(&init_proof.m2, Some(&mut ctx))?
                 .add(&init_proof.m2_tilde)?;
     
    @@ -1551,7 +1550,7 @@ impl ProofBuilder {
                 e,
                 v,
                 m: m_hat,
    -            m2,
    +            m2: m2_hat,
             };
     
             trace!(
    @@ -1686,7 +1685,6 @@ impl ProofBuilder {
             let m_prime = r.mul_mod(&r_prime_prime)?;
             let t = o.mul_mod(&r_cred.c)?;
             let t_prime = o_prime.mul_mod(&r_prime_prime)?;
    -        let m2 = GroupOrderElement::from_bytes(&r_cred.m2.to_bytes()?)?;
     
             let non_revoc_proof_x_list = NonRevocProofXList {
                 rho,
    @@ -1700,7 +1698,6 @@ impl ProofBuilder {
                 m_prime,
                 t,
                 t_prime,
    -            m2,
                 s: r_cred.vr_prime_prime,
                 c: r_cred.c,
             };
    @@ -1784,13 +1781,12 @@ impl ProofBuilder {
                 m_prime: GroupOrderElement::new()?,
                 t: GroupOrderElement::new()?,
                 t_prime: GroupOrderElement::new()?,
    -            m2: GroupOrderElement::new()?,
                 s: GroupOrderElement::new()?,
                 c: GroupOrderElement::new()?,
             };
     
             trace!(
    -            "ProofBuilder::_gen_tau_list_params: <<< Nnon_revoc_proof_x_list: {:?}",
    +            "ProofBuilder::_gen_tau_list_params: <<< non_revoc_proof_x_list: {:?}",
                 non_revoc_proof_x_list
             );
     
    @@ -1816,7 +1812,7 @@ impl ProofBuilder {
                 .iter()
                 .zip(init_proof.c_list_params.as_list()?.iter())
             {
    -            x_list.push(x.add_mod(&ch_num_z.mul_mod(y)?.mod_neg()?)?);
    +            x_list.push(x.add_mod(&ch_num_z.mul_mod(y)?)?);
             }
     
             let non_revoc_proof = NonRevocProof {
    @@ -2017,9 +2013,7 @@ mod tests {
             let non_cred_schema_elems = issuer::mocks::non_credential_schema();
             let credential = mocks::primary_credential();
             let sub_proof_request = mocks::sub_proof_request();
    -        let m2_tilde =
    -            group_element_to_bignum(&mocks::init_non_revocation_proof().tau_list_params.m2)
    -                .unwrap();
    +        let m2_tilde = mocks::primary_init_proof_m2tilde();
     
             let init_eq_proof = ProofBuilder::_init_eq_proof(
                 &common_attributes,
    @@ -2028,7 +2022,7 @@ mod tests {
                 &cred_schema,
                 &non_cred_schema_elems,
                 &sub_proof_request,
    -            Some(m2_tilde),
    +            &m2_tilde,
             )
             .unwrap();
     
    @@ -2066,9 +2060,7 @@ mod tests {
             let credential_values = issuer::mocks::credential_values();
             let sub_proof_request = mocks::sub_proof_request();
             let common_attributes = mocks::proof_common_attributes();
    -        let m2_tilde =
    -            group_element_to_bignum(&mocks::init_non_revocation_proof().tau_list_params.m2)
    -                .unwrap();
    +        let m2_tilde = mocks::primary_init_proof_m2tilde();
     
             let init_proof = ProofBuilder::_init_primary_proof(
                 &common_attributes,
    @@ -2078,7 +2070,7 @@ mod tests {
                 &credential_schema,
                 &non_credential_schema,
                 &sub_proof_request,
    -            Some(m2_tilde),
    +            &m2_tilde,
             )
             .unwrap();
             assert_eq!(mocks::primary_init_proof(), init_proof);
    @@ -2293,6 +2285,174 @@ mod tests {
             println!("Update Proof test -> end");
         }
     
    +    #[cfg(feature = "openssl_bn")]
    +    #[test]
    +    fn test_non_revocation_linking() {
    +        use crate::Verifier;
    +
    +        let max_cred_num = 100;
    +        let issuance_by_default = true;
    +
    +        let cred_schema = issuer::mocks::credential_schema();
    +        let non_cred_schema = issuer::mocks::non_credential_schema();
    +        let (cred_pub_key, cred_priv_key, cred_key_correctness_proof) =
    +            issuer::Issuer::new_credential_def(&cred_schema, &non_cred_schema, true)
    +                .expect("Error creating credential definition");
    +
    +        let (rev_key_pub, rev_key_priv, mut rev_reg, _rev_tails_generator) =
    +            issuer::Issuer::new_revocation_registry_def(
    +                &cred_pub_key,
    +                max_cred_num,
    +                issuance_by_default,
    +            )
    +            .expect("Error creating revocation registry");
    +
    +        let cred_values = issuer::mocks::credential_values();
    +        let credential_nonce = new_nonce().unwrap();
    +
    +        let (
    +            blinded_credential_secrets,
    +            credential_secrets_blinding_factors,
    +            blinded_credential_secrets_correctness_proof,
    +        ) = Prover::blind_credential_secrets(
    +            &cred_pub_key,
    +            &cred_key_correctness_proof,
    +            &cred_values,
    +            &credential_nonce,
    +        )
    +        .expect("Error creating linked secret commitment");
    +
    +        let cred_issuance_nonce = new_nonce().unwrap();
    +
    +        #[derive(Debug)]
    +        struct Cred {
    +            signature: CredentialSignature,
    +            witness: Witness,
    +        }
    +        impl Clone for Cred {
    +            fn clone(&self) -> Self {
    +                Cred {
    +                    signature: self.signature.try_clone().unwrap(),
    +                    witness: self.witness.clone(),
    +                }
    +            }
    +        }
    +
    +        let mut creds = Vec::new();
    +        let prover_ids = ["prover-id-1", "prover-id-2"];
    +        let mut rev_idx = 0;
    +
    +        for prover_id in prover_ids.iter() {
    +            rev_idx += 1;
    +            let (mut signature, signature_proof, witness, _) =
    +                issuer::Issuer::sign_credential_with_revoc(
    +                    prover_id,
    +                    &blinded_credential_secrets,
    +                    &blinded_credential_secrets_correctness_proof,
    +                    &credential_nonce,
    +                    &cred_issuance_nonce,
    +                    &cred_values,
    +                    &cred_pub_key,
    +                    &cred_priv_key,
    +                    rev_idx,
    +                    max_cred_num,
    +                    issuance_by_default,
    +                    &mut rev_reg,
    +                    &rev_key_priv,
    +                )
    +                .expect("Error signing revocable credential");
    +
    +            Prover::process_credential_signature(
    +                &mut signature,
    +                &cred_values,
    +                &signature_proof,
    +                &credential_secrets_blinding_factors,
    +                &cred_pub_key,
    +                &cred_issuance_nonce,
    +                Some(&rev_key_pub),
    +                Some(&rev_reg),
    +                Some(&witness),
    +            )
    +            .expect("Error processing credential signature");
    +
    +            creds.push(Cred { signature, witness });
    +        }
    +
    +        // Check issued credentials
    +
    +        let sub_proof_request = mocks::sub_proof_request();
    +
    +        for cred in creds.iter() {
    +            let mut proof_builder = Prover::new_proof_builder().unwrap();
    +            proof_builder.add_common_attribute("master_secret").unwrap();
    +            proof_builder
    +                .add_sub_proof_request(
    +                    &sub_proof_request,
    +                    &cred_schema,
    +                    &non_cred_schema,
    +                    &cred.signature,
    +                    &cred_values,
    +                    &cred_pub_key,
    +                    Some(&rev_reg),
    +                    Some(&cred.witness),
    +                )
    +                .unwrap();
    +            let proof_request_nonce = new_nonce().unwrap();
    +            let proof = proof_builder.finalize(&proof_request_nonce).unwrap();
    +
    +            let mut proof_verifier = Verifier::new_proof_verifier().unwrap();
    +            proof_verifier
    +                .add_sub_proof_request(
    +                    &sub_proof_request,
    +                    &cred_schema,
    +                    &non_cred_schema,
    +                    &cred_pub_key,
    +                    Some(&rev_key_pub),
    +                    Some(&rev_reg),
    +                )
    +                .unwrap();
    +
    +            assert!(proof_verifier.verify(&proof, &proof_request_nonce).unwrap());
    +        }
    +
    +        // Swap non-revocation credential
    +
    +        let mut cred = creds[0].clone();
    +        cred.signature.r_credential = creds[1].signature.r_credential.clone();
    +        cred.witness = creds[1].witness.clone();
    +
    +        let mut proof_builder = Prover::new_proof_builder().unwrap();
    +        proof_builder.add_common_attribute("master_secret").unwrap();
    +        proof_builder
    +            .add_sub_proof_request(
    +                &sub_proof_request,
    +                &cred_schema,
    +                &non_cred_schema,
    +                &cred.signature,
    +                &cred_values,
    +                &cred_pub_key,
    +                Some(&rev_reg),
    +                Some(&cred.witness),
    +            )
    +            .unwrap();
    +        let proof_request_nonce = new_nonce().unwrap();
    +        let proof = proof_builder.finalize(&proof_request_nonce).unwrap();
    +
    +        let mut proof_verifier = Verifier::new_proof_verifier().unwrap();
    +        proof_verifier
    +            .add_sub_proof_request(
    +                &sub_proof_request,
    +                &cred_schema,
    +                &non_cred_schema,
    +                &cred_pub_key,
    +                Some(&rev_key_pub),
    +                Some(&rev_reg),
    +            )
    +            .unwrap();
    +
    +        assert!(!proof_verifier.verify(&proof, &proof_request_nonce).unwrap());
    +    }
    +
         #[test]
         #[ignore]
         fn generate_proof_mocks() {
    @@ -2456,6 +2616,13 @@ pub mod mocks {
             }
         }
     
    +    pub fn primary_init_proof_m2tilde() -> BigNumber {
    +        BigNumber::from_dec(
    +            "14049198043322723487718055550558829839278677959655715165983472882418452212100",
    +        )
    +        .unwrap()
    +    }
    +
         pub fn primary_init_proof() -> PrimaryInitProof {
             PrimaryInitProof {
                 eq_proof: primary_equal_init_proof(),
    @@ -2477,7 +2644,7 @@ pub mod mocks {
                     "master_secret".to_string() => BigNumber::from_dec("67940925789970108743024738273926421512152745397724199848594503731042154269417576665420030681245389493783225644817826683796657351721363490290016166310023506339911751676800452438014771736117676826911321621579680668201191205819012441197794443970687648330757835198888257781967404396196813475280544039772512800509").unwrap(),
                     "sex".to_string() => BigNumber::from_dec("6461691768834933403326572830814516653957231030793837560544354737855803497655300429843454445497126567767486684087006218691084619904526729989680526652503377438786587511370042964338").unwrap()
                 ],
    -            m2_tilde: BigNumber::from_dec("14049198043322723487718055550558829839278677959655715165983472882418452212100").unwrap(),
    +            m2_tilde: primary_init_proof_m2tilde(),
                 m2: BigNumber::from_dec("69500003785041890145270364348670634122591474903142468939711692725859480163330").unwrap(),
             }
         }
    @@ -2814,7 +2981,6 @@ pub mod mocks {
                     m_prime: GroupOrderElement::from_string("1C9D01A3CC41CF3AD171A5E7E29C6E7423F2D09865A68A74A5110DF73182F127").unwrap(),
                     t: GroupOrderElement::from_string("0EB3CF17C8C6E60B0E46C2D475F22EE97DC0AEE10358FF21C8ADAD18FDDE30C5").unwrap(),
                     t_prime: GroupOrderElement::from_string("0314899F2FC10CD76785553F58E661D36607E159C1517FA490A07F08476E5AB9").unwrap(),
    -                m2: GroupOrderElement::from_string("099A79BA1F6D7DD6247DBE701CAE80805BED79B043B875CBB37D412BFCA6D402").unwrap(),
                     s: GroupOrderElement::from_string("07D1132A74742156EA34EE02CD0A782F36182CC464DFBFBD0DB009D6601604D9").unwrap(),
                     c: GroupOrderElement::from_string("02361F8FC95B27163873DF7D2C9B5223FAB7307B5E69297040FC3A0DC778C70B").unwrap(),
                 },
    @@ -2830,7 +2996,6 @@ pub mod mocks {
                     m_prime: GroupOrderElement::from_string("073C5D9384EFD20CCE013ABBD5D5532C248E7D665C7EDB74CD1BB49B5FC458E7").unwrap(),
                     t: GroupOrderElement::from_string("1172571F3FB78814E96FD962B2BD31C1BC7937E8C58FA05942372F58AEDBB4AC").unwrap(),
                     t_prime: GroupOrderElement::from_string("0E4FEED449204DBF040B11D8130635467C9429496BDA901DCE27AB5074A81972").unwrap(),
    -                m2: GroupOrderElement::from_string("1F0F9075F1F788A63440BC716F30DBCDB8010B8557020CC20B2156CC1D7B2984").unwrap(),
                     s: GroupOrderElement::from_string("0EA2C0F584D879AFACFE99CCF2DF0AFCCA7DEF831F0E28F05C2DE752A04C7430").unwrap(),
                     c: GroupOrderElement::from_string("01594829F554147480C7111A84A8BEB96D7983514DA58858A0819BCE9EE02FC4").unwrap(),
                 },
    @@ -2870,7 +3035,6 @@ pub mod mocks {
                     m_prime: GroupOrderElement::from_string("60F60877A17AB5 D18C7AFA6DBC2B 259C5531B7A142 E797E2D6C0DDCA B9E2616").unwrap(),
                     t: GroupOrderElement::from_string("15FB7F7FC34B3F 4C2F0140A4A584 14CD6B6D5D455B 9C63345F66E892 21B88E3F").unwrap(),
                     t_prime: GroupOrderElement::from_string("179B1F02AA6FB4 5E1E2ED844C75A BDF47D8F55BF90 192E37622D8CA0 1634FC27").unwrap(),
    -                m2: GroupOrderElement::from_string("EB43877A948FC4 52B12394658B53 394E050536B5E6 F44634D076AB0 1D89C97F").unwrap(),
                     s: GroupOrderElement::from_string("84BC05710625A1 DED5F03DF74609 5F72CE7609971B 2B43CA5E2A5C03 350174").unwrap(),
                     c: GroupOrderElement::from_string("7B5C7449CE3E59 34EADC67AD3E9E D634E35BF03EAC 63AE8185057976 9925E1").unwrap()
                 },
    
  • src/types.rs+5 8 modified
    @@ -1200,7 +1200,6 @@ pub struct NonRevocProofXList {
         pub(crate) m_prime: GroupOrderElement,
         pub(crate) t: GroupOrderElement,
         pub(crate) t_prime: GroupOrderElement,
    -    pub(crate) m2: GroupOrderElement,
         pub(crate) s: GroupOrderElement,
         pub(crate) c: GroupOrderElement,
     }
    @@ -1216,7 +1215,6 @@ impl NonRevocProofXList {
                 self.m_prime,
                 self.t,
                 self.t_prime,
    -            self.m2,
                 self.s,
                 self.r,
                 self.r_prime,
    @@ -1228,18 +1226,17 @@ impl NonRevocProofXList {
         pub fn from_list(seq: &[GroupOrderElement]) -> NonRevocProofXList {
             NonRevocProofXList {
                 rho: seq[0],
    -            r: seq[10],
    -            r_prime: seq[11],
    -            r_prime_prime: seq[12],
    -            r_prime_prime_prime: seq[13],
    +            r: seq[9],
    +            r_prime: seq[10],
    +            r_prime_prime: seq[11],
    +            r_prime_prime_prime: seq[12],
                 o: seq[1],
                 o_prime: seq[3],
                 m: seq[4],
                 m_prime: seq[5],
                 t: seq[6],
                 t_prime: seq[7],
    -            m2: seq[8],
    -            s: seq[9],
    +            s: seq[8],
                 c: seq[2],
             }
         }
    
  • src/verifier.rs+13 5 modified
    @@ -246,6 +246,7 @@ impl ProofVerifier {
                             rev_reg,
                             rev_key_pub,
                             &proof.aggregated_proof.c_hash,
    +                        &proof_item.primary_proof,
                             non_revocation_proof,
                         )?
                         .as_slice()?,
    @@ -568,17 +569,24 @@ impl ProofVerifier {
             rev_reg: &RevocationRegistry,
             rev_key_pub: &RevocationKeyPublic,
             c_hash: &BigNumber,
    -        proof: &NonRevocProof,
    +        primary_proof: &PrimaryProof,
    +        nonrev_proof: &NonRevocProof,
         ) -> ClResult<NonRevocProofTauList> {
             trace!("ProofVerifier::_verify_non_revocation_proof: >>> r_pub_key: {:?}, rev_reg: {:?}, rev_key_pub: {:?}, c_hash: {:?}",
                    r_pub_key, rev_reg, rev_key_pub, c_hash);
     
    -        let ch_num_z = bignum_to_group_element(c_hash)?;
    +        let ch_num_z = bignum_to_group_element(c_hash)?.mod_neg()?;
    +        let m2 = bignum_to_group_element_reduce(&primary_proof.eq_proof.m2, None)?;
     
             let t_hat_expected_values =
    -            create_tau_list_expected_values(r_pub_key, rev_reg, rev_key_pub, &proof.c_list)?;
    -        let t_hat_calc_values =
    -            create_tau_list_values(r_pub_key, rev_reg, &proof.x_list, &proof.c_list)?;
    +            create_tau_list_expected_values(r_pub_key, rev_reg, rev_key_pub, &nonrev_proof.c_list)?;
    +        let t_hat_calc_values = create_tau_list_values(
    +            r_pub_key,
    +            rev_reg,
    +            &nonrev_proof.x_list,
    +            &nonrev_proof.c_list,
    +            &m2,
    +        )?;
     
             let non_revoc_proof_tau_list = Ok(NonRevocProofTauList {
                 t1: t_hat_expected_values
    

Vulnerability mechanics

Generated by null/stub on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.

References

4

News mentions

0

No linked articles in our index yet.