Skip to content

Commit f8ecfd6

Browse files
authored
Merge pull request #31 from Indicio-tech/refactor/flexible-services
refactor: make services more flexible
2 parents 3fc3e98 + 3f9a6e4 commit f8ecfd6

File tree

4 files changed

+171
-82
lines changed

4 files changed

+171
-82
lines changed

didcomm_messaging/__init__.py

Lines changed: 91 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -46,24 +46,9 @@ class UnpackResult:
4646
sender_kid: Optional[str] = None
4747

4848

49-
class DIDCommMessaging(Generic[P, S]):
49+
class DIDCommMessagingService(Generic[P, S]):
5050
"""Main entrypoint for DIDComm Messaging."""
5151

52-
def __init__(
53-
self,
54-
crypto: CryptoService[P, S],
55-
secrets: SecretsManager[S],
56-
resolver: DIDResolver,
57-
packaging: PackagingService[P, S],
58-
routing: RoutingService,
59-
):
60-
"""Initialize the DIDComm Messaging service."""
61-
self.crypto = crypto
62-
self.secrets = secrets
63-
self.resolver = resolver
64-
self.packaging = packaging
65-
self.routing = routing
66-
6752
def service_to_target(self, service: DIDCommV2Service) -> str:
6853
"""Convert a service to a target uri.
6954
@@ -76,20 +61,49 @@ def service_to_target(self, service: DIDCommV2Service) -> str:
7661

7762
return service_endpoint.uri
7863

79-
async def pack(self, message: dict, to: str, frm: Optional[str] = None, **options):
64+
async def pack(
65+
self,
66+
crypto: CryptoService[P, S],
67+
resolver: DIDResolver,
68+
secrets: SecretsManager[S],
69+
packaging: PackagingService[P, S],
70+
routing: RoutingService,
71+
message: dict,
72+
to: str,
73+
frm: Optional[str] = None,
74+
**options,
75+
):
8076
"""Pack a message."""
8177
# TODO crypto layer permits packing to multiple recipients; should we as well?
8278

83-
encoded_message = await self.packaging.pack(
84-
json.dumps(message).encode(), [to], frm, **options
79+
encoded_message = await packaging.pack(
80+
crypto,
81+
resolver,
82+
secrets,
83+
json.dumps(message).encode(),
84+
[to],
85+
frm,
86+
**options,
8587
)
8688

87-
forward, services = await self.routing.prepare_forward(to, encoded_message)
89+
forward, services = await routing.prepare_forward(
90+
crypto, packaging, resolver, secrets, to, encoded_message
91+
)
8892
return PackResult(forward, services)
8993

90-
async def unpack(self, encoded_message: bytes, **options) -> UnpackResult:
94+
async def unpack(
95+
self,
96+
crypto: CryptoService[P, S],
97+
resolver: DIDResolver,
98+
secrets: SecretsManager[S],
99+
packaging: PackagingService[P, S],
100+
encoded_message: bytes,
101+
**options,
102+
) -> UnpackResult:
91103
"""Unpack a message."""
92-
unpacked, metadata = await self.packaging.unpack(encoded_message, **options)
104+
unpacked, metadata = await packaging.unpack(
105+
crypto, resolver, secrets, encoded_message, **options
106+
)
93107
message = json.loads(unpacked.decode())
94108
return UnpackResult(
95109
message,
@@ -98,3 +112,58 @@ async def unpack(self, encoded_message: bytes, **options) -> UnpackResult:
98112
recipient_kid=metadata.recip_key.kid,
99113
sender_kid=metadata.sender_kid,
100114
)
115+
116+
117+
class DIDCommMessaging(Generic[P, S]):
118+
"""Main entrypoint for DIDComm Messaging."""
119+
120+
def __init__(
121+
self,
122+
crypto: CryptoService[P, S],
123+
secrets: SecretsManager[S],
124+
resolver: DIDResolver,
125+
packaging: PackagingService[P, S],
126+
routing: RoutingService,
127+
):
128+
"""Initialize the DIDComm Messaging service."""
129+
self.crypto = crypto
130+
self.secrets = secrets
131+
self.resolver = resolver
132+
self.packaging = packaging
133+
self.routing = routing
134+
self.dmp = DIDCommMessagingService()
135+
136+
async def pack(
137+
self,
138+
message: dict,
139+
to: str,
140+
frm: Optional[str] = None,
141+
**options,
142+
) -> PackResult:
143+
"""Pack a message."""
144+
return await self.dmp.pack(
145+
self.crypto,
146+
self.resolver,
147+
self.secrets,
148+
self.packaging,
149+
self.routing,
150+
message,
151+
to,
152+
frm,
153+
**options,
154+
)
155+
156+
async def unpack(
157+
self,
158+
encoded_message: bytes,
159+
**options,
160+
) -> UnpackResult:
161+
"""Unpack a message."""
162+
return await self.dmp.unpack(
163+
self.crypto,
164+
self.resolver,
165+
self.secrets,
166+
self.packaging,
167+
encoded_message,
168+
**options,
169+
)

didcomm_messaging/packaging.py

Lines changed: 32 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -28,19 +28,8 @@ class PackagingServiceError(Exception):
2828
class PackagingService(Generic[P, S]):
2929
"""DIDComm Messaging interface."""
3030

31-
def __init__(
32-
self,
33-
resolver: DIDResolver,
34-
crypto: CryptoService[P, S],
35-
secrets: SecretsManager[S],
36-
):
37-
"""Initialize the KMS."""
38-
self.resolver = resolver
39-
self.crypto = crypto
40-
self.secrets = secrets
41-
4231
async def extract_packed_message_metadata( # noqa: C901
43-
self, enc_message: Union[str, bytes]
32+
self, enc_message: Union[str, bytes], secrets: SecretsManager[S]
4433
) -> PackedMessageMetadata:
4534
"""Extract metadata from a packed DIDComm message."""
4635
try:
@@ -61,7 +50,7 @@ async def extract_packed_message_metadata( # noqa: C901
6150
sender_kid = None
6251
recip_key = None
6352
for kid in wrapper.recipient_key_ids:
64-
recip_key = await self.secrets.get_secret_by_kid(kid)
53+
recip_key = await secrets.get_secret_by_kid(kid)
6554
if recip_key:
6655
break
6756

@@ -97,40 +86,42 @@ async def extract_packed_message_metadata( # noqa: C901
9786
return PackedMessageMetadata(wrapper, method, recip_key, sender_kid)
9887

9988
async def unpack(
100-
self, enc_message: Union[str, bytes]
89+
self,
90+
crypto: CryptoService[P, S],
91+
resolver: DIDResolver,
92+
secrets: SecretsManager[S],
93+
enc_message: Union[str, bytes],
10194
) -> Tuple[bytes, PackedMessageMetadata]:
10295
"""Unpack a DIDComm message."""
103-
metadata = await self.extract_packed_message_metadata(enc_message)
96+
metadata = await self.extract_packed_message_metadata(enc_message, secrets)
10497

10598
if metadata.method == "ECDH-ES":
10699
return (
107-
await self.crypto.ecdh_es_decrypt(enc_message, metadata.recip_key),
100+
await crypto.ecdh_es_decrypt(enc_message, metadata.recip_key),
108101
metadata,
109102
)
110103

111104
if not metadata.sender_kid:
112105
raise PackagingServiceError("Missing sender key ID")
113106

114-
sender_vm = await self.resolver.resolve_and_dereference_verification_method(
107+
sender_vm = await resolver.resolve_and_dereference_verification_method(
115108
metadata.sender_kid
116109
)
117-
sender_key = self.crypto.verification_method_to_public_key(sender_vm)
110+
sender_key = crypto.verification_method_to_public_key(sender_vm)
118111

119112
return (
120-
await self.crypto.ecdh_1pu_decrypt(
121-
enc_message, metadata.recip_key, sender_key
122-
),
113+
await crypto.ecdh_1pu_decrypt(enc_message, metadata.recip_key, sender_key),
123114
metadata,
124115
)
125116

126-
async def recip_for_kid_or_default_for_did(self, kid_or_did: str) -> P:
117+
async def recip_for_kid_or_default_for_did(
118+
self, crypto: CryptoService[P, S], resolver: DIDResolver, kid_or_did: str
119+
) -> P:
127120
"""Resolve a verification method for a kid or return default recip."""
128121
if "#" in kid_or_did:
129-
vm = await self.resolver.resolve_and_dereference_verification_method(
130-
kid_or_did
131-
)
122+
vm = await resolver.resolve_and_dereference_verification_method(kid_or_did)
132123
else:
133-
doc = await self.resolver.resolve_and_parse(kid_or_did)
124+
doc = await resolver.resolve_and_parse(kid_or_did)
134125
if not doc.key_agreement:
135126
raise PackagingServiceError(
136127
"No key agreement methods found; cannot determine recipient"
@@ -146,14 +137,14 @@ async def recip_for_kid_or_default_for_did(self, kid_or_did: str) -> P:
146137
else:
147138
vm = default
148139

149-
return self.crypto.verification_method_to_public_key(vm)
140+
return crypto.verification_method_to_public_key(vm)
150141

151-
async def default_sender_kid_for_did(self, did: str) -> str:
142+
async def default_sender_kid_for_did(self, resolver: DIDResolver, did: str) -> str:
152143
"""Determine the kid of the default sender key for a DID."""
153144
if "#" in did:
154145
return did
155146

156-
doc = await self.resolver.resolve_and_parse(did)
147+
doc = await resolver.resolve_and_parse(did)
157148
if not doc.key_agreement:
158149
raise PackagingServiceError(
159150
"No key agreement methods found; cannot determine recipient"
@@ -175,21 +166,27 @@ async def default_sender_kid_for_did(self, did: str) -> str:
175166

176167
async def pack(
177168
self,
169+
crypto: CryptoService[P, S],
170+
resolver: DIDResolver,
171+
secrets: SecretsManager[S],
178172
message: bytes,
179173
to: Sequence[str],
180174
frm: Optional[str] = None,
181175
**options,
182176
):
183177
"""Pack a DIDComm message."""
184-
recip_keys = [await self.recip_for_kid_or_default_for_did(kid) for kid in to]
185-
sender_kid = await self.default_sender_kid_for_did(frm) if frm else None
186-
sender_key = (
187-
await self.secrets.get_secret_by_kid(sender_kid) if sender_kid else None
178+
recip_keys = [
179+
await self.recip_for_kid_or_default_for_did(crypto, resolver, kid)
180+
for kid in to
181+
]
182+
sender_kid = (
183+
await self.default_sender_kid_for_did(resolver, frm) if frm else None
188184
)
185+
sender_key = await secrets.get_secret_by_kid(sender_kid) if sender_kid else None
189186
if frm and not sender_key:
190187
raise PackagingServiceError("No sender key found")
191188

192189
if sender_key:
193-
return await self.crypto.ecdh_1pu_encrypt(recip_keys, sender_key, message)
190+
return await crypto.ecdh_1pu_encrypt(recip_keys, sender_key, message)
194191
else:
195-
return await self.crypto.ecdh_es_encrypt(recip_keys, message)
192+
return await crypto.ecdh_es_encrypt(recip_keys, message)

0 commit comments

Comments
 (0)