@sphereon/ssi-sdk-ext.did-utils 0.28.1-feature.esm.cjs.8 → 0.28.1-feature.oyd.cmsm.improv.16
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/did-functions.d.ts +190 -0
- package/dist/did-functions.d.ts.map +1 -0
- package/dist/did-functions.js +817 -0
- package/dist/did-functions.js.map +1 -0
- package/dist/index.d.ts +3 -271
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +17 -719
- package/dist/index.js.map +1 -1
- package/dist/types.d.ts +85 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +19 -0
- package/dist/types.js.map +1 -0
- package/package.json +15 -26
- package/src/did-functions.ts +762 -756
- package/dist/index.cjs +0 -752
- package/dist/index.cjs.map +0 -1
- package/dist/index.d.cts +0 -271
package/src/did-functions.ts
CHANGED
|
@@ -1,201 +1,207 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import {computeAddress} from '@ethersproject/transactions'
|
|
2
|
+
import {UniResolver} from '@sphereon/did-uni-client'
|
|
3
3
|
import {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
4
|
+
ENC_KEY_ALGS,
|
|
5
|
+
getKms,
|
|
6
|
+
JwkKeyUse,
|
|
7
|
+
keyTypeFromCryptographicSuite,
|
|
8
|
+
sanitizedJwk,
|
|
9
|
+
signatureAlgorithmFromKey,
|
|
10
|
+
TKeyType,
|
|
11
|
+
toJwk,
|
|
12
12
|
} from '@sphereon/ssi-sdk-ext.key-utils'
|
|
13
|
-
import {
|
|
14
|
-
import {
|
|
15
|
-
import {
|
|
16
|
-
import {
|
|
17
|
-
import { DIDDocument, DIDDocumentSection, DIDResolutionResult, IAgentContext, IDIDManager, IIdentifier, IKey, IResolver } from '@veramo/core'
|
|
13
|
+
import {base64ToHex, hexKeyFromPEMBasedJwk} from '@sphereon/ssi-sdk-ext.x509-utils'
|
|
14
|
+
import {base58ToBytes, base64ToBytes, bytesToHex, hexToBytes, multibaseKeyToBytes} from '@sphereon/ssi-sdk.core'
|
|
15
|
+
import {JWK} from '@sphereon/ssi-types'
|
|
16
|
+
import {convertPublicKeyToX25519} from '@stablelib/ed25519'
|
|
18
17
|
import {
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
18
|
+
DIDDocument,
|
|
19
|
+
DIDDocumentSection,
|
|
20
|
+
DIDResolutionResult,
|
|
21
|
+
IAgentContext,
|
|
22
|
+
IDIDManager,
|
|
23
|
+
IIdentifier,
|
|
24
|
+
IKey,
|
|
25
|
+
IResolver
|
|
26
|
+
} from '@veramo/core'
|
|
27
|
+
import {
|
|
28
|
+
_ExtendedIKey,
|
|
29
|
+
_ExtendedVerificationMethod,
|
|
30
|
+
_NormalizedVerificationMethod,
|
|
31
|
+
compressIdentifierSecp256k1Keys,
|
|
32
|
+
convertIdentifierEncryptionKeys,
|
|
33
|
+
getEthereumAddress,
|
|
34
|
+
isDefined,
|
|
35
|
+
mapIdentifierKeysToDoc,
|
|
27
36
|
} from '@veramo/utils'
|
|
28
|
-
import {
|
|
29
|
-
import {
|
|
37
|
+
import {createJWT, Signer} from 'did-jwt'
|
|
38
|
+
import {DIDResolutionOptions, JsonWebKey, Resolvable, VerificationMethod} from 'did-resolver'
|
|
30
39
|
// @ts-ignore
|
|
31
40
|
import elliptic from 'elliptic'
|
|
32
|
-
|
|
33
|
-
import { fromString } from 'uint8arrays/from-string'
|
|
34
|
-
// @ts-ignore
|
|
35
|
-
import { toString } from 'uint8arrays/to-string'
|
|
41
|
+
import * as u8a from 'uint8arrays'
|
|
36
42
|
import {
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
43
|
+
CreateIdentifierOpts,
|
|
44
|
+
CreateOrGetIdentifierOpts,
|
|
45
|
+
DID_PREFIX,
|
|
46
|
+
GetOrCreateResult,
|
|
47
|
+
GetSignerArgs,
|
|
48
|
+
IdentifierAliasEnum,
|
|
49
|
+
IdentifierProviderOpts,
|
|
50
|
+
IDIDOptions,
|
|
51
|
+
SignJwtArgs,
|
|
52
|
+
SupportedDidMethodEnum,
|
|
47
53
|
} from './types'
|
|
48
54
|
|
|
49
55
|
export const getAuthenticationKey = async (
|
|
50
|
-
{
|
|
51
|
-
identifier,
|
|
52
|
-
offlineWhenNoDIDRegistered,
|
|
53
|
-
noVerificationMethodFallback,
|
|
54
|
-
keyType,
|
|
55
|
-
controllerKey,
|
|
56
|
-
}: {
|
|
57
|
-
identifier: IIdentifier
|
|
58
|
-
keyType?: TKeyType
|
|
59
|
-
offlineWhenNoDIDRegistered?: boolean
|
|
60
|
-
noVerificationMethodFallback?: boolean
|
|
61
|
-
controllerKey?: boolean
|
|
62
|
-
},
|
|
63
|
-
context: IAgentContext<IResolver & IDIDManager>
|
|
64
|
-
): Promise<_ExtendedIKey> => {
|
|
65
|
-
return await getFirstKeyWithRelation(
|
|
66
56
|
{
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
57
|
+
identifier,
|
|
58
|
+
offlineWhenNoDIDRegistered,
|
|
59
|
+
noVerificationMethodFallback,
|
|
60
|
+
keyType,
|
|
61
|
+
controllerKey,
|
|
62
|
+
}: {
|
|
63
|
+
identifier: IIdentifier
|
|
64
|
+
keyType?: TKeyType
|
|
65
|
+
offlineWhenNoDIDRegistered?: boolean
|
|
66
|
+
noVerificationMethodFallback?: boolean
|
|
67
|
+
controllerKey?: boolean
|
|
73
68
|
},
|
|
74
|
-
context
|
|
75
|
-
)
|
|
76
|
-
}
|
|
77
|
-
export const getFirstKeyWithRelation = async (
|
|
78
|
-
{
|
|
79
|
-
identifier,
|
|
80
|
-
offlineWhenNoDIDRegistered,
|
|
81
|
-
noVerificationMethodFallback,
|
|
82
|
-
keyType,
|
|
83
|
-
controllerKey,
|
|
84
|
-
vmRelationship,
|
|
85
|
-
}: {
|
|
86
|
-
identifier: IIdentifier
|
|
87
|
-
keyType?: TKeyType
|
|
88
|
-
offlineWhenNoDIDRegistered?: boolean
|
|
89
|
-
noVerificationMethodFallback?: boolean
|
|
90
|
-
controllerKey?: boolean
|
|
91
|
-
vmRelationship: DIDDocumentSection
|
|
92
|
-
},
|
|
93
|
-
context: IAgentContext<IResolver & IDIDManager>
|
|
69
|
+
context: IAgentContext<IResolver & IDIDManager>
|
|
94
70
|
): Promise<_ExtendedIKey> => {
|
|
95
|
-
|
|
96
|
-
try {
|
|
97
|
-
key =
|
|
98
|
-
(await getFirstKeyWithRelationFromDIDDoc(
|
|
99
|
-
{
|
|
100
|
-
identifier,
|
|
101
|
-
vmRelationship,
|
|
102
|
-
errorOnNotFound: false,
|
|
103
|
-
keyType,
|
|
104
|
-
controllerKey,
|
|
105
|
-
},
|
|
106
|
-
context
|
|
107
|
-
)) ??
|
|
108
|
-
(noVerificationMethodFallback || vmRelationship === 'verificationMethod' // let's not fallback to the same value again
|
|
109
|
-
? undefined
|
|
110
|
-
: await getFirstKeyWithRelationFromDIDDoc(
|
|
111
|
-
{
|
|
112
|
-
identifier,
|
|
113
|
-
vmRelationship: 'verificationMethod',
|
|
114
|
-
errorOnNotFound: false,
|
|
115
|
-
keyType,
|
|
116
|
-
controllerKey,
|
|
117
|
-
},
|
|
118
|
-
context
|
|
119
|
-
))
|
|
120
|
-
} catch (e) {
|
|
121
|
-
if (e instanceof Error) {
|
|
122
|
-
if (!e.message.includes('404') || !offlineWhenNoDIDRegistered) {
|
|
123
|
-
throw e
|
|
124
|
-
}
|
|
125
|
-
} else {
|
|
126
|
-
throw e
|
|
127
|
-
}
|
|
128
|
-
}
|
|
129
|
-
if (!key && offlineWhenNoDIDRegistered) {
|
|
130
|
-
const offlineDID = toDidDocument(identifier)
|
|
131
|
-
key =
|
|
132
|
-
(await getFirstKeyWithRelationFromDIDDoc(
|
|
71
|
+
return await getFirstKeyWithRelation(
|
|
133
72
|
{
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
73
|
+
identifier,
|
|
74
|
+
offlineWhenNoDIDRegistered,
|
|
75
|
+
noVerificationMethodFallback,
|
|
76
|
+
keyType,
|
|
77
|
+
controllerKey,
|
|
78
|
+
vmRelationship: 'authentication',
|
|
140
79
|
},
|
|
141
80
|
context
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
81
|
+
)
|
|
82
|
+
}
|
|
83
|
+
export const getFirstKeyWithRelation = async (
|
|
84
|
+
{
|
|
85
|
+
identifier,
|
|
86
|
+
offlineWhenNoDIDRegistered,
|
|
87
|
+
noVerificationMethodFallback,
|
|
88
|
+
keyType,
|
|
89
|
+
controllerKey,
|
|
90
|
+
vmRelationship,
|
|
91
|
+
}: {
|
|
92
|
+
identifier: IIdentifier
|
|
93
|
+
keyType?: TKeyType
|
|
94
|
+
offlineWhenNoDIDRegistered?: boolean
|
|
95
|
+
noVerificationMethodFallback?: boolean
|
|
96
|
+
controllerKey?: boolean
|
|
97
|
+
vmRelationship: DIDDocumentSection
|
|
98
|
+
},
|
|
99
|
+
context: IAgentContext<IResolver & IDIDManager>
|
|
100
|
+
): Promise<_ExtendedIKey> => {
|
|
101
|
+
let key: _ExtendedIKey | undefined = undefined
|
|
102
|
+
try {
|
|
103
|
+
key =
|
|
104
|
+
(await getFirstKeyWithRelationFromDIDDoc(
|
|
105
|
+
{
|
|
106
|
+
identifier,
|
|
107
|
+
vmRelationship,
|
|
108
|
+
errorOnNotFound: false,
|
|
109
|
+
keyType,
|
|
110
|
+
controllerKey,
|
|
111
|
+
},
|
|
112
|
+
context
|
|
113
|
+
)) ??
|
|
114
|
+
(noVerificationMethodFallback || vmRelationship === 'verificationMethod' // let's not fallback to the same value again
|
|
115
|
+
? undefined
|
|
116
|
+
: await getFirstKeyWithRelationFromDIDDoc(
|
|
117
|
+
{
|
|
118
|
+
identifier,
|
|
119
|
+
vmRelationship: 'verificationMethod',
|
|
120
|
+
errorOnNotFound: false,
|
|
121
|
+
keyType,
|
|
122
|
+
controllerKey,
|
|
123
|
+
},
|
|
124
|
+
context
|
|
125
|
+
))
|
|
126
|
+
} catch (e) {
|
|
127
|
+
if (e instanceof Error) {
|
|
128
|
+
if (!e.message.includes('404') || !offlineWhenNoDIDRegistered) {
|
|
129
|
+
throw e
|
|
130
|
+
}
|
|
131
|
+
} else {
|
|
132
|
+
throw e
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
if (!key && offlineWhenNoDIDRegistered) {
|
|
136
|
+
const offlineDID = toDidDocument(identifier)
|
|
137
|
+
key =
|
|
138
|
+
(await getFirstKeyWithRelationFromDIDDoc(
|
|
139
|
+
{
|
|
140
|
+
identifier,
|
|
141
|
+
vmRelationship,
|
|
142
|
+
errorOnNotFound: false,
|
|
143
|
+
didDocument: offlineDID,
|
|
144
|
+
keyType,
|
|
145
|
+
controllerKey,
|
|
146
|
+
},
|
|
147
|
+
context
|
|
148
|
+
)) ??
|
|
149
|
+
(noVerificationMethodFallback || vmRelationship === 'verificationMethod' // let's not fallback to the same value again
|
|
150
|
+
? undefined
|
|
151
|
+
: await getFirstKeyWithRelationFromDIDDoc(
|
|
152
|
+
{
|
|
153
|
+
identifier,
|
|
154
|
+
vmRelationship: 'verificationMethod',
|
|
155
|
+
errorOnNotFound: false,
|
|
156
|
+
didDocument: offlineDID,
|
|
157
|
+
keyType,
|
|
158
|
+
controllerKey,
|
|
159
|
+
},
|
|
160
|
+
context
|
|
161
|
+
))
|
|
162
|
+
if (!key) {
|
|
163
|
+
key = identifier.keys
|
|
164
|
+
.map((key) => key as _ExtendedIKey)
|
|
165
|
+
.filter((key) => keyType === undefined || key.type === keyType || (controllerKey && key.kid === identifier.controllerKeyId))
|
|
166
|
+
.find((key) => key.meta.verificationMethod?.type.includes('authentication') || key.meta.purposes?.includes('authentication'))
|
|
167
|
+
}
|
|
168
|
+
}
|
|
156
169
|
if (!key) {
|
|
157
|
-
|
|
158
|
-
.map((key) => key as _ExtendedIKey)
|
|
159
|
-
.filter((key) => keyType === undefined || key.type === keyType || (controllerKey && key.kid === identifier.controllerKeyId))
|
|
160
|
-
.find((key) => key.meta.verificationMethod?.type.includes('authentication') || key.meta.purposes?.includes('authentication'))
|
|
170
|
+
throw Error(`Could not find authentication key for DID ${identifier.did}`)
|
|
161
171
|
}
|
|
162
|
-
|
|
163
|
-
if (!key) {
|
|
164
|
-
throw Error(`Could not find authentication key for DID ${identifier.did}`)
|
|
165
|
-
}
|
|
166
|
-
return key
|
|
172
|
+
return key
|
|
167
173
|
}
|
|
168
174
|
|
|
169
175
|
export const getOrCreatePrimaryIdentifier = async (
|
|
170
|
-
|
|
171
|
-
|
|
176
|
+
context: IAgentContext<IDIDManager>,
|
|
177
|
+
opts?: CreateOrGetIdentifierOpts
|
|
172
178
|
): Promise<GetOrCreateResult<IIdentifier>> => {
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
179
|
+
const primaryIdentifier = await getPrimaryIdentifier(context, {...opts?.createOpts?.options, ...(opts?.method && {method: opts.method})})
|
|
180
|
+
if (primaryIdentifier !== undefined) {
|
|
181
|
+
return {
|
|
182
|
+
created: false,
|
|
183
|
+
result: primaryIdentifier,
|
|
184
|
+
}
|
|
178
185
|
}
|
|
179
|
-
}
|
|
180
186
|
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
187
|
+
if (opts?.method === SupportedDidMethodEnum.DID_KEY) {
|
|
188
|
+
const createOpts = opts?.createOpts ?? {}
|
|
189
|
+
createOpts.options = {codecName: 'EBSI', type: 'Secp256r1', ...createOpts}
|
|
190
|
+
opts.createOpts = createOpts
|
|
191
|
+
}
|
|
192
|
+
const createdIdentifier = await createIdentifier(context, opts)
|
|
193
|
+
return {
|
|
194
|
+
created: true,
|
|
195
|
+
result: createdIdentifier,
|
|
196
|
+
}
|
|
191
197
|
}
|
|
192
198
|
|
|
193
199
|
export const getPrimaryIdentifier = async (context: IAgentContext<IDIDManager>, opts?: IdentifierProviderOpts): Promise<IIdentifier | undefined> => {
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
200
|
+
const identifiers = (await context.agent.didManagerFind(opts?.method ? {provider: `${DID_PREFIX}${opts?.method}`} : {})).filter(
|
|
201
|
+
(identifier: IIdentifier) => opts?.type === undefined || identifier.keys.some((key: IKey) => key.type === opts?.type)
|
|
202
|
+
)
|
|
197
203
|
|
|
198
|
-
|
|
204
|
+
return identifiers && identifiers.length > 0 ? identifiers[0] : undefined
|
|
199
205
|
}
|
|
200
206
|
|
|
201
207
|
export const createIdentifier = async (context: IAgentContext<IDIDManager>, opts?: CreateIdentifierOpts): Promise<IIdentifier> => {
|
|
@@ -208,80 +214,80 @@ export const createIdentifier = async (context: IAgentContext<IDIDManager>, opts
|
|
|
208
214
|
}
|
|
209
215
|
|
|
210
216
|
export const getFirstKeyWithRelationFromDIDDoc = async (
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
217
|
+
{
|
|
218
|
+
identifier,
|
|
219
|
+
vmRelationship = 'verificationMethod',
|
|
220
|
+
keyType,
|
|
221
|
+
errorOnNotFound = false,
|
|
222
|
+
didDocument,
|
|
223
|
+
controllerKey,
|
|
224
|
+
}: {
|
|
225
|
+
identifier: IIdentifier
|
|
226
|
+
controllerKey?: boolean
|
|
227
|
+
vmRelationship?: DIDDocumentSection
|
|
228
|
+
keyType?: TKeyType
|
|
229
|
+
errorOnNotFound?: boolean
|
|
230
|
+
didDocument?: DIDDocument
|
|
231
|
+
},
|
|
232
|
+
context: IAgentContext<IResolver & IDIDManager>
|
|
227
233
|
): Promise<_ExtendedIKey | undefined> => {
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
234
|
+
const matchedKeys = await mapIdentifierKeysToDocWithJwkSupport({identifier, vmRelationship, didDocument}, context)
|
|
235
|
+
if (Array.isArray(matchedKeys) && matchedKeys.length > 0) {
|
|
236
|
+
const result = matchedKeys.find(
|
|
237
|
+
(key) => keyType === undefined || key.type === keyType || (controllerKey && key.kid === identifier.controllerKeyId)
|
|
238
|
+
)
|
|
239
|
+
if (result) {
|
|
240
|
+
return result
|
|
241
|
+
}
|
|
235
242
|
}
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
return undefined
|
|
243
|
+
if (errorOnNotFound) {
|
|
244
|
+
throw new Error(
|
|
245
|
+
`Could not find key with relationship ${vmRelationship} in DID document for ${identifier.did}${keyType ? ' and key type: ' + keyType : ''}`
|
|
246
|
+
)
|
|
247
|
+
}
|
|
248
|
+
return undefined
|
|
243
249
|
}
|
|
244
250
|
|
|
245
|
-
export const getEthereumAddressFromKey = ({
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
251
|
+
export const getEthereumAddressFromKey = ({key}: { key: IKey }) => {
|
|
252
|
+
if (key.type !== 'Secp256k1') {
|
|
253
|
+
throw Error(`Can only get ethereum address from a Secp256k1 key. Type is ${key.type} for keyRef: ${key.kid}`)
|
|
254
|
+
}
|
|
255
|
+
const ethereumAddress = key.meta?.ethereumAddress ?? key.meta?.account?.toLowerCase() ?? computeAddress(`0x${key.publicKeyHex}`).toLowerCase()
|
|
256
|
+
if (!ethereumAddress) {
|
|
257
|
+
throw Error(`Could not get or generate ethereum address from key with keyRef ${key.kid}`)
|
|
258
|
+
}
|
|
259
|
+
return ethereumAddress
|
|
254
260
|
}
|
|
255
261
|
|
|
256
|
-
export const getControllerKey = ({
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
+
export const getControllerKey = ({identifier}: { identifier: IIdentifier }) => {
|
|
263
|
+
const key = identifier.keys.find((key) => key.kid === identifier.controllerKeyId)
|
|
264
|
+
if (!key) {
|
|
265
|
+
throw Error(`Could not get controller key for identifier ${identifier}`)
|
|
266
|
+
}
|
|
267
|
+
return key
|
|
262
268
|
}
|
|
263
269
|
|
|
264
270
|
export const getKeys = ({
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
}: {
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
271
|
+
jwkThumbprint,
|
|
272
|
+
kms,
|
|
273
|
+
identifier,
|
|
274
|
+
kmsKeyRef,
|
|
275
|
+
keyType,
|
|
276
|
+
controllerKey,
|
|
277
|
+
}: {
|
|
278
|
+
identifier: IIdentifier
|
|
279
|
+
kmsKeyRef?: string
|
|
280
|
+
keyType?: TKeyType
|
|
281
|
+
kms?: string
|
|
282
|
+
jwkThumbprint?: string
|
|
283
|
+
controllerKey?: boolean
|
|
278
284
|
}) => {
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
+
return identifier.keys
|
|
286
|
+
.filter((key) => !keyType || key.type === keyType)
|
|
287
|
+
.filter((key) => !kms || key.kms === kms)
|
|
288
|
+
.filter((key) => !kmsKeyRef || key.kid === kmsKeyRef)
|
|
289
|
+
.filter((key) => !jwkThumbprint || key.meta?.jwkThumbprint === jwkThumbprint)
|
|
290
|
+
.filter((key) => !controllerKey || identifier.controllerKeyId === key.kid)
|
|
285
291
|
}
|
|
286
292
|
|
|
287
293
|
//TODO: Move to ssi-sdk/core and create PR upstream
|
|
@@ -296,52 +302,52 @@ export const getKeys = ({
|
|
|
296
302
|
* @beta This API may change without a BREAKING CHANGE notice.
|
|
297
303
|
*/
|
|
298
304
|
export async function dereferenceDidKeysWithJwkSupport(
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
305
|
+
didDocument: DIDDocument,
|
|
306
|
+
section: DIDDocumentSection = 'keyAgreement',
|
|
307
|
+
context: IAgentContext<IResolver>
|
|
302
308
|
): Promise<_NormalizedVerificationMethod[]> {
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
309
|
+
const convert = section === 'keyAgreement'
|
|
310
|
+
if (section === 'service') {
|
|
311
|
+
return []
|
|
312
|
+
}
|
|
313
|
+
return (
|
|
314
|
+
await Promise.all(
|
|
315
|
+
(didDocument[section] || []).map(async (key: string | VerificationMethod) => {
|
|
316
|
+
if (typeof key === 'string') {
|
|
317
|
+
try {
|
|
318
|
+
return (await context.agent.getDIDComponentById({
|
|
319
|
+
didDocument,
|
|
320
|
+
didUrl: key,
|
|
321
|
+
section,
|
|
322
|
+
})) as _ExtendedVerificationMethod
|
|
323
|
+
} catch (e) {
|
|
324
|
+
return null
|
|
325
|
+
}
|
|
326
|
+
} else {
|
|
327
|
+
return key as _ExtendedVerificationMethod
|
|
328
|
+
}
|
|
329
|
+
})
|
|
330
|
+
)
|
|
324
331
|
)
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
})
|
|
332
|
+
.filter(isDefined)
|
|
333
|
+
.map((key) => {
|
|
334
|
+
const hexKey = extractPublicKeyHexWithJwkSupport(key, convert)
|
|
335
|
+
const {publicKeyHex, publicKeyBase58, publicKeyBase64, publicKeyJwk, ...keyProps} = key
|
|
336
|
+
const newKey = {...keyProps, publicKeyHex: hexKey}
|
|
337
|
+
if (convert && 'Ed25519VerificationKey2018' === newKey.type) {
|
|
338
|
+
newKey.type = 'X25519KeyAgreementKey2019'
|
|
339
|
+
}
|
|
340
|
+
return newKey
|
|
341
|
+
})
|
|
336
342
|
}
|
|
337
343
|
|
|
338
344
|
export function jwkTtoPublicKeyHex(jwk: JWK): string {
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
+
// todo: Hacky way to convert this to a VM. Should extract the logic from the below methods
|
|
346
|
+
// @ts-ignore
|
|
347
|
+
const vm: _ExtendedVerificationMethod = {
|
|
348
|
+
publicKeyJwk: sanitizedJwk(jwk),
|
|
349
|
+
}
|
|
350
|
+
return extractPublicKeyHexWithJwkSupport(vm)
|
|
345
351
|
}
|
|
346
352
|
|
|
347
353
|
/**
|
|
@@ -354,42 +360,42 @@ export function jwkTtoPublicKeyHex(jwk: JWK): string {
|
|
|
354
360
|
* @beta This API may change without a BREAKING CHANGE notice.
|
|
355
361
|
*/
|
|
356
362
|
export function extractPublicKeyHexWithJwkSupport(pk: _ExtendedVerificationMethod, convert = false): string {
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
363
|
+
if (pk.publicKeyJwk) {
|
|
364
|
+
const jwk = sanitizedJwk(pk.publicKeyJwk)
|
|
365
|
+
if (jwk.kty === 'EC') {
|
|
366
|
+
const curve = jwk.crv ? toEcLibCurve(jwk.crv) : 'p256'
|
|
367
|
+
const xHex = base64ToHex(jwk.x!, 'base64url')
|
|
368
|
+
const yHex = base64ToHex(jwk.y!, 'base64url')
|
|
369
|
+
const prefix = '04' // isEven(yHex) ? '02' : '03'
|
|
370
|
+
// Uncompressed Hex format: 04<x><y>
|
|
371
|
+
// Compressed Hex format: 02<x> (for even y) or 03<x> (for uneven y)
|
|
372
|
+
const hex = `${prefix}${xHex}${yHex}`
|
|
373
|
+
try {
|
|
374
|
+
const ec = new elliptic.ec(curve)
|
|
375
|
+
// We return directly as we don't want to convert the result back into Uint8Array and then convert again to hex as the elliptic lib already returns hex strings
|
|
376
|
+
const publicKeyHex = ec.keyFromPublic(hex, 'hex').getPublic(true, 'hex')
|
|
377
|
+
// This returns a short form (x) with 02 or 03 prefix
|
|
378
|
+
return publicKeyHex
|
|
379
|
+
} catch (error: any) {
|
|
380
|
+
console.error(`Error converting EC with elliptic lib curve ${curve} from JWK to hex. x: ${jwk.x}, y: ${jwk.y}, error: ${error}`, error)
|
|
381
|
+
}
|
|
382
|
+
} else if (jwk.crv === 'Ed25519') {
|
|
383
|
+
return u8a.toString(u8a.fromString(jwk.x!, 'base64url'), 'base16')
|
|
384
|
+
} else if (jwk.kty === 'RSA') {
|
|
385
|
+
return hexKeyFromPEMBasedJwk(jwk, 'public')
|
|
386
|
+
}
|
|
387
|
+
}
|
|
388
|
+
// delegate the other types to the original Veramo function
|
|
389
|
+
return extractPublicKeyHex(pk, convert)
|
|
384
390
|
}
|
|
385
391
|
|
|
386
392
|
export function isEvenHexString(hex: string) {
|
|
387
|
-
|
|
388
|
-
|
|
393
|
+
const lastChar = hex[hex.length - 1].toLowerCase()
|
|
394
|
+
return ['0', '2', '4', '6', '8', 'a', 'c', 'e'].includes(lastChar)
|
|
389
395
|
}
|
|
390
396
|
|
|
391
397
|
interface LegacyVerificationMethod extends VerificationMethod {
|
|
392
|
-
|
|
398
|
+
publicKeyBase64: string
|
|
393
399
|
}
|
|
394
400
|
|
|
395
401
|
/**
|
|
@@ -402,86 +408,86 @@ interface LegacyVerificationMethod extends VerificationMethod {
|
|
|
402
408
|
* @beta This API may change without a BREAKING CHANGE notice.
|
|
403
409
|
*/
|
|
404
410
|
export function extractPublicKeyHex(pk: _ExtendedVerificationMethod, convert: boolean = false): string {
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
411
|
+
let keyBytes = extractPublicKeyBytes(pk)
|
|
412
|
+
const jwk = pk.publicKeyJwk ? sanitizedJwk(pk.publicKeyJwk) : undefined
|
|
413
|
+
if (convert) {
|
|
414
|
+
if (
|
|
415
|
+
['Ed25519', 'Ed25519VerificationKey2018', 'Ed25519VerificationKey2020'].includes(pk.type) ||
|
|
416
|
+
(pk.type === 'JsonWebKey2020' && jwk?.crv === 'Ed25519')
|
|
417
|
+
) {
|
|
418
|
+
keyBytes = convertPublicKeyToX25519(keyBytes)
|
|
419
|
+
} else if (
|
|
420
|
+
!['X25519', 'X25519KeyAgreementKey2019', 'X25519KeyAgreementKey2020'].includes(pk.type) &&
|
|
421
|
+
!(pk.type === 'JsonWebKey2020' && jwk?.crv === 'X25519')
|
|
422
|
+
) {
|
|
423
|
+
return ''
|
|
424
|
+
}
|
|
418
425
|
}
|
|
419
|
-
|
|
420
|
-
return bytesToHex(keyBytes)
|
|
426
|
+
return bytesToHex(keyBytes)
|
|
421
427
|
}
|
|
422
428
|
|
|
423
429
|
function toEcLibCurve(input: string) {
|
|
424
|
-
|
|
430
|
+
return input.toLowerCase().replace('-', '').replace('_', '')
|
|
425
431
|
}
|
|
426
432
|
|
|
427
433
|
function extractPublicKeyBytes(pk: VerificationMethod): Uint8Array {
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
434
|
+
if (pk.publicKeyBase58) {
|
|
435
|
+
return base58ToBytes(pk.publicKeyBase58)
|
|
436
|
+
} else if (pk.publicKeyMultibase) {
|
|
437
|
+
return multibaseKeyToBytes(pk.publicKeyMultibase)
|
|
438
|
+
} else if ((<LegacyVerificationMethod>pk).publicKeyBase64) {
|
|
439
|
+
return base64ToBytes((<LegacyVerificationMethod>pk).publicKeyBase64)
|
|
440
|
+
} else if (pk.publicKeyHex) {
|
|
441
|
+
return hexToBytes(pk.publicKeyHex)
|
|
442
|
+
} else if (pk.publicKeyJwk?.crv && pk.publicKeyJwk.x && pk.publicKeyJwk.y) {
|
|
443
|
+
return hexToBytes(
|
|
444
|
+
extractPublicKeyHexWithJwkSupport(pk)
|
|
445
|
+
)
|
|
446
|
+
} else if (pk.publicKeyJwk && (pk.publicKeyJwk.crv === 'Ed25519' || pk.publicKeyJwk.crv === 'X25519') && pk.publicKeyJwk.x) {
|
|
447
|
+
return base64ToBytes(pk.publicKeyJwk.x)
|
|
448
|
+
}
|
|
449
|
+
return new Uint8Array()
|
|
442
450
|
}
|
|
443
451
|
|
|
444
452
|
export function verificationMethodToJwk(vm: VerificationMethod): JWK {
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
453
|
+
let jwk: JWK | undefined = vm.publicKeyJwk as JWK
|
|
454
|
+
if (!jwk) {
|
|
455
|
+
let publicKeyHex = vm.publicKeyHex ?? u8a.toString(extractPublicKeyBytes(vm), 'hex')
|
|
456
|
+
jwk = toJwk(publicKeyHex, keyTypeFromCryptographicSuite({crv: vm.type}))
|
|
457
|
+
}
|
|
458
|
+
if (!jwk) {
|
|
459
|
+
throw Error(`Could not convert verification method to jwk`)
|
|
460
|
+
}
|
|
461
|
+
jwk.kid = vm.id
|
|
462
|
+
return sanitizedJwk(jwk)
|
|
455
463
|
}
|
|
456
464
|
|
|
457
465
|
function didDocumentSectionToJwks(
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
466
|
+
didDocumentSection: DIDDocumentSection,
|
|
467
|
+
searchForVerificationMethods?: (VerificationMethod | string)[],
|
|
468
|
+
verificationMethods?: VerificationMethod[]
|
|
461
469
|
) {
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
)
|
|
468
|
-
return { didDocumentSection, jwks: Array.from(jwks) }
|
|
470
|
+
const jwks = new Set((searchForVerificationMethods ?? [])
|
|
471
|
+
.map((vmOrId) => (typeof vmOrId === 'object' ? vmOrId : verificationMethods?.find((vm) => vm.id === vmOrId)))
|
|
472
|
+
.filter(isDefined)
|
|
473
|
+
.map((vm) => verificationMethodToJwk(vm)))
|
|
474
|
+
return {didDocumentSection, jwks: Array.from(jwks)}
|
|
469
475
|
}
|
|
470
476
|
|
|
471
477
|
export type DidDocumentJwks = Record<Exclude<DIDDocumentSection, 'publicKey' | 'service'>, Array<JWK>>
|
|
472
478
|
|
|
473
479
|
export function didDocumentToJwks(didDocument: DIDDocument): DidDocumentJwks {
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
480
|
+
return {
|
|
481
|
+
verificationMethod: [
|
|
482
|
+
...didDocumentSectionToJwks('publicKey', didDocument.publicKey, didDocument.verificationMethod).jwks, // legacy support
|
|
483
|
+
...didDocumentSectionToJwks('verificationMethod', didDocument.verificationMethod, didDocument.verificationMethod).jwks,
|
|
484
|
+
],
|
|
485
|
+
assertionMethod: didDocumentSectionToJwks('assertionMethod', didDocument.assertionMethod, didDocument.verificationMethod).jwks,
|
|
486
|
+
authentication: didDocumentSectionToJwks('authentication', didDocument.authentication, didDocument.verificationMethod).jwks,
|
|
487
|
+
keyAgreement: didDocumentSectionToJwks('keyAgreement', didDocument.keyAgreement, didDocument.verificationMethod).jwks,
|
|
488
|
+
capabilityInvocation: didDocumentSectionToJwks('capabilityInvocation', didDocument.capabilityInvocation, didDocument.verificationMethod).jwks,
|
|
489
|
+
capabilityDelegation: didDocumentSectionToJwks('capabilityDelegation', didDocument.capabilityDelegation, didDocument.verificationMethod).jwks,
|
|
490
|
+
}
|
|
485
491
|
}
|
|
486
492
|
|
|
487
493
|
/**
|
|
@@ -502,58 +508,58 @@ export function didDocumentToJwks(didDocument: DIDDocument): DidDocumentJwks {
|
|
|
502
508
|
* @beta This API may change without a BREAKING CHANGE notice.
|
|
503
509
|
*/
|
|
504
510
|
export async function mapIdentifierKeysToDocWithJwkSupport(
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
511
|
+
{
|
|
512
|
+
identifier,
|
|
513
|
+
vmRelationship = 'verificationMethod',
|
|
514
|
+
didDocument,
|
|
515
|
+
}: {
|
|
516
|
+
identifier: IIdentifier
|
|
517
|
+
vmRelationship?: DIDDocumentSection
|
|
518
|
+
didDocument?: DIDDocument
|
|
519
|
+
},
|
|
520
|
+
context: IAgentContext<IResolver & IDIDManager>
|
|
515
521
|
): Promise<_ExtendedIKey[]> {
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
522
|
+
const didDoc =
|
|
523
|
+
didDocument ??
|
|
524
|
+
(await getAgentResolver(context)
|
|
525
|
+
.resolve(identifier.did)
|
|
526
|
+
.then((result) => result.didDocument))
|
|
527
|
+
if (!didDoc) {
|
|
528
|
+
throw Error(`Could not resolve DID ${identifier.did}`)
|
|
529
|
+
}
|
|
524
530
|
|
|
525
|
-
|
|
531
|
+
// const rsaDidWeb = identifier.keys && identifier.keys.length > 0 && identifier.keys.find((key) => key.type === 'RSA') && didDocument
|
|
526
532
|
|
|
527
|
-
|
|
528
|
-
|
|
533
|
+
// We skip mapping in case the identifier is RSA and a did document is supplied.
|
|
534
|
+
const keys = didDoc ? [] : await mapIdentifierKeysToDoc(identifier, vmRelationship, context)
|
|
529
535
|
|
|
530
|
-
|
|
531
|
-
|
|
536
|
+
// dereference all key agreement keys from DID document and normalize
|
|
537
|
+
const documentKeys: VerificationMethod[] = await dereferenceDidKeysWithJwkSupport(didDoc, vmRelationship, context)
|
|
532
538
|
|
|
533
|
-
|
|
539
|
+
const localKeys = vmRelationship === 'keyAgreement' ? convertIdentifierEncryptionKeys(identifier) : compressIdentifierSecp256k1Keys(identifier)
|
|
534
540
|
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
541
|
+
// finally map the didDocument keys to the identifier keys by comparing `publicKeyHex`
|
|
542
|
+
const extendedKeys: _ExtendedIKey[] = documentKeys
|
|
543
|
+
.map((verificationMethod) => {
|
|
544
|
+
/*if (verificationMethod.type !== 'JsonWebKey2020') {
|
|
539
545
|
return null
|
|
540
546
|
}*/
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
547
|
+
const localKey = localKeys.find(
|
|
548
|
+
(localKey) =>
|
|
549
|
+
localKey.publicKeyHex === verificationMethod.publicKeyHex ||
|
|
550
|
+
verificationMethod.publicKeyHex?.startsWith(localKey.publicKeyHex) ||
|
|
551
|
+
compareBlockchainAccountId(localKey, verificationMethod)
|
|
552
|
+
)
|
|
553
|
+
if (localKey) {
|
|
554
|
+
const {meta, ...localProps} = localKey
|
|
555
|
+
return {...localProps, meta: {...meta, verificationMethod}}
|
|
556
|
+
} else {
|
|
557
|
+
return null
|
|
558
|
+
}
|
|
559
|
+
})
|
|
560
|
+
.filter(isDefined)
|
|
561
|
+
|
|
562
|
+
return keys.concat(extendedKeys)
|
|
557
563
|
}
|
|
558
564
|
|
|
559
565
|
/**
|
|
@@ -569,96 +575,96 @@ export async function mapIdentifierKeysToDocWithJwkSupport(
|
|
|
569
575
|
* @beta This API may change without a BREAKING CHANGE notice.
|
|
570
576
|
*/
|
|
571
577
|
function compareBlockchainAccountId(localKey: IKey, verificationMethod: VerificationMethod): boolean {
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
578
|
+
if (
|
|
579
|
+
(verificationMethod.type !== 'EcdsaSecp256k1RecoveryMethod2020' && verificationMethod.type !== 'EcdsaSecp256k1VerificationKey2019') ||
|
|
580
|
+
localKey.type !== 'Secp256k1'
|
|
581
|
+
) {
|
|
582
|
+
return false
|
|
583
|
+
}
|
|
584
|
+
let vmEthAddr = getEthereumAddress(verificationMethod)
|
|
585
|
+
if (localKey.meta?.account) {
|
|
586
|
+
return vmEthAddr === localKey.meta?.account.toLowerCase()
|
|
587
|
+
}
|
|
588
|
+
const computedAddr = computeAddress('0x' + localKey.publicKeyHex).toLowerCase()
|
|
589
|
+
return computedAddr === vmEthAddr
|
|
584
590
|
}
|
|
585
591
|
|
|
586
592
|
export async function getAgentDIDMethods(context: IAgentContext<IDIDManager>) {
|
|
587
|
-
|
|
593
|
+
return (await context.agent.didManagerGetProviders()).map((provider) => provider.toLowerCase().replace('did:', ''))
|
|
588
594
|
}
|
|
589
595
|
|
|
590
596
|
export function getDID(idOpts: { identifier: IIdentifier | string }): string {
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
+
if (typeof idOpts.identifier === 'string') {
|
|
598
|
+
return idOpts.identifier
|
|
599
|
+
} else if (typeof idOpts.identifier === 'object') {
|
|
600
|
+
return idOpts.identifier.did
|
|
601
|
+
}
|
|
602
|
+
throw Error(`Cannot get DID from identifier value`)
|
|
597
603
|
}
|
|
598
604
|
|
|
599
605
|
export function toDID(identifier: string | IIdentifier | Partial<IIdentifier>): string {
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
606
|
+
if (typeof identifier === 'string') {
|
|
607
|
+
return identifier
|
|
608
|
+
}
|
|
609
|
+
if (identifier.did) {
|
|
610
|
+
return identifier.did
|
|
611
|
+
}
|
|
612
|
+
throw Error(`No DID value present in identifier`)
|
|
607
613
|
}
|
|
608
614
|
|
|
609
615
|
export function toDIDs(identifiers?: (string | IIdentifier | Partial<IIdentifier>)[]): string[] {
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
616
|
+
if (!identifiers) {
|
|
617
|
+
return []
|
|
618
|
+
}
|
|
619
|
+
return identifiers.map(toDID)
|
|
614
620
|
}
|
|
615
621
|
|
|
616
622
|
export async function getKey(
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
623
|
+
{
|
|
624
|
+
identifier,
|
|
625
|
+
vmRelationship = 'authentication',
|
|
626
|
+
kmsKeyRef,
|
|
627
|
+
}: {
|
|
628
|
+
identifier: IIdentifier
|
|
629
|
+
vmRelationship?: DIDDocumentSection
|
|
630
|
+
kmsKeyRef?: string
|
|
631
|
+
},
|
|
632
|
+
context: IAgentContext<IResolver & IDIDManager>
|
|
627
633
|
): Promise<IKey> {
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
}
|
|
631
|
-
// normalize to kid, in case keyId was passed in as did#vm or #vm
|
|
632
|
-
const kmsKeyRefParts = kmsKeyRef?.split(`#`)
|
|
633
|
-
const kid = kmsKeyRefParts ? (kmsKeyRefParts?.length === 2 ? kmsKeyRefParts[1] : kmsKeyRefParts[0]) : undefined
|
|
634
|
-
// todo: We really should do a keyRef and external kid here
|
|
635
|
-
let identifierKey = kmsKeyRef ? identifier.keys.find((key: IKey) => key.kid === kid || key?.meta?.jwkThumbprint === kid) : undefined
|
|
636
|
-
if (!identifierKey) {
|
|
637
|
-
const keys = await mapIdentifierKeysToDocWithJwkSupport({ identifier, vmRelationship: vmRelationship }, context)
|
|
638
|
-
if (!keys || keys.length === 0) {
|
|
639
|
-
throw new Error(`No keys found for verificationMethodSection: ${vmRelationship} and did ${identifier.did}`)
|
|
640
|
-
}
|
|
641
|
-
if (kmsKeyRef) {
|
|
642
|
-
identifierKey = keys.find(
|
|
643
|
-
(key: _ExtendedIKey) => key.meta.verificationMethod?.id === kmsKeyRef || (kid && key.meta.verificationMethod?.id?.includes(kid))
|
|
644
|
-
)
|
|
634
|
+
if (!identifier) {
|
|
635
|
+
return Promise.reject(new Error(`No identifier provided to getKey method!`))
|
|
645
636
|
}
|
|
637
|
+
// normalize to kid, in case keyId was passed in as did#vm or #vm
|
|
638
|
+
const kmsKeyRefParts = kmsKeyRef?.split(`#`)
|
|
639
|
+
const kid = kmsKeyRefParts ? (kmsKeyRefParts?.length === 2 ? kmsKeyRefParts[1] : kmsKeyRefParts[0]) : undefined
|
|
640
|
+
// todo: We really should do a keyRef and external kid here
|
|
641
|
+
let identifierKey = kmsKeyRef ? identifier.keys.find((key: IKey) => key.kid === kid || key?.meta?.jwkThumbprint === kid) : undefined
|
|
646
642
|
if (!identifierKey) {
|
|
647
|
-
|
|
648
|
-
(
|
|
649
|
-
|
|
643
|
+
const keys = await mapIdentifierKeysToDocWithJwkSupport({identifier, vmRelationship: vmRelationship}, context)
|
|
644
|
+
if (!keys || keys.length === 0) {
|
|
645
|
+
throw new Error(`No keys found for verificationMethodSection: ${vmRelationship} and did ${identifier.did}`)
|
|
646
|
+
}
|
|
647
|
+
if (kmsKeyRef) {
|
|
648
|
+
identifierKey = keys.find(
|
|
649
|
+
(key: _ExtendedIKey) => key.meta.verificationMethod?.id === kmsKeyRef || (kid && key.meta.verificationMethod?.id?.includes(kid))
|
|
650
|
+
)
|
|
651
|
+
}
|
|
652
|
+
if (!identifierKey) {
|
|
653
|
+
identifierKey = keys.find(
|
|
654
|
+
(key: _ExtendedIKey) => key.meta.verificationMethod?.type === vmRelationship || key.meta.purposes?.includes(vmRelationship)
|
|
655
|
+
)
|
|
656
|
+
}
|
|
657
|
+
if (!identifierKey) {
|
|
658
|
+
identifierKey = keys[0]
|
|
659
|
+
}
|
|
650
660
|
}
|
|
651
661
|
if (!identifierKey) {
|
|
652
|
-
|
|
662
|
+
throw new Error(
|
|
663
|
+
`No matching verificationMethodSection key found for keyId: ${kmsKeyRef} and vmSection: ${vmRelationship} for id ${identifier.did}`
|
|
664
|
+
)
|
|
653
665
|
}
|
|
654
|
-
}
|
|
655
|
-
if (!identifierKey) {
|
|
656
|
-
throw new Error(
|
|
657
|
-
`No matching verificationMethodSection key found for keyId: ${kmsKeyRef} and vmSection: ${vmRelationship} for id ${identifier.did}`
|
|
658
|
-
)
|
|
659
|
-
}
|
|
660
666
|
|
|
661
|
-
|
|
667
|
+
return identifierKey
|
|
662
668
|
}
|
|
663
669
|
|
|
664
670
|
/**
|
|
@@ -669,17 +675,17 @@ export async function getKey(
|
|
|
669
675
|
* @deprecated Replaced by the identfier resolution plugin
|
|
670
676
|
*/
|
|
671
677
|
async function legacyGetIdentifier(
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
+
{
|
|
679
|
+
identifier,
|
|
680
|
+
}: {
|
|
681
|
+
identifier: string | IIdentifier
|
|
682
|
+
},
|
|
683
|
+
context: IAgentContext<IDIDManager>
|
|
678
684
|
): Promise<IIdentifier> {
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
685
|
+
if (typeof identifier === 'string') {
|
|
686
|
+
return await context.agent.didManagerGet({did: identifier})
|
|
687
|
+
}
|
|
688
|
+
return identifier
|
|
683
689
|
}
|
|
684
690
|
|
|
685
691
|
/**
|
|
@@ -689,132 +695,132 @@ async function legacyGetIdentifier(
|
|
|
689
695
|
* @param context
|
|
690
696
|
*/
|
|
691
697
|
export async function determineKid(
|
|
692
|
-
{
|
|
693
|
-
key,
|
|
694
|
-
idOpts,
|
|
695
|
-
}: {
|
|
696
|
-
key: IKey
|
|
697
|
-
idOpts: { identifier: IIdentifier | string; kmsKeyRef?: string }
|
|
698
|
-
},
|
|
699
|
-
context: IAgentContext<IResolver & IDIDManager>
|
|
700
|
-
): Promise<string> {
|
|
701
|
-
if (key.meta?.verificationMethod?.id) {
|
|
702
|
-
return key.meta?.verificationMethod?.id
|
|
703
|
-
}
|
|
704
|
-
const identifier = await legacyGetIdentifier(idOpts, context)
|
|
705
|
-
const mappedKeys = await mapIdentifierKeysToDocWithJwkSupport(
|
|
706
698
|
{
|
|
707
|
-
|
|
708
|
-
|
|
699
|
+
key,
|
|
700
|
+
idOpts,
|
|
701
|
+
}: {
|
|
702
|
+
key: IKey
|
|
703
|
+
idOpts: { identifier: IIdentifier | string; kmsKeyRef?: string }
|
|
709
704
|
},
|
|
710
|
-
context
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
705
|
+
context: IAgentContext<IResolver & IDIDManager>
|
|
706
|
+
): Promise<string> {
|
|
707
|
+
if (key.meta?.verificationMethod?.id) {
|
|
708
|
+
return key.meta?.verificationMethod?.id
|
|
709
|
+
}
|
|
710
|
+
const identifier = await legacyGetIdentifier(idOpts, context)
|
|
711
|
+
const mappedKeys = await mapIdentifierKeysToDocWithJwkSupport(
|
|
712
|
+
{
|
|
713
|
+
identifier,
|
|
714
|
+
vmRelationship: 'verificationMethod',
|
|
715
|
+
},
|
|
716
|
+
context
|
|
717
|
+
)
|
|
718
|
+
const vmKey = mappedKeys.find((extendedKey) => extendedKey.kid === key.kid)
|
|
719
|
+
if (vmKey) {
|
|
720
|
+
return vmKey.meta?.verificationMethod?.id ?? vmKey.meta?.jwkThumbprint ?? idOpts.kmsKeyRef ?? vmKey.kid
|
|
721
|
+
}
|
|
716
722
|
|
|
717
|
-
|
|
723
|
+
return key.meta?.jwkThumbprint ?? idOpts.kmsKeyRef ?? key.kid
|
|
718
724
|
}
|
|
719
725
|
|
|
720
726
|
export async function getSupportedDIDMethods(didOpts: IDIDOptions, context: IAgentContext<IDIDManager>) {
|
|
721
|
-
|
|
727
|
+
return didOpts.supportedDIDMethods ?? (await getAgentDIDMethods(context))
|
|
722
728
|
}
|
|
723
729
|
|
|
724
730
|
export function getAgentResolver(
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
+
context: IAgentContext<IResolver & IDIDManager>,
|
|
732
|
+
opts?: {
|
|
733
|
+
localResolution?: boolean // Resolve identifiers hosted by the agent
|
|
734
|
+
uniresolverResolution?: boolean // Resolve identifiers using universal resolver
|
|
735
|
+
resolverResolution?: boolean // Use registered drivers
|
|
736
|
+
}
|
|
731
737
|
): Resolvable {
|
|
732
|
-
|
|
738
|
+
return new AgentDIDResolver(context, opts)
|
|
733
739
|
}
|
|
734
740
|
|
|
735
741
|
export class AgentDIDResolver implements Resolvable {
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
742
|
+
private readonly context: IAgentContext<IResolver & IDIDManager>
|
|
743
|
+
private readonly resolverResolution: boolean
|
|
744
|
+
private readonly uniresolverResolution: boolean
|
|
745
|
+
private readonly localResolution: boolean
|
|
746
|
+
|
|
747
|
+
constructor(
|
|
748
|
+
context: IAgentContext<IResolver & IDIDManager>,
|
|
749
|
+
opts?: { uniresolverResolution?: boolean; localResolution?: boolean; resolverResolution?: boolean }
|
|
750
|
+
) {
|
|
751
|
+
this.context = context
|
|
752
|
+
this.resolverResolution = opts?.resolverResolution !== false
|
|
753
|
+
this.uniresolverResolution = opts?.uniresolverResolution !== false
|
|
754
|
+
this.localResolution = opts?.localResolution !== false
|
|
755
|
+
}
|
|
740
756
|
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
resolutionResult = await this.context.agent.resolveDid({ didUrl, options })
|
|
761
|
-
} catch (error: unknown) {
|
|
762
|
-
err = error
|
|
763
|
-
}
|
|
764
|
-
}
|
|
765
|
-
if (resolutionResult) {
|
|
766
|
-
origResolutionResult = resolutionResult
|
|
767
|
-
if (resolutionResult.didDocument === null) {
|
|
768
|
-
resolutionResult = undefined
|
|
769
|
-
}
|
|
770
|
-
} else {
|
|
771
|
-
console.log(`Agent resolver resolution is disabled. This typically isn't desirable!`)
|
|
772
|
-
}
|
|
773
|
-
if (!resolutionResult && this.localResolution) {
|
|
774
|
-
console.log(`Using local DID resolution, looking at DIDs hosted by the agent.`)
|
|
775
|
-
try {
|
|
776
|
-
const did = didUrl.split('#')[0]
|
|
777
|
-
const iIdentifier = await this.context.agent.didManagerGet({ did })
|
|
778
|
-
resolutionResult = toDidResolutionResult(iIdentifier, { did })
|
|
779
|
-
if (resolutionResult.didDocument) {
|
|
780
|
-
err = undefined
|
|
757
|
+
async resolve(didUrl: string, options?: DIDResolutionOptions): Promise<DIDResolutionResult> {
|
|
758
|
+
let resolutionResult: DIDResolutionResult | undefined
|
|
759
|
+
let origResolutionResult: DIDResolutionResult | undefined
|
|
760
|
+
let err: any
|
|
761
|
+
if (!this.resolverResolution && !this.localResolution && !this.uniresolverResolution) {
|
|
762
|
+
throw Error(`No agent hosted DID resolution, regular agent resolution nor universal resolver resolution is enabled. Cannot resolve DIDs.`)
|
|
763
|
+
}
|
|
764
|
+
if (this.resolverResolution) {
|
|
765
|
+
try {
|
|
766
|
+
resolutionResult = await this.context.agent.resolveDid({didUrl, options})
|
|
767
|
+
} catch (error: unknown) {
|
|
768
|
+
err = error
|
|
769
|
+
}
|
|
770
|
+
}
|
|
771
|
+
if (resolutionResult) {
|
|
772
|
+
origResolutionResult = resolutionResult
|
|
773
|
+
if (resolutionResult.didDocument === null) {
|
|
774
|
+
resolutionResult = undefined
|
|
775
|
+
}
|
|
781
776
|
} else {
|
|
782
|
-
|
|
777
|
+
console.log(`Agent resolver resolution is disabled. This typically isn't desirable!`)
|
|
783
778
|
}
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
779
|
+
if (!resolutionResult && this.localResolution) {
|
|
780
|
+
console.log(`Using local DID resolution, looking at DIDs hosted by the agent.`)
|
|
781
|
+
try {
|
|
782
|
+
const did = didUrl.split('#')[0]
|
|
783
|
+
const iIdentifier = await this.context.agent.didManagerGet({did})
|
|
784
|
+
resolutionResult = toDidResolutionResult(iIdentifier, {did})
|
|
785
|
+
if (resolutionResult.didDocument) {
|
|
786
|
+
err = undefined
|
|
787
|
+
} else {
|
|
788
|
+
console.log(`Local resolution resulted in a DID Document for ${did}`)
|
|
789
|
+
}
|
|
790
|
+
} catch (error: unknown) {
|
|
791
|
+
if (!err) {
|
|
792
|
+
err = error
|
|
793
|
+
}
|
|
794
|
+
}
|
|
795
|
+
}
|
|
796
|
+
if (resolutionResult) {
|
|
797
|
+
if (!origResolutionResult) {
|
|
798
|
+
origResolutionResult = resolutionResult
|
|
799
|
+
}
|
|
800
|
+
if (!resolutionResult.didDocument) {
|
|
801
|
+
resolutionResult = undefined
|
|
802
|
+
}
|
|
803
|
+
}
|
|
804
|
+
if (!resolutionResult && this.uniresolverResolution) {
|
|
805
|
+
console.log(`Using universal resolver resolution for did ${didUrl} `)
|
|
806
|
+
resolutionResult = await new UniResolver().resolve(didUrl, options)
|
|
807
|
+
if (!origResolutionResult) {
|
|
808
|
+
origResolutionResult = resolutionResult
|
|
809
|
+
}
|
|
810
|
+
if (resolutionResult.didDocument) {
|
|
811
|
+
err = undefined
|
|
812
|
+
}
|
|
787
813
|
}
|
|
788
|
-
}
|
|
789
|
-
}
|
|
790
|
-
if (resolutionResult) {
|
|
791
|
-
if (!origResolutionResult) {
|
|
792
|
-
origResolutionResult = resolutionResult
|
|
793
|
-
}
|
|
794
|
-
if (!resolutionResult.didDocument) {
|
|
795
|
-
resolutionResult = undefined
|
|
796
|
-
}
|
|
797
|
-
}
|
|
798
|
-
if (!resolutionResult && this.uniresolverResolution) {
|
|
799
|
-
console.log(`Using universal resolver resolution for did ${didUrl} `)
|
|
800
|
-
resolutionResult = await new UniResolver().resolve(didUrl, options)
|
|
801
|
-
if (!origResolutionResult) {
|
|
802
|
-
origResolutionResult = resolutionResult
|
|
803
|
-
}
|
|
804
|
-
if (resolutionResult.didDocument) {
|
|
805
|
-
err = undefined
|
|
806
|
-
}
|
|
807
|
-
}
|
|
808
814
|
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
+
if (err) {
|
|
816
|
+
// throw original error
|
|
817
|
+
throw err
|
|
818
|
+
}
|
|
819
|
+
if (!resolutionResult && !origResolutionResult) {
|
|
820
|
+
throw `Could not resolve ${didUrl}. Resolutions tried: online: ${this.resolverResolution}, local: ${this.localResolution}, uni resolver: ${this.uniresolverResolution}`
|
|
821
|
+
}
|
|
822
|
+
return resolutionResult ?? origResolutionResult!
|
|
815
823
|
}
|
|
816
|
-
return resolutionResult ?? origResolutionResult!
|
|
817
|
-
}
|
|
818
824
|
}
|
|
819
825
|
|
|
820
826
|
/**
|
|
@@ -828,190 +834,190 @@ export class AgentDIDResolver implements Resolvable {
|
|
|
828
834
|
* @param opts
|
|
829
835
|
*/
|
|
830
836
|
export function toDidDocument(
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
837
|
+
identifier?: IIdentifier,
|
|
838
|
+
opts?: {
|
|
839
|
+
did?: string
|
|
840
|
+
use?: JwkKeyUse[]
|
|
841
|
+
}
|
|
836
842
|
): DIDDocument | undefined {
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
}),
|
|
856
|
-
...((opts?.use === undefined || opts?.use?.includes(JwkKeyUse.Signature)) &&
|
|
857
|
-
identifier.keys && {
|
|
858
|
-
assertionMethod: identifier.keys
|
|
859
|
-
.filter(
|
|
860
|
-
(key) =>
|
|
861
|
-
key?.meta?.purpose === undefined || key?.meta?.purpose === 'assertionMethod' || key?.meta?.purposes?.includes('assertionMethod')
|
|
862
|
-
)
|
|
863
|
-
.map((key) => {
|
|
864
|
-
if (key.kid.startsWith(did) && key.kid.includes('#')) {
|
|
865
|
-
return key.kid
|
|
866
|
-
}
|
|
867
|
-
return `${did}#${key.kid}`
|
|
868
|
-
}),
|
|
869
|
-
}),
|
|
870
|
-
...((opts?.use === undefined || opts?.use?.includes(JwkKeyUse.Signature)) &&
|
|
871
|
-
identifier.keys && {
|
|
872
|
-
authentication: identifier.keys
|
|
873
|
-
.filter(
|
|
874
|
-
(key) => key?.meta?.purpose === undefined || key?.meta?.purpose === 'authentication' || key?.meta?.purposes?.includes('authentication')
|
|
875
|
-
)
|
|
876
|
-
.map((key) => {
|
|
877
|
-
if (key.kid.startsWith(did) && key.kid.includes('#')) {
|
|
878
|
-
return key.kid
|
|
879
|
-
}
|
|
880
|
-
return `${did}#${key.kid}`
|
|
843
|
+
let didDocument: DIDDocument | undefined = undefined
|
|
844
|
+
// TODO: Introduce jwk thumbprints here
|
|
845
|
+
if (identifier) {
|
|
846
|
+
const did = identifier.did ?? opts?.did
|
|
847
|
+
didDocument = {
|
|
848
|
+
'@context': 'https://www.w3.org/ns/did/v1',
|
|
849
|
+
id: did,
|
|
850
|
+
verificationMethod: identifier.keys.map((key) => {
|
|
851
|
+
const vm: VerificationMethod = {
|
|
852
|
+
controller: did,
|
|
853
|
+
id: key.kid.startsWith(did) && key.kid.includes('#') ? key.kid : `${did}#${key.kid}`,
|
|
854
|
+
publicKeyJwk: toJwk(key.publicKeyHex, key.type, {
|
|
855
|
+
use: ENC_KEY_ALGS.includes(key.type) ? JwkKeyUse.Encryption : JwkKeyUse.Signature,
|
|
856
|
+
key,
|
|
857
|
+
}) as JsonWebKey,
|
|
858
|
+
type: 'JsonWebKey2020',
|
|
859
|
+
}
|
|
860
|
+
return vm
|
|
881
861
|
}),
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
862
|
+
...((opts?.use === undefined || opts?.use?.includes(JwkKeyUse.Signature)) &&
|
|
863
|
+
identifier.keys && {
|
|
864
|
+
assertionMethod: identifier.keys
|
|
865
|
+
.filter(
|
|
866
|
+
(key) =>
|
|
867
|
+
key?.meta?.purpose === undefined || key?.meta?.purpose === 'assertionMethod' || key?.meta?.purposes?.includes('assertionMethod')
|
|
868
|
+
)
|
|
869
|
+
.map((key) => {
|
|
870
|
+
if (key.kid.startsWith(did) && key.kid.includes('#')) {
|
|
871
|
+
return key.kid
|
|
872
|
+
}
|
|
873
|
+
return `${did}#${key.kid}`
|
|
874
|
+
}),
|
|
875
|
+
}),
|
|
876
|
+
...((opts?.use === undefined || opts?.use?.includes(JwkKeyUse.Signature)) &&
|
|
877
|
+
identifier.keys && {
|
|
878
|
+
authentication: identifier.keys
|
|
879
|
+
.filter(
|
|
880
|
+
(key) => key?.meta?.purpose === undefined || key?.meta?.purpose === 'authentication' || key?.meta?.purposes?.includes('authentication')
|
|
881
|
+
)
|
|
882
|
+
.map((key) => {
|
|
883
|
+
if (key.kid.startsWith(did) && key.kid.includes('#')) {
|
|
884
|
+
return key.kid
|
|
885
|
+
}
|
|
886
|
+
return `${did}#${key.kid}`
|
|
887
|
+
}),
|
|
888
|
+
}),
|
|
889
|
+
...((opts?.use === undefined || opts?.use?.includes(JwkKeyUse.Encryption)) &&
|
|
890
|
+
identifier.keys && {
|
|
891
|
+
keyAgreement: identifier.keys
|
|
892
|
+
.filter((key) => key.type === 'X25519' || key?.meta?.purpose === 'keyAgreement' || key?.meta?.purposes?.includes('keyAgreement'))
|
|
893
|
+
.map((key) => {
|
|
894
|
+
if (key.kid.startsWith(did) && key.kid.includes('#')) {
|
|
895
|
+
return key.kid
|
|
896
|
+
}
|
|
897
|
+
return `${did}#${key.kid}`
|
|
898
|
+
}),
|
|
899
|
+
}),
|
|
900
|
+
...((opts?.use === undefined || opts?.use?.includes(JwkKeyUse.Encryption)) &&
|
|
901
|
+
identifier.keys && {
|
|
902
|
+
capabilityInvocation: identifier.keys
|
|
903
|
+
.filter(
|
|
904
|
+
(key) => key.type === 'X25519' || key?.meta?.purpose === 'capabilityInvocation' || key?.meta?.purposes?.includes('capabilityInvocation')
|
|
905
|
+
)
|
|
906
|
+
.map((key) => {
|
|
907
|
+
if (key.kid.startsWith(did) && key.kid.includes('#')) {
|
|
908
|
+
return key.kid
|
|
909
|
+
}
|
|
910
|
+
return `${did}#${key.kid}`
|
|
911
|
+
}),
|
|
912
|
+
}),
|
|
913
|
+
...((opts?.use === undefined || opts?.use?.includes(JwkKeyUse.Encryption)) &&
|
|
914
|
+
identifier.keys && {
|
|
915
|
+
capabilityDelegation: identifier.keys
|
|
916
|
+
.filter(
|
|
917
|
+
(key) => key.type === 'X25519' || key?.meta?.purpose === 'capabilityDelegation' || key?.meta?.purposes?.includes('capabilityDelegation')
|
|
918
|
+
)
|
|
919
|
+
.map((key) => {
|
|
920
|
+
if (key.kid.startsWith(did) && key.kid.includes('#')) {
|
|
921
|
+
return key.kid
|
|
922
|
+
}
|
|
923
|
+
return `${did}#${key.kid}`
|
|
924
|
+
}),
|
|
925
|
+
}),
|
|
926
|
+
...(identifier.services && identifier.services.length > 0 && {service: identifier.services}),
|
|
927
|
+
}
|
|
921
928
|
}
|
|
922
|
-
|
|
923
|
-
return didDocument
|
|
929
|
+
return didDocument
|
|
924
930
|
}
|
|
925
931
|
|
|
926
932
|
export function toDidResolutionResult(
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
933
|
+
identifier?: IIdentifier,
|
|
934
|
+
opts?: {
|
|
935
|
+
did?: string
|
|
936
|
+
supportedMethods?: string[]
|
|
937
|
+
}
|
|
932
938
|
): DIDResolutionResult {
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
939
|
+
const didDocument = toDidDocument(identifier, opts) ?? null // null is used in case of errors and required by the did resolution spec
|
|
940
|
+
|
|
941
|
+
const resolutionResult: DIDResolutionResult = {
|
|
942
|
+
'@context': 'https://w3id.org/did-resolution/v1',
|
|
943
|
+
didDocument,
|
|
944
|
+
didResolutionMetadata: {
|
|
945
|
+
...(!didDocument && {error: 'notFound'}),
|
|
946
|
+
...(Array.isArray(opts?.supportedMethods) &&
|
|
947
|
+
identifier &&
|
|
948
|
+
!opts?.supportedMethods.includes(identifier.provider.replace('did:', '')) && {error: 'unsupportedDidMethod'}),
|
|
949
|
+
},
|
|
950
|
+
didDocumentMetadata: {
|
|
951
|
+
...(identifier?.alias && {equivalentId: identifier?.alias}),
|
|
952
|
+
},
|
|
953
|
+
}
|
|
954
|
+
return resolutionResult
|
|
949
955
|
}
|
|
950
956
|
|
|
951
957
|
export async function asDidWeb(hostnameOrDID: string): Promise<string> {
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
958
|
+
let did = hostnameOrDID
|
|
959
|
+
if (!did) {
|
|
960
|
+
throw Error('Domain or DID expected, but received nothing.')
|
|
961
|
+
}
|
|
962
|
+
if (did.startsWith('did:web:')) {
|
|
963
|
+
return did
|
|
964
|
+
}
|
|
965
|
+
return `did:web:${did.replace(/https?:\/\/([^/?#]+).*/i, '$1').toLowerCase()}`
|
|
960
966
|
}
|
|
961
967
|
|
|
962
968
|
/**
|
|
963
969
|
* @deprecated Replaced by the new signer service
|
|
964
970
|
*/
|
|
965
971
|
export const signDidJWT = async (args: SignJwtArgs): Promise<string> => {
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
972
|
+
const {idOpts, header, payload, context, options} = args
|
|
973
|
+
const jwtOptions = {
|
|
974
|
+
...options,
|
|
975
|
+
signer: await getDidSigner({idOpts, context}),
|
|
976
|
+
}
|
|
971
977
|
|
|
972
|
-
|
|
978
|
+
return createJWT(payload, jwtOptions, header)
|
|
973
979
|
}
|
|
974
980
|
|
|
975
981
|
/**
|
|
976
982
|
* @deprecated Replaced by the new signer service
|
|
977
983
|
*/
|
|
978
984
|
export const getDidSigner = async (
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
|
|
985
|
+
args: GetSignerArgs & {
|
|
986
|
+
idOpts: {
|
|
987
|
+
/**
|
|
988
|
+
* @deprecated
|
|
989
|
+
*/
|
|
990
|
+
identifier: IIdentifier | string
|
|
991
|
+
/**
|
|
992
|
+
* @deprecated
|
|
993
|
+
*/
|
|
994
|
+
verificationMethodSection?: DIDDocumentSection
|
|
995
|
+
/**
|
|
996
|
+
* @deprecated
|
|
997
|
+
*/
|
|
998
|
+
kmsKeyRef?: string
|
|
999
|
+
}
|
|
1000
|
+
}
|
|
995
1001
|
): Promise<Signer> => {
|
|
996
|
-
|
|
1002
|
+
const {idOpts, context} = args
|
|
997
1003
|
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1004
|
+
const identifier = await legacyGetIdentifier(idOpts, context)
|
|
1005
|
+
const key = await getKey(
|
|
1006
|
+
{
|
|
1007
|
+
identifier,
|
|
1008
|
+
vmRelationship: idOpts.verificationMethodSection,
|
|
1009
|
+
kmsKeyRef: idOpts.kmsKeyRef,
|
|
1010
|
+
},
|
|
1011
|
+
context
|
|
1012
|
+
)
|
|
1013
|
+
const algorithm = await signatureAlgorithmFromKey({key})
|
|
1014
|
+
|
|
1015
|
+
return async (data: string | Uint8Array): Promise<string> => {
|
|
1016
|
+
const input = data instanceof Object.getPrototypeOf(Uint8Array) ? new TextDecoder().decode(data as Uint8Array) : (data as string)
|
|
1017
|
+
return await context.agent.keyManagerSign({
|
|
1018
|
+
keyRef: key.kid,
|
|
1019
|
+
algorithm,
|
|
1020
|
+
data: input,
|
|
1021
|
+
})
|
|
1022
|
+
}
|
|
1017
1023
|
}
|