@sphereon/ssi-sdk-ext.jwt-service 0.24.1-unstable.92 → 0.25.0

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.
@@ -1,113 +1,330 @@
1
- import { IIdentifierResolution, ManagedIdentifierOptsOrResult, ManagedIdentifierResult } from '@sphereon/ssi-sdk-ext.identifier-resolution'
2
- import { ISphereonKeyManager } from '@sphereon/ssi-sdk-ext.key-manager'
3
- import { JWK, SignatureAlgorithmJwa } from '@sphereon/ssi-sdk-ext.key-utils'
4
- import { IAgentContext, IPluginMethodMap } from '@veramo/core'
1
+ import {
2
+ ExternalIdentifierDidOpts,
3
+ ExternalIdentifierResult,
4
+ ExternalIdentifierX5cOpts,
5
+ IIdentifierResolution,
6
+ ManagedIdentifierOptsOrResult,
7
+ ManagedIdentifierResult,
8
+ } from '@sphereon/ssi-sdk-ext.identifier-resolution'
9
+ import {ClientIdScheme} from '@sphereon/ssi-sdk-ext.x509-utils'
10
+ import {
11
+ BaseJWK,
12
+ IValidationResult,
13
+ JoseSignatureAlgorithm,
14
+ JoseSignatureAlgorithmString,
15
+ JWK
16
+ } from '@sphereon/ssi-types'
17
+ import {IAgentContext, IKeyManager, IPluginMethodMap} from '@veramo/core'
18
+
19
+ export type IRequiredContext = IAgentContext<IIdentifierResolution & IKeyManager> // could we still interop with Veramo?
20
+
21
+ export const jwtServiceContextMethods: Array<string> = [
22
+ 'jwtPrepareJws',
23
+ 'jwtCreateJwsJsonGeneralSignature',
24
+ 'jwtCreateJwsJsonFlattenedSignature',
25
+ 'jwtCreateJwsCompactSignature',
26
+ 'jwtVerifyJwsSignature',
27
+ 'jwtEncryptJweCompactJwt',
28
+ 'jwtDecryptJweCompactJwt'
29
+ ]
5
30
 
6
- export type IRequiredContext = IAgentContext<IIdentifierResolution & ISphereonKeyManager> // could we still interop with Veramo?
7
31
  export interface IJwtService extends IPluginMethodMap {
8
- jwtPrepareJws(args: CreateJwsJsonArgs, context: IRequiredContext): Promise<PreparedJwsObject>
32
+ jwtPrepareJws(args: CreateJwsJsonArgs, context: IRequiredContext): Promise<PreparedJwsObject>
33
+
34
+ jwtCreateJwsJsonGeneralSignature(args: CreateJwsJsonArgs, context: IRequiredContext): Promise<JwsJsonGeneral>
35
+
36
+ jwtCreateJwsJsonFlattenedSignature(args: CreateJwsFlattenedArgs, context: IRequiredContext): Promise<JwsJsonFlattened>
37
+
38
+ jwtCreateJwsCompactSignature(args: CreateJwsCompactArgs, context: IRequiredContext): Promise<JwtCompactResult>
9
39
 
10
- jwtCreateJwsJsonGeneralSignature(args: CreateJwsJsonArgs, context: IRequiredContext): Promise<JwsJsonGeneral>
40
+ jwtVerifyJwsSignature(args: VerifyJwsArgs, context: IRequiredContext): Promise<IJwsValidationResult>
11
41
 
12
- jwtCreateJwsJsonFlattenedSignature(args: CreateJwsFlattenedArgs, context: IRequiredContext): Promise<JwsJsonFlattened>
42
+ jwtEncryptJweCompactJwt(args: EncryptJweCompactJwtArgs, context: IRequiredContext): Promise<JwtCompactResult>
13
43
 
14
- jwtCreateJwsCompactSignature(args: CreateJwsCompactArgs, context: IRequiredContext): Promise<JwsCompactResult>
44
+ jwtDecryptJweCompactJwt(args: DecryptJweCompactJwtArgs, context: IRequiredContext): Promise<JwtCompactResult>
15
45
 
16
- // jwtVerifyJwsCompactSignature(args: {jwt: string}): Promise<any>
46
+ // TODO: JWE/encryption general methods
47
+ }
17
48
 
18
- // TODO: JWE/encryption
49
+ export type IJwsValidationResult = IValidationResult & {
50
+ jws: JwsJsonGeneralWithIdentifiers // We always translate to general as that is the most flexible format allowing multiple sigs
19
51
  }
20
52
 
21
53
  export interface PreparedJws {
22
- protectedHeader: JwtHeader
23
- payload: Uint8Array
24
- unprotectedHeader?: JwtHeader // only for jws json and also then optional
25
- existingSignatures?: Array<JwsJsonSignature> // only for jws json and also then optional
54
+ protectedHeader: JwsHeader
55
+ payload: Uint8Array
56
+ unprotectedHeader?: JwsHeader // only for jws json and also then optional
57
+ existingSignatures?: Array<JwsJsonSignature> // only for jws json and also then optional
26
58
  }
27
59
 
28
60
  export interface JwsJsonSignature {
29
- protected: string
30
- header?: JwtHeader
31
- signature: string
61
+ protected: string
62
+ header?: JwsHeader
63
+ signature: string
64
+ }
65
+
66
+ /**
67
+ * The JWK representation of an ephemeral public key.
68
+ * See https://www.rfc-editor.org/rfc/rfc7518.html#section-6
69
+ */
70
+ // todo split into separate objects
71
+ export type EphemeralPublicKey = Omit<BaseJWK, 'alg'>
72
+
73
+ // export function isEcJWK(v)
74
+
75
+ export interface JweHeader extends Omit<BaseJwtHeader, 'alg'> {
76
+ alg: string,
77
+ enc: string,
78
+ jku?: string,
79
+ jwk?: BaseJWK,
80
+ epk?: EphemeralPublicKey,
81
+ x5u?: string
82
+ x5c?: string[]
83
+ x5t?: string,
84
+ cty?: string,
85
+ crit?: string[]
86
+
87
+ [k: string]: any
88
+
89
+ }
90
+
91
+
92
+ export interface JweRecipientUnprotectedHeader {
93
+ alg: string
94
+ iv: string
95
+ tag: string
96
+ epk?: EphemeralPublicKey
97
+ kid?: string
98
+ apv?: string
99
+ apu?: string
100
+ }
101
+
102
+ export interface JweProtectedHeader extends Partial<JweHeader> {
103
+ zip?: 'DEF' | string
32
104
  }
33
105
 
106
+
107
+ export type Jws = JwsCompact | JwsJsonFlattened | JwsJsonGeneral
108
+
34
109
  export type JwsCompact = string
35
110
 
36
111
  export interface JwsJsonFlattened {
37
- payload: string
38
- protected: string
39
- header?: JwtHeader
40
- signature: string
112
+ payload: string
113
+ protected: string
114
+ header?: JwsHeader
115
+ signature: string
41
116
  }
42
117
 
43
118
  export interface JwsJsonGeneral {
44
- payload: string
45
- signatures: Array<JwsJsonSignature>
119
+ payload: string
120
+ signatures: Array<JwsJsonSignature>
121
+ }
122
+
123
+ export interface JwsJsonGeneralWithIdentifiers extends JwsJsonGeneral {
124
+ signatures: Array<JwsJsonSignatureWithIdentifier>
125
+ }
126
+
127
+ export interface JwsJsonSignatureWithIdentifier extends JwsJsonSignature {
128
+ identifier: ExternalIdentifierResult
129
+ }
130
+
131
+
132
+ export type Jwe = JweCompact | JweJsonFlattened | JweJsonGeneral
133
+ export type JweCompact = string
134
+
135
+ export interface JweJsonFlattened {
136
+ protected: string
137
+ unprotected: JweHeader
138
+ header: JweHeader | JweRecipientUnprotectedHeader
139
+ encrypted_key?: string
140
+ aad?: string
141
+ iv: string
142
+ ciphertext: string
143
+ tag?: string
46
144
  }
47
145
 
146
+
147
+ export interface JweRecipient {
148
+ header?: JweRecipientUnprotectedHeader
149
+ encrypted_key?: string
150
+ }
151
+
152
+ export interface JweJsonGeneral {
153
+ protected: string
154
+ unprotected?: JweHeader
155
+ recipients: Array<JweRecipient>
156
+ aad?: string
157
+ iv: string
158
+ ciphertext: string
159
+ tag?: string
160
+ }
161
+
162
+
48
163
  export interface PreparedJwsObject {
49
- jws: PreparedJws
50
- b64: { payload: string; protectedHeader: string } // header is always json, as it can only be used in JwsJson
51
- identifier: ManagedIdentifierResult
164
+ jws: PreparedJws
165
+ b64: { payload: string; protectedHeader: string } // header is always json, as it can only be used in JwsJson
166
+ identifier: ManagedIdentifierResult
52
167
  }
53
168
 
54
169
  export interface BaseJwtHeader {
55
- typ?: string
56
- alg?: string
57
- kid?: string
170
+ typ?: string
171
+ alg?: string
172
+ kid?: string
58
173
  }
174
+
59
175
  export interface BaseJwtPayload {
60
- iss?: string
61
- sub?: string
62
- aud?: string[] | string
63
- exp?: number
64
- nbf?: number
65
- iat?: number
66
- jti?: string
176
+ iss?: string
177
+ sub?: string
178
+ aud?: string[] | string
179
+ exp?: number
180
+ nbf?: number
181
+ iat?: number
182
+ jti?: string
67
183
  }
68
184
 
69
- export interface JwtHeader extends BaseJwtHeader {
70
- kid?: string
71
- jwk?: JWK
72
- x5c?: string[]
185
+ export interface JwsHeader extends BaseJwtHeader {
186
+ kid?: string
187
+ jwk?: JWK
188
+ x5c?: string[]
73
189
 
74
- [key: string]: unknown
190
+ [key: string]: unknown
75
191
  }
76
192
 
77
- export interface JwtPayload extends BaseJwtPayload {
78
- [key: string]: unknown
193
+ export interface JwsPayload extends BaseJwtPayload {
194
+ [key: string]: unknown
79
195
  }
80
196
 
81
197
  export interface JwsHeaderOpts {
82
- als: SignatureAlgorithmJwa
198
+ alg: JoseSignatureAlgorithm | JoseSignatureAlgorithmString
83
199
  }
84
200
 
85
- export type CreateJwsMode = 'x5c' | 'kid' | 'jwk' | 'did' | 'auto'
201
+ export type JwsIdentifierMode = 'x5c' | 'kid' | 'jwk' | 'did' | 'auto'
202
+
203
+ export type EncryptJweCompactJwtArgs = {
204
+ payload: JwsPayload,
205
+ protectedHeader?: JweProtectedHeader | undefined,
206
+ aad?: Uint8Array | undefined
207
+ recipientKey: ExternalIdentifierResult & { kid?: string}
208
+ alg?: JweAlg
209
+ enc?: JweEnc
210
+ apu?: string // base64url
211
+ apv?: string // base64url
212
+ expirationTime?: number | string | Date
213
+ issuer?: string
214
+ audience?: string | string[]
215
+ }
216
+
217
+ export type DecryptJweCompactJwtArgs = {
218
+ jwe: JweCompact
219
+ idOpts: ManagedIdentifierOptsOrResult
220
+ }
86
221
 
87
222
  export type CreateJwsArgs = {
88
- mode?: CreateJwsMode
89
- issuer: ManagedIdentifierOptsOrResult & { noIssPayloadUpdate?: boolean; noIdentifierInHeader?: boolean }
90
- protectedHeader: JwtHeader
91
- payload: JwtPayload | Uint8Array | string
223
+ mode?: JwsIdentifierMode
224
+ issuer: ManagedIdentifierOptsOrResult & {
225
+ noIssPayloadUpdate?: boolean
226
+ noIdentifierInHeader?: boolean
227
+ }
228
+ clientId?: string
229
+ clientIdScheme?: ClientIdScheme | 'did' | string
230
+ protectedHeader: JwsHeader
231
+ payload: JwsPayload | Uint8Array | string
92
232
  }
93
233
 
234
+
235
+ export type CreateJweArgs = {
236
+ mode?: JwsIdentifierMode
237
+ issuer: ManagedIdentifierOptsOrResult & {
238
+ noIssPayloadUpdate?: boolean
239
+ noIdentifierInHeader?: boolean
240
+ }
241
+ protectedHeader: JweProtectedHeader
242
+ encryptedKey: string | EphemeralPublicKey // In case it is a string it is already encrypted; otherwise encrypt //TODO ??
243
+ iv: string
244
+ ciphertext: string
245
+ tag: string
246
+ }
94
247
  export type CreateJwsCompactArgs = CreateJwsArgs
95
248
 
96
249
  export type CreateJwsFlattenedArgs = Exclude<CreateJwsJsonArgs, 'existingSignatures'>
97
250
 
251
+
252
+
253
+
254
+ export type VerifyJwsArgs = {
255
+ jws: Jws
256
+ jwk?: JWK // Jwk will be resolved from jws, but you can also provide one
257
+ opts?: { x5c?: Omit<ExternalIdentifierX5cOpts, 'identifier'>; did?: Omit<ExternalIdentifierDidOpts, 'identifier'> }
258
+ }
259
+
98
260
  /**
99
261
  * @public
100
262
  */
101
263
  export type CreateJwsJsonArgs = CreateJwsArgs & {
102
- unprotectedHeader?: JwtHeader // only for jws json
103
- existingSignatures?: Array<JwsJsonSignature> // Only for jws json
264
+ unprotectedHeader?: JwsHeader // only for jws json
265
+ existingSignatures?: Array<JwsJsonSignature> // Only for jws json
266
+ }
267
+
268
+ export type CreateJweJsonArgs = CreateJweArgs & {
269
+ unprotectedHeader?: JweHeader
104
270
  }
105
271
 
106
272
  /**
107
273
  * @public
108
274
  */
109
- export interface JwsCompactResult {
110
- jwt: JwsCompact
275
+ export interface JwtCompactResult {
276
+ jwt: JwsCompact | JweCompact
277
+ }
278
+
279
+ export function isJwsCompact(jws: Jws): jws is JwsCompact {
280
+ return typeof jws === 'string' && jws.split('~')[0].match(COMPACT_JWS_REGEX) !== null
281
+ }
282
+
283
+ export function isJweCompact(jwe: Jwe): jwe is JweCompact {
284
+ return typeof jwe === 'string' && jwe.split('~')[0].match(COMPACT_JWE_REGEX) !== null
285
+ }
286
+
287
+
288
+ export function isJwsJsonFlattened(jws: Jws): jws is JwsJsonFlattened {
289
+ return typeof jws === 'object' && 'signature' in jws && 'protected' in jws && !('ciphertext' in jws)
290
+ }
291
+
292
+ export function isJwsJsonGeneral(jws: Jws): jws is JwsJsonGeneral {
293
+ return typeof jws === 'object' && 'signatures' in jws && !('ciphertext' in jws)
294
+ }
295
+
296
+
297
+ export function isJweJsonFlattened(jwe: Jwe): jwe is JweJsonFlattened {
298
+ return typeof jwe === 'object' && 'signature' in jwe && 'ciphertext' in jwe && !('payload' in jwe)
299
+ }
300
+
301
+ export function isJweJsonGeneral(jwe: Jwe): jwe is JweJsonGeneral {
302
+ return typeof jwe === 'object' && 'signatures' in jwe && 'ciphertext' in jwe && !('payload' in jwe)
303
+ }
304
+
305
+
306
+ export function isJwsHeader(header: BaseJwtHeader & Record<string, any>): header is JwsHeader {
307
+ return header && !isJweHeader(header)
308
+ }
309
+
310
+ export function isJweHeader(header: BaseJwtHeader & Record<string, any>): header is JweHeader {
311
+ return ('enc' in header && header.enc && jweEnc(header.enc)) || (header.alg && jweAlg(header.alg))
312
+ }
313
+
314
+ export const COMPACT_JWS_REGEX = /^([a-zA-Z0-9_=-]+).([a-zA-Z0-9_=-]+)?.([a-zA-Z0-9_=-]+)?$/
315
+ export const COMPACT_JWE_REGEX = /^([a-zA-Z0-9_=-]+)\.([a-zA-Z0-9_=-]+)?\.([a-zA-Z0-9_=-]+)\.([a-zA-Z0-9_=-]+)?\.([a-zA-Z0-9_=-]+)?$/
316
+
317
+ export const JweAlgs = ['RSA1_5', 'RSA-OAEP', 'RSA-OAEP-256', 'A128KW', 'A192KW', 'A256KW', 'dir', 'ECDH-ES'/*interop value*/, 'ECDH-ES+A128KW', 'ECDH-ES+A192KW', 'ECDH-ES+A256KW', 'A128GCMKW', 'A192GCMKW', 'A256GCMKW', 'PBES2-HS256+A128KW', 'PBES2-HS384+A192KW', 'PBES2-HS512+A256KW'] as const;
318
+ export type JweAlg = typeof JweAlgs[number]
319
+ export function jweAlg(alg?: string | JweAlg): JweAlg | undefined {
320
+ return JweAlgs.find((supportedVal) => supportedVal === alg);
321
+ }
322
+
323
+
324
+ export const JweEncs = ['A128CBC-HS256', 'A192CBC-HS384', 'A256CBC-HS512', 'A128GCM', 'A192GCM', 'A256GCM'/*interop value*/] as const
325
+ export type JweEnc = typeof JweEncs[number]
326
+
327
+ export function jweEnc(alg?: string | JweEnc): JweEnc | undefined {
328
+ return JweEncs.find((supportedVal) => supportedVal === alg);
111
329
  }
112
330
 
113
- // export const COMPACT_JWS_REGEX = /^([a-zA-Z0-9_=-]+)\.([a-zA-Z0-9_=-]+)?\.([a-zA-Z0-9_=-]+)$/