Skip to content

Commit

Permalink
feat: add did key resolver
Browse files Browse the repository at this point in the history
Signed-off-by: Daniel Bluhm <[email protected]>
  • Loading branch information
dbluhm committed Sep 17, 2024
1 parent eb108ad commit 3d89b09
Show file tree
Hide file tree
Showing 5 changed files with 136 additions and 7 deletions.
40 changes: 40 additions & 0 deletions didcomm_messaging/resolver/key.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
"""DID Key Resolver."""

from didcomm_messaging.resolver import DIDResolver


class DIDKey(DIDResolver):
"""did:key resolver."""

async def is_resolvable(self, did: str) -> bool:
"""Check to see if DID is resolvable by this resolver."""
return did.startswith("did:key:")

async def resolve(self, did: str) -> dict:
"""Resolve a did:key."""
_, multikey = did.split("did:key:")
id = f"{did}#{multikey}"
return {
"@context": [
"https://www.w3.org/ns/did/v1",
"https://w3id.org/security/multikey/v1",
],
"id": did,
"verificationMethod": [
{
"id": id,
"type": "Multikey",
"controller": did,
"publicKeyMultibase": multikey,
}
],
**{
rel: [id]
for rel in (
"authentication",
"assertionMethod",
"capabilityDelegation",
"capabilityInvocation",
)
},
}
5 changes: 3 additions & 2 deletions didcomm_messaging/v1/messaging.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
from pydid.service import DIDCommV1Service

from didcomm_messaging.crypto import P, S, SecretsManager
from didcomm_messaging.crypto.jwe import JweEnvelope
from didcomm_messaging.resolver import DIDResolver
from didcomm_messaging.v1.crypto.base import V1CryptoService
from didcomm_messaging.v1.packaging import V1PackagingService
Expand Down Expand Up @@ -222,7 +223,7 @@ async def unpack(
crypto: V1CryptoService[P, S],
secrets: SecretsManager[S],
packaging: V1PackagingService[P, S],
encoded_message: bytes,
encoded_message: Union[JweEnvelope, str, bytes, dict, Any],
**options,
) -> V1UnpackResult:
"""Unpack a message."""
Expand Down Expand Up @@ -285,7 +286,7 @@ async def pack(

async def unpack(
self,
encoded_message: bytes,
encoded_message: Union[JweEnvelope, str, bytes, dict, Any],
**options,
) -> V1UnpackResult:
"""Unpack a message."""
Expand Down
8 changes: 5 additions & 3 deletions didcomm_messaging/v1/packaging.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
"""V1PackagingService interface."""

from typing import Generic, Optional, Sequence, Tuple, Union
from typing import Any, Generic, Optional, Sequence, Tuple, Union

from didcomm_messaging.crypto.base import P, S, SecretsManager
from didcomm_messaging.crypto.jwe import JweEnvelope, JweRecipient
Expand Down Expand Up @@ -82,7 +82,7 @@ async def unpack(
self,
crypto: V1CryptoService[P, S],
secrets: SecretsManager[S],
enc_message: Union[JweEnvelope, str, bytes],
enc_message: Union[JweEnvelope, str, bytes, dict, Any],
) -> V1CryptoUnpackResult:
"""Unpack a DIDComm v1 message."""
if isinstance(enc_message, (str, bytes)):
Expand All @@ -92,8 +92,10 @@ async def unpack(
raise V1PackagingServiceError("Invalid packed message")
elif isinstance(enc_message, JweEnvelope):
wrapper = enc_message
elif isinstance(enc_message, dict):
wrapper = JweEnvelope.deserialize(enc_message)
else:
raise TypeError("Invalid enc_message")
raise TypeError("Invalid enc_message; expect envelope, str, bytes, or dict")

recip_key, recip_data = await self.extract_packed_message_metadata(
secrets, wrapper
Expand Down
10 changes: 8 additions & 2 deletions tests/v1/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@
import pytest_asyncio

from didcomm_messaging.crypto.backend.askar import AskarKey, AskarSecretsManager
from didcomm_messaging.resolver import DIDResolver
from didcomm_messaging.resolver import DIDResolver, PrefixResolver
from didcomm_messaging.resolver.key import DIDKey
from didcomm_messaging.resolver.peer import Peer4
from didcomm_messaging.v1.crypto.askar import AskarV1CryptoService
from didcomm_messaging.v1.crypto.nacl import (
Expand Down Expand Up @@ -51,7 +52,12 @@ def packer():

@pytest.fixture
def resolver():
yield Peer4()
yield PrefixResolver(
{
"did:peer:4": Peer4(),
"did:key": DIDKey(),
}
)


@pytest.fixture
Expand Down
80 changes: 80 additions & 0 deletions tests/v1/test_forward.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
"""Test forwarding."""

from aries_askar import Key, KeyAlg, Store
import base58
import did_peer_4
from did_peer_4.input_doc import KeySpec, input_doc_from_keys_and_services
import pytest
from didcomm_messaging.crypto.backend.askar import AskarKey
from didcomm_messaging.v1.crypto.nacl import EdPublicKey, InMemSecretsManager
from didcomm_messaging.v1.messaging import V1DIDCommMessaging


@pytest.mark.asyncio
async def test_nacl_forward(
alice: V1DIDCommMessaging,
nacl_secrets: InMemSecretsManager,
):
"""Test nacl crypto forwarding."""
local_key = EdPublicKey(nacl_secrets.create().verkey)
routing_key = EdPublicKey(nacl_secrets.create().verkey)
doc = input_doc_from_keys_and_services(
[KeySpec(local_key.multikey, relationships=["authentication"])],
[
{
"id": "#didcomm",
"type": "did-communication",
"recipientKeys": ["#key-0"],
"routingKeys": [f"did:key:{routing_key.multikey}#{routing_key.multikey}"],
"serviceEndpoint": "https://example.com",
}
],
)
did = did_peer_4.encode(doc)
msg = b"hello world"
packed = await alice.pack(msg, did, did)
unpacked = await alice.unpack(packed.message)
forward = unpacked.message
assert forward["@type"] == "https://didcomm.org/routing/1.0/forward"
unwrapped = await alice.unpack(forward["msg"])
assert unwrapped.unpacked == msg


@pytest.mark.asyncio
async def test_askar_forward(
bob: V1DIDCommMessaging,
store: Store,
):
"""Test nacl crypto forwarding."""
key = Key.generate(KeyAlg.ED25519)
kid = base58.b58encode(key.get_public_bytes()).decode()
async with store.session() as session:
await session.insert_key(kid, key)
local_key = AskarKey(key, kid)

key = Key.generate(KeyAlg.ED25519)
kid = base58.b58encode(key.get_public_bytes()).decode()
async with store.session() as session:
await session.insert_key(kid, key)
routing_key = AskarKey(key, kid)

doc = input_doc_from_keys_and_services(
[KeySpec(local_key.multikey, relationships=["authentication"])],
[
{
"id": "#didcomm",
"type": "did-communication",
"recipientKeys": ["#key-0"],
"routingKeys": [f"did:key:{routing_key.multikey}#{routing_key.multikey}"],
"serviceEndpoint": "https://example.com",
}
],
)
did = did_peer_4.encode(doc)
msg = b"hello world"
packed = await bob.pack(msg, did, did)
unpacked = await bob.unpack(packed.message)
forward = unpacked.message
assert forward["@type"] == "https://didcomm.org/routing/1.0/forward"
unwrapped = await bob.unpack(forward["msg"])
assert unwrapped.unpacked == msg

0 comments on commit 3d89b09

Please sign in to comment.