@sphereon/ssi-sdk-ext.jwt-service 0.28.1-feature.jose.vcdm.52 → 0.28.1-feature.oyd.cmsm.improv.20
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/agent/JwtService.d.ts +17 -0
- package/dist/agent/JwtService.d.ts.map +1 -0
- package/dist/agent/JwtService.js +137 -0
- package/dist/agent/JwtService.js.map +1 -0
- package/dist/functions/JWE.d.ts +75 -0
- package/dist/functions/JWE.d.ts.map +1 -0
- package/dist/functions/JWE.js +280 -0
- package/dist/functions/JWE.js.map +1 -0
- package/dist/functions/index.d.ts +35 -0
- package/dist/functions/index.d.ts.map +1 -0
- package/dist/functions/index.js +385 -0
- package/dist/functions/index.js.map +1 -0
- package/dist/index.d.ts +8 -273
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +30 -37709
- package/dist/index.js.map +1 -1
- package/dist/types/IJwtService.d.ts +222 -0
- package/dist/types/IJwtService.d.ts.map +1 -0
- package/dist/types/IJwtService.js +75 -0
- package/dist/types/IJwtService.js.map +1 -0
- package/package.json +23 -38
- package/plugin.schema.json +4978 -36005
- package/src/agent/JwtService.ts +18 -21
- package/src/functions/JWE.ts +14 -18
- package/src/functions/index.ts +21 -36
- package/src/types/IJwtService.ts +4 -4
- package/dist/index.cjs +0 -37739
- package/dist/index.cjs.map +0 -1
- package/dist/index.d.cts +0 -278
package/src/agent/JwtService.ts
CHANGED
|
@@ -1,34 +1,31 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import
|
|
3
|
-
const logger = Loggers.DEFAULT.get('sphereon:jwt-service')
|
|
1
|
+
import { IAgentPlugin } from '@veramo/core'
|
|
2
|
+
import debug from 'debug'
|
|
4
3
|
import { importJWK } from 'jose'
|
|
5
4
|
|
|
6
|
-
// @ts-ignore
|
|
7
5
|
import * as u8a from 'uint8arrays'
|
|
8
|
-
const { fromString } = u8a
|
|
9
6
|
import {
|
|
10
7
|
createJwsCompact,
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
8
|
+
CreateJwsCompactArgs,
|
|
9
|
+
CreateJwsFlattenedArgs,
|
|
10
|
+
CreateJwsJsonArgs,
|
|
14
11
|
createJwsJsonFlattened,
|
|
15
12
|
createJwsJsonGeneral,
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
13
|
+
DecryptJweCompactJwtArgs,
|
|
14
|
+
EncryptJweCompactJwtArgs,
|
|
15
|
+
IJwsValidationResult,
|
|
16
|
+
IJwtService,
|
|
17
|
+
IRequiredContext,
|
|
21
18
|
jweAlg,
|
|
22
19
|
jweEnc,
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
20
|
+
JwsJsonFlattened,
|
|
21
|
+
JwsJsonGeneral,
|
|
22
|
+
JwtCompactResult,
|
|
26
23
|
JwtLogger,
|
|
27
|
-
|
|
24
|
+
PreparedJwsObject,
|
|
28
25
|
prepareJwsObject,
|
|
29
26
|
schema,
|
|
30
27
|
verifyJws,
|
|
31
|
-
|
|
28
|
+
VerifyJwsArgs,
|
|
32
29
|
} from '..'
|
|
33
30
|
import { CompactJwtEncrypter } from '../functions/JWE'
|
|
34
31
|
|
|
@@ -72,7 +69,7 @@ export class JwtService implements IAgentPlugin {
|
|
|
72
69
|
const { payload, protectedHeader = { alg: args.alg, enc: args.enc }, recipientKey, issuer, expirationTime, audience } = args
|
|
73
70
|
|
|
74
71
|
try {
|
|
75
|
-
|
|
72
|
+
debug(`JWE Encrypt: ${JSON.stringify(args, null, 2)}`)
|
|
76
73
|
|
|
77
74
|
const alg = jweAlg(args.alg) ?? jweAlg(protectedHeader.alg) ?? 'ECDH-ES'
|
|
78
75
|
const enc = jweEnc(args.enc) ?? jweEnc(protectedHeader.enc) ?? 'A256GCM'
|
|
@@ -91,9 +88,9 @@ export class JwtService implements IAgentPlugin {
|
|
|
91
88
|
return Promise.reject(Error(`Currently only ECDH-ES is supported for encryption. JWK alg ${jwkInfo.jwk.kty}, header alg ${alg}`)) // TODO: Probably we support way more already
|
|
92
89
|
}
|
|
93
90
|
const apuVal = protectedHeader.apu ?? args.apu
|
|
94
|
-
const apu = apuVal ? fromString(apuVal, 'base64url') : undefined
|
|
91
|
+
const apu = apuVal ? u8a.fromString(apuVal, 'base64url') : undefined
|
|
95
92
|
const apvVal = protectedHeader.apv ?? args.apv
|
|
96
|
-
const apv = apvVal ? fromString(apvVal, 'base64url') : undefined
|
|
93
|
+
const apv = apvVal ? u8a.fromString(apvVal, 'base64url') : undefined
|
|
97
94
|
|
|
98
95
|
const pubKey = await importJWK(jwkInfo.jwk)
|
|
99
96
|
const encrypter = new CompactJwtEncrypter({
|
package/src/functions/JWE.ts
CHANGED
|
@@ -1,24 +1,20 @@
|
|
|
1
|
-
import { defaultRandomSource, randomBytes,
|
|
1
|
+
import { defaultRandomSource, randomBytes, RandomSource } from '@stablelib/random'
|
|
2
2
|
import { base64ToBytes, bytesToBase64url, decodeBase64url } from '@veramo/utils'
|
|
3
3
|
import * as jose from 'jose'
|
|
4
|
-
import
|
|
5
|
-
|
|
6
|
-
// import type { KeyLike } from 'jose/dist/types/types'
|
|
7
|
-
export type KeyLike = { type: string }
|
|
8
|
-
// @ts-ignore
|
|
4
|
+
import { JWEKeyManagementHeaderParameters, JWTDecryptOptions } from 'jose'
|
|
5
|
+
import type { KeyLike } from 'jose/dist/types/types'
|
|
9
6
|
import * as u8a from 'uint8arrays'
|
|
10
|
-
const { fromString, toString, concat } = u8a
|
|
11
7
|
import {
|
|
12
|
-
|
|
8
|
+
JweAlg,
|
|
13
9
|
JweAlgs,
|
|
14
|
-
|
|
10
|
+
JweEnc,
|
|
15
11
|
JweEncs,
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
12
|
+
JweHeader,
|
|
13
|
+
JweJsonGeneral,
|
|
14
|
+
JweProtectedHeader,
|
|
15
|
+
JweRecipient,
|
|
16
|
+
JweRecipientUnprotectedHeader,
|
|
17
|
+
JwsPayload,
|
|
22
18
|
} from '../types/IJwtService'
|
|
23
19
|
|
|
24
20
|
export interface EncryptionResult {
|
|
@@ -241,7 +237,7 @@ export class CompactJwtEncrypter implements JweEncrypter {
|
|
|
241
237
|
}
|
|
242
238
|
|
|
243
239
|
async encrypt(payload: Uint8Array, jweProtectedHeader: JweProtectedHeader, aad?: Uint8Array | undefined): Promise<EncryptionResult> {
|
|
244
|
-
const jwt = await this.encryptCompactJWT(JSON.parse(toString(payload)), jweProtectedHeader, aad)
|
|
240
|
+
const jwt = await this.encryptCompactJWT(JSON.parse(u8a.toString(payload)), jweProtectedHeader, aad)
|
|
245
241
|
const [protectedHeader, encryptedKey, ivB64, payloadB64, tagB64] = jwt.split('.')
|
|
246
242
|
//[jwe.protected, jwe.encrypted_key, jwe.iv, jwe.ciphertext, jwe.tag].join('.');
|
|
247
243
|
console.log(`FIXME: TO EncryptionResult`)
|
|
@@ -339,7 +335,7 @@ export async function decryptJwe(jwe: JweJsonGeneral, decrypter: JweDecrypter):
|
|
|
339
335
|
return Promise.reject(Error(`Decrypter enc '${decrypter.enc}' does not support header enc '${protectedHeader.enc}'`))
|
|
340
336
|
}
|
|
341
337
|
const sealed = toWebCryptoCiphertext(jwe.ciphertext, jwe.tag)
|
|
342
|
-
const aad = fromString(jwe.aad ? `${jwe.protected}.${jwe.aad}` : jwe.protected)
|
|
338
|
+
const aad = u8a.fromString(jwe.aad ? `${jwe.protected}.${jwe.aad}` : jwe.protected)
|
|
343
339
|
let cleartext = null
|
|
344
340
|
if (protectedHeader.alg === 'dir' && decrypter.alg === 'dir') {
|
|
345
341
|
cleartext = await decrypter.decrypt(sealed, base64ToBytes(jwe.iv), aad)
|
|
@@ -359,5 +355,5 @@ export async function decryptJwe(jwe: JweJsonGeneral, decrypter: JweDecrypter):
|
|
|
359
355
|
}
|
|
360
356
|
|
|
361
357
|
export function toWebCryptoCiphertext(ciphertext: string, tag: string): Uint8Array {
|
|
362
|
-
return concat([base64ToBytes(ciphertext), base64ToBytes(tag)])
|
|
358
|
+
return u8a.concat([base64ToBytes(ciphertext), base64ToBytes(tag)])
|
|
363
359
|
}
|
package/src/functions/index.ts
CHANGED
|
@@ -1,28 +1,28 @@
|
|
|
1
|
-
import { jwkTtoPublicKeyHex } from '@sphereon/ssi-sdk-ext.did-utils'
|
|
2
1
|
import {
|
|
3
2
|
ensureManagedIdentifierResult,
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
3
|
+
ExternalIdentifierDidOpts,
|
|
4
|
+
ExternalIdentifierX5cOpts,
|
|
5
|
+
IIdentifierResolution,
|
|
7
6
|
isManagedIdentifierDidResult,
|
|
8
7
|
isManagedIdentifierX5cResult,
|
|
9
|
-
|
|
10
|
-
|
|
8
|
+
ManagedIdentifierMethod,
|
|
9
|
+
ManagedIdentifierResult,
|
|
11
10
|
resolveExternalJwkIdentifier,
|
|
12
11
|
} from '@sphereon/ssi-sdk-ext.identifier-resolution'
|
|
13
|
-
import {
|
|
14
|
-
import {
|
|
15
|
-
import
|
|
16
|
-
import type { IAgentContext } from '@veramo/core'
|
|
12
|
+
import { verifyRawSignature } from '@sphereon/ssi-sdk-ext.key-utils'
|
|
13
|
+
import { JWK } from '@sphereon/ssi-types'
|
|
14
|
+
import { IAgentContext } from '@veramo/core'
|
|
17
15
|
import { base64ToBytes, bytesToBase64url, decodeJoseBlob, encodeJoseBlob } from '@veramo/utils'
|
|
18
|
-
// @ts-ignore
|
|
19
16
|
import * as u8a from 'uint8arrays'
|
|
20
|
-
import
|
|
17
|
+
import {
|
|
21
18
|
CreateJwsCompactArgs,
|
|
22
19
|
CreateJwsFlattenedArgs,
|
|
23
20
|
CreateJwsJsonArgs,
|
|
24
21
|
IJwsValidationResult,
|
|
25
22
|
IRequiredContext,
|
|
23
|
+
isJwsCompact,
|
|
24
|
+
isJwsJsonFlattened,
|
|
25
|
+
isJwsJsonGeneral,
|
|
26
26
|
JweHeader,
|
|
27
27
|
Jws,
|
|
28
28
|
JwsCompact,
|
|
@@ -37,14 +37,11 @@ import type {
|
|
|
37
37
|
PreparedJwsObject,
|
|
38
38
|
VerifyJwsArgs,
|
|
39
39
|
} from '../types/IJwtService'
|
|
40
|
-
import { isJwsCompact, isJwsJsonFlattened, isJwsJsonGeneral } from '../types/IJwtService'
|
|
41
|
-
|
|
42
|
-
const { fromString } = u8a
|
|
43
40
|
|
|
44
41
|
const payloadToBytes = (payload: string | JwsPayload | Uint8Array): Uint8Array => {
|
|
45
42
|
const isBytes = payload instanceof Uint8Array
|
|
46
43
|
const isString = typeof payload === 'string'
|
|
47
|
-
return isBytes ? payload : isString ? fromString(payload, 'base64url') : fromString(JSON.stringify(payload), 'utf-8')
|
|
44
|
+
return isBytes ? payload : isString ? u8a.fromString(payload, 'base64url') : u8a.fromString(JSON.stringify(payload), 'utf-8')
|
|
48
45
|
}
|
|
49
46
|
|
|
50
47
|
export const prepareJwsObject = async (args: CreateJwsJsonArgs, context: IRequiredContext): Promise<PreparedJwsObject> => {
|
|
@@ -114,15 +111,11 @@ export const createJwsJsonGeneral = async (args: CreateJwsJsonArgs, context: IRe
|
|
|
114
111
|
},
|
|
115
112
|
context
|
|
116
113
|
)
|
|
117
|
-
|
|
118
|
-
const alg: string | undefined = protectedHeader.alg ?? signatureAlgorithmFromKeyType({ type: identifier.key.type })
|
|
119
|
-
|
|
120
114
|
// const algorithm = await signatureAlgorithmFromKey({ key: identifier.key })
|
|
121
115
|
const signature = await context.agent.keyManagerSign({
|
|
122
116
|
keyRef: identifier.kmsKeyRef,
|
|
123
117
|
data: `${b64.protectedHeader}.${b64.payload}`,
|
|
124
118
|
encoding: undefined,
|
|
125
|
-
algorithm: alg,
|
|
126
119
|
})
|
|
127
120
|
const jsonSignature = {
|
|
128
121
|
protected: b64.protectedHeader,
|
|
@@ -158,8 +151,6 @@ export const checkAndUpdateJwsHeader = async (
|
|
|
158
151
|
},
|
|
159
152
|
context: IRequiredContext
|
|
160
153
|
) => {
|
|
161
|
-
// Make sure we have an alg in the header (https://datatracker.ietf.org/doc/html/rfc7515#section-4.1.1)
|
|
162
|
-
header.alg = header.alg ?? signatureAlgorithmFromKeyType({ type: identifier.key.type })
|
|
163
154
|
if (isIdentifierMode(mode, identifier.method, 'did')) {
|
|
164
155
|
// kid is VM of the DID
|
|
165
156
|
// @see https://datatracker.ietf.org/doc/html/rfc7515#section-4.1.4
|
|
@@ -321,31 +312,25 @@ export const verifyJws = async (args: VerifyJwsArgs, context: IAgentContext<IIde
|
|
|
321
312
|
// If we have a specific KMS agent plugin that can do the verification prefer that over the generic verification
|
|
322
313
|
index++
|
|
323
314
|
let valid: boolean
|
|
324
|
-
const data = fromString(`${sigWithId.protected}.${jws.payload}`, 'utf-8')
|
|
315
|
+
const data = u8a.fromString(`${sigWithId.protected}.${jws.payload}`, 'utf-8')
|
|
325
316
|
const jwkInfo = sigWithId.identifier.jwks[0]
|
|
326
|
-
|
|
327
|
-
if (sigWithId.protected.startsWith(`ey`)) {
|
|
328
|
-
const header = decodeJoseBlob(sigWithId.protected)
|
|
329
|
-
signatureAlg = header.alg as JoseSignatureAlgorithm | undefined
|
|
330
|
-
}
|
|
331
|
-
|
|
332
|
-
if (false && signatureAlg?.startsWith('PS') && contextHasPlugin(context, 'keyManagerVerify')) {
|
|
317
|
+
/* if (sigWithId.header?.alg === 'RSA' && contextHasPlugin(context, 'keyManagerVerify')) {
|
|
333
318
|
const publicKeyHex = jwkTtoPublicKeyHex(jwkInfo.jwk)
|
|
334
319
|
valid = await context.agent.keyManagerVerify({
|
|
335
320
|
signature: sigWithId.signature,
|
|
336
321
|
data,
|
|
337
322
|
publicKeyHex,
|
|
338
|
-
type: keyTypeFromCryptographicSuite({
|
|
323
|
+
type: keyTypeFromCryptographicSuite({ crv: jwkInfo.jwk.crv ?? 'ES256' }),
|
|
339
324
|
// no kms arg, as the current key manager needs a bit more work
|
|
340
325
|
})
|
|
341
|
-
} else {
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
}
|
|
326
|
+
} else {*/
|
|
327
|
+
const signature = base64ToBytes(sigWithId.signature)
|
|
328
|
+
valid = await verifyRawSignature({ data, signature, key: jwkInfo.jwk })
|
|
329
|
+
// }
|
|
346
330
|
if (!valid) {
|
|
347
331
|
errorMessages.push(`Signature ${index} was not valid`)
|
|
348
332
|
}
|
|
333
|
+
|
|
349
334
|
return {
|
|
350
335
|
sigWithId,
|
|
351
336
|
valid,
|
package/src/types/IJwtService.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import
|
|
1
|
+
import {
|
|
2
2
|
ExternalIdentifierDidOpts,
|
|
3
3
|
ExternalIdentifierResult,
|
|
4
4
|
ExternalIdentifierX5cOpts,
|
|
@@ -6,9 +6,9 @@ import type {
|
|
|
6
6
|
ManagedIdentifierOptsOrResult,
|
|
7
7
|
ManagedIdentifierResult,
|
|
8
8
|
} from '@sphereon/ssi-sdk-ext.identifier-resolution'
|
|
9
|
-
import
|
|
10
|
-
import
|
|
11
|
-
import
|
|
9
|
+
import { ClientIdScheme } from '@sphereon/ssi-sdk-ext.x509-utils'
|
|
10
|
+
import { BaseJWK, IValidationResult, JoseSignatureAlgorithm, JoseSignatureAlgorithmString, JWK } from '@sphereon/ssi-types'
|
|
11
|
+
import { IAgentContext, IKeyManager, IPluginMethodMap } from '@veramo/core'
|
|
12
12
|
|
|
13
13
|
export type IRequiredContext = IAgentContext<IIdentifierResolution & IKeyManager> // could we still interop with Veramo?
|
|
14
14
|
|