Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

put all builds together to create a final ACA-py build #5

Merged
merged 9 commits into from
Aug 9, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
"""Presentation request message handler."""

import base64
import json
from aries_cloudagent.resolver.did_resolver import DIDResolver
from aries_cloudagent.wallet.base import BaseWallet
from aries_cloudagent.wallet.key_type import ED25519
from .....anoncreds.holder import AnonCredsHolderError
from .....core.oob_processor import OobMessageProcessor
from .....indy.holder import IndyHolderError
Expand Down Expand Up @@ -64,6 +69,44 @@ async def handle(self, context: RequestContext, responder: BaseResponder):
profile = context.profile
pres_manager = V20PresManager(profile)

pres_request = context.message
if pres_request.verifier_did is not None:
verifier_did = pres_request.verifier_did
async with profile.session() as session:
did_resolver = session.inject(DIDResolver)
wallet = session.inject(BaseWallet)
did_document = await did_resolver.resolve(
profile=profile, did=verifier_did
)
verification_method_list = did_document.get("verificationMethod", [])
request_verified = False
for method in verification_method_list:
verkey = method.get("publicKeyBase58")
key_type = ED25519 # need to change this to support other key types
sr_pres_request = pres_request.serialize()
sr_pres_request.pop("~thread", None)
sr_pres_request.pop("signature", None)
sr_pres_request_bytes = json.dumps(sr_pres_request).encode("utf-8")
if verkey:
try:
request_verified = await wallet.verify_message(
sr_pres_request_bytes,
base64.b64decode(pres_request.signature),
verkey,
key_type,
)
if request_verified:
break
except Exception as e:
print(
f"Could not verify signature...Retrying with next verification method: {e}" # noqa: E501
)
continue
if not request_verified:
raise HandlerException(
"Presentation request signature verification failed. DID of verifier is not verifed" # noqa: E501
)

# Get pres ex record (holder initiated via proposal)
# or create it (verifier sent request first)
try:
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
"""A presentation request content message."""

import base64
from typing import Sequence

from marshmallow import EXCLUDE, ValidationError, fields, validates_schema
Expand Down Expand Up @@ -32,8 +33,10 @@ def __init__(
_id: str = None,
*,
comment: str = None,
verifier_did: str = None,
will_confirm: bool = None,
formats: Sequence[V20PresFormat] = None,
signature: bytes = None,
request_presentations_attach: Sequence[AttachDecorator] = None,
**kwargs,
):
Expand All @@ -42,19 +45,23 @@ def __init__(
Args:
_id (str, optional): The ID of the presentation request.
comment (str, optional): An optional comment.
verifier_did (str, optional): The DID of the verifier.
will_confirm (bool, optional): A flag indicating whether the presentation
request will be confirmed.
formats (Sequence[V20PresFormat], optional): A sequence of presentation
formats.
signature (dict, optional): signature object for verifier did.
request_presentations_attach (Sequence[AttachDecorator], optional): A
sequence of proof request attachments.
kwargs: Additional keyword arguments.

"""
super().__init__(_id=_id, **kwargs)
self.comment = comment
self.verifier_did = verifier_did
self.will_confirm = will_confirm or False
self.formats = list(formats) if formats else []
self.signature = signature
self.request_presentations_attach = (
list(request_presentations_attach) if request_presentations_attach else []
)
Expand Down Expand Up @@ -86,6 +93,10 @@ def attachment(self, fmt: V20PresFormat.Format = None) -> dict:
else None
)

def add_signature(self, sign: bytes):
"""Add signature to request."""
self.signature = base64.b64encode(sign).decode("utf-8")


class V20PresRequestSchema(AgentMessageSchema):
"""Presentation request schema."""
Expand All @@ -103,12 +114,20 @@ class Meta:
required=False,
metadata={"description": "Whether verifier will send confirmation ack"},
)
verifier_did = fields.Str(
required=False,
metadata={"description": "DID of the verifier"},
)
formats = fields.Nested(
V20PresFormatSchema,
many=True,
required=True,
metadata={"description": "Acceptable attachment formats"},
)
signature = fields.Str(
required=False,
metadata={"description": "signature for verifier did"},
)
request_presentations_attach = fields.Nested(
AttachDecoratorSchema,
many=True,
Expand Down
99 changes: 64 additions & 35 deletions aries_cloudagent/protocols/present_proof/v2_0/routes.py
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@
from .messages.pres_proposal import V20PresProposal
from .messages.pres_request import V20PresRequest
from .models.pres_exchange import V20PresExRecord, V20PresExRecordSchema
from ....wallet.base import BaseWallet


class V20PresentProofModuleResponseSchema(OpenAPISchema):
Expand Down Expand Up @@ -159,9 +160,7 @@ class V20PresProposalRequestSchema(AdminAPIMessageTracingSchema):
allow_none=True,
metadata={"description": "Human-readable comment"},
)
presentation_proposal = fields.Nested(
V20PresProposalByFormatSchema(), required=True
)
presentation_proposal = fields.Nested(V20PresProposalByFormatSchema(), required=True)
auto_present = fields.Boolean(
required=False,
dump_default=False,
Expand Down Expand Up @@ -409,9 +408,7 @@ def _formats_attach(by_format: Mapping, msg_type: str, spec: str) -> Mapping:
attach = []
for fmt_api, item_by_fmt in by_format.items():
if fmt_api == V20PresFormat.Format.INDY.api:
attach.append(
AttachDecorator.data_base64(mapping=item_by_fmt, ident=fmt_api)
)
attach.append(AttachDecorator.data_base64(mapping=item_by_fmt, ident=fmt_api))
elif fmt_api == V20PresFormat.Format.DIF.api:
attach.append(AttachDecorator.data_json(mapping=item_by_fmt, ident=fmt_api))
return {
Expand Down Expand Up @@ -604,9 +601,7 @@ async def present_proof_credentials_list(request: web.BaseRequest):
input_descriptors_list = dif_pres_request.get(
"presentation_definition", {}
).get("input_descriptors")
claim_fmt = dif_pres_request.get("presentation_definition", {}).get(
"format"
)
claim_fmt = dif_pres_request.get("presentation_definition", {}).get("format")
if claim_fmt and len(claim_fmt.keys()) > 0:
claim_fmt = ClaimFormat.deserialize(claim_fmt)
input_descriptors = []
Expand Down Expand Up @@ -658,16 +653,13 @@ async def present_proof_credentials_list(request: web.BaseRequest):
elif (
len(proof_types) == 1
and (
BbsBlsSignature2020.signature_type
not in proof_types
BbsBlsSignature2020.signature_type not in proof_types
)
and (
Ed25519Signature2018.signature_type
not in proof_types
Ed25519Signature2018.signature_type not in proof_types
)
and (
Ed25519Signature2020.signature_type
not in proof_types
Ed25519Signature2020.signature_type not in proof_types
)
):
raise web.HTTPBadRequest(
Expand All @@ -681,16 +673,13 @@ async def present_proof_credentials_list(request: web.BaseRequest):
elif (
len(proof_types) >= 2
and (
BbsBlsSignature2020.signature_type
not in proof_types
BbsBlsSignature2020.signature_type not in proof_types
)
and (
Ed25519Signature2018.signature_type
not in proof_types
Ed25519Signature2018.signature_type not in proof_types
)
and (
Ed25519Signature2020.signature_type
not in proof_types
Ed25519Signature2020.signature_type not in proof_types
)
):
raise web.HTTPBadRequest(
Expand All @@ -706,25 +695,18 @@ async def present_proof_credentials_list(request: web.BaseRequest):
proof_format
== Ed25519Signature2018.signature_type
):
proof_type = [
Ed25519Signature2018.signature_type
]
proof_type = [Ed25519Signature2018.signature_type]
break
elif (
proof_format
== Ed25519Signature2020.signature_type
):
proof_type = [
Ed25519Signature2020.signature_type
]
proof_type = [Ed25519Signature2020.signature_type]
break
elif (
proof_format
== BbsBlsSignature2020.signature_type
proof_format == BbsBlsSignature2020.signature_type
):
proof_type = [
BbsBlsSignature2020.signature_type
]
proof_type = [BbsBlsSignature2020.signature_type]
break
else:
raise web.HTTPBadRequest(
Expand Down Expand Up @@ -919,12 +901,24 @@ async def present_proof_create_request(request: web.BaseRequest):
body = await request.json()

comment = body.get("comment")
verifier_did = body.get("verifier_did")
verifier_verkey = None
if verifier_did is not None:
async with profile.session() as session:
wallet = session.inject(BaseWallet)
try:
didinfo = await wallet.get_local_did(did=verifier_did)
verifier_verkey = didinfo.verkey
except WalletNotFoundError as err:
raise web.HTTPBadRequest(reason="DID is not present in wallet!") from err

pres_request_spec = body.get("presentation_request")
if pres_request_spec and V20PresFormat.Format.INDY.api in pres_request_spec:
await _add_nonce(pres_request_spec[V20PresFormat.Format.INDY.api])

pres_request_message = V20PresRequest(
comment=comment,
verifier_did=verifier_did,
will_confirm=True,
**_formats_attach(pres_request_spec, PRES_20_REQUEST, "request_presentations"),
)
Expand All @@ -938,6 +932,18 @@ async def present_proof_create_request(request: web.BaseRequest):
trace_msg,
)

if verifier_verkey is not None:
async with profile.session() as session:
wallet = session.inject(BaseWallet)
sr_pres_request_message = pres_request_message.serialize()
sr_pres_request_message_bytes: bytes = json.dumps(
sr_pres_request_message
).encode("utf-8")
sign = await wallet.sign_message(
sr_pres_request_message_bytes, verifier_verkey
)
pres_request_message.add_signature(sign)

pres_manager = V20PresManager(profile)
pres_ex_record = None
try:
Expand Down Expand Up @@ -1003,11 +1009,23 @@ async def present_proof_send_free_request(request: web.BaseRequest):
raise web.HTTPForbidden(reason=f"Connection {connection_id} not ready")

comment = body.get("comment")
verifier_did = body.get("verifier_did")
verifier_verkey = None
if verifier_did is not None:
async with profile.session() as session:
wallet = session.inject(BaseWallet)
try:
didinfo = await wallet.get_local_did(did=verifier_did)
verifier_verkey = didinfo.verkey
except WalletNotFoundError as err:
raise web.HTTPBadRequest(reason="DID is not present in wallet!") from err

pres_request_spec = body.get("presentation_request")
if pres_request_spec and V20PresFormat.Format.INDY.api in pres_request_spec:
await _add_nonce(pres_request_spec[V20PresFormat.Format.INDY.api])
pres_request_message = V20PresRequest(
comment=comment,
verifier_did=verifier_did,
will_confirm=True,
**_formats_attach(pres_request_spec, PRES_20_REQUEST, "request_presentations"),
)
Expand All @@ -1021,6 +1039,19 @@ async def present_proof_send_free_request(request: web.BaseRequest):
trace_msg,
)

if verifier_verkey is not None:
async with profile.session() as session:
wallet = session.inject(BaseWallet)
sr_pres_request_message = pres_request_message.serialize()
sr_pres_request_message_bytes: bytes = json.dumps(
sr_pres_request_message
).encode("utf-8")
print(f"==========================>{sr_pres_request_message}")
sign = await wallet.sign_message(
sr_pres_request_message_bytes, verifier_verkey
)
pres_request_message.add_signature(sign)

pres_manager = V20PresManager(profile)
pres_ex_record = None
try:
Expand Down Expand Up @@ -1385,9 +1416,7 @@ async def present_proof_remove(request: web.BaseRequest):
try:
async with context.profile.session() as session:
try:
pres_ex_record = await V20PresExRecord.retrieve_by_id(
session, pres_ex_id
)
pres_ex_record = await V20PresExRecord.retrieve_by_id(session, pres_ex_id)
await pres_ex_record.delete_record(session)
except (BaseModelError, ValidationError):
storage = session.inject(BaseStorage)
Expand Down
1 change: 1 addition & 0 deletions plugins
Submodule plugins added at 71ad41
Loading