@sphereon/ssi-sdk.kms-rest 0.36.1-feature.SSISDK.70.integrate.digidentity.56 → 0.36.1-feature.SSISDK.78.41

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,14 +1,4 @@
1
- import {
2
- calculateJwkThumbprint,
3
- isHashString,
4
- joseAlgorithmToDigest,
5
- shaHasher,
6
- signatureAlgorithmFromKeyType,
7
- signatureAlgorithmToJoseAlgorithm,
8
- toJwk,
9
- x25519PublicHexFromPrivateHex,
10
- type X509Opts,
11
- } from '@sphereon/ssi-sdk-ext.key-utils'
1
+ import { calculateJwkThumbprint, toJwk, x25519PublicHexFromPrivateHex, type X509Opts } from '@sphereon/ssi-sdk-ext.key-utils'
12
2
  import { hexToPEM, jwkToPEM, pemCertChainTox5c, PEMToHex, PEMToJwk } from '@sphereon/ssi-sdk-ext.x509-utils'
13
3
  import type { ManagedKeyInfo as RestManagedKeyInfo } from '@sphereon/ssi-sdk.kms-rest-client'
14
4
  import {
@@ -37,17 +27,13 @@ interface KeyManagementSystemOptions {
37
27
  applicationId: string
38
28
  baseUrl: string
39
29
  providerId?: string
40
- tenantId?: string
41
- userId?: string
42
30
  authOpts?: RestClientAuthenticationOpts
43
31
  }
44
32
 
45
33
  export class RestKeyManagementSystem extends AbstractKeyManagementSystem {
46
34
  private client: KmsRestClient
47
35
  private readonly id: string
48
- private readonly providerId: string | undefined
49
- private readonly tenantId: string | undefined
50
- private readonly userId: string | undefined
36
+ private providerId: string | undefined
51
37
 
52
38
  constructor(options: KeyManagementSystemOptions) {
53
39
  super()
@@ -59,26 +45,18 @@ export class RestKeyManagementSystem extends AbstractKeyManagementSystem {
59
45
 
60
46
  this.id = options.applicationId
61
47
  this.providerId = options.providerId
62
- this.tenantId = options.tenantId
63
- this.userId = options.userId
64
48
  this.client = new KmsRestClient(config)
65
49
  }
66
50
 
67
51
  async createKey(args: CreateKeyArgs): Promise<ManagedKeyInfo> {
68
52
  const { type, meta } = args
69
53
 
70
- const joseAlg = signatureAlgorithmFromKeyType({
71
- type,
72
- algorithms: meta?.algorithms as string[] | undefined,
73
- })
74
- const signatureAlgorithm = this.mapJoseToRestSignatureAlgorithm(joseAlg)
54
+ const signatureAlgorithm = this.mapKeyTypeToSignatureAlgorithm(type)
75
55
  const options = {
76
56
  use: meta && 'keyUsage' in meta ? this.mapKeyUsage(meta.keyUsage) : JwkUse.Sig,
77
57
  alg: signatureAlgorithm,
78
58
  keyOperations: meta && meta.keyOperations ? this.mapKeyOperations(meta.keyOperations as string[]) : [KeyOperations.Sign],
79
59
  ...(meta && 'keyAlias' in meta && meta.keyAlias ? { alias: meta.keyAlias } : {}),
80
- ...(this.tenantId && { tenantId: this.tenantId }),
81
- ...(this.userId && { userId: this.userId }),
82
60
  }
83
61
 
84
62
  const key = this.providerId
@@ -90,7 +68,7 @@ export class RestKeyManagementSystem extends AbstractKeyManagementSystem {
90
68
 
91
69
  const jwk = {
92
70
  ...key.keyPair.jose.publicJwk,
93
- alg: key.keyPair.jose.publicJwk.alg ? signatureAlgorithmToJoseAlgorithm(key.keyPair.jose.publicJwk.alg) : undefined,
71
+ alg: key.keyPair.jose.publicJwk.alg ? this.mapJoseAlgorithm(key.keyPair.jose.publicJwk.alg) : undefined,
94
72
  } satisfies JWK
95
73
 
96
74
  const kid = key.keyPair.kid ?? key.keyPair.jose.publicJwk.kid
@@ -107,7 +85,7 @@ export class RestKeyManagementSystem extends AbstractKeyManagementSystem {
107
85
  algorithms: [key.keyPair.jose.publicJwk.alg ?? 'PS256'],
108
86
  jwkThumbprint: calculateJwkThumbprint({
109
87
  jwk,
110
- digestAlgorithm: jwk.alg ? joseAlgorithmToDigest(jwk.alg) : 'sha256',
88
+ digestAlgorithm: this.signatureAlgorithmToDigestAlgorithm(signatureAlgorithm),
111
89
  }),
112
90
  },
113
91
  publicKeyHex: Buffer.from(key.keyPair.jose.publicJwk.toString(), 'utf8').toString('base64'),
@@ -116,20 +94,15 @@ export class RestKeyManagementSystem extends AbstractKeyManagementSystem {
116
94
 
117
95
  async importKey(args: ImportKeyArgs): Promise<ManagedKeyInfo> {
118
96
  const { type } = args
97
+ const signatureAlgorithm = this.mapKeyTypeToSignatureAlgorithm(type)
119
98
  const importKey = this.mapImportKey(args)
120
99
 
121
100
  const result = this.providerId
122
101
  ? await this.client.methods.kmsClientProviderStoreKey({
123
102
  ...importKey.key,
124
103
  providerId: this.providerId,
125
- ...(this.tenantId && { tenantId: this.tenantId }),
126
- ...(this.userId && { userId: this.userId }),
127
- })
128
- : await this.client.methods.kmsClientStoreKey({
129
- ...importKey.key,
130
- ...(this.tenantId && { tenantId: this.tenantId }),
131
- ...(this.userId && { userId: this.userId }),
132
104
  })
105
+ : await this.client.methods.kmsClientStoreKey(importKey.key)
133
106
 
134
107
  return {
135
108
  kid: importKey.kid,
@@ -140,7 +113,7 @@ export class RestKeyManagementSystem extends AbstractKeyManagementSystem {
140
113
  algorithms: [result.keyInfo.key.alg ?? 'PS256'],
141
114
  jwkThumbprint: calculateJwkThumbprint({
142
115
  jwk: importKey.publicKeyJwk,
143
- digestAlgorithm: importKey.publicKeyJwk.alg ? joseAlgorithmToDigest(importKey.publicKeyJwk.alg) : 'sha256',
116
+ digestAlgorithm: this.signatureAlgorithmToDigestAlgorithm(signatureAlgorithm),
144
117
  }),
145
118
  },
146
119
  publicKeyHex: Buffer.from(result.keyInfo.key.toString(), 'utf8').toString('base64'),
@@ -154,27 +127,14 @@ export class RestKeyManagementSystem extends AbstractKeyManagementSystem {
154
127
  ? await this.client.methods.kmsClientProviderDeleteKey({
155
128
  aliasOrKid: kid,
156
129
  providerId: this.providerId,
157
- ...(this.tenantId && { tenantId: this.tenantId }),
158
- ...(this.userId && { userId: this.userId }),
159
- })
160
- : await this.client.methods.kmsClientDeleteKey({
161
- aliasOrKid: kid,
162
- ...(this.tenantId && { tenantId: this.tenantId }),
163
- ...(this.userId && { userId: this.userId }),
164
130
  })
131
+ : await this.client.methods.kmsClientDeleteKey({ aliasOrKid: kid })
165
132
  }
166
133
 
167
134
  async listKeys(): Promise<ManagedKeyInfo[]> {
168
135
  const keys = this.providerId
169
- ? await this.client.methods.kmsClientProviderListKeys({
170
- providerId: this.providerId,
171
- ...(this.tenantId && { tenantId: this.tenantId }),
172
- ...(this.userId && { userId: this.userId }),
173
- })
174
- : await this.client.methods.kmsClientListKeys({
175
- ...(this.tenantId && { tenantId: this.tenantId }),
176
- ...(this.userId && { userId: this.userId }),
177
- })
136
+ ? await this.client.methods.kmsClientProviderListKeys({ providerId: this.providerId })
137
+ : await this.client.methods.kmsClientListKeys()
178
138
 
179
139
  const restKeys = ListKeysResponseToJSONTyped(keys, false).keyInfos
180
140
 
@@ -203,7 +163,7 @@ export class RestKeyManagementSystem extends AbstractKeyManagementSystem {
203
163
  jwk,
204
164
  jwkThumbprint: calculateJwkThumbprint({
205
165
  jwk: jwk as JWK,
206
- digestAlgorithm: restKey.key.alg ? joseAlgorithmToDigest(restKey.key.alg) : 'sha256',
166
+ digestAlgorithm: restKey.signatureAlgorithm ? this.signatureAlgorithmToDigestAlgorithm(restKey.signatureAlgorithm) : 'sha256',
207
167
  }),
208
168
  alias: restKey.alias,
209
169
  providerId: restKey.providerId,
@@ -235,84 +195,35 @@ export class RestKeyManagementSystem extends AbstractKeyManagementSystem {
235
195
  }
236
196
 
237
197
  async sign(args: SignArgs): Promise<string> {
238
- const { keyRef, data, algorithm = 'SHA-256' } = args
198
+ const { keyRef, data } = args
239
199
  const key = this.providerId
240
200
  ? await this.client.methods.kmsClientProviderGetKey({
241
201
  aliasOrKid: keyRef.kid,
242
202
  providerId: this.providerId,
243
- ...(this.tenantId && { tenantId: this.tenantId }),
244
- ...(this.userId && { userId: this.userId }),
245
- })
246
- : await this.client.methods.kmsClientGetKey({
247
- aliasOrKid: keyRef.kid,
248
- ...(this.tenantId && { tenantId: this.tenantId }),
249
- ...(this.userId && { userId: this.userId }),
250
203
  })
251
-
252
- // Check if this is an EdDSA/Ed25519 key - these algorithms MUST sign the raw message, not a hash
253
- const keyAlg = key.keyInfo.key.alg
254
- const isEdDSA = keyAlg === 'EdDSA' || keyAlg === 'ED25519' || key.keyInfo.key.crv === 'Ed25519'
255
-
256
- let dataToBeSigned: Uint8Array
257
- if (isEdDSA) {
258
- // EdDSA signatures are computed over the raw message (PureEdDSA)
259
- // The algorithm internally handles hashing with SHA-512
260
- dataToBeSigned = data
261
- } else {
262
- // For other algorithms (RSA, ECDSA), hash the data before signing
263
- // with remote signing we are not going to send the whole data over the network, we need to hash it (unless we already get a hash)
264
- dataToBeSigned = isHashString(data)
265
- ? data
266
- : shaHasher(data.buffer.slice(data.byteOffset, data.byteOffset + data.byteLength), algorithm)
267
- }
204
+ : await this.client.methods.kmsClientGetKey({ aliasOrKid: keyRef.kid })
268
205
 
269
206
  const signingResult = await this.client.methods.kmsClientCreateRawSignature({
270
207
  keyInfo: key.keyInfo,
271
- input: toString(dataToBeSigned, 'base64'),
272
- ...(this.tenantId && { tenantId: this.tenantId }),
273
- ...(this.userId && { userId: this.userId }),
208
+ input: toString(data, 'base64'),
274
209
  })
275
210
 
276
211
  return signingResult.signature
277
212
  }
278
213
 
279
214
  async verify(args: VerifyArgs): Promise<boolean> {
280
- const { keyRef, data, signature, algorithm = 'SHA-256' } = args
215
+ const { keyRef, data, signature } = args
281
216
  const key = this.providerId
282
217
  ? await this.client.methods.kmsClientProviderGetKey({
283
218
  aliasOrKid: keyRef.kid,
284
219
  providerId: this.providerId,
285
- ...(this.tenantId && { tenantId: this.tenantId }),
286
- ...(this.userId && { userId: this.userId }),
287
- })
288
- : await this.client.methods.kmsClientGetKey({
289
- aliasOrKid: keyRef.kid,
290
- ...(this.tenantId && { tenantId: this.tenantId }),
291
- ...(this.userId && { userId: this.userId }),
292
220
  })
293
-
294
- // Check if this is an EdDSA/Ed25519 key - these algorithms MUST verify the raw message, not a hash
295
- const keyAlg = key.keyInfo.key.alg
296
- const isEdDSA = keyAlg === 'EdDSA' || keyAlg === 'ED25519' || key.keyInfo.key.crv === 'Ed25519'
297
-
298
- let dataToBeVerified: Uint8Array
299
- if (isEdDSA) {
300
- // EdDSA signatures are verified over the raw message (PureEdDSA)
301
- dataToBeVerified = data
302
- } else {
303
- // For other algorithms (RSA, ECDSA), hash the data before verifying
304
- // with remote signing we are not going to send the whole data over the network, we need to hash it (unless we already get a hash)
305
- dataToBeVerified = isHashString(data)
306
- ? data
307
- : shaHasher(data.buffer.slice(data.byteOffset, data.byteOffset + data.byteLength), algorithm)
308
- }
221
+ : await this.client.methods.kmsClientGetKey({ aliasOrKid: keyRef.kid })
309
222
 
310
223
  const verification = await this.client.methods.kmsClientIsValidRawSignature({
311
224
  keyInfo: key.keyInfo,
312
- input: toString(dataToBeVerified, 'base64'),
225
+ input: toString(data, 'base64'),
313
226
  signature,
314
- ...(this.tenantId && { tenantId: this.tenantId }),
315
- ...(this.userId && { userId: this.userId }),
316
227
  })
317
228
 
318
229
  return verification.isValid
@@ -322,6 +233,23 @@ export class RestKeyManagementSystem extends AbstractKeyManagementSystem {
322
233
  throw new Error('sharedSecret is not implemented for REST KMS.')
323
234
  }
324
235
 
236
+ private signatureAlgorithmToDigestAlgorithm = (signatureAlgorithm: SignatureAlgorithm): 'sha256' | 'sha512' => {
237
+ switch (signatureAlgorithm) {
238
+ case SignatureAlgorithm.EcdsaSha256:
239
+ case SignatureAlgorithm.RsaSsaPssSha256Mgf1:
240
+ case SignatureAlgorithm.EckaDhSha256:
241
+ case SignatureAlgorithm.HmacSha256:
242
+ case SignatureAlgorithm.Es256K:
243
+ return 'sha256'
244
+ case SignatureAlgorithm.EcdsaSha512:
245
+ case SignatureAlgorithm.HmacSha512:
246
+ case SignatureAlgorithm.RsaSsaPssSha512Mgf1:
247
+ return 'sha512'
248
+ default:
249
+ throw new Error(`Signature algorithm ${signatureAlgorithm} is not supported by REST KMS`)
250
+ }
251
+ }
252
+
325
253
  private mapKeyUsage = (usage: string): JwkUse => {
326
254
  switch (usage) {
327
255
  case 'sig':
@@ -333,32 +261,53 @@ export class RestKeyManagementSystem extends AbstractKeyManagementSystem {
333
261
  }
334
262
  }
335
263
 
336
- private mapJoseToRestSignatureAlgorithm = (alg: JoseSignatureAlgorithm): SignatureAlgorithm => {
337
- switch (alg) {
338
- case JoseSignatureAlgorithm.RS256:
339
- return SignatureAlgorithm.RsaSha256
340
- case JoseSignatureAlgorithm.RS384:
341
- return SignatureAlgorithm.RsaSha384
342
- case JoseSignatureAlgorithm.RS512:
343
- return SignatureAlgorithm.RsaSha512
344
- case JoseSignatureAlgorithm.PS256:
345
- return SignatureAlgorithm.RsaSsaPssSha256Mgf1
346
- case JoseSignatureAlgorithm.PS384:
347
- return SignatureAlgorithm.RsaSsaPssSha384Mgf1
348
- case JoseSignatureAlgorithm.PS512:
349
- return SignatureAlgorithm.RsaSsaPssSha512Mgf1
350
- case JoseSignatureAlgorithm.ES256:
264
+ private mapKeyTypeToSignatureAlgorithm = (type: TKeyType): SignatureAlgorithm => {
265
+ switch (type) {
266
+ case 'Secp256r1':
351
267
  return SignatureAlgorithm.EcdsaSha256
352
- case JoseSignatureAlgorithm.ES384:
353
- return SignatureAlgorithm.EcdsaSha384
354
- case JoseSignatureAlgorithm.ES512:
355
- return SignatureAlgorithm.EcdsaSha512
356
- case JoseSignatureAlgorithm.ES256K:
357
- return SignatureAlgorithm.Es256K
358
- case JoseSignatureAlgorithm.EdDSA:
359
- return SignatureAlgorithm.Ed25519
268
+ case 'RSA':
269
+ return SignatureAlgorithm.RsaSsaPssSha256Mgf1
270
+ case 'X25519':
271
+ return SignatureAlgorithm.EckaDhSha256
272
+ default:
273
+ throw new Error(`Key type ${type} is not supported by REST KMS`)
274
+ }
275
+ }
276
+
277
+ private mapJoseAlgorithm = (alg: string): JoseSignatureAlgorithm => {
278
+ switch (alg) {
279
+ case 'RS256':
280
+ return JoseSignatureAlgorithm.RS256
281
+ case 'RS384':
282
+ return JoseSignatureAlgorithm.RS384
283
+ case 'RS512':
284
+ return JoseSignatureAlgorithm.RS512
285
+ case 'ES256':
286
+ return JoseSignatureAlgorithm.ES256
287
+ case 'ES256K':
288
+ return JoseSignatureAlgorithm.ES256K
289
+ case 'ES384':
290
+ return JoseSignatureAlgorithm.ES384
291
+ case 'ES512':
292
+ return JoseSignatureAlgorithm.ES512
293
+ case 'EdDSA':
294
+ return JoseSignatureAlgorithm.EdDSA
295
+ case 'HS256':
296
+ return JoseSignatureAlgorithm.HS256
297
+ case 'HS384':
298
+ return JoseSignatureAlgorithm.HS384
299
+ case 'HS512':
300
+ return JoseSignatureAlgorithm.HS512
301
+ case 'PS256':
302
+ return JoseSignatureAlgorithm.PS256
303
+ case 'PS384':
304
+ return JoseSignatureAlgorithm.PS384
305
+ case 'PS512':
306
+ return JoseSignatureAlgorithm.PS512
307
+ case 'none':
308
+ return JoseSignatureAlgorithm.none
360
309
  default:
361
- throw new Error(`JOSE algorithm ${alg} not supported by REST KMS`)
310
+ throw new Error(`Signature algorithm ${alg} is not supported by REST KMS`)
362
311
  }
363
312
  }
364
313
 
@@ -15,7 +15,6 @@ export type CreateKeyArgs = {
15
15
  export type SignArgs = {
16
16
  keyRef: Pick<IKey, 'kid'>
17
17
  data: Uint8Array
18
- algorithm?: string
19
18
  [x: string]: any
20
19
  }
21
20
 
@@ -23,7 +22,6 @@ export type VerifyArgs = {
23
22
  keyRef: Pick<IKey, 'kid'>
24
23
  data: Uint8Array
25
24
  signature: string
26
- algorithm?: string
27
25
  [x: string]: any
28
26
  }
29
27