From 346752f97783c7f076c02dff81f20d19f1dcf3af Mon Sep 17 00:00:00 2001 From: Shaanjot Gill Date: Tue, 6 Jul 2021 04:09:59 -0700 Subject: [PATCH 1/5] is_holder property implementation Signed-off-by: Shaanjot Gill --- .../protocols/present_proof/dif/pres_exch.py | 4 +- .../present_proof/dif/pres_exch_handler.py | 59 ++++++++++++++++++- .../present_proof/dif/tests/test_data.py | 42 +++++++++++++ .../present_proof/dif/tests/test_pres_exch.py | 13 +++- .../dif/tests/test_pres_exch_handler.py | 55 +++++++++++++++++ 5 files changed, 168 insertions(+), 5 deletions(-) diff --git a/aries_cloudagent/protocols/present_proof/dif/pres_exch.py b/aries_cloudagent/protocols/present_proof/dif/pres_exch.py index f5f4e7c6f6..0f232beace 100644 --- a/aries_cloudagent/protocols/present_proof/dif/pres_exch.py +++ b/aries_cloudagent/protocols/present_proof/dif/pres_exch.py @@ -236,7 +236,6 @@ class Meta: **UUID4, ), required=False, - data_key="field_id", ) directive = fields.Str( description="Preference", @@ -384,6 +383,7 @@ class Meta: def __init__( self, *, + id: str = None, paths: Sequence[str] = None, purpose: str = None, predicate: str = None, @@ -394,6 +394,7 @@ def __init__( self.purpose = purpose self.predicate = predicate self._filter = _filter + self.id = id class DIFFieldSchema(BaseModelSchema): @@ -405,6 +406,7 @@ class Meta: model_class = DIFField unknown = EXCLUDE + id = fields.Str(description="ID", required=False) paths = fields.List( fields.Str(description="Path", required=False), required=False, diff --git a/aries_cloudagent/protocols/present_proof/dif/pres_exch_handler.py b/aries_cloudagent/protocols/present_proof/dif/pres_exch_handler.py index 141e5077a4..a7d44e75d5 100644 --- a/aries_cloudagent/protocols/present_proof/dif/pres_exch_handler.py +++ b/aries_cloudagent/protocols/present_proof/dif/pres_exch_handler.py @@ -38,6 +38,7 @@ ) from ....vc.vc_ld.prove import sign_presentation, create_presentation, derive_credential from ....wallet.base import BaseWallet, DIDInfo +from ....wallet.did_method import DIDMethod from ....wallet.key_type import KeyType from .pres_exch import ( @@ -99,6 +100,7 @@ def __init__( self.proof_type = Ed25519Signature2018.signature_type else: self.proof_type = proof_type + self.local_dids = None async def _get_issue_suite( self, @@ -373,9 +375,23 @@ async def filter_constraints( continue applicable = False + is_holder_field_ids = self.field_ids_for_is_holder(constraints) for field in constraints._fields: applicable = await self.filter_by_field(field, credential) - if applicable: + # is_holder with required directive requested for this field + if applicable and field.id and field.id in is_holder_field_ids: + # Missing credentialSubject.id - cannot verify that holder of claim + # is same as subject + if not credential.subject_ids or len(credential.subject_ids) == 0: + applicable = False + break + # Holder of claim is not same as the subject + if not await self.process_constraint_holders( + subject_ids=credential.subject_ids + ): + applicable = False + break + if not applicable: break if not applicable: continue @@ -400,6 +416,41 @@ async def filter_constraints( result.append(credential) return result + async def local_dids_list(self): + """Build a local DIDs list used to verify that holder controls subject ident.""" + async with self.profile.session() as session: + wallet = session.inject(BaseWallet) + local_did_info_list = await wallet.get_local_dids() + self.local_dids = [] + for did_info in local_did_info_list: + if did_info.method == DIDMethod.SOV: + self.local_dids.append(f"did:sov:{did_info.did}") + else: + self.local_dids.append(did_info.did) + + def field_ids_for_is_holder(self, constraints: Constraints) -> Sequence[str]: + """Return list of field ids for whose subject holder verification is requested.""" + reqd_field_ids = set() + if not constraints.holders: + reqd_field_ids = [] + return reqd_field_ids + for holder in constraints.holders: + if holder.directive == "required": + reqd_field_ids = set.union(reqd_field_ids, set(holder.field_ids)) + return list(reqd_field_ids) + + async def process_constraint_holders( + self, + subject_ids: Sequence[str], + ) -> bool: + """Check if holder or subject of claim still controls the identifier.""" + if not self.local_dids: + await self.local_dids_list() + for subject_id in subject_ids: + if subject_id not in self.local_dids: + return False + return True + def create_vcrecord(self, cred_dict: dict) -> VCRecord: """Return VCRecord from a credential dict.""" proofs = cred_dict.get("proof") or [] @@ -1202,8 +1253,10 @@ async def create_vp( def check_sign_pres(self, creds: Sequence[VCRecord]) -> bool: """Check if applicable creds have CredentialSubject.id set.""" for cred in creds: - if len(cred.subject_ids) > 0 and not self.check_if_cred_id_derived( - next(iter(cred.subject_ids)) + if ( + cred.subject_ids + and len(cred.subject_ids) > 0 + and not self.check_if_cred_id_derived(next(iter(cred.subject_ids))) ): return True return False diff --git a/aries_cloudagent/protocols/present_proof/dif/tests/test_data.py b/aries_cloudagent/protocols/present_proof/dif/tests/test_data.py index f90912d314..eb64877df3 100644 --- a/aries_cloudagent/protocols/present_proof/dif/tests/test_data.py +++ b/aries_cloudagent/protocols/present_proof/dif/tests/test_data.py @@ -49,6 +49,48 @@ def create_vcrecord(cred_dict: dict, expanded_types: list): ) +is_holder_pd = PresentationDefinition.deserialize( + { + "id": "32f54163-7166-48f1-93d8-ff217bdb0653", + "submission_requirements": [ + { + "name": "European Union Citizenship Proofs", + "rule": "all", + "from": "A", + } + ], + "input_descriptors": [ + { + "id": "citizenship_input_1", + "group": ["A"], + "schema": [ + {"uri": "https://www.w3.org/2018/credentials#VerifiableCredential"}, + {"uri": "https://w3id.org/citizenship#PermanentResidentCard"}, + ], + "constraints": { + "is_holder": [ + { + "directive": "required", + "field_ids": ["1f44d55f-f161-4938-a659-f8026467f126"], + } + ], + "fields": [ + { + "id": "1f44d55f-f161-4938-a659-f8026467f126", + "path": ["$.issuanceDate", "$.vc.issuanceDate"], + "filter": { + "type": "string", + "format": "date", + "maximum": "2014-5-16", + }, + } + ], + }, + } + ], + } +) + creds_with_no_id = [ create_vcrecord( { diff --git a/aries_cloudagent/protocols/present_proof/dif/tests/test_pres_exch.py b/aries_cloudagent/protocols/present_proof/dif/tests/test_pres_exch.py index 60d9b1edc4..21da8b1c6f 100644 --- a/aries_cloudagent/protocols/present_proof/dif/tests/test_pres_exch.py +++ b/aries_cloudagent/protocols/present_proof/dif/tests/test_pres_exch.py @@ -142,10 +142,21 @@ def test_submission_requirements_from_both_present(self): with self.assertRaises(BaseModelError) as cm: (SubmissionRequirements.deserialize(test_json)).serialize() + def test_submission_requirements_from_both_missing(self): + test_json = """ + { + "name": "Citizenship Information", + "rule": "pick", + "count": 1 + } + """ + with self.assertRaises(BaseModelError) as cm: + (SubmissionRequirements.deserialize(test_json)).serialize() + def test_is_holder(self): test_json = """ { - "field_id": [ + "field_ids": [ "ce66380c-1990-4aec-b8b4-5d532e92a616", "dd69e8a4-4cc0-4540-b34a-b4aa0e0d2214", "d15802b4-eec8-45ef-b78f-e35125ac1bb8", diff --git a/aries_cloudagent/protocols/present_proof/dif/tests/test_pres_exch_handler.py b/aries_cloudagent/protocols/present_proof/dif/tests/test_pres_exch_handler.py index c619dc9089..816f461b8d 100644 --- a/aries_cloudagent/protocols/present_proof/dif/tests/test_pres_exch_handler.py +++ b/aries_cloudagent/protocols/present_proof/dif/tests/test_pres_exch_handler.py @@ -48,6 +48,7 @@ bbs_signed_cred_no_credsubjectid, bbs_signed_cred_credsubjectid, creds_with_no_id, + is_holder_pd, ) @@ -77,6 +78,10 @@ async def setup_tuple(profile): await wallet.create_local_did( method=DIDMethod.SOV, key_type=KeyType.ED25519, did="WgWxqztrNooG92RXvxSTWv" ) + await wallet.create_local_did( + method=DIDMethod.KEY, + key_type=KeyType.BLS12381G2, + ) creds, pds = get_test_data() return creds, pds @@ -3062,3 +3067,53 @@ async def test_multiple_applicable_creds_with_no_auto_and_no_record_ids( pd=tmp_pd, challenge="1f44d55f-f161-4938-a659-f8026467f126", ) + + @pytest.mark.asyncio + @pytest.mark.ursa_bbs_signatures + async def test_is_holder_valid(self, profile, setup_tuple): + context = profile.context + context.update_settings({"debug.auto_respond_presentation_request": True}) + dif_pres_exch_handler = DIFPresExchHandler( + profile, proof_type=BbsBlsSignature2020.signature_type + ) + cred_list, pd_list = setup_tuple + tmp_vp = await dif_pres_exch_handler.create_vp( + credentials=cred_list, + pd=is_holder_pd, + challenge="1f44d55f-f161-4938-a659-f8026467f126", + ) + assert len(tmp_vp.get("verifiableCredential")) == 6 + + @pytest.mark.asyncio + @pytest.mark.ursa_bbs_signatures + async def test_is_holder_invalid_a(self, profile, setup_tuple): + dif_pres_exch_handler = DIFPresExchHandler( + profile, proof_type=BbsBlsSignature2020.signature_type + ) + cred_list, pd_list = setup_tuple + updated_cred_list = [] + for tmp_cred in deepcopy(cred_list): + tmp_cred.subject_ids = ["did:sov:test"] + updated_cred_list.append(tmp_cred) + tmp_vp = await dif_pres_exch_handler.create_vp( + credentials=updated_cred_list, + pd=is_holder_pd, + challenge="1f44d55f-f161-4938-a659-f8026467f126", + ) + assert len(tmp_vp.get("verifiableCredential")) == 0 + + @pytest.mark.asyncio + @pytest.mark.ursa_bbs_signatures + async def test_is_holder_invalid_b(self, profile, setup_tuple): + dif_pres_exch_handler = DIFPresExchHandler( + profile, proof_type=BbsBlsSignature2020.signature_type + ) + cred_list, pd_list = setup_tuple + tmp_cred = deepcopy(cred_list[0]) + tmp_cred.subject_ids = None + tmp_vp = await dif_pres_exch_handler.create_vp( + credentials=[tmp_cred], + pd=is_holder_pd, + challenge="1f44d55f-f161-4938-a659-f8026467f126", + ) + assert len(tmp_vp.get("verifiableCredential")) == 0 From 7e6fa4dbf37d52ac3bab0571764a51d4543d9b3e Mon Sep 17 00:00:00 2001 From: Shaanjot Gill Date: Tue, 6 Jul 2021 12:31:44 -0700 Subject: [PATCH 2/5] updates and more tests Signed-off-by: Shaanjot Gill --- .../protocols/present_proof/dif/pres_exch.py | 1 + .../present_proof/dif/pres_exch_handler.py | 6 +- .../present_proof/dif/tests/test_data.py | 107 +++++++++++++++++- .../present_proof/dif/tests/test_pres_exch.py | 2 +- .../dif/tests/test_pres_exch_handler.py | 36 +++++- 5 files changed, 144 insertions(+), 8 deletions(-) diff --git a/aries_cloudagent/protocols/present_proof/dif/pres_exch.py b/aries_cloudagent/protocols/present_proof/dif/pres_exch.py index 0f232beace..a00942c35b 100644 --- a/aries_cloudagent/protocols/present_proof/dif/pres_exch.py +++ b/aries_cloudagent/protocols/present_proof/dif/pres_exch.py @@ -236,6 +236,7 @@ class Meta: **UUID4, ), required=False, + data_key="field_id", ) directive = fields.Str( description="Preference", diff --git a/aries_cloudagent/protocols/present_proof/dif/pres_exch_handler.py b/aries_cloudagent/protocols/present_proof/dif/pres_exch_handler.py index a7d44e75d5..24ca199aa5 100644 --- a/aries_cloudagent/protocols/present_proof/dif/pres_exch_handler.py +++ b/aries_cloudagent/protocols/present_proof/dif/pres_exch_handler.py @@ -378,6 +378,9 @@ async def filter_constraints( is_holder_field_ids = self.field_ids_for_is_holder(constraints) for field in constraints._fields: applicable = await self.filter_by_field(field, credential) + # all fields in the constraint should be satisfied + if not applicable: + break # is_holder with required directive requested for this field if applicable and field.id and field.id in is_holder_field_ids: # Missing credentialSubject.id - cannot verify that holder of claim @@ -391,11 +394,8 @@ async def filter_constraints( ): applicable = False break - if not applicable: - break if not applicable: continue - if constraints.limit_disclosure == "required": credential_dict = credential.cred_value new_credential_dict = self.reveal_doc( diff --git a/aries_cloudagent/protocols/present_proof/dif/tests/test_data.py b/aries_cloudagent/protocols/present_proof/dif/tests/test_data.py index eb64877df3..f45a09743d 100644 --- a/aries_cloudagent/protocols/present_proof/dif/tests/test_data.py +++ b/aries_cloudagent/protocols/present_proof/dif/tests/test_data.py @@ -71,7 +71,7 @@ def create_vcrecord(cred_dict: dict, expanded_types: list): "is_holder": [ { "directive": "required", - "field_ids": ["1f44d55f-f161-4938-a659-f8026467f126"], + "field_id": ["1f44d55f-f161-4938-a659-f8026467f126"], } ], "fields": [ @@ -91,6 +91,111 @@ def create_vcrecord(cred_dict: dict, expanded_types: list): } ) +is_holder_pd_multiple_fields_included = PresentationDefinition.deserialize( + { + "id": "32f54163-7166-48f1-93d8-ff217bdb0653", + "submission_requirements": [ + { + "name": "European Union Citizenship Proofs", + "rule": "all", + "from": "A", + } + ], + "input_descriptors": [ + { + "id": "citizenship_input_1", + "group": ["A"], + "schema": [ + {"uri": "https://www.w3.org/2018/credentials#VerifiableCredential"}, + {"uri": "https://w3id.org/citizenship#PermanentResidentCard"}, + ], + "constraints": { + "is_holder": [ + { + "directive": "required", + "field_id": [ + "1f44d55f-f161-4938-a659-f8026467f126", + "1f44d55f-f161-4938-a659-f8026467f127", + ], + } + ], + "fields": [ + { + "id": "1f44d55f-f161-4938-a659-f8026467f126", + "path": ["$.issuanceDate", "$.vc.issuanceDate"], + "filter": { + "type": "string", + "format": "date", + "maximum": "2014-5-16", + }, + }, + { + "id": "1f44d55f-f161-4938-a659-f8026467f127", + "path": ["$.issuanceDate", "$.vc.issuanceDate"], + "filter": { + "type": "string", + "format": "date", + "minimum": "2005-5-16", + }, + }, + ], + }, + } + ], + } +) + +is_holder_pd_multiple_fields_excluded = PresentationDefinition.deserialize( + { + "id": "32f54163-7166-48f1-93d8-ff217bdb0653", + "submission_requirements": [ + { + "name": "European Union Citizenship Proofs", + "rule": "all", + "from": "A", + } + ], + "input_descriptors": [ + { + "id": "citizenship_input_1", + "group": ["A"], + "schema": [ + {"uri": "https://www.w3.org/2018/credentials#VerifiableCredential"}, + {"uri": "https://w3id.org/citizenship#PermanentResidentCard"}, + ], + "constraints": { + "is_holder": [ + { + "directive": "required", + "field_id": ["1f44d55f-f161-4938-a659-f8026467f126"], + } + ], + "fields": [ + { + "id": "1f44d55f-f161-4938-a659-f8026467f126", + "path": ["$.issuanceDate", "$.vc.issuanceDate"], + "filter": { + "type": "string", + "format": "date", + "maximum": "2014-5-16", + }, + }, + { + "id": "1f44d55f-f161-4938-a659-f8026467f127", + "path": ["$.issuanceDate", "$.vc.issuanceDate"], + "filter": { + "type": "string", + "format": "date", + "minimum": "2005-5-16", + }, + }, + ], + }, + } + ], + } +) + creds_with_no_id = [ create_vcrecord( { diff --git a/aries_cloudagent/protocols/present_proof/dif/tests/test_pres_exch.py b/aries_cloudagent/protocols/present_proof/dif/tests/test_pres_exch.py index 21da8b1c6f..417b11edaa 100644 --- a/aries_cloudagent/protocols/present_proof/dif/tests/test_pres_exch.py +++ b/aries_cloudagent/protocols/present_proof/dif/tests/test_pres_exch.py @@ -156,7 +156,7 @@ def test_submission_requirements_from_both_missing(self): def test_is_holder(self): test_json = """ { - "field_ids": [ + "field_id": [ "ce66380c-1990-4aec-b8b4-5d532e92a616", "dd69e8a4-4cc0-4540-b34a-b4aa0e0d2214", "d15802b4-eec8-45ef-b78f-e35125ac1bb8", diff --git a/aries_cloudagent/protocols/present_proof/dif/tests/test_pres_exch_handler.py b/aries_cloudagent/protocols/present_proof/dif/tests/test_pres_exch_handler.py index 816f461b8d..4ff4492f6f 100644 --- a/aries_cloudagent/protocols/present_proof/dif/tests/test_pres_exch_handler.py +++ b/aries_cloudagent/protocols/present_proof/dif/tests/test_pres_exch_handler.py @@ -49,6 +49,8 @@ bbs_signed_cred_credsubjectid, creds_with_no_id, is_holder_pd, + is_holder_pd_multiple_fields_excluded, + is_holder_pd_multiple_fields_included, ) @@ -3070,7 +3072,7 @@ async def test_multiple_applicable_creds_with_no_auto_and_no_record_ids( @pytest.mark.asyncio @pytest.mark.ursa_bbs_signatures - async def test_is_holder_valid(self, profile, setup_tuple): + async def test_is_holder_valid_a(self, profile, setup_tuple): context = profile.context context.update_settings({"debug.auto_respond_presentation_request": True}) dif_pres_exch_handler = DIFPresExchHandler( @@ -3086,7 +3088,35 @@ async def test_is_holder_valid(self, profile, setup_tuple): @pytest.mark.asyncio @pytest.mark.ursa_bbs_signatures - async def test_is_holder_invalid_a(self, profile, setup_tuple): + async def test_is_holder_valid_b(self, profile, setup_tuple): + dif_pres_exch_handler = DIFPresExchHandler( + profile, proof_type=BbsBlsSignature2020.signature_type + ) + cred_list, pd_list = setup_tuple + tmp_vp = await dif_pres_exch_handler.create_vp( + credentials=cred_list, + pd=is_holder_pd_multiple_fields_included, + challenge="1f44d55f-f161-4938-a659-f8026467f126", + ) + assert len(tmp_vp.get("verifiableCredential")) == 6 + + @pytest.mark.asyncio + @pytest.mark.ursa_bbs_signatures + async def test_is_holder_valid_c(self, profile, setup_tuple): + dif_pres_exch_handler = DIFPresExchHandler( + profile, proof_type=BbsBlsSignature2020.signature_type + ) + cred_list, pd_list = setup_tuple + tmp_vp = await dif_pres_exch_handler.create_vp( + credentials=cred_list, + pd=is_holder_pd_multiple_fields_excluded, + challenge="1f44d55f-f161-4938-a659-f8026467f126", + ) + assert len(tmp_vp.get("verifiableCredential")) == 6 + + @pytest.mark.asyncio + @pytest.mark.ursa_bbs_signatures + async def test_is_holder_subject_mismatch(self, profile, setup_tuple): dif_pres_exch_handler = DIFPresExchHandler( profile, proof_type=BbsBlsSignature2020.signature_type ) @@ -3104,7 +3134,7 @@ async def test_is_holder_invalid_a(self, profile, setup_tuple): @pytest.mark.asyncio @pytest.mark.ursa_bbs_signatures - async def test_is_holder_invalid_b(self, profile, setup_tuple): + async def test_is_holder_missing_subject(self, profile, setup_tuple): dif_pres_exch_handler = DIFPresExchHandler( profile, proof_type=BbsBlsSignature2020.signature_type ) From 07e8c1367152b0fba79dbf41d9a01412be6d4b09 Mon Sep 17 00:00:00 2001 From: Shaanjot Gill Date: Wed, 7 Jul 2021 17:41:17 -0700 Subject: [PATCH 3/5] using get_local_did() for better performace Signed-off-by: Shaanjot Gill --- .../present_proof/dif/pres_exch_handler.py | 27 ++++++------------- 1 file changed, 8 insertions(+), 19 deletions(-) diff --git a/aries_cloudagent/protocols/present_proof/dif/pres_exch_handler.py b/aries_cloudagent/protocols/present_proof/dif/pres_exch_handler.py index 24ca199aa5..2cb32b448c 100644 --- a/aries_cloudagent/protocols/present_proof/dif/pres_exch_handler.py +++ b/aries_cloudagent/protocols/present_proof/dif/pres_exch_handler.py @@ -38,7 +38,7 @@ ) from ....vc.vc_ld.prove import sign_presentation, create_presentation, derive_credential from ....wallet.base import BaseWallet, DIDInfo -from ....wallet.did_method import DIDMethod +from ....wallet.error import WalletError, WalletNotFoundError from ....wallet.key_type import KeyType from .pres_exch import ( @@ -100,7 +100,6 @@ def __init__( self.proof_type = Ed25519Signature2018.signature_type else: self.proof_type = proof_type - self.local_dids = None async def _get_issue_suite( self, @@ -416,18 +415,6 @@ async def filter_constraints( result.append(credential) return result - async def local_dids_list(self): - """Build a local DIDs list used to verify that holder controls subject ident.""" - async with self.profile.session() as session: - wallet = session.inject(BaseWallet) - local_did_info_list = await wallet.get_local_dids() - self.local_dids = [] - for did_info in local_did_info_list: - if did_info.method == DIDMethod.SOV: - self.local_dids.append(f"did:sov:{did_info.did}") - else: - self.local_dids.append(did_info.did) - def field_ids_for_is_holder(self, constraints: Constraints) -> Sequence[str]: """Return list of field ids for whose subject holder verification is requested.""" reqd_field_ids = set() @@ -444,12 +431,14 @@ async def process_constraint_holders( subject_ids: Sequence[str], ) -> bool: """Check if holder or subject of claim still controls the identifier.""" - if not self.local_dids: - await self.local_dids_list() - for subject_id in subject_ids: - if subject_id not in self.local_dids: + async with self.profile.session() as session: + wallet = session.inject(BaseWallet) + try: + for subject_id in subject_ids: + await wallet.get_local_did(subject_id.replace("did:sov:", "")) + return True + except (WalletError, WalletNotFoundError): return False - return True def create_vcrecord(self, cred_dict: dict) -> VCRecord: """Return VCRecord from a credential dict.""" From ca648c0290416076268f4e121106d9c53bf66dc1 Mon Sep 17 00:00:00 2001 From: Shaanjot Gill Date: Wed, 7 Jul 2021 18:22:31 -0700 Subject: [PATCH 4/5] is_holder linked to VP signing Signed-off-by: Shaanjot Gill --- .../protocols/present_proof/dif/pres_exch_handler.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/aries_cloudagent/protocols/present_proof/dif/pres_exch_handler.py b/aries_cloudagent/protocols/present_proof/dif/pres_exch_handler.py index 2cb32b448c..b94dcbe36a 100644 --- a/aries_cloudagent/protocols/present_proof/dif/pres_exch_handler.py +++ b/aries_cloudagent/protocols/present_proof/dif/pres_exch_handler.py @@ -100,6 +100,7 @@ def __init__( self.proof_type = Ed25519Signature2018.signature_type else: self.proof_type = proof_type + self.is_holder = False async def _get_issue_suite( self, @@ -436,6 +437,7 @@ async def process_constraint_holders( try: for subject_id in subject_ids: await wallet.get_local_did(subject_id.replace("did:sov:", "")) + self.is_holder = True return True except (WalletError, WalletNotFoundError): return False @@ -1186,7 +1188,7 @@ async def create_vp( submission_property = PresentationSubmission( id=str(uuid4()), definition_id=pd.id, descriptor_maps=descriptor_maps ) - if self.check_sign_pres(applicable_creds): + if self.is_holder and self.check_sign_pres(applicable_creds): ( issuer_id, filtered_creds_list, From 33b7bc4548f2d12f40893b75241d91a06dbc9591 Mon Sep 17 00:00:00 2001 From: Shaanjot Gill Date: Thu, 8 Jul 2021 00:56:01 -0700 Subject: [PATCH 5/5] test updates and removing check_sign_pres Signed-off-by: Shaanjot Gill --- .../present_proof/dif/pres_exch_handler.py | 15 +----- .../dif/tests/test_pres_exch_handler.py | 46 ++++++++++--------- 2 files changed, 26 insertions(+), 35 deletions(-) diff --git a/aries_cloudagent/protocols/present_proof/dif/pres_exch_handler.py b/aries_cloudagent/protocols/present_proof/dif/pres_exch_handler.py index b94dcbe36a..be33ca5c60 100644 --- a/aries_cloudagent/protocols/present_proof/dif/pres_exch_handler.py +++ b/aries_cloudagent/protocols/present_proof/dif/pres_exch_handler.py @@ -193,7 +193,7 @@ async def get_sign_key_credential_subject_id( else: reqd_key_type = KeyType.ED25519 for cred in applicable_creds: - if len(cred.subject_ids) > 0: + if cred.subject_ids and len(cred.subject_ids) > 0: if not issuer_id: for cred_subject_id in cred.subject_ids: if not cred_subject_id.startswith("urn:"): @@ -1188,7 +1188,7 @@ async def create_vp( submission_property = PresentationSubmission( id=str(uuid4()), definition_id=pd.id, descriptor_maps=descriptor_maps ) - if self.is_holder and self.check_sign_pres(applicable_creds): + if self.is_holder: ( issuer_id, filtered_creds_list, @@ -1241,17 +1241,6 @@ async def create_vp( else: return vp - def check_sign_pres(self, creds: Sequence[VCRecord]) -> bool: - """Check if applicable creds have CredentialSubject.id set.""" - for cred in creds: - if ( - cred.subject_ids - and len(cred.subject_ids) > 0 - and not self.check_if_cred_id_derived(next(iter(cred.subject_ids))) - ): - return True - return False - def check_if_cred_id_derived(self, id: str) -> bool: """Check if credential or credentialSubjet id is derived.""" if id.startswith("urn:bnid:_:c14n"): diff --git a/aries_cloudagent/protocols/present_proof/dif/tests/test_pres_exch_handler.py b/aries_cloudagent/protocols/present_proof/dif/tests/test_pres_exch_handler.py index 4ff4492f6f..7bf07c49bb 100644 --- a/aries_cloudagent/protocols/present_proof/dif/tests/test_pres_exch_handler.py +++ b/aries_cloudagent/protocols/present_proof/dif/tests/test_pres_exch_handler.py @@ -2156,10 +2156,6 @@ async def test_create_vp_no_issuer(self, profile, setup_tuple): "merge", async_mock.CoroutineMock(), ) as mock_merge, async_mock.patch.object( - DIFPresExchHandler, - "check_sign_pres", - async_mock.CoroutineMock(), - ) as mock_check_sign_pres, async_mock.patch.object( test_module, "create_presentation", async_mock.CoroutineMock(), @@ -2167,7 +2163,7 @@ async def test_create_vp_no_issuer(self, profile, setup_tuple): mock_make_req.return_value = async_mock.MagicMock() mock_apply_req.return_value = async_mock.MagicMock() mock_merge.return_value = (VC_RECORDS, {}) - mock_check_sign_pres.return_value = True + dif_pres_exch_handler.is_holder = True mock_create_vp.return_value = {"test": "1"} did_info = DIDInfo( did="did:key:z6Mkgg342Ycpuk263R9d8Aq6MUaxPn1DDeHyGo38EefXmgDL", @@ -2211,10 +2207,6 @@ async def test_create_vp_with_bbs_suite(self, profile, setup_tuple): "merge", async_mock.CoroutineMock(), ) as mock_merge, async_mock.patch.object( - DIFPresExchHandler, - "check_sign_pres", - async_mock.CoroutineMock(), - ) as mock_check_sign_pres, async_mock.patch.object( test_module, "create_presentation", async_mock.CoroutineMock(), @@ -2226,7 +2218,7 @@ async def test_create_vp_with_bbs_suite(self, profile, setup_tuple): mock_make_req.return_value = async_mock.MagicMock() mock_apply_req.return_value = async_mock.MagicMock() mock_merge.return_value = (cred_list, {}) - mock_check_sign_pres.return_value = True + dif_pres_exch_handler.is_holder = True mock_create_vp.return_value = {"test": "1", "@context": ["test"]} mock_sign_vp.return_value = { "test": "1", @@ -2271,10 +2263,6 @@ async def test_create_vp_no_issuer_with_bbs_suite(self, profile, setup_tuple): "merge", async_mock.CoroutineMock(), ) as mock_merge, async_mock.patch.object( - DIFPresExchHandler, - "check_sign_pres", - async_mock.CoroutineMock(), - ) as mock_check_sign_pres, async_mock.patch.object( test_module, "create_presentation", async_mock.CoroutineMock(), @@ -2286,7 +2274,7 @@ async def test_create_vp_no_issuer_with_bbs_suite(self, profile, setup_tuple): mock_make_req.return_value = async_mock.MagicMock() mock_apply_req.return_value = async_mock.MagicMock() mock_merge.return_value = (cred_list, {}) - mock_check_sign_pres.return_value = True + dif_pres_exch_handler.is_holder = True mock_create_vp.return_value = {"test": "1", "@context": ["test"]} mock_sign_key_cred_subject.return_value = (None, []) did_info = DIDInfo( @@ -3075,9 +3063,7 @@ async def test_multiple_applicable_creds_with_no_auto_and_no_record_ids( async def test_is_holder_valid_a(self, profile, setup_tuple): context = profile.context context.update_settings({"debug.auto_respond_presentation_request": True}) - dif_pres_exch_handler = DIFPresExchHandler( - profile, proof_type=BbsBlsSignature2020.signature_type - ) + dif_pres_exch_handler = DIFPresExchHandler(profile) cred_list, pd_list = setup_tuple tmp_vp = await dif_pres_exch_handler.create_vp( credentials=cred_list, @@ -3085,13 +3071,12 @@ async def test_is_holder_valid_a(self, profile, setup_tuple): challenge="1f44d55f-f161-4938-a659-f8026467f126", ) assert len(tmp_vp.get("verifiableCredential")) == 6 + assert tmp_vp.get("proof") @pytest.mark.asyncio @pytest.mark.ursa_bbs_signatures async def test_is_holder_valid_b(self, profile, setup_tuple): - dif_pres_exch_handler = DIFPresExchHandler( - profile, proof_type=BbsBlsSignature2020.signature_type - ) + dif_pres_exch_handler = DIFPresExchHandler(profile) cred_list, pd_list = setup_tuple tmp_vp = await dif_pres_exch_handler.create_vp( credentials=cred_list, @@ -3099,20 +3084,35 @@ async def test_is_holder_valid_b(self, profile, setup_tuple): challenge="1f44d55f-f161-4938-a659-f8026467f126", ) assert len(tmp_vp.get("verifiableCredential")) == 6 + assert tmp_vp.get("proof") @pytest.mark.asyncio @pytest.mark.ursa_bbs_signatures async def test_is_holder_valid_c(self, profile, setup_tuple): + dif_pres_exch_handler = DIFPresExchHandler(profile) + cred_list, pd_list = setup_tuple + tmp_vp = await dif_pres_exch_handler.create_vp( + credentials=cred_list, + pd=is_holder_pd_multiple_fields_excluded, + challenge="1f44d55f-f161-4938-a659-f8026467f126", + ) + assert len(tmp_vp.get("verifiableCredential")) == 6 + assert tmp_vp.get("proof") + + @pytest.mark.asyncio + @pytest.mark.ursa_bbs_signatures + async def test_is_holder_signature_suite_mismatch(self, profile, setup_tuple): dif_pres_exch_handler = DIFPresExchHandler( profile, proof_type=BbsBlsSignature2020.signature_type ) cred_list, pd_list = setup_tuple tmp_vp = await dif_pres_exch_handler.create_vp( credentials=cred_list, - pd=is_holder_pd_multiple_fields_excluded, + pd=is_holder_pd, challenge="1f44d55f-f161-4938-a659-f8026467f126", ) assert len(tmp_vp.get("verifiableCredential")) == 6 + assert not tmp_vp.get("proof") @pytest.mark.asyncio @pytest.mark.ursa_bbs_signatures @@ -3131,6 +3131,7 @@ async def test_is_holder_subject_mismatch(self, profile, setup_tuple): challenge="1f44d55f-f161-4938-a659-f8026467f126", ) assert len(tmp_vp.get("verifiableCredential")) == 0 + assert not tmp_vp.get("proof") @pytest.mark.asyncio @pytest.mark.ursa_bbs_signatures @@ -3147,3 +3148,4 @@ async def test_is_holder_missing_subject(self, profile, setup_tuple): challenge="1f44d55f-f161-4938-a659-f8026467f126", ) assert len(tmp_vp.get("verifiableCredential")) == 0 + assert not tmp_vp.get("proof")