Skip to content

Commit f87ad89

Browse files
authored
(fix) W3C LDP Fixes for alternative VMs (openwallet-foundation#3641)
1 parent e3dcabf commit f87ad89

File tree

9 files changed

+335
-243
lines changed

9 files changed

+335
-243
lines changed

acapy_agent/protocols/issue_credential/v2_0/formats/ld_proof/handler.py

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,11 @@
77
from pyld import jsonld
88
from pyld.jsonld import JsonLdProcessor
99

10+
from acapy_agent.wallet.default_verification_key_strategy import (
11+
BaseVerificationKeyStrategy,
12+
VerificationKeyStrategyError,
13+
)
14+
1015
from ......messaging.decorators.attach_decorator import AttachDecorator
1116
from ......storage.vc_holder.base import VCHolder
1217
from ......storage.vc_holder.vc_record import VCRecord
@@ -185,10 +190,16 @@ async def create_offer(
185190

186191
# Make sure we can issue with the did and proof type
187192
try:
188-
await manager.assert_can_issue_with_id_and_proof_type(
189-
detail.credential.issuer_id, detail.options.proof_type
193+
# Check suitable verification method for signing (fails if none suitable)
194+
verkey_id_strategy = self.profile.context.inject(BaseVerificationKeyStrategy)
195+
_ = await verkey_id_strategy.get_verification_method_id_for_did(
196+
detail.credential.issuer_id,
197+
self.profile,
198+
proof_type=detail.options.proof_type,
199+
proof_purpose="assertionMethod",
200+
verification_method_id=detail.options.verification_method,
190201
)
191-
except VcLdpManagerError as err:
202+
except VerificationKeyStrategyError as err:
192203
raise V20CredFormatError(
193204
"Checking whether issuance is possible failed"
194205
) from err

acapy_agent/protocols/issue_credential/v2_0/formats/ld_proof/tests/fixtures.py

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
TEST_DID_SOV = "did:sov:LjgpST2rjsoxYegQDRm7EL"
2-
TEST_DID_KEY = "did:key:z6Mkgg342Ycpuk263R9d8Aq6MUaxPn1DDeHyGo38EefXmgDL"
2+
TEST_DID_KEY_ED25519 = "did:key:z6Mkgg342Ycpuk263R9d8Aq6MUaxPn1DDeHyGo38EefXmgDL"
3+
TEST_DID_KEY_BLS_G2 = "did:key:zUC74E9UD2W6Q1MgPexCEdpstiCsY1Vbnyqepygk7McZVce38L1tGX7qZ2SgY4Zz2m9FUB4Xb5cEHSujks9XeKDzqe4QzW3CyyJ1cv8iBLNqU61EfkBoW2yEkg6VgqHTDtANYRS"
34

45
LD_PROOF_VC_DETAIL = {
56
"credential": {
@@ -10,7 +11,7 @@
1011
"type": ["VerifiableCredential", "UniversityDegreeCredential"],
1112
"credentialSubject": {"test": "key"},
1213
"issuanceDate": "2021-04-12",
13-
"issuer": TEST_DID_KEY,
14+
"issuer": TEST_DID_KEY_ED25519,
1415
},
1516
"options": {
1617
"proofType": "Ed25519Signature2018",
@@ -26,7 +27,7 @@
2627
"type": ["VerifiableCredential", "UniversityDegreeCredential"],
2728
"credentialSubject": {"test": "key"},
2829
"issuanceDate": "2021-04-12",
29-
"issuer": TEST_DID_KEY,
30+
"issuer": TEST_DID_KEY_BLS_G2,
3031
},
3132
"options": {
3233
"proofType": "BbsBlsSignature2020",
@@ -42,7 +43,7 @@
4243
"type": ["VerifiableCredential", "UniversityDegreeCredential"],
4344
"credentialSubject": {"test": "key"},
4445
"issuanceDate": "2021-04-12",
45-
"issuer": TEST_DID_KEY,
46+
"issuer": TEST_DID_KEY_ED25519,
4647
},
4748
"options": {
4849
"proofType": "Ed25519Signature2020",
@@ -57,7 +58,7 @@
5758
"type": ["VerifiableCredential", "UniversityDegreeCredential"],
5859
"credentialSubject": {"test": "key"},
5960
"issuanceDate": "2021-04-12",
60-
"issuer": TEST_DID_KEY,
61+
"issuer": TEST_DID_KEY_ED25519,
6162
"proof": {
6263
"proofPurpose": "assertionMethod",
6364
"created": "2019-12-11T03:50:55",

acapy_agent/protocols/issue_credential/v2_0/formats/ld_proof/tests/test_handler.py

Lines changed: 0 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -192,22 +192,12 @@ async def test_receive_proposal(self):
192192

193193
async def test_create_offer(self):
194194
with (
195-
mock.patch.object(
196-
VcLdpManager,
197-
"assert_can_issue_with_id_and_proof_type",
198-
mock.CoroutineMock(),
199-
) as mock_can_issue,
200195
patch.object(test_module, "get_properties_without_context", return_value=[]),
201196
):
202197
(cred_format, attachment) = await self.handler.create_offer(
203198
self.cred_proposal
204199
)
205200

206-
mock_can_issue.assert_called_once_with(
207-
LD_PROOF_VC_DETAIL["credential"]["issuer"],
208-
LD_PROOF_VC_DETAIL["options"]["proofType"],
209-
)
210-
211201
# assert identifier match
212202
assert cred_format.attach_id == self.handler.format.api == attachment.ident
213203

@@ -233,11 +223,6 @@ async def test_create_offer_adds_bbs_context(self):
233223
)
234224

235225
with (
236-
mock.patch.object(
237-
VcLdpManager,
238-
"assert_can_issue_with_id_and_proof_type",
239-
mock.CoroutineMock(),
240-
),
241226
patch.object(test_module, "get_properties_without_context", return_value=[]),
242227
):
243228
(cred_format, attachment) = await self.handler.create_offer(cred_proposal)
@@ -261,11 +246,6 @@ async def test_create_offer_adds_ed25519_2020_context(self):
261246
)
262247

263248
with (
264-
mock.patch.object(
265-
VcLdpManager,
266-
"assert_can_issue_with_id_and_proof_type",
267-
mock.CoroutineMock(),
268-
),
269249
patch.object(test_module, "get_properties_without_context", return_value=[]),
270250
):
271251
(cred_format, attachment) = await self.handler.create_offer(cred_proposal)
@@ -286,11 +266,6 @@ async def test_create_offer_x_no_proposal(self):
286266
async def test_create_offer_x_wrong_attributes(self):
287267
missing_properties = ["foo"]
288268
with (
289-
mock.patch.object(
290-
self.manager,
291-
"assert_can_issue_with_id_and_proof_type",
292-
mock.CoroutineMock(),
293-
),
294269
patch.object(
295270
test_module,
296271
"get_properties_without_context",

acapy_agent/vc/data_integrity/cryptosuites/eddsa_jcs_2022.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -194,7 +194,7 @@ async def proof_verification(
194194
"""
195195
multikey = await MultikeyManager(
196196
self.session
197-
).resolve_multikey_from_verification_method(options.verification_method)
197+
).resolve_multikey_from_verification_method_id(options.verification_method)
198198
verkey = multikey_to_verkey(multikey)
199199
key_type = key_type_from_multikey(multikey)
200200
return await self.wallet.verify_message(

acapy_agent/vc/vc_ld/manager.py

Lines changed: 13 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
from datetime import datetime, timezone
44
from typing import Dict, List, Optional, Type, Union, cast
55

6+
from acapy_agent.wallet.keys.manager import MultikeyManager, multikey_to_verkey
67
from pyld import jsonld
78
from pyld.jsonld import JsonLdProcessor
89

@@ -16,7 +17,6 @@
1617
from ...wallet.base import BaseWallet
1718
from ...wallet.default_verification_key_strategy import BaseVerificationKeyStrategy
1819
from ...wallet.did_info import DIDInfo
19-
from ...wallet.error import WalletNotFoundError
2020
from ...wallet.key_type import BLS12381G2, ED25519, P256, KeyType
2121
from ..ld_proofs.constants import (
2222
CREDENTIALS_CONTEXT_V1_URL,
@@ -133,60 +133,6 @@ async def _did_info_for_did(self, did: str) -> DIDInfo:
133133
# All other methods we can just query
134134
return await wallet.get_local_did(did)
135135

136-
async def assert_can_issue_with_id_and_proof_type(
137-
self, issuer_id: Optional[str], proof_type: Optional[str]
138-
):
139-
"""Assert that it is possible to issue using the specified id and proof type.
140-
141-
Args:
142-
issuer_id (str): The issuer id
143-
proof_type (str): the signature suite proof type
144-
145-
Raises:
146-
VcLdpManagerError:
147-
- If the proof type is not supported
148-
- If the issuer id is not a did
149-
- If the did is not found in th wallet
150-
- If the did does not support to create signatures for the proof type
151-
152-
"""
153-
if not issuer_id or not proof_type:
154-
raise VcLdpManagerError(
155-
"Issuer id and proof type are required to issue a credential."
156-
)
157-
158-
try:
159-
# Check if it is a proof type we can issue with
160-
if proof_type not in PROOF_TYPE_SIGNATURE_SUITE_MAPPING.keys():
161-
raise VcLdpManagerError(
162-
f"Unable to sign credential with unsupported proof type {proof_type}."
163-
f" Supported proof types: {PROOF_TYPE_SIGNATURE_SUITE_MAPPING.keys()}"
164-
)
165-
166-
if not issuer_id.startswith("did:"):
167-
raise VcLdpManagerError(
168-
f"Unable to issue credential with issuer id: {issuer_id}."
169-
" Only issuance with DIDs is supported"
170-
)
171-
172-
# Retrieve did from wallet. Will throw if not found
173-
did = await self._did_info_for_did(issuer_id)
174-
175-
# Raise error if we cannot issue a credential with this proof type
176-
# using this DID from
177-
did_proof_types = KEY_TYPE_SIGNATURE_TYPE_MAPPING[did.key_type]
178-
if proof_type not in did_proof_types:
179-
raise VcLdpManagerError(
180-
f"Unable to issue credential with issuer id {issuer_id} and proof "
181-
f"type {proof_type}. DID only supports proof types {did_proof_types}"
182-
)
183-
184-
except WalletNotFoundError:
185-
raise VcLdpManagerError(
186-
f"Issuer did {issuer_id} not found."
187-
" Unable to issue credential with this DID."
188-
)
189-
190136
async def _get_suite(
191137
self,
192138
*,
@@ -210,6 +156,11 @@ async def _get_suite(
210156
"using external provider."
211157
) from error
212158

159+
async with self.profile.session() as session:
160+
key_manager = MultikeyManager(session)
161+
key_info = await key_manager.resolve_and_bind_kid(verification_method)
162+
multikey = key_info["multikey"]
163+
213164
# Get signature class based on proof type
214165
SignatureClass = PROOF_TYPE_SIGNATURE_SUITE_MAPPING[proof_type]
215166

@@ -220,7 +171,7 @@ async def _get_suite(
220171
key_pair=WalletKeyPair(
221172
profile=self.profile,
222173
key_type=SIGNATURE_SUITE_KEY_TYPE_MAPPING[SignatureClass],
223-
public_key_base58=did_info.verkey if did_info else None,
174+
public_key_base58=multikey_to_verkey(multikey),
224175
),
225176
)
226177

@@ -360,9 +311,6 @@ async def _get_suite_for_document(
360311
if not proof_type:
361312
raise VcLdpManagerError("Proof type is required")
362313

363-
# Assert we can issue the credential based on issuer + proof_type
364-
await self.assert_can_issue_with_id_and_proof_type(issuer_id, proof_type)
365-
366314
# Create base proof object with options
367315
proof = LDProof(
368316
created=options.created,
@@ -371,20 +319,22 @@ async def _get_suite_for_document(
371319
)
372320

373321
did_info = await self._did_info_for_did(issuer_id)
322+
323+
# Determine/check suitable verification method for signing. fails if none suitable
374324
verkey_id_strategy = self.profile.context.inject(BaseVerificationKeyStrategy)
375-
verification_method = (
376-
options.verification_method
377-
or await verkey_id_strategy.get_verification_method_id_for_did(
325+
verification_method_id = (
326+
await verkey_id_strategy.get_verification_method_id_for_did(
378327
issuer_id,
379328
self.profile,
380329
proof_type=proof_type,
381330
proof_purpose="assertionMethod",
331+
verification_method_id=options.verification_method,
382332
)
383333
)
384334

385335
suite = await self._get_suite(
386336
proof_type=proof_type,
387-
verification_method=verification_method,
337+
verification_method=verification_method_id,
388338
proof=proof.serialize(),
389339
did_info=did_info,
390340
)

0 commit comments

Comments
 (0)