@sphereon/ssi-sdk.ebsi-support 0.26.1-unstable.101
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/LICENSE +201 -0
- package/README.md +13 -0
- package/dist/agent/EbsiSupport.d.ts +12 -0
- package/dist/agent/EbsiSupport.d.ts.map +1 -0
- package/dist/agent/EbsiSupport.js +202 -0
- package/dist/agent/EbsiSupport.js.map +1 -0
- package/dist/did/EbsiDidProvider.d.ts +47 -0
- package/dist/did/EbsiDidProvider.d.ts.map +1 -0
- package/dist/did/EbsiDidProvider.js +172 -0
- package/dist/did/EbsiDidProvider.js.map +1 -0
- package/dist/did/EbsiDidResolver.d.ts +5 -0
- package/dist/did/EbsiDidResolver.d.ts.map +1 -0
- package/dist/did/EbsiDidResolver.js +10 -0
- package/dist/did/EbsiDidResolver.js.map +1 -0
- package/dist/did/functions.d.ts +66 -0
- package/dist/did/functions.d.ts.map +1 -0
- package/dist/did/functions.js +416 -0
- package/dist/did/functions.js.map +1 -0
- package/dist/did/index.d.ts +6 -0
- package/dist/did/index.d.ts.map +1 -0
- package/dist/did/index.js +6 -0
- package/dist/did/index.js.map +1 -0
- package/dist/did/services/EbsiRPCService.d.ts +13 -0
- package/dist/did/services/EbsiRPCService.d.ts.map +1 -0
- package/dist/did/services/EbsiRPCService.js +64 -0
- package/dist/did/services/EbsiRPCService.js.map +1 -0
- package/dist/did/services/EbsiRestService.d.ts +37 -0
- package/dist/did/services/EbsiRestService.d.ts.map +1 -0
- package/dist/did/services/EbsiRestService.js +90 -0
- package/dist/did/services/EbsiRestService.js.map +1 -0
- package/dist/did/types.d.ts +386 -0
- package/dist/did/types.d.ts.map +1 -0
- package/dist/did/types.js +47 -0
- package/dist/did/types.js.map +1 -0
- package/dist/functions/Attestation.d.ts +32 -0
- package/dist/functions/Attestation.d.ts.map +1 -0
- package/dist/functions/Attestation.js +182 -0
- package/dist/functions/Attestation.js.map +1 -0
- package/dist/functions/AttestationHeadlessCallbacks.d.ts +17 -0
- package/dist/functions/AttestationHeadlessCallbacks.d.ts.map +1 -0
- package/dist/functions/AttestationHeadlessCallbacks.js +194 -0
- package/dist/functions/AttestationHeadlessCallbacks.js.map +1 -0
- package/dist/functions/index.d.ts +7 -0
- package/dist/functions/index.d.ts.map +1 -0
- package/dist/functions/index.js +8 -0
- package/dist/functions/index.js.map +1 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +8 -0
- package/dist/index.js.map +1 -0
- package/dist/types/IEbsiSupport.d.ts +211 -0
- package/dist/types/IEbsiSupport.d.ts.map +1 -0
- package/dist/types/IEbsiSupport.js +5 -0
- package/dist/types/IEbsiSupport.js.map +1 -0
- package/package.json +86 -0
- package/src/agent/EbsiSupport.ts +250 -0
- package/src/did/EbsiDidProvider.ts +269 -0
- package/src/did/EbsiDidResolver.ts +16 -0
- package/src/did/functions.ts +528 -0
- package/src/did/index.ts +5 -0
- package/src/did/services/EbsiRPCService.ts +68 -0
- package/src/did/services/EbsiRestService.ts +117 -0
- package/src/did/types.ts +449 -0
- package/src/functions/Attestation.ts +262 -0
- package/src/functions/AttestationHeadlessCallbacks.ts +242 -0
- package/src/functions/index.ts +15 -0
- package/src/index.ts +8 -0
- package/src/types/IEbsiSupport.ts +241 -0
|
@@ -0,0 +1,269 @@
|
|
|
1
|
+
import { getControllerKey, getEthereumAddressFromKey } from '@sphereon/ssi-sdk-ext.did-utils'
|
|
2
|
+
import { calculateJwkThumbprint, calculateJwkThumbprintForKey, toJwk } from '@sphereon/ssi-sdk-ext.key-utils'
|
|
3
|
+
import { IAgentContext, IDIDManager, IIdentifier, IKeyManager } from '@veramo/core'
|
|
4
|
+
import { IKey, IService } from '@veramo/core'
|
|
5
|
+
import { AbstractIdentifierProvider } from '@veramo/did-manager'
|
|
6
|
+
import Debug from 'debug'
|
|
7
|
+
import { ApiOpts, IRequiredContext } from '../types/IEbsiSupport'
|
|
8
|
+
import {
|
|
9
|
+
ebsiCreateDidOnLedger,
|
|
10
|
+
ebsiGenerateOrUseKeyPair,
|
|
11
|
+
ebsiSignAndSendTransaction,
|
|
12
|
+
formatEbsiPublicKey,
|
|
13
|
+
generateEbsiMethodSpecificId,
|
|
14
|
+
randomRpcId,
|
|
15
|
+
} from './functions'
|
|
16
|
+
import { EBSI_DID_SPEC_INFOS, EbsiRpcMethod, ICreateIdentifierArgs, UpdateIdentifierParams } from './types'
|
|
17
|
+
|
|
18
|
+
const debug = Debug('sphereon:did-provider-ebsi')
|
|
19
|
+
|
|
20
|
+
export class EbsiDidProvider extends AbstractIdentifierProvider {
|
|
21
|
+
static readonly PROVIDER = 'did:ebsi'
|
|
22
|
+
private readonly defaultKms?: string
|
|
23
|
+
private readonly apiOpts?: ApiOpts
|
|
24
|
+
|
|
25
|
+
constructor(options: { defaultKms?: string; apiOpts?: ApiOpts }) {
|
|
26
|
+
super()
|
|
27
|
+
this.defaultKms = options.defaultKms
|
|
28
|
+
this.apiOpts = options.apiOpts
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
async createIdentifier(args: ICreateIdentifierArgs, context: IRequiredContext): Promise<Omit<IIdentifier, 'provider'>> {
|
|
32
|
+
const { type, options, kms = this.defaultKms, alias } = args
|
|
33
|
+
const {
|
|
34
|
+
notBefore,
|
|
35
|
+
notAfter,
|
|
36
|
+
secp256k1Key,
|
|
37
|
+
secp256r1Key,
|
|
38
|
+
accessTokenOpts,
|
|
39
|
+
executeLedgerOperation = !!args.options?.accessTokenOpts,
|
|
40
|
+
methodSpecificId = generateEbsiMethodSpecificId(EBSI_DID_SPEC_INFOS.V1),
|
|
41
|
+
baseDocument,
|
|
42
|
+
services,
|
|
43
|
+
} = { ...options }
|
|
44
|
+
|
|
45
|
+
if (executeLedgerOperation && !accessTokenOpts) {
|
|
46
|
+
throw new Error('Access token options must be provided to execute ledger operation')
|
|
47
|
+
}
|
|
48
|
+
const rpcId = options?.rpcId ?? randomRpcId()
|
|
49
|
+
|
|
50
|
+
if (type === EBSI_DID_SPEC_INFOS.KEY) {
|
|
51
|
+
throw new Error(`Type ${type} not supported. Please use @sphereon/ssi-sdk-ext.did-provider-key for Natural Person EBSI DIDs`)
|
|
52
|
+
} else if (!kms) {
|
|
53
|
+
return Promise.reject(Error(`No KMS value provided`))
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
// CapabilityInvocation purpose
|
|
57
|
+
const secp256k1ImportKey = await ebsiGenerateOrUseKeyPair(
|
|
58
|
+
{
|
|
59
|
+
keyOpts: secp256k1Key,
|
|
60
|
+
keyType: 'Secp256k1',
|
|
61
|
+
kms,
|
|
62
|
+
controllerKey: true,
|
|
63
|
+
},
|
|
64
|
+
context,
|
|
65
|
+
)
|
|
66
|
+
const secp256k1ManagedKeyInfo = await context.agent.keyManagerImport(secp256k1ImportKey)
|
|
67
|
+
|
|
68
|
+
// Authentication, assertionMethod purpose
|
|
69
|
+
const secp256r1ImportKey = await ebsiGenerateOrUseKeyPair(
|
|
70
|
+
{
|
|
71
|
+
keyOpts: secp256r1Key,
|
|
72
|
+
keyType: 'Secp256r1',
|
|
73
|
+
kms,
|
|
74
|
+
},
|
|
75
|
+
context,
|
|
76
|
+
)
|
|
77
|
+
|
|
78
|
+
const secp256r1ManagedKeyInfo = await context.agent.keyManagerImport(secp256r1ImportKey)
|
|
79
|
+
|
|
80
|
+
const identifier: IIdentifier = {
|
|
81
|
+
did: `${EBSI_DID_SPEC_INFOS.V1.method}${methodSpecificId}`,
|
|
82
|
+
controllerKeyId: secp256k1ManagedKeyInfo.kid,
|
|
83
|
+
keys: [secp256k1ManagedKeyInfo, secp256r1ManagedKeyInfo],
|
|
84
|
+
alias,
|
|
85
|
+
services: services ?? [],
|
|
86
|
+
provider: EbsiDidProvider.PROVIDER,
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
const apiOpts = { ...this.apiOpts }
|
|
90
|
+
if (!apiOpts.environment) {
|
|
91
|
+
apiOpts.environment = accessTokenOpts?.environment ?? 'pilot'
|
|
92
|
+
}
|
|
93
|
+
if (!apiOpts.version) {
|
|
94
|
+
apiOpts.version = 'v5'
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
if (executeLedgerOperation) {
|
|
98
|
+
await ebsiCreateDidOnLedger(
|
|
99
|
+
{
|
|
100
|
+
identifier,
|
|
101
|
+
baseDocument,
|
|
102
|
+
accessTokenOpts: accessTokenOpts!,
|
|
103
|
+
rpcId,
|
|
104
|
+
notBefore,
|
|
105
|
+
notAfter,
|
|
106
|
+
},
|
|
107
|
+
context,
|
|
108
|
+
)
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
debug('Created', identifier.did)
|
|
112
|
+
return identifier
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
async addKey(
|
|
116
|
+
args: {
|
|
117
|
+
identifier: IIdentifier
|
|
118
|
+
key: IKey
|
|
119
|
+
options: {
|
|
120
|
+
rpcId?: number
|
|
121
|
+
accessToken: string
|
|
122
|
+
vmRelationships: 'authentication' | 'assertionMethod' | 'keyAgreement' | 'capabilityInvocation' | 'capabilityDelegation'[]
|
|
123
|
+
apiOpts?: ApiOpts
|
|
124
|
+
}
|
|
125
|
+
},
|
|
126
|
+
context: IAgentContext<IKeyManager>,
|
|
127
|
+
): Promise<any> {
|
|
128
|
+
const { identifier, key, options } = args
|
|
129
|
+
const { accessToken, vmRelationships, apiOpts, rpcId = randomRpcId() } = options
|
|
130
|
+
if (vmRelationships.length === 0) {
|
|
131
|
+
return Promise.reject(Error(`No verification method relationship provided`))
|
|
132
|
+
}
|
|
133
|
+
const controllerKey = getControllerKey({ identifier })
|
|
134
|
+
const from = getEthereumAddressFromKey({ key: controllerKey })
|
|
135
|
+
const kid = controllerKey.kid
|
|
136
|
+
const did = identifier.did
|
|
137
|
+
|
|
138
|
+
const addVerificationMethodRequest = {
|
|
139
|
+
params: [
|
|
140
|
+
{
|
|
141
|
+
from,
|
|
142
|
+
did,
|
|
143
|
+
isSecp256k1: true,
|
|
144
|
+
vMethodId: calculateJwkThumbprint({ jwk: toJwk(key.publicKeyHex, key.type) }),
|
|
145
|
+
publicKey: formatEbsiPublicKey({ key: key, type: key.type }),
|
|
146
|
+
},
|
|
147
|
+
],
|
|
148
|
+
rpcMethod: EbsiRpcMethod.ADD_VERIFICATION_METHOD,
|
|
149
|
+
rpcId,
|
|
150
|
+
apiOpts,
|
|
151
|
+
accessToken,
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
let rpcResponse = await ebsiSignAndSendTransaction(
|
|
155
|
+
{
|
|
156
|
+
rpcRequest: addVerificationMethodRequest,
|
|
157
|
+
kid,
|
|
158
|
+
accessToken: accessToken,
|
|
159
|
+
apiOpts,
|
|
160
|
+
},
|
|
161
|
+
context,
|
|
162
|
+
)
|
|
163
|
+
|
|
164
|
+
const vMethodId = calculateJwkThumbprintForKey({ key })
|
|
165
|
+
for (const vmRelationshipsKey in vmRelationships as string[]) {
|
|
166
|
+
const addVerificationMethodRelationshipRequest = {
|
|
167
|
+
params: [
|
|
168
|
+
{
|
|
169
|
+
from,
|
|
170
|
+
did,
|
|
171
|
+
vMethodId,
|
|
172
|
+
name: vmRelationshipsKey,
|
|
173
|
+
notAfter: Date.now() / 1000 - 60_000,
|
|
174
|
+
notBefore: Date.now() / 1000 + 5 * 365 * 24 * 60 * 60,
|
|
175
|
+
},
|
|
176
|
+
],
|
|
177
|
+
rpcMethod: EbsiRpcMethod.ADD_VERIFICATION_RELATIONSHIP,
|
|
178
|
+
rpcId,
|
|
179
|
+
apiOpts,
|
|
180
|
+
accessToken,
|
|
181
|
+
}
|
|
182
|
+
rpcResponse = await ebsiSignAndSendTransaction(
|
|
183
|
+
{
|
|
184
|
+
rpcRequest: addVerificationMethodRelationshipRequest,
|
|
185
|
+
previousTxResponse: rpcResponse,
|
|
186
|
+
kid,
|
|
187
|
+
accessToken,
|
|
188
|
+
apiOpts,
|
|
189
|
+
},
|
|
190
|
+
context,
|
|
191
|
+
)
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
async addService(
|
|
196
|
+
args: {
|
|
197
|
+
identifier: IIdentifier
|
|
198
|
+
service: IService
|
|
199
|
+
options: {
|
|
200
|
+
rpcId?: number
|
|
201
|
+
accessToken: string
|
|
202
|
+
apiOpts?: ApiOpts
|
|
203
|
+
}
|
|
204
|
+
},
|
|
205
|
+
context: IAgentContext<IKeyManager>,
|
|
206
|
+
): Promise<any> {
|
|
207
|
+
const { identifier, service, options } = args
|
|
208
|
+
const { accessToken, apiOpts, rpcId = randomRpcId() } = options
|
|
209
|
+
const controllerKey = getControllerKey({ identifier })
|
|
210
|
+
const from = getEthereumAddressFromKey({ key: controllerKey })
|
|
211
|
+
const did = identifier.did
|
|
212
|
+
const kid = controllerKey.kid
|
|
213
|
+
|
|
214
|
+
const addServiceRequest = {
|
|
215
|
+
params: [
|
|
216
|
+
{
|
|
217
|
+
from,
|
|
218
|
+
did,
|
|
219
|
+
service,
|
|
220
|
+
},
|
|
221
|
+
],
|
|
222
|
+
rpcMethod: EbsiRpcMethod.ADD_SERVICE,
|
|
223
|
+
rpcId,
|
|
224
|
+
apiOpts,
|
|
225
|
+
accessToken,
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
return await ebsiSignAndSendTransaction(
|
|
229
|
+
{
|
|
230
|
+
rpcRequest: addServiceRequest,
|
|
231
|
+
kid,
|
|
232
|
+
accessToken,
|
|
233
|
+
apiOpts,
|
|
234
|
+
},
|
|
235
|
+
context,
|
|
236
|
+
)
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
deleteIdentifier(args: IIdentifier, context: IAgentContext<IKeyManager>): Promise<boolean> {
|
|
240
|
+
return Promise.resolve(true)
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
removeKey(
|
|
244
|
+
args: {
|
|
245
|
+
identifier: IIdentifier
|
|
246
|
+
kid: string
|
|
247
|
+
options?: any
|
|
248
|
+
},
|
|
249
|
+
context: IAgentContext<IKeyManager>,
|
|
250
|
+
): Promise<any> {
|
|
251
|
+
throw new Error(`Not (yet) implemented for the EBSI did provider`)
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
removeService(
|
|
255
|
+
args: {
|
|
256
|
+
identifier: IIdentifier
|
|
257
|
+
id: string
|
|
258
|
+
options?: any
|
|
259
|
+
},
|
|
260
|
+
context: IAgentContext<IKeyManager>,
|
|
261
|
+
): Promise<any> {
|
|
262
|
+
throw new Error(`Not (yet) implemented for the EBSI did provider`)
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
// TODO How does it work? Not inferable from the api: https://hub.ebsi.eu/apis/pilot/did-registry/v5/post-jsonrpc#updatebasedocument
|
|
266
|
+
async updateIdentifier(args: UpdateIdentifierParams, context: IAgentContext<IKeyManager & IDIDManager>): Promise<IIdentifier> {
|
|
267
|
+
throw new Error(`Not (yet) implemented for the EBSI did provider`)
|
|
268
|
+
}
|
|
269
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { DIDResolutionOptions, DIDResolutionResult, DIDResolver, ParsedDID, Resolvable, Resolver } from 'did-resolver'
|
|
2
|
+
import { getResolver } from '@sphereon/ssi-sdk-ext.did-resolver-ebsi'
|
|
3
|
+
|
|
4
|
+
const resolveDidEbsi: DIDResolver = async (
|
|
5
|
+
didUrl: string,
|
|
6
|
+
_parsed: ParsedDID,
|
|
7
|
+
_resolver: Resolvable,
|
|
8
|
+
options: DIDResolutionOptions,
|
|
9
|
+
): Promise<DIDResolutionResult> => {
|
|
10
|
+
const resolver = new Resolver({ ...getResolver() })
|
|
11
|
+
return resolver.resolve(didUrl, options)
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export function getDidEbsiResolver() {
|
|
15
|
+
return { key: resolveDidEbsi }
|
|
16
|
+
}
|