Skip to content

Commit

Permalink
Merge pull request #5 from Northern-Block/oob-verifier-did
Browse files Browse the repository at this point in the history
put all builds together to create a final ACA-py build
  • Loading branch information
aritroCoder committed Aug 9, 2024
2 parents 43ae387 + 17ff006 commit b6ed2cb
Show file tree
Hide file tree
Showing 4 changed files with 127 additions and 35 deletions.
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

0 comments on commit b6ed2cb

Please sign in to comment.