Skip to content

Commit

Permalink
Different predicate representation + pass cred def into conversion me…
Browse files Browse the repository at this point in the history
…thod

Signed-off-by: artem.ivanov <[email protected]>
  • Loading branch information
Artemkaaas committed Nov 14, 2023
1 parent 572001a commit 65eb5b6
Show file tree
Hide file tree
Showing 12 changed files with 389 additions and 97 deletions.
13 changes: 0 additions & 13 deletions src/data_types/cred_def.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,19 +13,6 @@ pub const CL_SIGNATURE_TYPE: &str = "CL";

impl_anoncreds_object_identifier!(CredentialDefinitionId);

impl CredentialDefinitionId {
// FIXME: As AnonCreds-rs is DID method agnostic, so it does not analyze/handle the values of id fields.
// For conversion into W3C Credentials form we need to set issuer_id attribute but legacy credentials do not contain it explicitly.
// We only can parse issuer from the legacy form?
pub fn issuer_did(&self) -> IssuerId {
if let Some(caps) = LEGACY_CRED_DEF_IDENTIFIER.captures(&self.0) {
IssuerId(caps[0].to_string())
} else {
IssuerId(self.0.to_owned())
}
}
}

#[derive(Copy, Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
pub enum SignatureType {
CL,
Expand Down
148 changes: 142 additions & 6 deletions src/data_types/w3c/credential.rs
Original file line number Diff line number Diff line change
@@ -1,14 +1,17 @@
use chrono::{DateTime, Utc};
use serde::{Deserialize, Serialize};
use std::collections::HashSet;
use serde_json::{json, Value};
use std::collections::{HashMap, HashSet};
use std::string::ToString;
use zeroize::Zeroize;

use crate::data_types::pres_request::{PredicateInfo, PredicateTypes};
use crate::data_types::w3c::constants::{ANONCREDS_CONTEXTS, ANONCREDS_TYPES};
use crate::data_types::w3c::credential_proof::{CredentialProof, CredentialSignatureProof};
use crate::data_types::w3c::presentation_proof::CredentialPresentationProof;
use crate::data_types::{
cred_def::CredentialDefinitionId,
credential::{CredentialValuesEncoding, RawCredentialValues},
credential::CredentialValuesEncoding,
issuer_id::IssuerId,
rev_reg_def::RevocationRegistryDefinitionId,
schema::SchemaId,
Expand All @@ -20,7 +23,9 @@ use crate::data_types::{
uri::URI,
},
};
use crate::utils::datetime;
use crate::error::ValidationError;
use crate::types::{CredentialValues, MakeCredentialValues};
use crate::utils::validation::Validatable;
use crate::Result;

/// AnonCreds W3C Credential definition
Expand Down Expand Up @@ -61,7 +66,138 @@ pub struct CredentialSubject {
#[serde(skip_serializing_if = "Option::is_none")]
pub id: Option<URI>,
#[serde(flatten)]
pub attributes: RawCredentialValues,
pub attributes: CredentialAttributes,
}

#[derive(Clone, Debug, Default, PartialEq, Eq, Deserialize, Serialize)]
pub struct CredentialAttributes(pub HashMap<String, Value>);

#[cfg(feature = "zeroize")]
impl Drop for CredentialAttributes {
fn drop(&mut self) {
self.zeroize();
}
}

#[cfg(feature = "zeroize")]
impl Zeroize for CredentialAttributes {
fn zeroize(&mut self) {
for attr in self.0.values_mut() {
if let Value::String(attr) = attr {
attr.zeroize()
}
}
}
}

impl Validatable for CredentialAttributes {
fn validate(&self) -> std::result::Result<(), ValidationError> {
if self.0.is_empty() {
return Err(
"CredentialAttributes validation failed: empty list has been passed".into(),
);
}
for (attribute, value) in self.0.iter() {
match value {
Value::String(_) | Value::Object(_) => {}
_ => {
return Err(format!(
"CredentialAttributes validation failed: {} value format is not supported",
attribute
)
.into())
}
}
}

Ok(())
}
}

impl From<&CredentialValues> for CredentialAttributes {
fn from(values: &CredentialValues) -> Self {
CredentialAttributes(
values
.0
.iter()
.map(|(attribute, values)| {
(attribute.to_owned(), Value::String(values.raw.to_owned()))
})
.collect(),
)
}
}

impl CredentialAttributes {
pub fn add_attribute(&mut self, attribute: String, value: Value) {
self.0.insert(attribute, value);
}

pub fn add_predicate(&mut self, attribute: String, value: PredicateAttribute) {
self.0.insert(attribute, json!(value));
}

pub fn get_attribute(&self, attribute: &str) -> Result<&Value> {
self.0
.get(attribute)
.ok_or_else(|| err_msg!("Credential attribute {} not found", attribute))
}

pub fn encode(&self, encoding: &CredentialValuesEncoding) -> Result<CredentialValues> {
match encoding {
CredentialValuesEncoding::Auto => {
let mut cred_values = MakeCredentialValues::default();
for (attribute, raw_value) in self.0.iter() {
match raw_value {
Value::String(raw_value) => {
cred_values.add_raw(attribute, &raw_value.to_string())?
}
value => {
return Err(err_msg!(
"Encoding is not supported for credential value {:?}",
value
));
}
}
}
Ok(cred_values.into())
}
encoding => Err(err_msg!(
"Credential values encoding {:?} is not supported",
encoding
)),
}
}
}

#[derive(Clone, Debug, Eq, PartialEq, Deserialize, Serialize)]
pub struct PredicateAttribute {
#[serde(rename = "type")]
pub type_: PredicateAttributeType,
pub p_type: PredicateTypes,
pub p_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,
p_type: info.p_type,
p_value: info.p_value,
}
}
}

#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize)]
Expand Down Expand Up @@ -118,7 +254,7 @@ impl W3CCredential {
W3CCredential {
context: ANONCREDS_CONTEXTS.clone(),
type_: ANONCREDS_TYPES.clone(),
issuance_date: datetime::today(),
issuance_date: Utc::now(),
proof: OneOrMany::Many(Vec::new()),
..Default::default()
}
Expand All @@ -136,7 +272,7 @@ impl W3CCredential {
self.credential_schema = credential_schema
}

pub fn set_attributes(&mut self, attributes: RawCredentialValues) {
pub fn set_attributes(&mut self, attributes: CredentialAttributes) {
self.credential_subject.attributes = attributes
}

Expand Down
16 changes: 9 additions & 7 deletions src/ffi/credential.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@ use super::error::{catch_error, ErrorCode};
use super::object::{AnoncredsObject, ObjectHandle};
use super::util::FfiStrList;
use crate::conversion::{credential_from_w3c, credential_to_w3c};
use crate::data_types::credential::{CredentialValuesEncoding, RawCredentialValues};
use crate::data_types::credential::CredentialValuesEncoding;
use crate::data_types::w3c::credential::CredentialAttributes;
use crate::data_types::w3c::credential_proof::{CredentialProof, NonAnonCredsDataIntegrityProof};
use crate::data_types::w3c::uri::URI;
use crate::data_types::{link_secret::LinkSecret, w3c::credential::W3CCredential};
Expand All @@ -18,7 +19,7 @@ use crate::services::{
prover::{process_credential, process_w3c_credential},
types::{Credential, CredentialRevocationConfig, MakeCredentialValues},
};
use crate::types::{CredentialValues, MakeRawCredentialValues};
use crate::types::{CredentialValues, MakeCredentialAttributes};
use crate::Error;

#[derive(Debug)]
Expand Down Expand Up @@ -226,7 +227,7 @@ pub extern "C" fn anoncreds_create_w3c_credential(
catch_error(|| {
check_useful_c_ptr!(cred_p);

let cred_values = _raw_credential_values(attr_names, attr_raw_values)?;
let cred_values = _credential_attributes(attr_names, attr_raw_values)?;
let revocation_config = _revocation_config(revocation)?;
let encoding = encoding.as_opt_str().map(CredentialValuesEncoding::from);

Expand Down Expand Up @@ -305,6 +306,7 @@ pub extern "C" fn anoncreds_process_w3c_credential(
#[no_mangle]
pub extern "C" fn anoncreds_credential_to_w3c(
cred: ObjectHandle,
cred_def: ObjectHandle,
cred_p: *mut ObjectHandle,
) -> ErrorCode {
catch_error(|| {
Expand All @@ -313,7 +315,7 @@ pub extern "C" fn anoncreds_credential_to_w3c(
let credential = cred.load()?;
let credential = credential.cast_ref::<Credential>()?;

let w3c_credential = credential_to_w3c(credential)?;
let w3c_credential = credential_to_w3c(credential, cred_def.load()?.cast_ref()?)?;
let w3c_cred = ObjectHandle::create(w3c_credential)?;

unsafe { *cred_p = w3c_cred };
Expand Down Expand Up @@ -583,10 +585,10 @@ fn _encoded_credential_values(
Ok(cred_values.into())
}

fn _raw_credential_values(
fn _credential_attributes(
attr_names: FfiStrList,
attr_raw_values: FfiStrList,
) -> Result<RawCredentialValues> {
) -> Result<CredentialAttributes> {
if attr_names.is_empty() {
return Err(err_msg!("Cannot create credential with no attribute"));
}
Expand All @@ -595,7 +597,7 @@ fn _raw_credential_values(
"Mismatch between length of attribute names and raw values"
));
}
let mut cred_values = MakeRawCredentialValues::default();
let mut cred_values = MakeCredentialAttributes::default();
for (name, raw) in attr_names.as_slice().iter().zip(attr_raw_values.as_slice()) {
let name = name
.as_opt_str()
Expand Down
Loading

0 comments on commit 65eb5b6

Please sign in to comment.