Skip to content

Commit 39f2c9a

Browse files
committed
Merge branch 'main' into feature/event-bus
2 parents b1e9a2c + 56f38c8 commit 39f2c9a

File tree

65 files changed

+1343
-470
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

65 files changed

+1343
-470
lines changed

aries_cloudagent/admin/server.py

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,22 @@
11
"""Admin server classes."""
22

33
import asyncio
4+
from hmac import compare_digest
45
import logging
56
import re
7+
from typing import Callable, Coroutine
68
import uuid
79
import warnings
8-
from typing import Callable, Coroutine
910

10-
import aiohttp_cors
11-
import jwt
1211
from aiohttp import web
1312
from aiohttp_apispec import (
1413
docs,
1514
response_schema,
1615
setup_aiohttp_apispec,
1716
validation_middleware,
1817
)
18+
import aiohttp_cors
19+
import jwt
1920
from marshmallow import fields
2021

2122
from ..config.injection_context import InjectionContext
@@ -197,6 +198,13 @@ async def debug_middleware(request: web.BaseRequest, handler: Coroutine):
197198
return await handler(request)
198199

199200

201+
def const_compare(string1, string2):
202+
"""Compare two strings in constant time."""
203+
if string1 is None or string2 is None:
204+
return False
205+
return compare_digest(string1.encode(), string2.encode())
206+
207+
200208
class AdminServer(BaseAdminServer):
201209
"""Admin HTTP server class."""
202210

@@ -275,7 +283,7 @@ def is_unprotected_path(path: str):
275283
@web.middleware
276284
async def check_token(request: web.Request, handler):
277285
header_admin_api_key = request.headers.get("x-api-key")
278-
valid_key = self.admin_api_key == header_admin_api_key
286+
valid_key = const_compare(self.admin_api_key, header_admin_api_key)
279287

280288
if valid_key or is_unprotected_path(request.path):
281289
return await handler(request)
@@ -696,7 +704,9 @@ async def websocket_handler(self, request):
696704
else:
697705
header_admin_api_key = request.headers.get("x-api-key")
698706
# authenticated via http header?
699-
queue.authenticated = header_admin_api_key == self.admin_api_key
707+
queue.authenticated = const_compare(
708+
header_admin_api_key, self.admin_api_key
709+
)
700710

701711
try:
702712
self.websocket_queues[socket_id] = queue
@@ -739,7 +749,9 @@ async def websocket_handler(self, request):
739749
LOGGER.exception(
740750
"Exception in websocket receiving task:"
741751
)
742-
if self.admin_api_key and self.admin_api_key == msg_api_key:
752+
if self.admin_api_key and const_compare(
753+
self.admin_api_key, msg_api_key
754+
):
743755
# authenticated via websocket message
744756
queue.authenticated = True
745757

aries_cloudagent/config/argparse.py

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -307,7 +307,6 @@ def add_arguments(self, parser: ArgumentParser):
307307
env_var="ACAPY_TEST_SUITE_ENDPOINT",
308308
help="URL endpoint for sending messages to the test suite agent.",
309309
)
310-
311310
parser.add_argument(
312311
"--auto-accept-invites",
313312
action="store_true",
@@ -735,6 +734,12 @@ def add_arguments(self, parser: ArgumentParser):
735734
"marking a connection as 'active'. Default: false."
736735
),
737736
)
737+
parser.add_argument(
738+
"--auto-accept-intro-invitation-requests",
739+
action="store_true",
740+
env_var="ACAPY_AUTO_ACCEPT_INTRO_INVITATION_REQUESTS",
741+
help="Automatically accept introduction invitations. Default: false.",
742+
)
738743
parser.add_argument(
739744
"--invite-base-url",
740745
type=str,
@@ -840,6 +845,8 @@ def get_settings(self, args: Namespace) -> dict:
840845
settings = {}
841846
if args.auto_ping_connection:
842847
settings["auto_ping_connection"] = True
848+
if args.auto_accept_intro_invitation_requests:
849+
settings["auto_accept_intro_invitation_requests"] = True
843850
if args.invite_base_url:
844851
settings["invite_base_url"] = args.invite_base_url
845852
if args.monitor_ping:

aries_cloudagent/config/default_context.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,7 @@ async def bind_providers(self, context: InjectionContext):
9696
# Allow action menu to be provided by driver
9797
context.injector.bind_instance(BaseMenuService, DriverMenuService(context))
9898
context.injector.bind_instance(
99-
BaseIntroductionService, DemoIntroductionService(context)
99+
BaseIntroductionService, DemoIntroductionService()
100100
)
101101

102102
async def load_plugins(self, context: InjectionContext):
@@ -115,7 +115,7 @@ async def load_plugins(self, context: InjectionContext):
115115
"aries_cloudagent.messaging.credential_definitions"
116116
)
117117
plugin_registry.register_plugin("aries_cloudagent.messaging.schemas")
118-
# plugin_registry.register_plugin("aries_cloudagent.messaging.jsonld")
118+
plugin_registry.register_plugin("aries_cloudagent.messaging.jsonld")
119119
plugin_registry.register_plugin("aries_cloudagent.revocation")
120120
plugin_registry.register_plugin("aries_cloudagent.resolver")
121121
plugin_registry.register_plugin("aries_cloudagent.wallet")

aries_cloudagent/messaging/jsonld/create_verify_data.py

Lines changed: 46 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,11 @@
1111

1212
from pyld import jsonld
1313

14-
from .error import DroppedAttributeError, MissingVerificationMethodError
14+
from .error import (
15+
DroppedAttributeError,
16+
MissingVerificationMethodError,
17+
SignatureTypeError,
18+
)
1519

1620

1721
def _canonize(data):
@@ -38,49 +42,62 @@ def _canonize_document(doc):
3842
return _canonize(_doc)
3943

4044

45+
def _created_at():
46+
"""Creation Timestamp."""
47+
48+
stamp = datetime.datetime.now(datetime.timezone.utc)
49+
return stamp.strftime("%Y-%m-%dT%H:%M:%SZ")
50+
51+
4152
def create_verify_data(data, signature_options):
4253
"""Encapsulate the process of constructing the string used during sign and verify."""
4354

44-
if "creator" in signature_options:
45-
signature_options["verificationMethod"] = signature_options["creator"]
55+
type_ = signature_options.get("type", "Ed25519Signature2018")
56+
if type_ and type_ != "Ed25519Signature2018":
57+
raise SignatureTypeError(f"invalid signature type {type_}.")
58+
59+
signature_options["verificationMethod"] = signature_options.get(
60+
"creator", signature_options.get("verificationMethod")
61+
)
4662

4763
if not signature_options.get("verificationMethod"):
4864
raise MissingVerificationMethodError(
4965
"signature_options.verificationMethod is required"
5066
)
5167

52-
if "created" not in signature_options:
53-
signature_options["created"] = datetime.datetime.now(
54-
datetime.timezone.utc
55-
).strftime("%Y-%m-%dT%H:%M:%SZ")
56-
57-
if (
58-
"type" not in signature_options
59-
or signature_options["type"] != "Ed25519Signature2018"
60-
):
61-
signature_options["type"] = "Ed25519Signature2018"
62-
68+
signature_options["created"] = signature_options.get("created", _created_at())
6369
[expanded] = jsonld.expand(data)
6470
framed = jsonld.compact(
6571
expanded, "https://w3id.org/security/v2", {"skipExpansion": True}
6672
)
6773

6874
# Detect any dropped attributes during the expand/contract step.
69-
if len(data) != len(framed):
70-
raise DroppedAttributeError("Extra Attribute Detected")
71-
if (
72-
"proof" in data
73-
and "proof" in framed
74-
and len(data["proof"]) != len(framed["proof"])
75-
):
76-
raise DroppedAttributeError("Extra Attribute Detected")
77-
if (
78-
"credentialSubject" in data
79-
and "https://www.w3.org/2018/credentials#credentialSubject" in framed
80-
and len(data["credentialSubject"])
81-
!= len(framed["https://www.w3.org/2018/credentials#credentialSubject"])
82-
):
83-
raise DroppedAttributeError("Extra Attribute Detected")
75+
if len(data) > len(framed):
76+
# > check indicates dropped attrs < is a different error
77+
# attempt to collect error report data
78+
for_diff = jsonld.compact(expanded, data.get("@context"))
79+
dropped = set(data.keys()) - set(for_diff.keys())
80+
raise DroppedAttributeError(
81+
f"{dropped} attributes dropped. "
82+
"Provide definitions in context to correct."
83+
)
84+
# Check proof for dropped attributes
85+
attr = [
86+
("proof", "proof"),
87+
("credentialSubject", "https://www.w3.org/2018/credentials#credentialSubject"),
88+
]
89+
data_context = data.get("@context")
90+
for mapping in attr:
91+
data_attribute = data.get(mapping[0], {})
92+
frame_attribute = framed.get(mapping[1], {})
93+
if len(data_attribute) > len(frame_attribute):
94+
for_diff = jsonld.compact(expanded, data_context)
95+
for_diff_attribute = for_diff.get(mapping[1], {})
96+
dropped = set(data_attribute.keys()) - set(for_diff_attribute.keys())
97+
raise DroppedAttributeError(
98+
f"in {mapping[0]}, {dropped} attributes dropped. "
99+
"Provide definitions in context to correct."
100+
)
84101

85102
canonized_signature_options = _canonize_signature_options(signature_options)
86103
hash_of_canonized_signature_options = _sha256(canonized_signature_options)

aries_cloudagent/messaging/jsonld/credential.py

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,14 @@
22

33
import json
44

5+
from ...wallet.base import BaseWallet
56
from ...wallet.util import (
67
b64_to_bytes,
78
b64_to_str,
89
bytes_to_b64,
9-
str_to_b64,
1010
naked_to_did_key,
11+
str_to_b64,
1112
)
12-
1313
from .create_verify_data import create_verify_data
1414
from .error import BadJWSHeaderError
1515

@@ -35,7 +35,7 @@ def create_jws(encoded_header, verify_data):
3535
return (encoded_header + ".").encode("utf-8") + verify_data
3636

3737

38-
async def jws_sign(verify_data, verkey, wallet):
38+
async def jws_sign(session, verify_data, verkey):
3939
"""Sign JWS."""
4040

4141
header = {"alg": "EdDSA", "b64": False, "crit": ["b64"]}
@@ -44,6 +44,7 @@ async def jws_sign(verify_data, verkey, wallet):
4444

4545
jws_to_sign = create_jws(encoded_header, verify_data)
4646

47+
wallet = session.inject(BaseWallet, required=True)
4748
signature = await wallet.sign_message(jws_to_sign, verkey)
4849

4950
encoded_signature = bytes_to_b64(signature, urlsafe=True, pad=False)
@@ -60,7 +61,7 @@ def verify_jws_header(header):
6061
)
6162

6263

63-
async def jws_verify(verify_data, signature, public_key, wallet):
64+
async def jws_verify(session, verify_data, signature, public_key):
6465
"""Detatched jws verify handling."""
6566

6667
encoded_header, _, encoded_signature = signature.partition("..")
@@ -71,26 +72,25 @@ async def jws_verify(verify_data, signature, public_key, wallet):
7172
decoded_signature = b64_to_bytes(encoded_signature, urlsafe=True)
7273

7374
jws_to_verify = create_jws(encoded_header, verify_data)
74-
75+
wallet = session.inject(BaseWallet, required=True)
7576
verified = await wallet.verify_message(jws_to_verify, decoded_signature, public_key)
7677

7778
return verified
7879

7980

80-
async def sign_credential(credential, signature_options, verkey, wallet):
81+
async def sign_credential(session, credential, signature_options, verkey):
8182
"""Sign Credential."""
8283

8384
framed, verify_data_hex_string = create_verify_data(credential, signature_options)
8485
verify_data_bytes = bytes.fromhex(verify_data_hex_string)
85-
jws = await jws_sign(verify_data_bytes, verkey, wallet)
86-
document_with_proof = {**credential, "proof": {**signature_options, "jws": jws}}
87-
return document_with_proof
86+
jws = await jws_sign(session, verify_data_bytes, verkey)
87+
return {**credential, "proof": {**signature_options, "jws": jws}}
8888

8989

90-
async def verify_credential(doc, verkey, wallet):
90+
async def verify_credential(session, doc, verkey):
9191
"""Verify credential."""
9292

9393
framed, verify_data_hex_string = create_verify_data(doc, doc["proof"])
9494
verify_data_bytes = bytes.fromhex(verify_data_hex_string)
95-
valid = await jws_verify(verify_data_bytes, framed["proof"]["jws"], verkey, wallet)
95+
valid = await jws_verify(session, verify_data_bytes, framed["proof"]["jws"], verkey)
9696
return valid

aries_cloudagent/messaging/jsonld/error.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,3 +17,11 @@ class DroppedAttributeError(BaseJSONLDMessagingError):
1717

1818
class MissingVerificationMethodError(BaseJSONLDMessagingError):
1919
"""Exception indicating missing verification method from signature options."""
20+
21+
22+
class SignatureTypeError(BaseJSONLDMessagingError):
23+
"""Exception indicating Signature type error."""
24+
25+
26+
class InvalidVerificationMethod(BaseJSONLDMessagingError):
27+
"""Exception indicating an invalid verification method in doc to verify."""

0 commit comments

Comments
 (0)