Skip to content

Commit 9144f76

Browse files
committed
feat: more robust vm selection for all did types
Signed-off-by: Daniel Bluhm <[email protected]>
1 parent 92430f6 commit 9144f76

File tree

4 files changed

+61
-42
lines changed

4 files changed

+61
-42
lines changed

acapy_agent/protocols/present_proof/dif/pres_exch_handler.py

Lines changed: 6 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -118,21 +118,14 @@ async def _get_issue_suite(
118118
):
119119
"""Get signature suite for signing presentation."""
120120
did_info = await self._did_info_for_did(issuer_id)
121-
verkey_id_strategy = self.profile.context.inject(BaseVerificationKeyStrategy)
122-
verification_method = (
123-
await verkey_id_strategy.get_verification_method_id_for_did(
124-
issuer_id,
125-
self.profile,
126-
proof_type=self.proof_type,
127-
proof_purpose="assertionMethod",
128-
)
121+
vm_id_strategy = self.profile.context.inject(BaseVerificationKeyStrategy)
122+
verification_method = await vm_id_strategy.get_verification_method_id_for_did(
123+
issuer_id,
124+
self.profile,
125+
proof_type=self.proof_type,
126+
proof_purpose="assertionMethod",
129127
)
130128

131-
if verification_method is None:
132-
raise DIFPresExchError(
133-
f"Unable to get retrieve verification method for did {issuer_id}"
134-
)
135-
136129
# Get signature class based on proof type
137130
SignatureClass = self.PROOF_TYPE_SIGNATURE_SUITE_MAPPING[self.proof_type]
138131

acapy_agent/vc/vc_ld/manager.py

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -344,15 +344,13 @@ async def _get_suite_for_document(
344344
verification_method = (
345345
options.verification_method
346346
or await verkey_id_strategy.get_verification_method_id_for_did(
347-
issuer_id, self.profile, proof_type, proof_purpose="assertionMethod"
347+
issuer_id,
348+
self.profile,
349+
proof_type=proof_type,
350+
proof_purpose="assertionMethod",
348351
)
349352
)
350353

351-
if verification_method is None:
352-
raise VcLdpManagerError(
353-
f"Unable to get retrieve verification method for did {issuer_id}"
354-
)
355-
356354
suite = await self._get_suite(
357355
proof_type=proof_type,
358356
verification_method=verification_method,

acapy_agent/wallet/default_verification_key_strategy.py

Lines changed: 51 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,20 @@
11
"""Utilities for specifying which verification method is in use for a given DID."""
22

33
from abc import ABC, abstractmethod
4-
from typing import List, Optional
4+
import logging
5+
from typing import Optional
56

7+
from acapy_agent.core.error import BaseError
68
from acapy_agent.core.profile import Profile
79
from acapy_agent.did.did_key import DIDKey
8-
from acapy_agent.wallet.key_type import KeyType
9-
1010
from acapy_agent.resolver.did_resolver import DIDResolver
1111

12+
LOGGER = logging.getLogger(__name__)
13+
14+
15+
class VerificationKeyStrategyError(BaseError):
16+
"""Raised on issues with verfication method derivation."""
17+
1218

1319
class BaseVerificationKeyStrategy(ABC):
1420
"""Base class for defining which verification method is in use."""
@@ -17,9 +23,9 @@ class BaseVerificationKeyStrategy(ABC):
1723
async def get_verification_method_id_for_did(
1824
self,
1925
did: str,
20-
profile: Optional[Profile],
26+
profile: Profile,
27+
*,
2128
proof_type: Optional[str] = None,
22-
allowed_verification_method_types: Optional[List[KeyType]] = None,
2329
proof_purpose: Optional[str] = None,
2430
) -> Optional[str]:
2531
"""Given a DID, returns the verification key ID in use.
@@ -40,6 +46,7 @@ class DefaultVerificationKeyStrategy(BaseVerificationKeyStrategy):
4046
4147
Supports did:key: and did:sov only.
4248
"""
49+
4350
def __init__(self):
4451
"""Initialize the key types mapping."""
4552
self.key_types_mapping = {
@@ -50,9 +57,9 @@ def __init__(self):
5057
async def get_verification_method_id_for_did(
5158
self,
5259
did: str,
53-
profile: Optional[Profile],
60+
profile: Profile,
61+
*,
5462
proof_type: Optional[str] = None,
55-
allowed_verification_method_types: Optional[List[KeyType]] = None,
5663
proof_purpose: Optional[str] = None,
5764
) -> Optional[str]:
5865
"""Given a did:key or did:sov, returns the verification key ID in use.
@@ -65,22 +72,45 @@ async def get_verification_method_id_for_did(
6572
:params proof_purpose: the verkey relationship (assertionMethod, keyAgreement, ..)
6673
:returns Optional[str]: the current verkey ID
6774
"""
75+
proof_type = proof_type or "Ed25519Signature2018"
76+
proof_purpose = proof_purpose or "assertionMethod"
77+
78+
if proof_purpose not in (
79+
"authentication",
80+
"assertionMethod",
81+
"capabilityInvocation",
82+
"capabilityDelegation",
83+
):
84+
raise ValueError("Invalid proof purpose")
85+
6886
if did.startswith("did:key:"):
6987
return DIDKey.from_did(did).key_id
7088
elif did.startswith("did:sov:"):
7189
# key-1 is what uniresolver uses for key id
7290
return did + "#key-1"
73-
elif did.startswith("did:web:"):
74-
did_resolver = profile.inject(DIDResolver)
75-
did_document = await did_resolver.resolve(profile=profile, did=did)
76-
if proof_type:
77-
verification_method_types = self.key_types_mapping[proof_type]
78-
verification_method_list = did_document.get("verificationMethod", None)
79-
for method in verification_method_list:
80-
if method.get("type") in verification_method_types:
81-
return method.get("id")
82-
else:
83-
# taking the first verification method from did document
84-
verification_method_id = verification_method_list[0].get("id")
85-
return verification_method_id
86-
return None
91+
92+
resolver = profile.inject(DIDResolver)
93+
did_document = await resolver.resolve(profile=profile, did=did)
94+
method_types = self.key_types_mapping[proof_type]
95+
96+
methods = did_document.get(proof_purpose, [])
97+
methods = [vm for vm in methods if vm.get("type") in method_types]
98+
if not methods:
99+
raise VerificationKeyStrategyError(
100+
f"No matching verification method found for did {did} with proof "
101+
f"type {proof_type} and purpose {proof_purpose}"
102+
)
103+
104+
if len(methods) > 1:
105+
LOGGER.info(
106+
(
107+
"More than 1 verification method matched for did %s with proof "
108+
"type %s and purpose %s; returning the first: %s"
109+
),
110+
did,
111+
proof_type,
112+
proof_purpose,
113+
methods[0].id,
114+
)
115+
116+
return methods[0].id

acapy_agent/wallet/jwt.py

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -61,8 +61,6 @@ async def jwt_sign(
6161
verification_method = await verkey_strat.get_verification_method_id_for_did(
6262
did, profile
6363
)
64-
if not verification_method:
65-
raise ValueError("Could not determine verification method from DID")
6664
else:
6765
# We look up keys by did for now
6866
did = DIDUrl.parse(verification_method).did

0 commit comments

Comments
 (0)