indy_credx/services/
helpers.rs1use 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 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 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}