@veramo/credential-ld 3.1.1-next.8

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.
Files changed (55) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +6 -0
  3. package/build/action-handler.d.ts +28 -0
  4. package/build/action-handler.d.ts.map +1 -0
  5. package/build/action-handler.js +155 -0
  6. package/build/action-handler.js.map +1 -0
  7. package/build/index.d.ts +15 -0
  8. package/build/index.d.ts.map +1 -0
  9. package/build/index.js +31 -0
  10. package/build/index.js.map +1 -0
  11. package/build/ld-context-loader.d.ts +16 -0
  12. package/build/ld-context-loader.d.ts.map +1 -0
  13. package/build/ld-context-loader.js +33 -0
  14. package/build/ld-context-loader.js.map +1 -0
  15. package/build/ld-credential-module.d.ts +25 -0
  16. package/build/ld-credential-module.d.ts.map +1 -0
  17. package/build/ld-credential-module.js +148 -0
  18. package/build/ld-credential-module.js.map +1 -0
  19. package/build/ld-default-contexts.d.ts +2 -0
  20. package/build/ld-default-contexts.d.ts.map +1 -0
  21. package/build/ld-default-contexts.js +42 -0
  22. package/build/ld-default-contexts.js.map +1 -0
  23. package/build/ld-suite-loader.d.ts +15 -0
  24. package/build/ld-suite-loader.d.ts.map +1 -0
  25. package/build/ld-suite-loader.js +28 -0
  26. package/build/ld-suite-loader.js.map +1 -0
  27. package/build/ld-suites.d.ts +13 -0
  28. package/build/ld-suites.d.ts.map +1 -0
  29. package/build/ld-suites.js +15 -0
  30. package/build/ld-suites.js.map +1 -0
  31. package/build/suites/EcdsaSecp256k1RecoverySignature2020.d.ts +11 -0
  32. package/build/suites/EcdsaSecp256k1RecoverySignature2020.d.ts.map +1 -0
  33. package/build/suites/EcdsaSecp256k1RecoverySignature2020.js +100 -0
  34. package/build/suites/EcdsaSecp256k1RecoverySignature2020.js.map +1 -0
  35. package/build/suites/Ed25519Signature2018.d.ts +11 -0
  36. package/build/suites/Ed25519Signature2018.d.ts.map +1 -0
  37. package/build/suites/Ed25519Signature2018.js +92 -0
  38. package/build/suites/Ed25519Signature2018.js.map +1 -0
  39. package/build/tsdoc-metadata.json +11 -0
  40. package/build/types.d.ts +174 -0
  41. package/build/types.d.ts.map +1 -0
  42. package/build/types.js +3 -0
  43. package/build/types.js.map +1 -0
  44. package/package.json +50 -0
  45. package/plugin.schema.json +398 -0
  46. package/src/action-handler.ts +229 -0
  47. package/src/index.ts +14 -0
  48. package/src/ld-context-loader.ts +29 -0
  49. package/src/ld-credential-module.ts +170 -0
  50. package/src/ld-default-contexts.ts +21 -0
  51. package/src/ld-suite-loader.ts +29 -0
  52. package/src/ld-suites.ts +45 -0
  53. package/src/suites/EcdsaSecp256k1RecoverySignature2020.ts +83 -0
  54. package/src/suites/Ed25519Signature2018.ts +75 -0
  55. package/src/types.ts +208 -0
@@ -0,0 +1,229 @@
1
+ import {
2
+ CredentialPayload,
3
+ IAgentContext,
4
+ IAgentPlugin,
5
+ IIdentifier,
6
+ IKey,
7
+ IResolver,
8
+ PresentationPayload,
9
+ VerifiableCredential,
10
+ VerifiablePresentation,
11
+ } from '@veramo/core'
12
+ import { schema, VeramoLdSignature } from './'
13
+ import Debug from 'debug'
14
+ import { LdContextLoader } from './ld-context-loader'
15
+ import {
16
+ _ExtendedIKey,
17
+ extractIssuer,
18
+ isDefined,
19
+ MANDATORY_CREDENTIAL_CONTEXT,
20
+ mapIdentifierKeysToDoc,
21
+ OrPromise,
22
+ processEntryToArray,
23
+ RecordLike,
24
+ } from '@veramo/utils'
25
+
26
+ import { LdCredentialModule } from './ld-credential-module'
27
+ import { LdSuiteLoader } from './ld-suite-loader'
28
+ import {
29
+ ContextDoc,
30
+ ICreateVerifiableCredentialLDArgs,
31
+ ICreateVerifiablePresentationLDArgs,
32
+ ICredentialIssuerLD,
33
+ IRequiredContext,
34
+ IVerifyCredentialLDArgs,
35
+ IVerifyPresentationLDArgs,
36
+ } from './types'
37
+
38
+ const debug = Debug('veramo:w3c:action-handler')
39
+
40
+ /**
41
+ * A Veramo plugin that implements the {@link ICredentialIssuerLD} methods.
42
+ *
43
+ * @public
44
+ */
45
+ export class CredentialIssuerLD implements IAgentPlugin {
46
+ readonly methods: ICredentialIssuerLD
47
+ readonly schema = schema.ICredentialIssuer
48
+
49
+ private ldCredentialModule: LdCredentialModule
50
+
51
+ constructor(options: { contextMaps: RecordLike<OrPromise<ContextDoc>>[]; suites: VeramoLdSignature[] }) {
52
+ this.ldCredentialModule = new LdCredentialModule({
53
+ ldContextLoader: new LdContextLoader({ contextsPaths: options.contextMaps }),
54
+ ldSuiteLoader: new LdSuiteLoader({ veramoLdSignatures: options.suites }),
55
+ })
56
+
57
+ this.methods = {
58
+ createVerifiablePresentationLD: this.createVerifiablePresentationLD.bind(this),
59
+ createVerifiableCredentialLD: this.createVerifiableCredentialLD.bind(this),
60
+ verifyCredentialLD: this.verifyCredentialLD.bind(this),
61
+ verifyPresentationLD: this.verifyPresentationLD.bind(this),
62
+ }
63
+ }
64
+
65
+ /** {@inheritdoc ICredentialIssuerLD.createVerifiablePresentationLD} */
66
+ public async createVerifiablePresentationLD(
67
+ args: ICreateVerifiablePresentationLDArgs,
68
+ context: IRequiredContext,
69
+ ): Promise<VerifiablePresentation> {
70
+ const presentationContext = processEntryToArray(
71
+ args?.presentation?.['@context'],
72
+ MANDATORY_CREDENTIAL_CONTEXT,
73
+ )
74
+ const presentationType = processEntryToArray(args?.presentation?.type, 'VerifiablePresentation')
75
+
76
+ const presentation: PresentationPayload = {
77
+ ...args?.presentation,
78
+ '@context': presentationContext,
79
+ type: presentationType,
80
+ }
81
+
82
+ if (!isDefined(presentation.holder)) {
83
+ throw new Error('invalid_argument: args.presentation.holder must not be empty')
84
+ }
85
+
86
+ if (args.presentation.verifiableCredential) {
87
+ const credentials = args.presentation.verifiableCredential.map((cred) => {
88
+ if (typeof cred !== 'string' && cred.proof.jwt) {
89
+ return cred.proof.jwt
90
+ } else {
91
+ return cred
92
+ }
93
+ })
94
+ presentation.verifiableCredential = credentials
95
+ }
96
+
97
+ //issuanceDate must not be present for presentations because it is not defined in a @context
98
+ delete presentation.issuanceDate
99
+
100
+ let identifier: IIdentifier
101
+ try {
102
+ identifier = await context.agent.didManagerGet({ did: presentation.holder })
103
+ } catch (e) {
104
+ throw new Error('invalid_argument: args.presentation.holder must be a DID managed by this agent')
105
+ }
106
+ try {
107
+ const { signingKey, verificationMethodId } = await this.findSigningKeyWithId(
108
+ context,
109
+ identifier,
110
+ args.keyRef,
111
+ )
112
+
113
+ return await this.ldCredentialModule.signLDVerifiablePresentation(
114
+ presentation,
115
+ identifier.did,
116
+ signingKey,
117
+ verificationMethodId,
118
+ args.challenge,
119
+ args.domain,
120
+ context,
121
+ )
122
+ } catch (error) {
123
+ debug(error)
124
+ return Promise.reject(error)
125
+ }
126
+ }
127
+
128
+ /** {@inheritdoc ICredentialIssuerLD.createVerifiableCredentialLD} */
129
+ public async createVerifiableCredentialLD(
130
+ args: ICreateVerifiableCredentialLDArgs,
131
+ context: IRequiredContext,
132
+ ): Promise<VerifiableCredential> {
133
+ const credentialContext = processEntryToArray(
134
+ args?.credential?.['@context'],
135
+ MANDATORY_CREDENTIAL_CONTEXT,
136
+ )
137
+ const credentialType = processEntryToArray(args?.credential?.type, 'VerifiableCredential')
138
+ let issuanceDate = args?.credential?.issuanceDate || new Date().toISOString()
139
+ if (issuanceDate instanceof Date) {
140
+ issuanceDate = issuanceDate.toISOString()
141
+ }
142
+ const credential: CredentialPayload = {
143
+ ...args?.credential,
144
+ '@context': credentialContext,
145
+ type: credentialType,
146
+ issuanceDate,
147
+ }
148
+
149
+ const issuer = extractIssuer(credential)
150
+ if (!issuer || typeof issuer === 'undefined') {
151
+ throw new Error('invalid_argument: args.credential.issuer must not be empty')
152
+ }
153
+
154
+ let identifier: IIdentifier
155
+ try {
156
+ identifier = await context.agent.didManagerGet({ did: issuer })
157
+ } catch (e) {
158
+ throw new Error(`invalid_argument: args.credential.issuer must be a DID managed by this agent. ${e}`)
159
+ }
160
+ try {
161
+ const { signingKey, verificationMethodId } = await this.findSigningKeyWithId(
162
+ context,
163
+ identifier,
164
+ args.keyRef,
165
+ )
166
+
167
+ return await this.ldCredentialModule.issueLDVerifiableCredential(
168
+ credential,
169
+ identifier.did,
170
+ signingKey,
171
+ verificationMethodId,
172
+ context,
173
+ )
174
+ } catch (error) {
175
+ debug(error)
176
+ return Promise.reject(error)
177
+ }
178
+ }
179
+
180
+ /** {@inheritdoc ICredentialIssuerLD.verifyCredentialLD} */
181
+ public async verifyCredentialLD(
182
+ args: IVerifyCredentialLDArgs,
183
+ context: IRequiredContext,
184
+ ): Promise<boolean> {
185
+ const credential = args.credential
186
+ return this.ldCredentialModule.verifyCredential(credential, context)
187
+ }
188
+
189
+ /** {@inheritdoc ICredentialIssuerLD.verifyPresentationLD} */
190
+ public async verifyPresentationLD(
191
+ args: IVerifyPresentationLDArgs,
192
+ context: IRequiredContext,
193
+ ): Promise<boolean> {
194
+ const presentation = args.presentation
195
+ return this.ldCredentialModule.verifyPresentation(presentation, args.challenge, args.domain, context)
196
+ }
197
+
198
+ private async findSigningKeyWithId(
199
+ context: IAgentContext<IResolver>,
200
+ identifier: IIdentifier,
201
+ keyRef?: string,
202
+ ): Promise<{ signingKey: IKey; verificationMethodId: string }> {
203
+ const extendedKeys: _ExtendedIKey[] = await mapIdentifierKeysToDoc(identifier, 'assertionMethod', context)
204
+ let supportedTypes = this.ldCredentialModule.ldSuiteLoader.getAllSignatureSuiteTypes()
205
+ let signingKey: _ExtendedIKey | undefined
206
+ let verificationMethodId: string
207
+ if (keyRef) {
208
+ signingKey = extendedKeys.find((k) => k.kid === keyRef)
209
+ }
210
+ if (signingKey && !supportedTypes.includes(signingKey.meta.verificationMethod.type)) {
211
+ debug(
212
+ 'WARNING: requested signing key DOES NOT correspond to a supported Signature suite type. Looking for the next best key.',
213
+ )
214
+ signingKey = undefined
215
+ }
216
+ if (!signingKey) {
217
+ if (keyRef) {
218
+ debug(
219
+ 'WARNING: no signing key was found that matches the reference provided. Searching for the first available signing key.',
220
+ )
221
+ }
222
+ signingKey = extendedKeys.find((k) => supportedTypes.includes(k.meta.verificationMethod.type))
223
+ }
224
+
225
+ if (!signingKey) throw Error(`key_not_found: No suitable signing key found for ${identifier.did}`)
226
+ verificationMethodId = signingKey.meta.verificationMethod.id
227
+ return { signingKey, verificationMethodId }
228
+ }
229
+ }
package/src/index.ts ADDED
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Provides a {@link @veramo/credential-ld#CredentialIssuerLD | plugin} for the {@link @veramo/core#Agent} that implements
3
+ * {@link @veramo/credential-ld#ICredentialIssuerLD} interface.
4
+ *
5
+ * @packageDocumentation
6
+ */
7
+ export { CredentialIssuerLD } from './action-handler'
8
+ export * from './types'
9
+ export { LdDefaultContexts } from './ld-default-contexts'
10
+ export { VeramoLdSignature } from './ld-suites'
11
+ export * from './suites/EcdsaSecp256k1RecoverySignature2020'
12
+ export * from './suites/Ed25519Signature2018'
13
+ const schema = require('../plugin.schema.json')
14
+ export { schema }
@@ -0,0 +1,29 @@
1
+ /**
2
+ * The LdContextLoader is initialized with a List of Map<string, ContextDoc>
3
+ * that it unifies into a single Map to provide to the documentLoader within
4
+ * the w3c credential module.
5
+ */
6
+ import { OrPromise, RecordLike } from '@veramo/utils'
7
+ import { ContextDoc } from './types'
8
+
9
+ export class LdContextLoader {
10
+ private contexts: Record<string, OrPromise<ContextDoc>>
11
+
12
+ constructor(options: { contextsPaths: RecordLike<OrPromise<ContextDoc>>[] }) {
13
+ this.contexts = {}
14
+ // generate-plugin-schema is failing unless we use the cast to `any[]`
15
+ Array.from(options.contextsPaths as any[], (mapItem) => {
16
+ for (const [key, value] of mapItem) {
17
+ this.contexts[key] = value
18
+ }
19
+ })
20
+ }
21
+
22
+ has(url: string): boolean {
23
+ return this.contexts[url] !== null && typeof this.contexts[url] !== 'undefined'
24
+ }
25
+
26
+ async get(url: string): Promise<ContextDoc> {
27
+ return this.contexts[url]
28
+ }
29
+ }
@@ -0,0 +1,170 @@
1
+ import {
2
+ CredentialPayload,
3
+ IAgentContext,
4
+ IKey,
5
+ IResolver,
6
+ PresentationPayload,
7
+ VerifiableCredential,
8
+ VerifiablePresentation,
9
+ } from '@veramo/core'
10
+ import Debug from 'debug'
11
+ import { extendContextLoader, purposes } from 'jsonld-signatures'
12
+ import * as vc from 'vc-js'
13
+ import { LdContextLoader } from './ld-context-loader'
14
+ import { LdSuiteLoader } from './ld-suite-loader'
15
+ import { RequiredAgentMethods } from './ld-suites'
16
+
17
+ const AssertionProofPurpose = purposes.AssertionProofPurpose
18
+
19
+ const debug = Debug('veramo:w3c:ld-credential-module')
20
+
21
+ export class LdCredentialModule {
22
+ /**
23
+ * TODO: General Implementation Notes
24
+ * - (SOLVED) EcdsaSecp256k1Signature2019 (Signature) and EcdsaSecp256k1VerificationKey2019 (Key)
25
+ * are not useable right now, since they are not able to work with blockChainId and ECRecover.
26
+ * - DID Fragment Resolution.
27
+ * - Key Manager and Verification Methods: Veramo currently implements no link between those.
28
+ */
29
+
30
+ private ldContextLoader: LdContextLoader
31
+ ldSuiteLoader: LdSuiteLoader
32
+ constructor(options: { ldContextLoader: LdContextLoader; ldSuiteLoader: LdSuiteLoader }) {
33
+ this.ldContextLoader = options.ldContextLoader
34
+ this.ldSuiteLoader = options.ldSuiteLoader
35
+ }
36
+
37
+ getDocumentLoader(context: IAgentContext<IResolver>) {
38
+ return extendContextLoader(async (url: string) => {
39
+ // console.log(`resolving context for: ${url}`)
40
+
41
+ // did resolution
42
+ if (url.toLowerCase().startsWith('did:')) {
43
+ const resolutionResult = await context.agent.resolveDid({ didUrl: url })
44
+ const didDoc = resolutionResult.didDocument
45
+
46
+ if (!didDoc) return
47
+
48
+ // currently Veramo LD suites can modify the resolution response for DIDs from
49
+ // the document Loader. This allows to fix incompatibilities between DID Documents
50
+ // and LD suites to be fixed specifically within the Veramo LD Suites definition
51
+ this.ldSuiteLoader.getAllSignatureSuites().forEach((x) => x.preDidResolutionModification(url, didDoc))
52
+
53
+ // console.log(`Returning from Documentloader: ${JSON.stringify(returnDocument)}`)
54
+ return {
55
+ contextUrl: null,
56
+ documentUrl: url,
57
+ document: didDoc,
58
+ }
59
+ }
60
+
61
+ if (this.ldContextLoader.has(url)) {
62
+ const contextDoc = await this.ldContextLoader.get(url)
63
+ return {
64
+ contextUrl: null,
65
+ documentUrl: url,
66
+ document: contextDoc,
67
+ }
68
+ }
69
+
70
+ debug('WARNING: Possible unknown context/identifier for', url)
71
+ console.log(`WARNING: Possible unknown context/identifier for: ${url}`)
72
+
73
+ return vc.defaultDocumentLoader(url)
74
+ })
75
+ }
76
+
77
+ async issueLDVerifiableCredential(
78
+ credential: CredentialPayload,
79
+ issuerDid: string,
80
+ key: IKey,
81
+ verificationMethodId: string,
82
+ context: IAgentContext<RequiredAgentMethods>,
83
+ ): Promise<VerifiableCredential> {
84
+ const suite = this.ldSuiteLoader.getSignatureSuiteForKeyType(key.type)
85
+ const documentLoader = this.getDocumentLoader(context)
86
+
87
+ // some suites can modify the incoming credential (e.g. add required contexts)W
88
+ suite.preSigningCredModification(credential)
89
+
90
+ return await vc.issue({
91
+ credential,
92
+ suite: suite.getSuiteForSigning(key, issuerDid, verificationMethodId, context),
93
+ documentLoader,
94
+ compactProof: false,
95
+ })
96
+ }
97
+
98
+ async signLDVerifiablePresentation(
99
+ presentation: PresentationPayload,
100
+ holderDid: string,
101
+ key: IKey,
102
+ verificationMethodId: string,
103
+ challenge: string | undefined,
104
+ domain: string | undefined,
105
+ context: IAgentContext<RequiredAgentMethods>,
106
+ ): Promise<VerifiablePresentation> {
107
+ const suite = this.ldSuiteLoader.getSignatureSuiteForKeyType(key.type)
108
+ const documentLoader = this.getDocumentLoader(context)
109
+
110
+ suite.preSigningPresModification(presentation)
111
+
112
+ return await vc.signPresentation({
113
+ presentation,
114
+ suite: suite.getSuiteForSigning(key, holderDid, verificationMethodId, context),
115
+ challenge,
116
+ domain,
117
+ documentLoader,
118
+ purpose: new AssertionProofPurpose(),
119
+ compactProof: false,
120
+ })
121
+ }
122
+
123
+ async verifyCredential(
124
+ credential: VerifiableCredential,
125
+ context: IAgentContext<IResolver>,
126
+ ): Promise<boolean> {
127
+ const result = await vc.verifyCredential({
128
+ credential,
129
+ suite: this.ldSuiteLoader.getAllSignatureSuites().map((x) => x.getSuiteForVerification()),
130
+ documentLoader: this.getDocumentLoader(context),
131
+ purpose: new AssertionProofPurpose(),
132
+ compactProof: false,
133
+ })
134
+
135
+ if (result.verified) return true
136
+
137
+ // NOT verified.
138
+
139
+ // result can include raw Error
140
+ debug(`Error verifying LD Verifiable Credential: ${JSON.stringify(result, null, 2)}`)
141
+ // console.log(JSON.stringify(result, null, 2));
142
+ throw Error('Error verifying LD Verifiable Credential')
143
+ }
144
+
145
+ async verifyPresentation(
146
+ presentation: VerifiablePresentation,
147
+ challenge: string | undefined,
148
+ domain: string | undefined,
149
+ context: IAgentContext<IResolver>,
150
+ ): Promise<boolean> {
151
+ const result = await vc.verify({
152
+ presentation,
153
+ suite: this.ldSuiteLoader.getAllSignatureSuites().map((x) => x.getSuiteForVerification()),
154
+ documentLoader: this.getDocumentLoader(context),
155
+ challenge,
156
+ domain,
157
+ purpose: new AssertionProofPurpose(),
158
+ compactProof: false,
159
+ })
160
+
161
+ if (result.verified) return true
162
+
163
+ // NOT verified.
164
+
165
+ // result can include raw Error
166
+ console.log(`Error verifying LD Verifiable Presentation`)
167
+ console.log(JSON.stringify(result, null, 2))
168
+ throw Error('Error verifying LD Verifiable Presentation')
169
+ }
170
+ }
@@ -0,0 +1,21 @@
1
+ import * as fs from 'fs'
2
+ import * as path from 'path'
3
+
4
+ function _read(_path: string) {
5
+ return JSON.parse(fs.readFileSync(path.join(__dirname, '../contexts', _path), { encoding: 'utf8' }))
6
+ }
7
+
8
+ export const LdDefaultContexts = new Map([
9
+ ['https://veramo.io/contexts/socialmedia/v1', _read('socialmedia-v1.jsonld')],
10
+ ['https://veramo.io/contexts/kyc/v1', _read('kyc-v1.jsonld')],
11
+ ['https://veramo.io/contexts/profile/v1', _read('profile-v1.jsonld')],
12
+ ['https://www.w3.org/ns/did/v1', _read('security_context_v1.jsonld')],
13
+ ['https://w3id.org/did/v0.11', _read('did_v0.11.jsonld')],
14
+ ['https://ns.did.ai/transmute/v1', _read('transmute_v1.jsonld')],
15
+ [
16
+ 'https://identity.foundation/EcdsaSecp256k1RecoverySignature2020/lds-ecdsa-secp256k1-recovery2020-0.0.jsonld',
17
+ _read('lds-ecdsa-secp256k1-recovery2020-0.0.jsonld'),
18
+ ],
19
+ ['https://w3id.org/security/suites/ed25519-2018/v1', _read('ed25519-signature-2018-v1.jsonld')],
20
+ ['https://w3id.org/security/suites/x25519-2019/v1', _read('X25519KeyAgreementKey2019.jsonld')],
21
+ ])
@@ -0,0 +1,29 @@
1
+ import { VeramoLdSignature } from './ld-suites'
2
+ import { TKeyType } from '@veramo/core'
3
+
4
+ /**
5
+ * Initializes a list of Veramo-wrapped LD Signature suites and exposes those to the Agent Module
6
+ */
7
+ export class LdSuiteLoader {
8
+ constructor(options: { veramoLdSignatures: VeramoLdSignature[] }) {
9
+ options.veramoLdSignatures.forEach((obj) => {
10
+ this.signatureMap[obj.getSupportedVeramoKeyType()] = obj
11
+ })
12
+ }
13
+ private signatureMap: Record<string, VeramoLdSignature> = {}
14
+
15
+ getSignatureSuiteForKeyType(type: TKeyType) {
16
+ const suite = this.signatureMap[type]
17
+ if (suite) return suite
18
+
19
+ throw new Error('No Veramo LD Signature Suite for ' + type)
20
+ }
21
+
22
+ getAllSignatureSuites() {
23
+ return Object.values(this.signatureMap)
24
+ }
25
+
26
+ getAllSignatureSuiteTypes() {
27
+ return Object.values(this.signatureMap).map((x) => x.getSupportedVerificationType())
28
+ }
29
+ }
@@ -0,0 +1,45 @@
1
+ import {
2
+ CredentialPayload,
3
+ IAgentContext,
4
+ IKey,
5
+ IKeyManager,
6
+ IResolver,
7
+ PresentationPayload,
8
+ TKeyType,
9
+ } from '@veramo/core'
10
+ import { DIDDocument } from 'did-resolver/src/resolver'
11
+
12
+ export type RequiredAgentMethods = IResolver & Pick<IKeyManager, 'keyManagerGet' | 'keyManagerSign'>
13
+
14
+ export abstract class VeramoLdSignature {
15
+ // LinkedDataSignature Suites according to
16
+ // https://github.com/digitalbazaar/jsonld-signatures/blob/main/lib/suites/LinkedDataSignature.js
17
+ // Add type definition as soon as https://github.com/digitalbazaar/jsonld-signatures
18
+ // supports those.
19
+
20
+ abstract getSupportedVerificationType(): string
21
+
22
+ abstract getSupportedVeramoKeyType(): TKeyType
23
+
24
+ abstract getSuiteForSigning(
25
+ key: IKey,
26
+ issuerDid: string,
27
+ verificationMethodId: string,
28
+ context: IAgentContext<RequiredAgentMethods>,
29
+ ): any
30
+
31
+ abstract getSuiteForVerification(): any
32
+
33
+ abstract preDidResolutionModification(didUrl: string, didDoc: DIDDocument): void
34
+
35
+ abstract preSigningCredModification(credential: CredentialPayload): void
36
+
37
+ preSigningPresModification(presentation: PresentationPayload): void {
38
+ // TODO: Remove invalid field 'verifiers' from Presentation. Needs to be adapted for LD credentials
39
+ // Only remove empty array (vc.signPresentation will throw then)
40
+ const sanitizedPresentation = presentation as any
41
+ if (sanitizedPresentation.verifier.length == 0) {
42
+ delete sanitizedPresentation.verifier
43
+ }
44
+ }
45
+ }
@@ -0,0 +1,83 @@
1
+ import { RequiredAgentMethods, VeramoLdSignature } from '../ld-suites'
2
+ import { CredentialPayload, DIDDocument, IAgentContext, IKey, TKeyType } from '@veramo/core'
3
+ import {
4
+ EcdsaSecp256k1RecoveryMethod2020,
5
+ EcdsaSecp256k1RecoverySignature2020,
6
+ } from '@transmute/lds-ecdsa-secp256k1-recovery2020'
7
+
8
+ import * as u8a from 'uint8arrays'
9
+ import { asArray, encodeJoseBlob } from '@veramo/utils'
10
+
11
+ export class VeramoEcdsaSecp256k1RecoverySignature2020 extends VeramoLdSignature {
12
+ getSupportedVerificationType(): string {
13
+ return 'EcdsaSecp256k1RecoveryMethod2020'
14
+ }
15
+
16
+ getSupportedVeramoKeyType(): TKeyType {
17
+ return 'Secp256k1'
18
+ }
19
+
20
+ getSuiteForSigning(
21
+ key: IKey,
22
+ did: string,
23
+ verifiableMethodId: string,
24
+ context: IAgentContext<RequiredAgentMethods>,
25
+ ): any {
26
+ const controller = did
27
+ const signer = {
28
+ //returns a JWS detached
29
+ sign: async (args: { data: Uint8Array }): Promise<string> => {
30
+ const header = {
31
+ alg: 'ES256K-R',
32
+ b64: false,
33
+ crit: ['b64'],
34
+ }
35
+ const headerString = encodeJoseBlob(header)
36
+ const messageBuffer = u8a.concat([u8a.fromString(`${headerString}.`, 'utf-8'), args.data])
37
+ const messageString = u8a.toString(messageBuffer, 'base64')
38
+ const signature = await context.agent.keyManagerSign({
39
+ keyRef: key.kid,
40
+ algorithm: 'ES256K-R',
41
+ data: messageString,
42
+ encoding: 'base64',
43
+ })
44
+ return `${headerString}..${signature}`
45
+ },
46
+ }
47
+
48
+ return new EcdsaSecp256k1RecoverySignature2020({
49
+ // signer,
50
+ key: new EcdsaSecp256k1RecoveryMethod2020({
51
+ publicKeyHex: key.publicKeyHex,
52
+ signer: () => signer,
53
+ type: this.getSupportedVerificationType(),
54
+ controller,
55
+ id: verifiableMethodId,
56
+ }),
57
+ })
58
+ }
59
+
60
+ getSuiteForVerification(): any {
61
+ return new EcdsaSecp256k1RecoverySignature2020()
62
+ }
63
+
64
+ preSigningCredModification(credential: CredentialPayload): void {
65
+ credential['@context'] = [
66
+ ...asArray(credential['@context'] || []),
67
+ 'https://identity.foundation/EcdsaSecp256k1RecoverySignature2020/lds-ecdsa-secp256k1-recovery2020-0.0.jsonld',
68
+ ]
69
+ }
70
+
71
+ preDidResolutionModification(didUrl: string, didDoc: DIDDocument): void {
72
+ // did:ethr
73
+ if (didUrl.toLowerCase().startsWith('did:ethr')) {
74
+ // TODO: EcdsaSecp256k1RecoveryMethod2020 does not support blockchainAccountId
75
+ // blockchainAccountId to ethereumAddress
76
+ didDoc.verificationMethod?.forEach((x) => {
77
+ if (x.blockchainAccountId) {
78
+ x.ethereumAddress = x.blockchainAccountId.substring(0, x.blockchainAccountId.lastIndexOf('@'))
79
+ }
80
+ })
81
+ }
82
+ }
83
+ }