Skip to content

Commit

Permalink
feat: add vc ldp routes and implement verify
Browse files Browse the repository at this point in the history
Signed-off-by: Daniel Bluhm <[email protected]>
  • Loading branch information
dbluhm committed Oct 5, 2023
1 parent b303b6b commit d6905a6
Show file tree
Hide file tree
Showing 8 changed files with 148 additions and 26 deletions.
1 change: 1 addition & 0 deletions aries_cloudagent/config/default_context.py
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,7 @@ async def load_plugins(self, context: InjectionContext):
plugin_registry.register_plugin("aries_cloudagent.revocation")
plugin_registry.register_plugin("aries_cloudagent.resolver")
plugin_registry.register_plugin("aries_cloudagent.settings")
plugin_registry.register_plugin("aries_cloudagent.vc")
plugin_registry.register_plugin("aries_cloudagent.wallet")

if context.settings.get("multitenant.admin_enabled"):
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ def validate(
document_loader=document_loader,
)
except Exception as e:
return PurposeResult(valid=False, error=e)
return PurposeResult(valid=False, error=str(e))

def update(self, proof: dict) -> dict:
"""Update poof purpose, challenge and domain on proof."""
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -90,4 +90,4 @@ def validate(
return result

except Exception as e:
return PurposeResult(valid=False, error=e)
return PurposeResult(valid=False, error=str(e))
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@

# Avoid circular dependency
if TYPE_CHECKING:
from ..suites import LinkedDataProof
from ..suites import _LinkedDataProof as LinkedDataProof


class CredentialIssuancePurpose(AssertionProofPurpose):
Expand Down Expand Up @@ -70,4 +70,4 @@ def validate(

return result
except Exception as e:
return PurposeResult(valid=False, error=e)
return PurposeResult(valid=False, error=str(e))
2 changes: 1 addition & 1 deletion aries_cloudagent/vc/ld_proofs/purposes/proof_purpose.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ def validate(

return PurposeResult(valid=True)
except Exception as err:
return PurposeResult(valid=False, error=err)
return PurposeResult(valid=False, error=str(err))

def update(self, proof: dict) -> dict:
"""Update proof purpose on proof."""
Expand Down
86 changes: 75 additions & 11 deletions aries_cloudagent/vc/ld_proofs/validation_result.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,26 @@
"""Proof verification and validation result classes."""

from typing import List
from typing import Any, List, Optional

from marshmallow import fields

class PurposeResult:
from ...messaging.models.base import BaseModel, BaseModelSchema


class PurposeResult(BaseModel):
"""Proof purpose result class."""

class Meta:
"""PurposeResult metadata."""

schema_class = "PurposeResultSchema"

def __init__(
self, *, valid: bool, error: Exception = None, controller: dict = None
self,
*,
valid: bool,
error: Optional[str] = None,
controller: Optional[Any] = None,
) -> None:
"""Create new PurposeResult instance."""
self.valid = valid
Expand Down Expand Up @@ -35,16 +48,34 @@ def __eq__(self, other: object) -> bool:
return False


class ProofResult:
class PurposeResultSchema(BaseModelSchema):
"""Proof purpose result schema."""

class Meta:
"""PurposeResultSchema metadata."""

model_class = PurposeResult

valid = fields.Boolean()
error = fields.Str()
controller = fields.Dict()


class ProofResult(BaseModel):
"""Proof result class."""

class Meta:
"""ProofResult metadata."""

schema_class = "ProofResultSchema"

def __init__(
self,
*,
verified: bool,
proof: dict = None,
error: Exception = None,
purpose_result: PurposeResult = None,
proof: Optional[dict] = None,
error: Optional[str] = None,
purpose_result: Optional[PurposeResult] = None,
) -> None:
"""Create new ProofResult instance."""
self.verified = verified
Expand Down Expand Up @@ -74,16 +105,35 @@ def __eq__(self, other: object) -> bool:
return False


class DocumentVerificationResult:
class ProofResultSchema(BaseModelSchema):
"""Proof result schema."""

class Meta:
"""ProofResultSchema metadata."""

model_class = ProofResult

verified = fields.Boolean()
proof = fields.Dict()
error = fields.Str()
purpose_result = fields.Nested(PurposeResultSchema)


class DocumentVerificationResult(BaseModel):
"""Domain verification result class."""

class Meta:
"""DocumentVerificationResult metadata."""

schema_class = "DocumentVerificationResultSchema"

def __init__(
self,
*,
verified: bool,
document: dict = None,
results: List[ProofResult] = None,
errors: List[Exception] = None,
document: Optional[dict] = None,
results: Optional[List[ProofResult]] = None,
errors: Optional[List[str]] = None,
) -> None:
"""Create new DocumentVerificationResult instance."""
self.verified = verified
Expand Down Expand Up @@ -141,3 +191,17 @@ def __eq__(self, other: object) -> bool:
)
)
return False


class DocumentVerificationResultSchema(BaseModelSchema):
"""Document verification result schema."""

class Meta:
"""DocumentVerificationResultSchema metadata."""

model_class = DocumentVerificationResult

verified = fields.Boolean(required=True)
document = fields.Dict(required=False)
results = fields.Nested(ProofResultSchema, many=True)
errors = fields.List(fields.Str(), required=False)
44 changes: 39 additions & 5 deletions aries_cloudagent/vc/vc_ld/manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
SECURITY_CONTEXT_BBS_URL,
SECURITY_CONTEXT_ED25519_2020_URL,
)
from aries_cloudagent.vc.ld_proofs.document_loader import DocumentLoader

from ...core.profile import Profile
from ...wallet.base import BaseWallet
Expand All @@ -16,17 +15,21 @@
from ...wallet.error import WalletNotFoundError
from ...wallet.key_type import BLS12381G2, ED25519
from ..ld_proofs.crypto.wallet_key_pair import WalletKeyPair
from ..ld_proofs.document_loader import DocumentLoader
from ..ld_proofs.purposes.authentication_proof_purpose import AuthenticationProofPurpose
from ..ld_proofs.purposes.credential_issuance_purpose import CredentialIssuancePurpose
from ..ld_proofs.purposes.proof_purpose import ProofPurpose
from ..ld_proofs.suites.bbs_bls_signature_2020 import BbsBlsSignature2020
from ..ld_proofs.suites.ed25519_signature_2018 import Ed25519Signature2018
from ..ld_proofs.suites.ed25519_signature_2020 import Ed25519Signature2020
from ..ld_proofs.suites.linked_data_proof import LinkedDataProof
from ..ld_proofs.validation_result import DocumentVerificationResult
from ..vc_ld.validation_result import PresentationVerificationResult
from .issue import issue as ldp_issue
from .models.credential import VerifiableCredential
from .models.linked_data_proof import LDProof
from .models.options import LDProofVCOptions
from .verify import verify_credential, verify_presentation


SUPPORTED_ISSUANCE_PROOF_PURPOSES = {
Expand Down Expand Up @@ -297,7 +300,20 @@ async def _get_suite_for_credential(

return suite

async def issue(self, credential: VerifiableCredential, options: LDProofVCOptions):
async def _get_all_suites(self):
"""Get all supported suites for verifying presentation."""
suites = []
for suite, key_type in SIGNATURE_SUITE_KEY_TYPE_MAPPING.items():
suites.append(
suite(
key_pair=WalletKeyPair(profile=self.profile, key_type=key_type),
)
)
return suites

async def issue(
self, credential: VerifiableCredential, options: LDProofVCOptions
) -> VerifiableCredential:
"""Sign a VC with a Linked Data Proof."""
credential = await self._prepare_credential(credential, options)

Expand All @@ -317,10 +333,28 @@ async def issue(self, credential: VerifiableCredential, options: LDProofVCOption
document_loader=document_loader,
purpose=proof_purpose,
)
return vc
return VerifiableCredential.deserialize(vc)

async def verify_presentation(self):
async def verify_presentation(
self, vp: VerifiableCredential, options: LDProofVCOptions
) -> PresentationVerificationResult:
"""Verify a VP with a Linked Data Proof."""
if not options.challenge:
raise VcLdpManagerError("Challenge is required for verifying a VP")

async def verify_credential(self):
return await verify_presentation(
presentation=vp.serialize(),
suites=await self._get_all_suites(),
document_loader=self.profile.inject(DocumentLoader),
challenge=options.challenge,
)

async def verify_credential(
self, vc: VerifiableCredential
) -> DocumentVerificationResult:
"""Verify a VC with a Linked Data Proof."""
return await verify_credential(
credential=vc.serialize(),
suites=await self._get_all_suites(),
document_loader=self.profile.inject(DocumentLoader),
)
33 changes: 28 additions & 5 deletions aries_cloudagent/vc/vc_ld/validation_result.py
Original file line number Diff line number Diff line change
@@ -1,20 +1,29 @@
"""Presentation verification and validation result classes."""

from typing import List
from typing import List, Optional

from marshmallow import fields

from ...messaging.models.base import BaseModel, BaseModelSchema
from ...vc.ld_proofs.validation_result import DocumentVerificationResultSchema
from ..ld_proofs import DocumentVerificationResult


class PresentationVerificationResult:
class PresentationVerificationResult(BaseModel):
"""Presentation verification result class."""

class Meta:
"""PresentationVerificationResult metadata."""

schema_class = "PresentationVerificationResultSchema"

def __init__(
self,
*,
verified: bool,
presentation_result: DocumentVerificationResult = None,
credential_results: List[DocumentVerificationResult] = None,
errors: List[Exception] = None,
presentation_result: Optional[DocumentVerificationResult] = None,
credential_results: Optional[List[DocumentVerificationResult]] = None,
errors: Optional[List[str]] = None,
) -> None:
"""Create new PresentationVerificationResult instance."""
self.verified = verified
Expand Down Expand Up @@ -72,3 +81,17 @@ def __eq__(self, other: object) -> bool:
)
)
return False


class PresentationVerificationResultSchema(BaseModelSchema):
"""Presentation verification result schema."""

class Meta:
"""PresentationVerificationResultSchema metadata."""

model_class = PresentationVerificationResult

verified = fields.Bool(required=True)
presentation_result = fields.Nested(DocumentVerificationResultSchema)
credential_results = fields.List(fields.Nested(DocumentVerificationResultSchema))
errors = fields.List(fields.Str())

0 comments on commit d6905a6

Please sign in to comment.