From 99df0824b41d90c33b5b4460d32e199bbc227442 Mon Sep 17 00:00:00 2001 From: Ian Costanzo Date: Thu, 7 Feb 2019 15:45:43 -0800 Subject: [PATCH 1/6] Implement ZKP for vcx agents Signed-off-by: Ian Costanzo --- vcx/libvcx/src/disclosed_proof.rs | 50 ++++++++++++++++++++--- vcx/libvcx/src/utils/constants.rs | 1 + vcx/libvcx/src/utils/libindy/anoncreds.rs | 47 +++++++++++++-------- vcx/wrappers/python3/demo/demo_utils.py | 4 +- vcx/wrappers/python3/demo/faber-pg.py | 6 ++- vcx/wrappers/python3/vcx/api/proof.py | 4 +- 6 files changed, 82 insertions(+), 30 deletions(-) diff --git a/vcx/libvcx/src/disclosed_proof.rs b/vcx/libvcx/src/disclosed_proof.rs index d073922d1b..b82b592032 100644 --- a/vcx/libvcx/src/disclosed_proof.rs +++ b/vcx/libvcx/src/disclosed_proof.rs @@ -147,6 +147,17 @@ fn _get_revocation_interval(attr_name: &str, proof_req: &ProofRequestData) return Ok(None) } // Todo: Handle case for predicates + if let Some(ref attr) = proof_req.requested_predicates.get(attr_name) { + + if let Some(ref interval) = attr.non_revoked { + return Ok(Some(NonRevokedInterval {from: interval.from, to: interval.to})) + } + else if let Some(ref interval) = proof_req.non_revoked { + return Ok(Some(NonRevokedInterval { from: interval.from, to: interval.to })) + } + + return Ok(None) + } Err(ProofError::InvalidCredData()) } @@ -325,7 +336,8 @@ impl DisclosedProof { fn build_requested_credentials_json(&self, credentials_identifiers: &Vec, - self_attested_attrs: &str) -> Result { + self_attested_attrs: &str, + proof_req: &ProofRequestData) -> Result { let mut rtn: Value = json!({ "self_attested_attributes":{}, "requested_attributes":{}, @@ -335,8 +347,19 @@ impl DisclosedProof { //Todo: need to handle if the attribute is not revealed if let Value::Object(ref mut map) = rtn["requested_attributes"] { for ref cred_info in credentials_identifiers { - let insert_val = json!({"cred_id": cred_info.referent, "revealed": true, "timestamp": cred_info.timestamp}); - map.insert(cred_info.requested_attr.to_owned(), insert_val); + if let Some(ref attr) = proof_req.requested_attributes.get(&cred_info.requested_attr) { + let insert_val = json!({"cred_id": cred_info.referent, "revealed": true, "timestamp": cred_info.timestamp}); + map.insert(cred_info.requested_attr.to_owned(), insert_val); + } + } + } + + if let Value::Object(ref mut map) = rtn["requested_predicates"] { + for ref cred_info in credentials_identifiers { + if let Some(ref attr) = proof_req.requested_predicates.get(&cred_info.requested_attr) { + let insert_val = json!({"cred_id": cred_info.referent, "revealed": false, "timestamp": cred_info.timestamp}); + map.insert(cred_info.requested_attr.to_owned(), insert_val); + } } } @@ -358,13 +381,13 @@ impl DisclosedProof { let proof_req_data_json = serde_json::to_string(&proof_req.proof_request_data) .or(Err(ProofError::CommonError(error::INVALID_JSON.code_num)))?; - let mut credentials_identifiers = credential_def_identifiers(credentials, &proof_req.proof_request_data)?; let revoc_states_json = build_rev_states_json(&mut credentials_identifiers)?; let requested_credentials = self.build_requested_credentials_json(&credentials_identifiers, - self_attested_attrs)?; + self_attested_attrs, + &proof_req.proof_request_data)?; let schemas_json = self.build_schemas_json(&credentials_identifiers)?; let credential_defs_json = self.build_cred_def_json(&credentials_identifiers)?; @@ -882,7 +905,22 @@ mod tests { }); let proof: DisclosedProof = Default::default(); - let requested_credential = proof.build_requested_credentials_json(&creds, &self_attested_attrs).unwrap(); + let proof_req = json!({ + "nonce": "123432421212", + "name": "proof_req_1", + "version": "0.1", + "requested_attributes": { + "height_1": { + "name": "height_1", + "non_revoked": {"from": 123, "to": 456} + }, + "zip_2": { "name": "zip_2" } + }, + "requested_predicates": {}, + "non_revoked": {"from": 098, "to": 123} + }); + let proof_req: ProofRequestData = serde_json::from_value(proof_req).unwrap(); + let requested_credential = proof.build_requested_credentials_json(&creds, &self_attested_attrs, &proof_req).unwrap(); assert_eq!(test.to_string(), requested_credential); } diff --git a/vcx/libvcx/src/utils/constants.rs b/vcx/libvcx/src/utils/constants.rs index 211d6e8427..9a7691bb3e 100644 --- a/vcx/libvcx/src/utils/constants.rs +++ b/vcx/libvcx/src/utils/constants.rs @@ -141,6 +141,7 @@ pub static PROOF_LIBINDY: &str = r#"{"proofs":{"claim::1f927d68-8905-4188-afd6-3 pub static PROOF_REQUEST: &str = r#"{"name":"proof name","nonce":"2771519439","requested_attrs":{"height_0":{"issuer_did":"DunkM3x1y7S4ECgSL4Wkru","name":"height","schema_seq_no":694},"weight_1":{"issuer_did":"DunkM3x1y7S4ECgSL4Wkru","name":"weight","schema_seq_no":694}},"requested_predicates":{"age_2":{"attr_name":"age","p_type":"GE","issuer_did":"DunkM3x1y7S4ECgSL4Wkru","schema_seq_no":694,"value":18}},"version":"0.1"}"#; pub static REQUESTED_ATTRIBUTES: &str = "requested_attributes"; +pub static PROOF_REQUESTED_PREDICATES: &str = "requested_predicates"; pub static ATTRS: &str = "attrs"; pub static ENTERPRISE_PREFIX: &str = "enterprise"; pub static CONSUMER_PREFIX: &str = "consumer"; diff --git a/vcx/libvcx/src/utils/libindy/anoncreds.rs b/vcx/libvcx/src/utils/libindy/anoncreds.rs index 6d4821cc8f..2e4ae37554 100644 --- a/vcx/libvcx/src/utils/libindy/anoncreds.rs +++ b/vcx/libvcx/src/utils/libindy/anoncreds.rs @@ -4,7 +4,7 @@ use futures::Future; use serde_json; use serde_json::{ map::Map, Value}; use settings; -use utils::constants::{ LIBINDY_CRED_OFFER, REQUESTED_ATTRIBUTES, ATTRS, REV_STATE_JSON}; +use utils::constants::{ LIBINDY_CRED_OFFER, REQUESTED_ATTRIBUTES, PROOF_REQUESTED_PREDICATES, ATTRS, REV_STATE_JSON}; use utils::error::{ INVALID_PROOF_REQUEST, INVALID_ATTRIBUTES_STRUCTURE, INVALID_CONFIGURATION, INVALID_JSON, DUPLICATE_SCHEMA, UNKNOWN_SCHEMA_REJECTION } ; use utils::libindy::{ error_codes::map_rust_indy_sdk_error, mock_libindy_rc, wallet::get_wallet_handle }; use utils::libindy::payments::{pay_for_txn, PaymentTxn}; @@ -152,24 +152,35 @@ pub fn libindy_prover_get_credentials_for_proof_req(proof_req: &str) -> Result> = proof_request_json.get(PROOF_REQUESTED_PREDICATES).and_then(|v| { + serde_json::from_value(v.clone()).map_err(|_| { + error!("Invalid Json Parsing of Requested Predicates Retrieved From Libindy. Did Libindy change its structure?"); + }).ok() + }); - match requested_attributes { - Some(attrs) => { - let search_handle = anoncreds::prover_search_credentials_for_proof_req(wallet_handle, proof_req, None) - .wait() - .map_err(|ec| { - error!("Opening Indy Search for Credentials Failed"); - map_rust_indy_sdk_error(ec) - })?; - let creds: String = fetch_credentials(search_handle, attrs)?; - // should an error on closing a search handle throw an error, or just a warning? - // for now we're are just outputting to the user that there is an issue, and continuing on. - let _ = close_search_handle(search_handle); - Ok(creds) - }, - None => { - Err(INVALID_ATTRIBUTES_STRUCTURE.code_num) - } + let mut fetch_attrs: Map = match requested_attributes { + Some(attrs) => attrs.clone(), + None => Map::new() + }; + match requested_predicates { + Some(attrs) => fetch_attrs.extend(attrs), + None => () + } + if 0 < fetch_attrs.len() { + let search_handle = anoncreds::prover_search_credentials_for_proof_req(wallet_handle, proof_req, None) + .wait() + .map_err(|ec| { + error!("Opening Indy Search for Credentials Failed"); + map_rust_indy_sdk_error(ec) + })?; + let creds: String = fetch_credentials(search_handle, fetch_attrs)?; + + // should an error on closing a search handle throw an error, or just a warning? + // for now we're are just outputting to the user that there is an issue, and continuing on. + let _ = close_search_handle(search_handle); + Ok(creds) + } else { + Err(INVALID_ATTRIBUTES_STRUCTURE.code_num) } } diff --git a/vcx/wrappers/python3/demo/demo_utils.py b/vcx/wrappers/python3/demo/demo_utils.py index 7c4e6def3b..420d738fcf 100644 --- a/vcx/wrappers/python3/demo/demo_utils.py +++ b/vcx/wrappers/python3/demo/demo_utils.py @@ -85,10 +85,10 @@ async def send_credential_request(my_connection, cred_def_json, schema_attrs, cr print("Done") -async def send_proof_request(my_connection, institution_did, proof_attrs, proof_uuid, proof_name): +async def send_proof_request(my_connection, institution_did, proof_attrs, proof_uuid, proof_name, proof_predicates): print("#19 Create a Proof object") - proof = await Proof.create(proof_uuid, proof_name, proof_attrs, {}) + proof = await Proof.create(proof_uuid, proof_name, proof_attrs, {}, requested_predicates=proof_predicates) print("#20 Request proof of degree from alice") await proof.request_proof(my_connection) diff --git a/vcx/wrappers/python3/demo/faber-pg.py b/vcx/wrappers/python3/demo/faber-pg.py index 128f5109c5..2d1962b16f 100644 --- a/vcx/wrappers/python3/demo/faber-pg.py +++ b/vcx/wrappers/python3/demo/faber-pg.py @@ -74,7 +74,7 @@ async def main(): print("#3 Create a new schema and cred def on the ledger") schema_uuid = 'schema_uuid' schema_name = 'degree schema' - schema_attrs = ['name', 'date', 'degree'] + schema_attrs = ['name', 'date', 'degree', 'age'] creddef_uuid = 'credef_uuid' creddef_name = 'degree' cred_def_json = await create_schema_and_cred_def(schema_uuid, schema_name, schema_attrs, creddef_uuid, creddef_name) @@ -121,6 +121,7 @@ async def main(): 'name': 'alice', 'date': '05-2018', 'degree': 'maths', + 'age': '24', } cred_tag = 'alice_degree' cred_name = 'cred' @@ -133,10 +134,11 @@ async def main(): {'name': 'date', 'restrictions': [{'issuer_did': config['institution_did']}]}, {'name': 'degree', 'restrictions': [{'issuer_did': config['institution_did']}]} ] + proof_predicates = [{'name':'age', 'p_type':'>=', 'p_value':18},] proof_uuid = 'proof_uuid' proof_name = 'proof_from_alice' - await send_proof_request(my_connection, config['institution_did'], proof_attrs, proof_uuid, proof_name) + await send_proof_request(my_connection, config['institution_did'], proof_attrs, proof_uuid, proof_name, proof_predicates) elif option == '3': await handle_messages(my_connection, handled_offers, handled_requests) diff --git a/vcx/wrappers/python3/vcx/api/proof.py b/vcx/wrappers/python3/vcx/api/proof.py index 89c7f76048..8b4f1f0ad0 100644 --- a/vcx/wrappers/python3/vcx/api/proof.py +++ b/vcx/wrappers/python3/vcx/api/proof.py @@ -24,7 +24,7 @@ def proof_state(self, x): self._proof_state = x @staticmethod - async def create(source_id: str, name: str, requested_attrs: list, revocation_interval: dict): + async def create(source_id: str, name: str, requested_attrs: list, revocation_interval: dict, requested_predicates: list = []): """ Builds a generic proof object :param source_id: Tag associated by user of sdk @@ -42,7 +42,7 @@ async def create(source_id: str, name: str, requested_attrs: list, revocation_in c_source_id = c_char_p(source_id.encode('utf-8')) c_name = c_char_p(name.encode('utf-8')) - c_req_predicates = c_char_p('[]'.encode('utf-8')) + c_req_predicates = c_char_p(json.dumps(requested_predicates).encode('utf-8')) c_req_attrs = c_char_p(json.dumps(requested_attrs).encode('utf-8')) c_revocation_interval = c_char_p(json.dumps(revocation_interval).encode('utf-8')) c_params = (c_source_id, c_req_attrs, c_req_predicates, c_revocation_interval, c_name) From 21b57710751d61fb394a77ef732f0ef0b0922a96 Mon Sep 17 00:00:00 2001 From: Ian Costanzo Date: Mon, 18 Feb 2019 16:36:41 -0800 Subject: [PATCH 2/6] Added a self-attested attribute to the alice/faber vcx demo Signed-off-by: Ian Costanzo --- vcx/wrappers/python3/demo/demo_utils.py | 21 ++++++++++++++++----- vcx/wrappers/python3/demo/faber-pg.py | 3 ++- 2 files changed, 18 insertions(+), 6 deletions(-) diff --git a/vcx/wrappers/python3/demo/demo_utils.py b/vcx/wrappers/python3/demo/demo_utils.py index 420d738fcf..c5a4f88b28 100644 --- a/vcx/wrappers/python3/demo/demo_utils.py +++ b/vcx/wrappers/python3/demo/demo_utils.py @@ -188,15 +188,26 @@ async def handle_proof_request(my_connection, request): print("#24 Query for credentials in the wallet that satisfy the proof request") credentials = await proof.get_creds() - # TODO list credentials and let Alice select + # include self-attested attributes (not included in credentials) + self_attested = {} + # Use the first available credentials to satisfy the proof request for attr in credentials['attrs']: - credentials['attrs'][attr] = { - 'credential': credentials['attrs'][attr][0] - } + if 0 < len(credentials['attrs'][attr]): + credentials['attrs'][attr] = { + 'credential': credentials['attrs'][attr][0] + } + else: + self_attested[attr] = 'my self-attested value' + + for attr in self_attested: + del credentials['attrs'][attr] + + print('credentials', credentials) + print('self_attested', self_attested) print("#25 Generate the proof") - await proof.generate_proof(credentials, {}) + await proof.generate_proof(credentials, self_attested) # TODO figure out why this always segfaults print("#26 Send the proof to X") diff --git a/vcx/wrappers/python3/demo/faber-pg.py b/vcx/wrappers/python3/demo/faber-pg.py index 2d1962b16f..9598baf2c8 100644 --- a/vcx/wrappers/python3/demo/faber-pg.py +++ b/vcx/wrappers/python3/demo/faber-pg.py @@ -132,7 +132,8 @@ async def main(): proof_attrs = [ {'name': 'name', 'restrictions': [{'issuer_did': config['institution_did']}]}, {'name': 'date', 'restrictions': [{'issuer_did': config['institution_did']}]}, - {'name': 'degree', 'restrictions': [{'issuer_did': config['institution_did']}]} + {'name': 'degree', 'restrictions': [{'issuer_did': config['institution_did']}]}, + {'name': 'self_attested_thing'} ] proof_predicates = [{'name':'age', 'p_type':'>=', 'p_value':18},] proof_uuid = 'proof_uuid' From 68679fbf11c2939514588eccf2f54f7503c0c02c Mon Sep 17 00:00:00 2001 From: Ian Costanzo Date: Wed, 13 Mar 2019 14:33:33 -0700 Subject: [PATCH 3/6] Fix comments Signed-off-by: Ian Costanzo --- vcx/libvcx/src/disclosed_proof.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/vcx/libvcx/src/disclosed_proof.rs b/vcx/libvcx/src/disclosed_proof.rs index 527d253a36..51f38bea29 100644 --- a/vcx/libvcx/src/disclosed_proof.rs +++ b/vcx/libvcx/src/disclosed_proof.rs @@ -132,7 +132,7 @@ fn _get_revocation_interval(attr_name: &str, proof_req: &ProofRequestData) -> Vc return Ok(attr.non_revoked.clone().or(proof_req.non_revoked.clone().or(None))); }, None => { - // Todo: Handle case for predicates + // Handle case for predicates match proof_req.requested_predicates.get(attr_name) { Some (attr) => { return Ok(attr.non_revoked.clone().or(proof_req.non_revoked.clone().or(None))); @@ -319,8 +319,7 @@ impl DisclosedProof { "requested_attributes":{}, "requested_predicates":{} }); - //Todo: need to do same for predicates and self_attested - //Todo: need to handle if the attribute is not revealed + // do same for predicates and self_attested if let Value::Object(ref mut map) = rtn["requested_attributes"] { for ref cred_info in credentials_identifiers { if let Some(ref attr) = proof_req.requested_attributes.get(&cred_info.requested_attr) { @@ -339,6 +338,7 @@ impl DisclosedProof { } } + // handle if the attribute is not revealed let self_attested_attrs: Value = serde_json::from_str(self_attested_attrs) .map_err(|err| VcxError::from_msg(VcxErrorKind::InvalidJson, format!("Cannot deserialize self attested attributes: {}", err)))?; rtn["self_attested_attributes"] = self_attested_attrs; From 439cc93c3deb46c19a136ccd414d533a8b88d646 Mon Sep 17 00:00:00 2001 From: Ian Costanzo Date: Thu, 14 Mar 2019 09:39:30 -0700 Subject: [PATCH 4/6] Added predicates unit tests Signed-off-by: Ian Costanzo --- vcx/libvcx/src/disclosed_proof.rs | 61 ++++++++++++ vcx/libvcx/src/utils/libindy/anoncreds.rs | 109 ++++++++++++++++++++++ 2 files changed, 170 insertions(+) diff --git a/vcx/libvcx/src/disclosed_proof.rs b/vcx/libvcx/src/disclosed_proof.rs index 51f38bea29..c6468e0850 100644 --- a/vcx/libvcx/src/disclosed_proof.rs +++ b/vcx/libvcx/src/disclosed_proof.rs @@ -1249,6 +1249,67 @@ mod tests { assert!(generated_proof.is_ok()); } + #[cfg(feature = "pool_tests")] + #[test] + fn test_generate_proof_with_predicates() { + init!("ledger"); + let did = settings::get_config_value(settings::CONFIG_INSTITUTION_DID).unwrap(); + let (schema_id, _, cred_def_id, _, _, _, _, cred_id, _, _) = ::utils::libindy::anoncreds::tests::create_and_store_credential(::utils::constants::DEFAULT_SCHEMA_ATTRS, true); + let mut proof_req = ProofRequestMessage::create(); + let to = time::get_time().sec; + let indy_proof_req = json!({ + "nonce": "123432421212", + "name": "proof_req_1", + "version": "0.1", + "requested_attributes": { + "address1_1": { + "name": "address1", + "restrictions": [{"issuer_did": did}], + "non_revoked": {"from": 123, "to": to} + }, + "zip_2": { "name": "zip" } + }, + "self_attested_attr_3": json!({ + "name":"self_attested_attr", + }), + "requested_predicates": json!({ + "zip_3": {"name":"zip", "p_type":">=", "p_value":18} + }), + "non_revoked": {"from": 098, "to": to} + }).to_string(); + proof_req.proof_request_data = serde_json::from_str(&indy_proof_req).unwrap(); + + let mut proof: DisclosedProof = Default::default(); + proof.proof_request = Some(proof_req); + proof.link_secret_alias = "main".to_string(); + + let all_creds: Value = serde_json::from_str(&proof.retrieve_credentials().unwrap()).unwrap(); + let selected_credentials: Value = json!({ + "attrs":{ + "address1_1": { + "credential": all_creds["attrs"]["address1_1"][0], + "tails_file": get_temp_dir_path(Some(TEST_TAILS_FILE)).to_str().unwrap().to_string() + }, + "zip_2": { + "credential": all_creds["attrs"]["zip_2"][0], + "tails_file": get_temp_dir_path(Some(TEST_TAILS_FILE)).to_str().unwrap().to_string() + }, + }, + "predicates":{ + "zip_3": { + "credential": all_creds["attrs"]["zip_3"][0], + } + } + }); + + let self_attested: Value = json!({ + "self_attested_attr_3":"attested_val" + }); + + let generated_proof = proof.generate_proof(&selected_credentials.to_string(), &self_attested.to_string()); + assert!(generated_proof.is_ok()); + } + #[test] fn test_build_rev_states_json() { init!("true"); diff --git a/vcx/libvcx/src/utils/libindy/anoncreds.rs b/vcx/libvcx/src/utils/libindy/anoncreds.rs index b117db26df..cc62c86a46 100644 --- a/vcx/libvcx/src/utils/libindy/anoncreds.rs +++ b/vcx/libvcx/src/utils/libindy/anoncreds.rs @@ -679,6 +679,77 @@ pub mod tests { (proof_req, proof) } + pub fn create_proof_with_predicate(include_predicate_cred: bool) -> (String, String, String, String) { + let did = settings::get_config_value(settings::CONFIG_INSTITUTION_DID).unwrap(); + let (schema_id, schema_json, cred_def_id, cred_def_json, offer, req, req_meta, cred_id, _, _) + = create_and_store_credential(::utils::constants::DEFAULT_SCHEMA_ATTRS, false); + + let proof_req = json!({ + "nonce":"123432421212", + "name":"proof_req_1", + "version":"0.1", + "requested_attributes": json!({ + "address1_1": json!({ + "name":"address1", + "restrictions": [json!({ "issuer_did": did })] + }), + "self_attest_3": json!({ + "name":"self_attest", + }), + }), + "requested_predicates": json!({ + "zip_3": {"name":"zip", "p_type":">=", "p_value":18} + }), + }).to_string(); + + let requested_credentials_json; + if include_predicate_cred { + requested_credentials_json = json!({ + "self_attested_attributes":{ + "self_attest_3": "my_self_attested_val" + }, + "requested_attributes":{ + "address1_1": {"cred_id": cred_id, "revealed": true} + }, + "requested_predicates":{ + "zip_3": {"cred_id": cred_id} + } + }).to_string(); + } else { + requested_credentials_json = json!({ + "self_attested_attributes":{ + "self_attest_3": "my_self_attested_val" + }, + "requested_attributes":{ + "address1_1": {"cred_id": cred_id, "revealed": true} + }, + "requested_predicates":{ + } + }).to_string(); + } + + let schema_json: serde_json::Value = serde_json::from_str(&schema_json).unwrap(); + let schemas = json!({ + schema_id: schema_json, + }).to_string(); + + let cred_def_json: serde_json::Value = serde_json::from_str(&cred_def_json).unwrap(); + let cred_defs = json!({ + cred_def_id: cred_def_json, + }).to_string(); + + libindy_prover_get_credentials_for_proof_req(&proof_req).unwrap(); + + let proof = libindy_prover_create_proof( + &proof_req, + &requested_credentials_json, + "main", + &schemas, + &cred_defs, + None).unwrap(); + (schemas, cred_defs, proof_req, proof) + } + #[cfg(feature = "pool_tests")] #[test] fn test_prover_verify_proof() { @@ -699,6 +770,44 @@ pub mod tests { assert!(proof_validation, true); } + #[cfg(feature = "pool_tests")] + #[test] + fn test_prover_verify_proof_with_predicate_success_case() { + init!("ledger"); + let (schemas, cred_defs, proof_req, proof) = create_proof_with_predicate(true); + + let result = libindy_verifier_verify_proof( + &proof_req, + &proof, + &schemas, + &cred_defs, + "{}", + "{}", + ); + + assert!(result.is_ok()); + let proof_validation = result.unwrap(); + assert!(proof_validation, true); + } + + #[cfg(feature = "pool_tests")] + #[test] + fn test_prover_verify_proof_with_predicate_fail_case() { + init!("ledger"); + let (schemas, cred_defs, proof_req, proof) = create_proof_with_predicate(false); + + let result = libindy_verifier_verify_proof( + &proof_req, + &proof, + &schemas, + &cred_defs, + "{}", + "{}", + ); + + assert!(!result.is_ok()); + } + #[cfg(feature = "pool_tests")] #[test] fn tests_libindy_prover_get_credentials() { From 933961433ef928214a3a8e34e4e6c39cdb5eb19c Mon Sep 17 00:00:00 2001 From: Ian Costanzo Date: Thu, 14 Mar 2019 14:37:06 -0700 Subject: [PATCH 5/6] Fix for get creds for proof request for edge cases Signed-off-by: Ian Costanzo --- vcx/libvcx/src/utils/libindy/anoncreds.rs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/vcx/libvcx/src/utils/libindy/anoncreds.rs b/vcx/libvcx/src/utils/libindy/anoncreds.rs index cc62c86a46..4f8af2b50f 100644 --- a/vcx/libvcx/src/utils/libindy/anoncreds.rs +++ b/vcx/libvcx/src/utils/libindy/anoncreds.rs @@ -163,6 +163,11 @@ pub fn libindy_prover_get_credentials_for_proof_req(proof_req: &str) -> VcxResul }).ok() }); + // handle special case of "empty because json is bad" vs "empty because no attributes sepected" + if requested_attributes == None && requested_predicates == None { + return Err(VcxError::from_msg(VcxErrorKind::InvalidAttributesStructure, "Invalid Json Parsing of Requested Attributes Retrieved From Libindy")); + } + let mut fetch_attrs: Map = match requested_attributes { Some(attrs) => attrs.clone(), None => Map::new() @@ -185,7 +190,7 @@ pub fn libindy_prover_get_credentials_for_proof_req(proof_req: &str) -> VcxResul let _ = close_search_handle(search_handle); Ok(creds) } else { - Err(VcxError::from_msg(VcxErrorKind::InvalidAttributesStructure, "Invalid Json Parsing of Requested Attributes Retrieved From Libindy")) + Ok("{}".to_string()) } } From cb65825b841323d3858e50180cb2753d7cbc30dc Mon Sep 17 00:00:00 2001 From: Ian Costanzo Date: Fri, 15 Mar 2019 13:31:29 -0700 Subject: [PATCH 6/6] Code cleanup Signed-off-by: Ian Costanzo --- vcx/libvcx/src/disclosed_proof.rs | 24 ++++++++---------------- 1 file changed, 8 insertions(+), 16 deletions(-) diff --git a/vcx/libvcx/src/disclosed_proof.rs b/vcx/libvcx/src/disclosed_proof.rs index c6468e0850..638ed3c1c9 100644 --- a/vcx/libvcx/src/disclosed_proof.rs +++ b/vcx/libvcx/src/disclosed_proof.rs @@ -127,21 +127,13 @@ fn credential_def_identifiers(credentials: &str, proof_req: &ProofRequestData) - } fn _get_revocation_interval(attr_name: &str, proof_req: &ProofRequestData) -> VcxResult> { - match proof_req.requested_attributes.get(attr_name) { - Some(attr) => { - return Ok(attr.non_revoked.clone().or(proof_req.non_revoked.clone().or(None))); - }, - None => { - // Handle case for predicates - match proof_req.requested_predicates.get(attr_name) { - Some (attr) => { - return Ok(attr.non_revoked.clone().or(proof_req.non_revoked.clone().or(None))); - }, - None => { - return Err(VcxError::from_msg(VcxErrorKind::InvalidProofCredentialData, format!("Attribute not found for: {}", attr_name))); - } - } - } + if let Some(attr) = proof_req.requested_attributes.get(attr_name) { + Ok(attr.non_revoked.clone().or(proof_req.non_revoked.clone().or(None))) + } else if let Some(attr) = proof_req.requested_predicates.get(attr_name) { + // Handle case for predicates + Ok(attr.non_revoked.clone().or(proof_req.non_revoked.clone().or(None))) + } else { + Err(VcxError::from_msg(VcxErrorKind::InvalidProofCredentialData, format!("Attribute not found for: {}", attr_name))) } } @@ -332,7 +324,7 @@ impl DisclosedProof { if let Value::Object(ref mut map) = rtn["requested_predicates"] { for ref cred_info in credentials_identifiers { if let Some(ref attr) = proof_req.requested_predicates.get(&cred_info.requested_attr) { - let insert_val = json!({"cred_id": cred_info.referent, "revealed": false, "timestamp": cred_info.timestamp}); + let insert_val = json!({"cred_id": cred_info.referent, "timestamp": cred_info.timestamp}); map.insert(cred_info.requested_attr.to_owned(), insert_val); } }