indy_data_types/anoncreds/
credential.rs1use std::collections::HashMap;
2
3use zeroize::Zeroize;
4
5use crate::identifiers::cred_def::CredentialDefinitionId;
6use crate::identifiers::rev_reg::RevocationRegistryId;
7use crate::identifiers::schema::SchemaId;
8use crate::{Validatable, ValidationError};
9
10#[derive(Debug)]
11#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
12pub struct Credential {
13 pub schema_id: SchemaId,
14 pub cred_def_id: CredentialDefinitionId,
15 pub rev_reg_id: Option<RevocationRegistryId>,
16 pub values: CredentialValues,
17 pub signature: cl_type!(CredentialSignature),
18 pub signature_correctness_proof: cl_type!(SignatureCorrectnessProof),
19 pub rev_reg: Option<cl_type!(RevocationRegistry)>,
20 pub witness: Option<cl_type!(Witness)>,
21}
22
23#[cfg(any(feature = "cl", feature = "cl_native"))]
24impl Credential {
25 pub fn try_clone(&self) -> Result<Self, crate::ConversionError> {
26 Ok(Self {
27 schema_id: self.schema_id.clone(),
28 cred_def_id: self.cred_def_id.clone(),
29 rev_reg_id: self.rev_reg_id.clone(),
30 values: self.values.clone(),
31 signature: self.signature.try_clone().map_err(|e| e.to_string())?,
32 signature_correctness_proof: self
33 .signature_correctness_proof
34 .try_clone()
35 .map_err(|e| e.to_string())?,
36 rev_reg: self.rev_reg.clone(),
37 witness: self.witness.clone(),
38 })
39 }
40}
41
42impl Credential {
43 pub const QUALIFIABLE_TAGS: [&'static str; 5] = [
44 "issuer_did",
45 "cred_def_id",
46 "schema_id",
47 "schema_issuer_did",
48 "rev_reg_id",
49 ];
50}
51
52impl Validatable for Credential {
53 fn validate(&self) -> Result<(), ValidationError> {
54 self.schema_id.validate()?;
55 self.cred_def_id.validate()?;
56 self.values.validate()?;
57
58 if self.rev_reg_id.is_some() && (self.witness.is_none() || self.rev_reg.is_none()) {
59 return Err("Credential validation failed: `witness` and `rev_reg` must be passed for revocable Credential".into());
60 }
61
62 if self.values.0.is_empty() {
63 return Err("Credential validation failed: `values` is empty".into());
64 }
65
66 Ok(())
67 }
68}
69
70#[derive(Clone, Debug, PartialEq, Eq)]
71#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
72pub struct CredentialInfo {
73 pub referent: String,
74 pub attrs: ShortCredentialValues,
75 pub schema_id: SchemaId,
76 pub cred_def_id: CredentialDefinitionId,
77 pub rev_reg_id: Option<RevocationRegistryId>,
78 pub cred_rev_id: Option<String>,
79}
80
81pub type ShortCredentialValues = HashMap<String, String>;
82
83#[derive(Clone, Debug, Default, PartialEq, Eq)]
84#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
85pub struct CredentialValues(pub HashMap<String, AttributeValues>);
86
87impl Drop for CredentialValues {
88 fn drop(&mut self) {
89 self.zeroize();
90 }
91}
92
93impl Validatable for CredentialValues {
94 fn validate(&self) -> Result<(), ValidationError> {
95 if self.0.is_empty() {
96 return Err("CredentialValues validation failed: empty list has been passed".into());
97 }
98
99 Ok(())
100 }
101}
102
103impl Zeroize for CredentialValues {
104 fn zeroize(&mut self) {
105 for attr in self.0.values_mut() {
106 attr.zeroize();
107 }
108 }
109}
110
111#[derive(Clone, Debug, PartialEq, Eq, Zeroize)]
112#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
113pub struct AttributeValues {
114 pub raw: String,
115 pub encoded: String,
116}