Source code for aries_cloudagent.vc.ld_proofs.suites.linked_data_proof

"""Abstract base class for linked data proofs."""

from abc import ABC
from typing import ClassVar, List, Optional, Union

from pyld import jsonld
from typing_extensions import TypedDict

from ..check import get_properties_without_context
from ..constants import SECURITY_CONTEXT_URL
from ..document_loader import DocumentLoaderMethod
from ..error import LinkedDataProofException
from ..purposes import _ProofPurpose as ProofPurpose
from ..validation_result import ProofResult


[docs]class DeriveProofResult(TypedDict): """Result dict for deriving a proof.""" document: dict proof: Union[dict, List[dict]]
[docs]class LinkedDataProof(ABC): """Base Linked data proof.""" signature_type: ClassVar[str] def __init__( self, *, proof: Optional[dict] = None, supported_derive_proof_types: Optional[List[str]] = None, ): """Initialize new LinkedDataProof instance.""" self.proof = proof self.supported_derive_proof_types = supported_derive_proof_types
[docs] async def create_proof( self, *, document: dict, purpose: ProofPurpose, document_loader: DocumentLoaderMethod, ) -> dict: """Create proof for document. Args: document (dict): The document to create the proof for purpose (ProofPurpose): The proof purpose to include in the proof document_loader (DocumentLoader): Document loader used for resolving Returns: dict: The proof object """ raise LinkedDataProofException( f"{self.signature_type} signature suite does not support creating proofs" )
[docs] async def verify_proof( self, *, proof: dict, document: dict, purpose: ProofPurpose, document_loader: DocumentLoaderMethod, ) -> ProofResult: """Verify proof against document and proof purpose. Args: proof (dict): The proof to verify document (dict): The document to verify the proof against purpose (ProofPurpose): The proof purpose to verify the proof against document_loader (DocumentLoader): Document loader used for resolving Returns: ValidationResult: The results of the proof verification """ raise LinkedDataProofException( f"{self.signature_type} signature suite does not support verifying proofs" )
[docs] async def derive_proof( self, *, proof: dict, document: dict, reveal_document: dict, document_loader: DocumentLoaderMethod, nonce: Optional[bytes] = None, ) -> DeriveProofResult: """Derive proof for document, returning derived document and proof. Args: proof (dict): The proof to derive from document (dict): The document to derive the proof for reveal_document (dict): The JSON-LD frame the revealed attributes document_loader (DocumentLoader): Document loader used for resolving nonce (bytes, optional): Nonce to use for the proof. Defaults to None. Returns: DeriveProofResult: The derived document and proof """ raise LinkedDataProofException( f"{self.signature_type} signature suite does not support deriving proofs" )
def _canonize(self, *, input, document_loader: DocumentLoaderMethod) -> str: """Canonize input document using URDNA2015 algorithm.""" # application/n-quads format always returns str missing_properties = get_properties_without_context(input, document_loader) if len(missing_properties) > 0: raise LinkedDataProofException( f"{len(missing_properties)} attributes dropped. " f"Provide definitions in context to correct. {missing_properties}" ) return jsonld.normalize( input, { "algorithm": "URDNA2015", "format": "application/n-quads", "documentLoader": document_loader, }, ) def _get_verification_method( self, *, proof: dict, document_loader: DocumentLoaderMethod ) -> dict: """Get verification method for proof.""" verification_method = proof.get("verificationMethod") if isinstance(verification_method, dict): verification_method: str = verification_method.get("id") if not verification_method: raise LinkedDataProofException('No "verificationMethod" found in proof') # TODO: This should optionally use the context of the document? framed = jsonld.frame( verification_method, frame={ "@context": SECURITY_CONTEXT_URL, "@embed": "@always", "id": verification_method, }, options={ "documentLoader": document_loader, "expandContext": SECURITY_CONTEXT_URL, # if we don't set base explicitly it will remove the base in returned # document (e.g. use key:z... instead of did:key:z...) # same as compactToRelative in jsonld.js "base": None, }, ) if not framed: raise LinkedDataProofException( f"Verification method {verification_method} not found" ) if framed.get("revoked"): raise LinkedDataProofException("The verification method has been revoked.") return framed
[docs] def match_proof(self, signature_type: str) -> bool: """Match signature type to signature type of this suite.""" return signature_type == self.signature_type