Skip to content

Commit

Permalink
Reworked presented credential to use true as the result of a predicate
Browse files Browse the repository at this point in the history
Signed-off-by: artem.ivanov <artem.ivanov@dsr-corporation.com>
  • Loading branch information
Artemkaaas committed Jan 15, 2024
1 parent 4937151 commit 6ae14d5
Show file tree
Hide file tree
Showing 9 changed files with 382 additions and 436 deletions.
22 changes: 9 additions & 13 deletions src/data_types/w3c/credential_attributes.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
use crate::data_types::w3c::presentation::PredicateAttribute;
use crate::error::ValidationError;
use crate::types::{CredentialValues, MakeCredentialValues};
use crate::utils::validation::Validatable;
Expand Down Expand Up @@ -59,23 +58,20 @@ impl CredentialAttributes {
self.0.insert(attribute, value);
}

pub(crate) fn add_predicate(
&mut self,
attribute: String,
predicate: PredicateAttribute,
) -> crate::Result<()> {
match self.0.get_mut(&attribute) {
pub(crate) fn add_predicate(&mut self, attribute: String) -> crate::Result<()> {
match self.0.get(&attribute) {
Some(value) => match value {
CredentialAttributeValue::Attribute(_) => {
return Err(err_msg!("Predicate cannot be added for revealed attribute"));
}
CredentialAttributeValue::Predicate(predicates) => predicates.push(predicate),
CredentialAttributeValue::Predicate(_) => {
// predicate already exists
return Ok(());
}
},
None => {
self.0.insert(
attribute,
CredentialAttributeValue::Predicate(vec![predicate]),
);
self.0
.insert(attribute, CredentialAttributeValue::Predicate(true));
}
}
Ok(())
Expand Down Expand Up @@ -104,5 +100,5 @@ impl CredentialAttributes {
#[serde(untagged)]
pub enum CredentialAttributeValue {
Attribute(String),
Predicate(Vec<PredicateAttribute>),
Predicate(bool),
}
31 changes: 0 additions & 31 deletions src/data_types/w3c/presentation.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
use crate::data_types::pres_request::{PredicateInfo, PredicateTypes};
use serde::{Deserialize, Serialize};

use crate::data_types::w3c::constants::ANONCREDS_PRESENTATION_TYPES;
Expand Down Expand Up @@ -63,33 +62,3 @@ impl W3CPresentation {
Ok(())
}
}

#[derive(Clone, Debug, Eq, PartialEq, Deserialize, Serialize)]
pub struct PredicateAttribute {
#[serde(rename = "type")]
pub type_: PredicateAttributeType,
pub predicate: PredicateTypes,
pub value: i32,
}

#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub enum PredicateAttributeType {
#[serde(rename = "AnonCredsPredicate")]
AnonCredsPredicate,
}

impl Default for PredicateAttributeType {
fn default() -> Self {
PredicateAttributeType::AnonCredsPredicate
}
}

impl From<PredicateInfo> for PredicateAttribute {
fn from(info: PredicateInfo) -> Self {
PredicateAttribute {
type_: PredicateAttributeType::AnonCredsPredicate,
predicate: info.p_type,
value: info.p_value,
}
}
}
15 changes: 15 additions & 0 deletions src/data_types/w3c/proof.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ use anoncreds_clsignatures::{
use serde::de::DeserializeOwned;
use serde::Serialize;
use serde_json::json;
use std::collections::HashSet;
use std::fmt::Debug;

#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
Expand Down Expand Up @@ -205,9 +206,22 @@ pub struct CredentialPresentationProofValue {
pub rev_reg_id: Option<RevocationRegistryDefinitionId>,
#[serde(skip_serializing_if = "Option::is_none")]
pub timestamp: Option<u64>,
pub mapping: CredentialAttributesMapping,
pub sub_proof: SubProof,
}

#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct CredentialAttributesMapping {
#[serde(default)]
pub revealed_attributes: HashSet<String>,
pub revealed_attribute_groups: HashSet<String>,
#[serde(default)]
pub unrevealed_attributes: HashSet<String>,
#[serde(default)]
pub predicates: HashSet<String>,
}

#[derive(Debug, Serialize, Deserialize)]
pub struct PresentationProofValue {
pub aggregated: AggregatedProof,
Expand Down Expand Up @@ -335,6 +349,7 @@ pub(crate) mod tests {
cred_def_id: cred_def_id(),
rev_reg_id: Some(verifier::tests::revocation_id()),
timestamp: Some(PROOF_TIMESTAMP),
mapping: Default::default(),
sub_proof: credential_sub_proof(),
}
}
Expand Down
26 changes: 13 additions & 13 deletions src/services/helpers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use crate::cl::{
bn::BigNumber, CredentialSchema, CredentialValues as CLCredentialValues, Issuer,
NonCredentialSchema, SubProofRequest, Verifier,
};
use crate::data_types::pres_request::{PredicateTypes, PredicateValue};
use crate::data_types::pres_request::PredicateInfo;
use crate::data_types::presentation::RequestedProof;
use crate::data_types::rev_reg_def::RevocationRegistryDefinitionId;
use crate::data_types::schema::Schema;
Expand Down Expand Up @@ -89,7 +89,7 @@ pub fn encode_credential_attribute(raw_value: &str) -> Result<String> {

pub fn build_sub_proof_request(
attrs_for_credential: &[String],
predicates_for_credential: &HashMap<String, (PredicateTypes, PredicateValue)>,
predicates_for_credential: &[PredicateInfo],
) -> Result<SubProofRequest> {
trace!(
"build_sub_proof_request >>> attrs_for_credential: {:?}, predicates_for_credential: {:?}",
Expand All @@ -103,10 +103,14 @@ pub fn build_sub_proof_request(
sub_proof_request_builder.add_revealed_attr(&attr_common_view(attr))?;
}

for (name, (p_type, p_value)) in predicates_for_credential {
let p_type = format!("{}", p_type);
for predicate in predicates_for_credential {
let p_type = format!("{}", predicate.p_type);

sub_proof_request_builder.add_predicate(&attr_common_view(name), &p_type, *p_value)?;
sub_proof_request_builder.add_predicate(
&attr_common_view(&predicate.name),
&p_type,
predicate.p_value,
)?;
}

let res = sub_proof_request_builder.finalize()?;
Expand Down Expand Up @@ -231,18 +235,14 @@ impl PresentationRequestPayload {
Ok((attributes, non_revoked_interval))
}

#[allow(clippy::type_complexity)]
pub(crate) fn get_requested_predicates(
&self,
referents: &HashSet<String>,
) -> Result<(
HashMap<String, (PredicateTypes, PredicateValue)>,
Option<NonRevokedInterval>,
)> {
) -> Result<(Vec<PredicateInfo>, Option<NonRevokedInterval>)> {
trace!("get_requested_predicates >>> referents: {:?}", referents);
let mut non_revoked_interval: Option<NonRevokedInterval> = None;
let mut predicates: HashMap<String, (PredicateTypes, PredicateValue)> =
HashMap::with_capacity(self.requested_predicates.len());
let mut predicates: Vec<PredicateInfo> =
Vec::with_capacity(self.requested_predicates.len());

for referent in referents {
let requested = self
Expand All @@ -259,7 +259,7 @@ impl PresentationRequestPayload {
None => non_revoked_interval = Some(int.clone()),
}
}
predicates.insert(requested.name, (requested.p_type, requested.p_value));
predicates.push(requested);
}

trace!(
Expand Down
47 changes: 26 additions & 21 deletions src/services/verifier.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ use crate::data_types::cred_def::CredentialDefinition;
use crate::data_types::cred_def::CredentialDefinitionId;
use crate::data_types::issuer_id::IssuerId;
use crate::data_types::nonce::Nonce;
use crate::data_types::pres_request::PresentationRequestPayload;
use crate::data_types::pres_request::{AttributeInfo, NonRevokedInterval};
use crate::data_types::pres_request::{PredicateTypes, PredicateValue, PresentationRequestPayload};
use crate::data_types::presentation::{Identifier, RequestedProof};
use crate::data_types::rev_reg_def::RevocationRegistryDefinitionId;
use crate::data_types::schema::Schema;
Expand Down Expand Up @@ -105,29 +105,13 @@ pub fn verify_presentation(
.requested_proof
.get_predicates_for_credential(sub_proof_index as u32);

let (attributes, attrs_nonrevoked_interval) =
pres_req.get_requested_attributes(&attributes)?;
let (predicates, pred_nonrevoked_interval) =
pres_req.get_requested_predicates(&predicates)?;

{
check_non_revoked_interval(
proof_verifier.get_credential_definition(&identifier.cred_def_id)?,
attrs_nonrevoked_interval,
pred_nonrevoked_interval,
pres_req,
identifier.rev_reg_id.as_ref(),
nonrevoke_interval_override,
identifier.timestamp,
)?;
}

proof_verifier.add_sub_proof(
&attributes,
&predicates,
&identifier.schema_id,
&identifier.cred_def_id,
identifier.rev_reg_id.as_ref(),
nonrevoke_interval_override,
identifier.timestamp,
)?;
}
Expand Down Expand Up @@ -851,11 +835,14 @@ impl<'a> CLProofVerifier<'a> {
#[allow(clippy::too_many_arguments)]
pub(crate) fn add_sub_proof(
&mut self,
attributes: &[String],
predicates: &HashMap<String, (PredicateTypes, PredicateValue)>,
attributes: &HashSet<String>,
predicates: &HashSet<String>,
schema_id: &SchemaId,
cred_def_id: &CredentialDefinitionId,
rev_reg_def_id: Option<&RevocationRegistryDefinitionId>,
nonrevoke_interval_override: Option<
&HashMap<RevocationRegistryDefinitionId, HashMap<u64, u64>>,
>,
timestamp: Option<u64>,
) -> Result<()> {
let schema = self.get_schema(schema_id)?;
Expand All @@ -867,7 +854,25 @@ impl<'a> CLProofVerifier<'a> {
&cred_def.value.primary,
cred_def.value.revocation.as_ref(),
)?;
let sub_pres_request = build_sub_proof_request(attributes, predicates)?;

let (attributes, attrs_nonrevoked_interval) = self
.presentation_request
.get_requested_attributes(attributes)?;
let (predicates, pred_nonrevoked_interval) = self
.presentation_request
.get_requested_predicates(predicates)?;

check_non_revoked_interval(
self.get_credential_definition(cred_def_id)?,
attrs_nonrevoked_interval,
pred_nonrevoked_interval,
self.presentation_request,
rev_reg_def_id,
nonrevoke_interval_override,
timestamp,
)?;

let sub_pres_request = build_sub_proof_request(&attributes, &predicates)?;
let rev_key_pub = rev_reg_def.map(|d| &d.value.public_keys.accum_key);
self.proof_verifier.add_sub_proof_request(
&sub_pres_request,
Expand Down
42 changes: 3 additions & 39 deletions src/services/w3c/helpers.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
use crate::data_types::pres_request::{PredicateInfo, PredicateTypes, PredicateValue};
use crate::data_types::schema::Schema;
use crate::data_types::w3c::credential::W3CCredential;
use crate::data_types::w3c::credential_attributes::CredentialAttributeValue;
use crate::error::Result;
Expand Down Expand Up @@ -31,21 +29,12 @@ impl W3CCredential {
matches!(value, CredentialAttributeValue::Attribute(_))
}

pub(crate) fn has_predicate(&self, predicate: &PredicateInfo) -> bool {
let (_, value) = match self.get_case_insensitive_attribute(&predicate.name) {
pub(crate) fn has_predicate(&self, requested_predicate: &str) -> bool {
let (_, value) = match self.get_case_insensitive_attribute(requested_predicate) {
Ok(value) => value,
Err(_) => return false,
};

match value {
CredentialAttributeValue::Predicate(ref predicates) => {
predicates.iter().any(|shared_predicate| {
shared_predicate.predicate == predicate.p_type
&& shared_predicate.value == predicate.p_value
})
}
_ => false,
}
matches!(value, CredentialAttributeValue::Predicate(_))
}

pub(crate) fn get_attributes(&self) -> HashMap<String, String> {
Expand All @@ -57,29 +46,4 @@ impl W3CCredential {
}
attributes
}

pub(crate) fn get_predicates(&self) -> HashMap<String, (PredicateTypes, PredicateValue)> {
let mut predicates: HashMap<String, (PredicateTypes, PredicateValue)> = HashMap::new();
for (name, attribute) in self.credential_subject.attributes.0.iter() {
if let CredentialAttributeValue::Predicate(predicate_list) = attribute {
predicate_list.iter().for_each(|predicate| {
predicates.insert(
name.to_string(),
(predicate.predicate.to_owned(), predicate.value),
);
});
}
}
predicates
}
}

impl Schema {
pub(crate) fn has_case_insensitive_attribute(&self, requested_attribute: &str) -> bool {
let requested_attribute = attr_common_view(requested_attribute);
self.attr_names
.0
.iter()
.any(|attribute| attr_common_view(attribute) == requested_attribute)
}
}
41 changes: 37 additions & 4 deletions src/services/w3c/prover.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,9 @@ use crate::types::{
use crate::utils::validation::Validatable;

use crate::data_types::w3c::credential_attributes::CredentialAttributes;
use crate::data_types::w3c::presentation::PredicateAttribute;
use crate::data_types::w3c::proof::{
CredentialPresentationProofValue, DataIntegrityProof, PresentationProofValue,
CredentialAttributesMapping, CredentialPresentationProofValue, DataIntegrityProof,
PresentationProofValue,
};
use crate::data_types::w3c::VerifiableCredentialSpecVersion;
use crate::prover::{CLCredentialProver, CLProofBuilder};
Expand Down Expand Up @@ -191,6 +191,7 @@ pub fn create_presentation(
cred_def_id: credential_proof.cred_def_id.to_owned(),
rev_reg_id: credential_proof.rev_reg_id.to_owned(),
timestamp: present.timestamp,
mapping: build_mapping(presentation_request, present)?,
sub_proof,
};
let proof = DataIntegrityProof::new_credential_presentation_proof(&proof);
Expand Down Expand Up @@ -253,9 +254,41 @@ fn build_credential_attributes<'p>(
let (attribute, _) = credentials
.cred
.get_case_insensitive_attribute(&predicate_info.name)?;
let predicate = PredicateAttribute::from(predicate_info);
attributes.add_predicate(attribute, predicate)?;
attributes.add_predicate(attribute)?;
}

Ok(attributes)
}

fn build_mapping<'p>(
pres_req: &PresentationRequestPayload,
credential: &PresentCredential<'p, W3CCredential>,
) -> Result<CredentialAttributesMapping> {
let mut mapping = CredentialAttributesMapping::default();

for (referent, reveal) in credential.requested_attributes.iter() {
let requested_attribute = pres_req.requested_attributes.get(referent).ok_or_else(|| {
err_msg!(
"Attribute with referent \"{}\" not found in ProofRequest",
referent
)
})?;
if requested_attribute.name.is_some() {
if *reveal {
mapping.revealed_attributes.insert(referent.to_string());
} else {
mapping.unrevealed_attributes.insert(referent.to_string());
}
}
if requested_attribute.names.is_some() {
mapping
.revealed_attribute_groups
.insert(referent.to_string());
}
}
for referent in credential.requested_predicates.iter() {
mapping.predicates.insert(referent.to_string());
}

Ok(mapping)
}
Loading

0 comments on commit 6ae14d5

Please sign in to comment.