Skip to main content

indy_credx/services/
helpers.rs

1use std::collections::{HashMap, HashSet};
2
3use indy_data_types::anoncreds::{
4    credential::AttributeValues,
5    nonce::Nonce,
6    pres_request::{AttributeInfo, NonRevocedInterval, PredicateInfo},
7};
8
9use crate::anoncreds_clsignatures::{
10    hash_credential_attribute, CredentialSchema, CredentialValues as ClCredentialValues,
11    Issuer as ClIssuer, LinkSecret as ClLinkSecret, NonCredentialSchema, SubProofRequest,
12    Verifier as ClVerifier,
13};
14use crate::error::Result;
15
16pub fn attr_common_view(attr: &str) -> String {
17    attr.replace(' ', "").to_lowercase()
18}
19
20pub fn build_credential_schema(attrs: &HashSet<String>) -> Result<CredentialSchema> {
21    trace!("build_credential_schema >>> attrs: {:?}", attrs);
22
23    let mut credential_schema_builder = ClIssuer::new_credential_schema_builder()?;
24    for attr in attrs {
25        credential_schema_builder.add_attr(&attr_common_view(attr))?;
26    }
27
28    let res = credential_schema_builder.finalize()?;
29
30    trace!("build_credential_schema <<< res: {:?}", res);
31
32    Ok(res)
33}
34
35pub fn build_non_credential_schema() -> Result<NonCredentialSchema> {
36    trace!("build_non_credential_schema");
37
38    let mut non_credential_schema_builder = ClIssuer::new_non_credential_schema_builder()?;
39    non_credential_schema_builder.add_attr("master_secret")?;
40    let res = non_credential_schema_builder.finalize()?;
41
42    trace!("build_non_credential_schema <<< res: {:?}", res);
43    Ok(res)
44}
45
46pub fn build_credential_values(
47    credential_values: &HashMap<String, AttributeValues>,
48    link_secret: Option<&ClLinkSecret>,
49) -> Result<ClCredentialValues> {
50    trace!(
51        "build_credential_values >>> credential_values: {:?}",
52        credential_values
53    );
54
55    let mut credential_values_builder = ClIssuer::new_credential_values_builder()?;
56    for (attr, values) in credential_values {
57        credential_values_builder.add_dec_known(&attr_common_view(attr), &values.encoded)?;
58    }
59    if let Some(ms) = link_secret {
60        credential_values_builder.add_value_hidden("master_secret", &ms.value()?)?;
61    }
62
63    let res = credential_values_builder.finalize()?;
64
65    trace!("build_credential_values <<< res: {:?}", res);
66
67    Ok(res)
68}
69
70pub fn encode_credential_attribute(raw_value: &str) -> Result<String> {
71    if let Ok(val) = raw_value.parse::<i32>() {
72        Ok(val.to_string())
73    } else {
74        Ok(hash_credential_attribute(raw_value)?)
75    }
76}
77
78pub fn build_sub_proof_request(
79    attrs_for_credential: &[AttributeInfo],
80    predicates_for_credential: &[PredicateInfo],
81) -> Result<SubProofRequest> {
82    trace!(
83        "build_sub_proof_request >>> attrs_for_credential: {:?}, predicates_for_credential: {:?}",
84        attrs_for_credential,
85        predicates_for_credential
86    );
87
88    let mut sub_proof_request_builder = ClVerifier::new_sub_proof_request_builder()?;
89
90    for attr in attrs_for_credential {
91        let names = if let Some(name) = &attr.name {
92            vec![name.clone()]
93        } else if let Some(names) = &attr.names {
94            names.to_owned()
95        } else {
96            error!(
97                r#"Attr for credential restriction should contain "name" or "names" param. Current attr: {:?}"#,
98                attr
99            );
100            return Err(err_msg!(
101                r#"Attr for credential restriction should contain "name" or "names" param."#,
102            ));
103        };
104
105        for name in names {
106            sub_proof_request_builder.add_revealed_attr(&attr_common_view(&name))?
107        }
108    }
109
110    for predicate in predicates_for_credential {
111        let p_type = format!("{}", predicate.p_type);
112
113        sub_proof_request_builder.add_predicate(
114            &attr_common_view(&predicate.name),
115            &p_type,
116            predicate.p_value,
117        )?;
118    }
119
120    let res = sub_proof_request_builder.finalize()?;
121
122    trace!("build_sub_proof_request <<< res: {:?}", res);
123
124    Ok(res)
125}
126
127pub fn get_non_revoc_interval(
128    global_interval: &Option<NonRevocedInterval>,
129    local_interval: &Option<NonRevocedInterval>,
130) -> Option<NonRevocedInterval> {
131    trace!(
132        "get_non_revoc_interval >>> global_interval: {:?}, local_interval: {:?}",
133        global_interval,
134        local_interval
135    );
136
137    let interval = local_interval
138        .clone()
139        .or_else(|| global_interval.clone().or(None));
140
141    trace!("get_non_revoc_interval <<< interval: {:?}", interval);
142
143    interval
144}
145
146pub fn new_nonce() -> Result<Nonce> {
147    Nonce::new().map_err(err_map!(Unexpected))
148}
149
150#[cfg(test)]
151mod tests {
152    use super::*;
153
154    fn _interval() -> NonRevocedInterval {
155        NonRevocedInterval {
156            from: None,
157            to: Some(123),
158        }
159    }
160
161    #[test]
162    fn test_encode_attribute() {
163        assert_eq!(
164            encode_credential_attribute("101 Wilson Lane").unwrap(),
165            "68086943237164982734333428280784300550565381723532936263016368251445461241953"
166        );
167        assert_eq!(encode_credential_attribute("87121").unwrap(), "87121");
168        assert_eq!(
169            encode_credential_attribute("SLC").unwrap(),
170            "101327353979588246869873249766058188995681113722618593621043638294296500696424"
171        );
172        assert_eq!(
173            encode_credential_attribute("101 Tela Lane").unwrap(),
174            "63690509275174663089934667471948380740244018358024875547775652380902762701972"
175        );
176        assert_eq!(
177            encode_credential_attribute("UT").unwrap(),
178            "93856629670657830351991220989031130499313559332549427637940645777813964461231"
179        );
180        assert_eq!(
181            encode_credential_attribute("").unwrap(),
182            "102987336249554097029535212322581322789799900648198034993379397001115665086549"
183        );
184        assert_eq!(
185            encode_credential_attribute("None").unwrap(),
186            "99769404535520360775991420569103450442789945655240760487761322098828903685777"
187        );
188        assert_eq!(encode_credential_attribute("0").unwrap(), "0");
189        assert_eq!(encode_credential_attribute("1").unwrap(), "1");
190
191        // max i32
192        assert_eq!(
193            encode_credential_attribute("2147483647").unwrap(),
194            "2147483647"
195        );
196        assert_eq!(
197            encode_credential_attribute("2147483648").unwrap(),
198            "26221484005389514539852548961319751347124425277437769688639924217837557266135"
199        );
200
201        // min i32
202        assert_eq!(
203            encode_credential_attribute("-2147483648").unwrap(),
204            "-2147483648"
205        );
206        assert_eq!(
207            encode_credential_attribute("-2147483649").unwrap(),
208            "68956915425095939579909400566452872085353864667122112803508671228696852865689"
209        );
210
211        assert_eq!(
212            encode_credential_attribute("0.0").unwrap(),
213            "62838607218564353630028473473939957328943626306458686867332534889076311281879"
214        );
215        assert_eq!(
216            encode_credential_attribute("\x00").unwrap(),
217            "49846369543417741186729467304575255505141344055555831574636310663216789168157"
218        );
219        assert_eq!(
220            encode_credential_attribute("\x01").unwrap(),
221            "34356466678672179216206944866734405838331831190171667647615530531663699592602"
222        );
223        assert_eq!(
224            encode_credential_attribute("\x02").unwrap(),
225            "99398763056634537812744552006896172984671876672520535998211840060697129507206"
226        );
227    }
228
229    #[test]
230    fn get_non_revoc_interval_for_global() {
231        let res = get_non_revoc_interval(&Some(_interval()), &None).unwrap();
232        assert_eq!(_interval(), res);
233    }
234
235    #[test]
236    fn get_non_revoc_interval_for_local() {
237        let res = get_non_revoc_interval(&None, &Some(_interval())).unwrap();
238        assert_eq!(_interval(), res);
239    }
240
241    #[test]
242    fn get_non_revoc_interval_for_none() {
243        let res = get_non_revoc_interval(&None, &None);
244        assert_eq!(None, res);
245    }
246}