2
2
3
3
import json
4
4
import logging
5
- from typing import Any , Mapping , Optional , Tuple
5
+ from typing import Any , Mapping , Optional
6
6
7
7
from marshmallow import fields
8
- from pydid import DIDUrl , Resource , VerificationMethod
9
- from pydid .verification_method import Ed25519VerificationKey2018 , Multikey
10
8
11
- from acapy_agent .wallet .keys .manager import key_type_from_multikey , multikey_to_verkey
9
+ from acapy_agent .wallet .keys .manager import (
10
+ MultikeyManager ,
11
+ key_type_from_multikey ,
12
+ multikey_to_verkey ,
13
+ )
12
14
13
15
from ..core .profile import Profile
14
- from ..messaging .jsonld .error import BadJWSHeaderError , InvalidVerificationMethod
16
+ from ..messaging .jsonld .error import BadJWSHeaderError
15
17
from ..messaging .models .base import BaseModel , BaseModelSchema
16
- from ..resolver .did_resolver import DIDResolver
17
18
from .base import BaseWallet
18
19
from .default_verification_key_strategy import BaseVerificationKeyStrategy
19
- from .key_type import ED25519 , KeyType
20
20
from .util import b64_to_bytes , bytes_to_b64
21
21
22
22
LOGGER = logging .getLogger (__name__ )
@@ -64,19 +64,18 @@ async def jwt_sign(
64
64
verification_method = await verkey_strat .get_verification_method_id_for_did (
65
65
did , profile
66
66
)
67
- else :
68
- # We look up keys by did for now
69
- did = DIDUrl .parse (verification_method ).did
70
- if not did :
71
- raise ValueError ("DID URL must be absolute" )
72
67
73
68
async with profile .session () as session :
74
69
wallet = session .inject (BaseWallet )
75
- did_info = await wallet .get_local_did (did_lookup_name (did ))
70
+ key_manager = MultikeyManager (session )
71
+ key_info = await key_manager .resolve_and_bind_kid (verification_method )
72
+ multikey = key_info ["multikey" ]
73
+ key_type = key_type_from_multikey (multikey )
74
+ public_key_base58 = multikey_to_verkey (multikey )
76
75
77
- header_alg = did_info . key_type .jws_algorithm
76
+ header_alg = key_type .jws_algorithm
78
77
if not header_alg :
79
- raise ValueError (f"DID key type '{ did_info . key_type } ' cannot be used for JWS" )
78
+ raise ValueError (f"DID key type '{ key_type } ' cannot be used for JWS" )
80
79
81
80
if not headers .get ("typ" , None ):
82
81
headers ["typ" ] = "JWT"
@@ -88,9 +87,9 @@ async def jwt_sign(
88
87
encoded_headers = dict_to_b64 (headers )
89
88
encoded_payload = dict_to_b64 (payload )
90
89
91
- LOGGER .info (f"jwt sign: { did } " )
90
+ LOGGER .info (f"jwt sign: { verification_method } " )
92
91
sig_bytes = await wallet .sign_message (
93
- f"{ encoded_headers } .{ encoded_payload } " .encode (), did_info . verkey
92
+ f"{ encoded_headers } .{ encoded_payload } " .encode (), public_key_base58
94
93
)
95
94
96
95
sig = bytes_to_b64 (sig_bytes , urlsafe = True , pad = False )
@@ -138,38 +137,6 @@ class Meta:
138
137
error = fields .Str (required = False , metadata = {"description" : "Error text" })
139
138
140
139
141
- async def resolve_public_key_by_kid_for_verify (
142
- profile : Profile , kid : str
143
- ) -> Tuple [str , KeyType ]:
144
- """Resolve public key verkey (base58 public key) and key type from a kid."""
145
- resolver = profile .inject (DIDResolver )
146
- vmethod : Resource = await resolver .dereference (
147
- profile ,
148
- kid ,
149
- )
150
-
151
- if not isinstance (vmethod , VerificationMethod ):
152
- raise InvalidVerificationMethod (
153
- "Dereferenced resource is not a verification method"
154
- )
155
-
156
- if isinstance (vmethod , Ed25519VerificationKey2018 ):
157
- verkey = vmethod .public_key_base58
158
- ktyp = ED25519
159
- return (verkey , ktyp )
160
-
161
- if isinstance (vmethod , Multikey ):
162
- multikey = vmethod .public_key_multibase
163
- verkey = multikey_to_verkey (multikey )
164
- ktyp = key_type_from_multikey (multikey = multikey )
165
- return (verkey , ktyp )
166
-
167
- # unsupported
168
- raise InvalidVerificationMethod (
169
- f"Dereferenced method { type (vmethod ).__name__ } is not supported"
170
- )
171
-
172
-
173
140
async def jwt_verify (profile : Profile , jwt : str ) -> JWTVerifyResult :
174
141
"""Verify a JWT and return the headers and payload."""
175
142
encoded_headers , encoded_payload , encoded_signature = jwt .split ("." , 3 )
@@ -189,15 +156,19 @@ async def jwt_verify(profile: Profile, jwt: str) -> JWTVerifyResult:
189
156
decoded_signature = b64_to_bytes (encoded_signature , urlsafe = True )
190
157
191
158
async with profile .session () as session :
192
- (verkey , ktyp ) = await resolve_public_key_by_kid_for_verify (
193
- profile , verification_method
159
+ key_manager = MultikeyManager (session )
160
+ multikey = await key_manager .resolve_multikey_from_verification_method_id (
161
+ verification_method
194
162
)
163
+ key_type = key_type_from_multikey (multikey )
164
+ public_key_base58 = multikey_to_verkey (multikey )
165
+
195
166
wallet = session .inject (BaseWallet )
196
167
valid = await wallet .verify_message (
197
168
f"{ encoded_headers } .{ encoded_payload } " .encode (),
198
169
decoded_signature ,
199
- from_verkey = verkey ,
200
- key_type = ktyp ,
170
+ from_verkey = public_key_base58 ,
171
+ key_type = key_type ,
201
172
)
202
173
203
174
return JWTVerifyResult (headers , payload , valid , verification_method )
0 commit comments