Source code for aries_cloudagent.vc.vc_ld.verify

"""Verifiable Credential and Presentation verification methods."""

import asyncio
from typing import List
from pyld.jsonld import JsonLdProcessor

from ..ld_proofs import (
    LinkedDataProof,
    CredentialIssuancePurpose,
    DocumentLoaderMethod,
    ProofPurpose,
    AuthenticationProofPurpose,
    verify as ld_proofs_verify,
    DocumentVerificationResult,
    LinkedDataProofException,
)
from .models.credential import VerifiableCredentialSchema
from .validation_result import PresentationVerificationResult


async def _verify_credential(
    *,
    credential: dict,
    suites: List[LinkedDataProof],
    document_loader: DocumentLoaderMethod,
    purpose: ProofPurpose = None,
) -> DocumentVerificationResult:
    """Verify credential structure, proof purpose and signature."""

    # Validate credential structure
    errors = VerifiableCredentialSchema().validate(credential)
    if len(errors) > 0:
        raise LinkedDataProofException(
            f"Unable to verify credential with invalid structure: {errors}"
        )

    if not purpose:
        purpose = CredentialIssuancePurpose()

    result = await ld_proofs_verify(
        document=credential,
        suites=suites,
        purpose=purpose,
        document_loader=document_loader,
    )

    return result


[docs]async def verify_credential( *, credential: dict, suites: List[LinkedDataProof], document_loader: DocumentLoaderMethod, purpose: ProofPurpose = None, ) -> DocumentVerificationResult: """Verify credential structure, proof purpose and signature. Args: credential (dict): The credential to verify suites (List[LinkedDataProof]): The signature suites to verify with document_loader (DocumentLoader): Document loader used for resolving of documents purpose (ProofPurpose, optional): Proof purpose to use. Defaults to CredentialIssuancePurpose Returns: DocumentVerificationResult: The result of the verification. Verified property indicates whether the verification was successful """ try: return await _verify_credential( credential=credential, document_loader=document_loader, suites=suites, purpose=purpose, ) except Exception as e: return DocumentVerificationResult( verified=False, document=credential, errors=[e] )
async def _verify_presentation( *, presentation: dict, suites: List[LinkedDataProof], document_loader: DocumentLoaderMethod, challenge: str = None, domain: str = None, purpose: ProofPurpose = None, ): """Verify presentation structure, credentials, proof purpose and signature.""" if not purpose and not challenge: raise LinkedDataProofException( 'A "challenge" param is required for AuthenticationProofPurpose.' ) elif not purpose: purpose = AuthenticationProofPurpose(challenge=challenge, domain=domain) # TODO validate presentation structure here if "proof" not in presentation: raise LinkedDataProofException('presentation must contain "proof"') presentation_result = await ld_proofs_verify( document=presentation, suites=suites, purpose=purpose, document_loader=document_loader, ) credential_results = None credentials = JsonLdProcessor.get_values(presentation, "verifiableCredential") credential_results = await asyncio.gather( *[ verify_credential( credential=credential, suites=suites, document_loader=document_loader, # FIXME: we don't want to interhit the authentication purpose # from the presentation. However we do want to have subject # authentication I guess # purpose=purpose, ) for credential in credentials ] ) credentials_verified = all(result.verified for result in credential_results) verified = credentials_verified and presentation_result.verified return PresentationVerificationResult( verified=verified, presentation_result=presentation_result, credential_results=credential_results, errors=presentation_result.errors, )
[docs]async def verify_presentation( *, presentation: dict, suites: List[LinkedDataProof], document_loader: DocumentLoaderMethod, purpose: ProofPurpose = None, challenge: str = None, domain: str = None, ) -> PresentationVerificationResult: """Verify presentation structure, credentials, proof purpose and signature. Args: presentation (dict): The presentation to verify suites (List[LinkedDataProof]): The signature suites to verify with document_loader (DocumentLoader): Document loader used for resolving of documents purpose (ProofPurpose, optional): Proof purpose to use. Defaults to AuthenticationProofPurpose challenge (str, optional): The challenge to use for authentication. Required if purpose is not passed, not used if purpose is passed domain (str, optional): Domain to use for the authentication proof purpose. Not used if purpose is passed Returns: PresentationVerificationResult: The result of the verification. Verified property indicates whether the verification was successful """ # TODO: I think we should add some sort of options to authenticate the subject id # to the presentation verification method controller try: return await _verify_presentation( presentation=presentation, challenge=challenge, purpose=purpose, suites=suites, domain=domain, document_loader=document_loader, ) except Exception as e: return PresentationVerificationResult(verified=False, errors=[e])
__all__ = ["verify_presentation", "verify_credential"]