@opentdf/sdk 0.9.0-beta.91 → 0.9.0-beta.93

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 (182) hide show
  1. package/dist/cjs/src/access/access-fetch.js +1 -2
  2. package/dist/cjs/src/access/access-rpc.js +1 -3
  3. package/dist/cjs/src/access.js +1 -14
  4. package/dist/cjs/src/auth/auth.js +13 -10
  5. package/dist/cjs/src/auth/dpop.js +121 -0
  6. package/dist/cjs/src/auth/oidc-clientcredentials-provider.js +37 -3
  7. package/dist/cjs/src/auth/oidc-externaljwt-provider.js +37 -3
  8. package/dist/cjs/src/auth/oidc-refreshtoken-provider.js +37 -3
  9. package/dist/cjs/src/auth/oidc.js +10 -8
  10. package/dist/cjs/src/auth/providers.js +35 -12
  11. package/dist/cjs/src/crypto/index.js +16 -2
  12. package/dist/cjs/src/crypto/pemPublicToCrypto.js +17 -11
  13. package/dist/cjs/src/opentdf.js +40 -10
  14. package/dist/cjs/tdf3/index.js +4 -2
  15. package/dist/cjs/tdf3/src/assertions.js +71 -31
  16. package/dist/cjs/tdf3/src/ciphers/aes-gcm-cipher.js +1 -1
  17. package/dist/cjs/tdf3/src/ciphers/symmetric-cipher-base.js +4 -2
  18. package/dist/cjs/tdf3/src/client/index.js +23 -33
  19. package/dist/cjs/tdf3/src/crypto/crypto-utils.js +12 -5
  20. package/dist/cjs/tdf3/src/crypto/declarations.js +1 -1
  21. package/dist/cjs/tdf3/src/crypto/index.js +849 -88
  22. package/dist/cjs/tdf3/src/crypto/jose/jwt-claims-set.js +11 -0
  23. package/dist/cjs/tdf3/src/crypto/jose/validate-crit.js +8 -0
  24. package/dist/cjs/tdf3/src/crypto/jose/vendor/lib/buffer_utils.js +41 -0
  25. package/dist/cjs/tdf3/src/crypto/jose/vendor/lib/epoch.js +6 -0
  26. package/dist/cjs/tdf3/src/crypto/jose/vendor/lib/is_object.js +21 -0
  27. package/dist/cjs/tdf3/src/crypto/jose/vendor/lib/jwt_claims_set.js +112 -0
  28. package/dist/cjs/tdf3/src/crypto/jose/vendor/lib/secs.js +60 -0
  29. package/dist/cjs/tdf3/src/crypto/jose/vendor/lib/validate_crit.js +38 -0
  30. package/dist/cjs/tdf3/src/crypto/jose/vendor/util/errors.js +135 -0
  31. package/dist/cjs/tdf3/src/crypto/jwt.js +183 -0
  32. package/dist/cjs/tdf3/src/crypto/salt.js +14 -8
  33. package/dist/cjs/tdf3/src/models/encryption-information.js +17 -20
  34. package/dist/cjs/tdf3/src/models/key-access.js +43 -63
  35. package/dist/cjs/tdf3/src/tdf.js +75 -75
  36. package/dist/cjs/tdf3/src/utils/index.js +5 -39
  37. package/dist/types/src/access/access-fetch.d.ts.map +1 -1
  38. package/dist/types/src/access/access-rpc.d.ts.map +1 -1
  39. package/dist/types/src/access.d.ts +0 -5
  40. package/dist/types/src/access.d.ts.map +1 -1
  41. package/dist/types/src/auth/auth.d.ts +9 -6
  42. package/dist/types/src/auth/auth.d.ts.map +1 -1
  43. package/dist/types/src/auth/dpop.d.ts +60 -0
  44. package/dist/types/src/auth/dpop.d.ts.map +1 -0
  45. package/dist/types/src/auth/oidc-clientcredentials-provider.d.ts +3 -2
  46. package/dist/types/src/auth/oidc-clientcredentials-provider.d.ts.map +1 -1
  47. package/dist/types/src/auth/oidc-externaljwt-provider.d.ts +3 -2
  48. package/dist/types/src/auth/oidc-externaljwt-provider.d.ts.map +1 -1
  49. package/dist/types/src/auth/oidc-refreshtoken-provider.d.ts +3 -2
  50. package/dist/types/src/auth/oidc-refreshtoken-provider.d.ts.map +1 -1
  51. package/dist/types/src/auth/oidc.d.ts +6 -4
  52. package/dist/types/src/auth/oidc.d.ts.map +1 -1
  53. package/dist/types/src/auth/providers.d.ts +5 -4
  54. package/dist/types/src/auth/providers.d.ts.map +1 -1
  55. package/dist/types/src/crypto/index.d.ts +2 -1
  56. package/dist/types/src/crypto/index.d.ts.map +1 -1
  57. package/dist/types/src/crypto/pemPublicToCrypto.d.ts +18 -0
  58. package/dist/types/src/crypto/pemPublicToCrypto.d.ts.map +1 -1
  59. package/dist/types/src/opentdf.d.ts +13 -4
  60. package/dist/types/src/opentdf.d.ts.map +1 -1
  61. package/dist/types/tdf3/index.d.ts +3 -3
  62. package/dist/types/tdf3/index.d.ts.map +1 -1
  63. package/dist/types/tdf3/src/assertions.d.ts +23 -8
  64. package/dist/types/tdf3/src/assertions.d.ts.map +1 -1
  65. package/dist/types/tdf3/src/ciphers/aes-gcm-cipher.d.ts +3 -3
  66. package/dist/types/tdf3/src/ciphers/aes-gcm-cipher.d.ts.map +1 -1
  67. package/dist/types/tdf3/src/ciphers/symmetric-cipher-base.d.ts +4 -4
  68. package/dist/types/tdf3/src/ciphers/symmetric-cipher-base.d.ts.map +1 -1
  69. package/dist/types/tdf3/src/client/builders.d.ts +2 -2
  70. package/dist/types/tdf3/src/client/builders.d.ts.map +1 -1
  71. package/dist/types/tdf3/src/client/index.d.ts +6 -5
  72. package/dist/types/tdf3/src/client/index.d.ts.map +1 -1
  73. package/dist/types/tdf3/src/crypto/crypto-utils.d.ts +14 -4
  74. package/dist/types/tdf3/src/crypto/crypto-utils.d.ts.map +1 -1
  75. package/dist/types/tdf3/src/crypto/declarations.d.ts +283 -18
  76. package/dist/types/tdf3/src/crypto/declarations.d.ts.map +1 -1
  77. package/dist/types/tdf3/src/crypto/index.d.ts +105 -28
  78. package/dist/types/tdf3/src/crypto/index.d.ts.map +1 -1
  79. package/dist/types/tdf3/src/crypto/jose/jwt-claims-set.d.ts +3 -0
  80. package/dist/types/tdf3/src/crypto/jose/jwt-claims-set.d.ts.map +1 -0
  81. package/dist/types/tdf3/src/crypto/jose/validate-crit.d.ts +5 -0
  82. package/dist/types/tdf3/src/crypto/jose/validate-crit.d.ts.map +1 -0
  83. package/dist/types/tdf3/src/crypto/jose/vendor/lib/buffer_utils.d.ts +6 -0
  84. package/dist/types/tdf3/src/crypto/jose/vendor/lib/buffer_utils.d.ts.map +1 -0
  85. package/dist/types/tdf3/src/crypto/jose/vendor/lib/epoch.d.ts +3 -0
  86. package/dist/types/tdf3/src/crypto/jose/vendor/lib/epoch.d.ts.map +1 -0
  87. package/dist/types/tdf3/src/crypto/jose/vendor/lib/is_object.d.ts +3 -0
  88. package/dist/types/tdf3/src/crypto/jose/vendor/lib/is_object.d.ts.map +1 -0
  89. package/dist/types/tdf3/src/crypto/jose/vendor/lib/jwt_claims_set.d.ts +3 -0
  90. package/dist/types/tdf3/src/crypto/jose/vendor/lib/jwt_claims_set.d.ts.map +1 -0
  91. package/dist/types/tdf3/src/crypto/jose/vendor/lib/secs.d.ts +3 -0
  92. package/dist/types/tdf3/src/crypto/jose/vendor/lib/secs.d.ts.map +1 -0
  93. package/dist/types/tdf3/src/crypto/jose/vendor/lib/validate_crit.d.ts +3 -0
  94. package/dist/types/tdf3/src/crypto/jose/vendor/lib/validate_crit.d.ts.map +1 -0
  95. package/dist/types/tdf3/src/crypto/jose/vendor/util/errors.d.ts +76 -0
  96. package/dist/types/tdf3/src/crypto/jose/vendor/util/errors.d.ts.map +1 -0
  97. package/dist/types/tdf3/src/crypto/jwt.d.ts +76 -0
  98. package/dist/types/tdf3/src/crypto/jwt.d.ts.map +1 -0
  99. package/dist/types/tdf3/src/crypto/salt.d.ts +6 -1
  100. package/dist/types/tdf3/src/crypto/salt.d.ts.map +1 -1
  101. package/dist/types/tdf3/src/models/encryption-information.d.ts +4 -4
  102. package/dist/types/tdf3/src/models/encryption-information.d.ts.map +1 -1
  103. package/dist/types/tdf3/src/models/key-access.d.ts +8 -5
  104. package/dist/types/tdf3/src/models/key-access.d.ts.map +1 -1
  105. package/dist/types/tdf3/src/tdf.d.ts +8 -8
  106. package/dist/types/tdf3/src/tdf.d.ts.map +1 -1
  107. package/dist/types/tdf3/src/utils/index.d.ts +4 -3
  108. package/dist/types/tdf3/src/utils/index.d.ts.map +1 -1
  109. package/dist/web/src/access/access-fetch.js +3 -4
  110. package/dist/web/src/access/access-rpc.js +3 -5
  111. package/dist/web/src/access.js +1 -13
  112. package/dist/web/src/auth/auth.js +13 -10
  113. package/dist/web/src/auth/dpop.js +118 -0
  114. package/dist/web/src/auth/oidc-clientcredentials-provider.js +4 -3
  115. package/dist/web/src/auth/oidc-externaljwt-provider.js +4 -3
  116. package/dist/web/src/auth/oidc-refreshtoken-provider.js +4 -3
  117. package/dist/web/src/auth/oidc.js +11 -9
  118. package/dist/web/src/auth/providers.js +13 -12
  119. package/dist/web/src/crypto/index.js +4 -2
  120. package/dist/web/src/crypto/pemPublicToCrypto.js +11 -9
  121. package/dist/web/src/opentdf.js +7 -10
  122. package/dist/web/tdf3/index.js +3 -2
  123. package/dist/web/tdf3/src/assertions.js +71 -31
  124. package/dist/web/tdf3/src/ciphers/aes-gcm-cipher.js +1 -1
  125. package/dist/web/tdf3/src/ciphers/symmetric-cipher-base.js +4 -2
  126. package/dist/web/tdf3/src/client/index.js +25 -35
  127. package/dist/web/tdf3/src/crypto/crypto-utils.js +12 -5
  128. package/dist/web/tdf3/src/crypto/declarations.js +1 -1
  129. package/dist/web/tdf3/src/crypto/index.js +830 -84
  130. package/dist/web/tdf3/src/crypto/jose/jwt-claims-set.js +5 -0
  131. package/dist/web/tdf3/src/crypto/jose/validate-crit.js +3 -0
  132. package/dist/web/tdf3/src/crypto/jose/vendor/lib/buffer_utils.js +35 -0
  133. package/dist/web/tdf3/src/crypto/jose/vendor/lib/epoch.js +4 -0
  134. package/dist/web/tdf3/src/crypto/jose/vendor/lib/is_object.js +19 -0
  135. package/dist/web/tdf3/src/crypto/jose/vendor/lib/jwt_claims_set.js +107 -0
  136. package/dist/web/tdf3/src/crypto/jose/vendor/lib/secs.js +58 -0
  137. package/dist/web/tdf3/src/crypto/jose/vendor/lib/validate_crit.js +36 -0
  138. package/dist/web/tdf3/src/crypto/jose/vendor/util/errors.js +117 -0
  139. package/dist/web/tdf3/src/crypto/jwt.js +174 -0
  140. package/dist/web/tdf3/src/crypto/salt.js +13 -7
  141. package/dist/web/tdf3/src/models/encryption-information.js +11 -14
  142. package/dist/web/tdf3/src/models/key-access.js +44 -31
  143. package/dist/web/tdf3/src/tdf.js +71 -71
  144. package/dist/web/tdf3/src/utils/index.js +5 -6
  145. package/package.json +11 -4
  146. package/src/access/access-fetch.ts +2 -8
  147. package/src/access/access-rpc.ts +0 -7
  148. package/src/access.ts +0 -17
  149. package/src/auth/auth.ts +21 -12
  150. package/src/auth/dpop.ts +222 -0
  151. package/src/auth/oidc-clientcredentials-provider.ts +23 -15
  152. package/src/auth/oidc-externaljwt-provider.ts +23 -15
  153. package/src/auth/oidc-refreshtoken-provider.ts +23 -15
  154. package/src/auth/oidc.ts +21 -10
  155. package/src/auth/providers.ts +46 -29
  156. package/src/crypto/index.ts +21 -1
  157. package/src/crypto/pemPublicToCrypto.ts +11 -9
  158. package/src/opentdf.ts +19 -14
  159. package/tdf3/index.ts +32 -5
  160. package/tdf3/src/assertions.ts +99 -30
  161. package/tdf3/src/ciphers/aes-gcm-cipher.ts +7 -2
  162. package/tdf3/src/ciphers/symmetric-cipher-base.ts +7 -4
  163. package/tdf3/src/client/builders.ts +2 -2
  164. package/tdf3/src/client/index.ts +60 -59
  165. package/tdf3/src/crypto/crypto-utils.ts +15 -8
  166. package/tdf3/src/crypto/declarations.ts +338 -22
  167. package/tdf3/src/crypto/index.ts +1021 -118
  168. package/tdf3/src/crypto/jose/jwt-claims-set.ts +10 -0
  169. package/tdf3/src/crypto/jose/validate-crit.ts +9 -0
  170. package/tdf3/src/crypto/jose/vendor/lib/buffer_utils.ts +34 -0
  171. package/tdf3/src/crypto/jose/vendor/lib/epoch.ts +3 -0
  172. package/tdf3/src/crypto/jose/vendor/lib/is_object.ts +18 -0
  173. package/tdf3/src/crypto/jose/vendor/lib/jwt_claims_set.ts +106 -0
  174. package/tdf3/src/crypto/jose/vendor/lib/secs.ts +57 -0
  175. package/tdf3/src/crypto/jose/vendor/lib/validate_crit.ts +35 -0
  176. package/tdf3/src/crypto/jose/vendor/util/errors.ts +101 -0
  177. package/tdf3/src/crypto/jwt.ts +256 -0
  178. package/tdf3/src/crypto/salt.ts +16 -8
  179. package/tdf3/src/models/encryption-information.ts +14 -21
  180. package/tdf3/src/models/key-access.ts +57 -41
  181. package/tdf3/src/tdf.ts +110 -93
  182. package/tdf3/src/utils/index.ts +5 -6
@@ -7,6 +7,7 @@ import {
7
7
  type CryptoService,
8
8
  type DecryptResult,
9
9
  type EncryptResult,
10
+ type SymmetricKey,
10
11
  } from '../crypto/declarations.js';
11
12
 
12
13
  const KEY_LENGTH = 32;
@@ -45,7 +46,7 @@ export class AesGcmCipher extends SymmetricCipher {
45
46
  * result from the crypto service and construct the payload automatically from
46
47
  * it's parts. There is no need to process the payload.
47
48
  */
48
- override async encrypt(payload: Binary, key: Binary, iv: Binary): Promise<EncryptResult> {
49
+ override async encrypt(payload: Binary, key: SymmetricKey, iv: Binary): Promise<EncryptResult> {
49
50
  const toConcat: Uint8Array[] = [];
50
51
  const result = await this.cryptoService.encrypt(payload, key, iv, Algorithms.AES_256_GCM);
51
52
  toConcat.push(new Uint8Array(iv.asArrayBuffer()));
@@ -62,7 +63,11 @@ export class AesGcmCipher extends SymmetricCipher {
62
63
  * @returns
63
64
  */
64
65
  // eslint-disable-next-line @typescript-eslint/no-unused-vars
65
- override async decrypt(buffer: ArrayBuffer, key: Binary, iv?: Binary): Promise<DecryptResult> {
66
+ override async decrypt(
67
+ buffer: ArrayBuffer,
68
+ key: SymmetricKey,
69
+ iv?: Binary
70
+ ): Promise<DecryptResult> {
66
71
  const { payload, payloadIv, payloadAuthTag } = processGcmPayload(buffer);
67
72
 
68
73
  return this.cryptoService.decrypt(
@@ -3,7 +3,9 @@ import {
3
3
  type CryptoService,
4
4
  type DecryptResult,
5
5
  type EncryptResult,
6
+ type SymmetricKey,
6
7
  } from '../crypto/declarations.js';
8
+ import { encodeArrayBuffer as hexEncode } from '../../../src/encodings/hex.js';
7
9
 
8
10
  export abstract class SymmetricCipher {
9
11
  cryptoService: CryptoService;
@@ -22,17 +24,18 @@ export abstract class SymmetricCipher {
22
24
  if (!this.ivLength) {
23
25
  throw Error('No iv length');
24
26
  }
25
- return this.cryptoService.generateInitializationVector(this.ivLength);
27
+ const bytes = await this.cryptoService.randomBytes(this.ivLength);
28
+ return hexEncode(bytes.buffer);
26
29
  }
27
30
 
28
- async generateKey(): Promise<string> {
31
+ async generateKey(): Promise<SymmetricKey> {
29
32
  if (!this.keyLength) {
30
33
  throw Error('No key length');
31
34
  }
32
35
  return this.cryptoService.generateKey(this.keyLength);
33
36
  }
34
37
 
35
- abstract encrypt(payload: Binary, key: Binary, iv: Binary): Promise<EncryptResult>;
38
+ abstract encrypt(payload: Binary, key: SymmetricKey, iv: Binary): Promise<EncryptResult>;
36
39
 
37
- abstract decrypt(payload: Uint8Array, key: Binary, iv?: Binary): Promise<DecryptResult>;
40
+ abstract decrypt(payload: Uint8Array, key: SymmetricKey, iv?: Binary): Promise<DecryptResult>;
38
41
  }
@@ -4,7 +4,7 @@ import { type Metadata } from '../tdf.js';
4
4
  import { Binary } from '../binary.js';
5
5
 
6
6
  import { ConfigurationError } from '../../../src/errors.js';
7
- import { PemKeyPair } from '../crypto/declarations.js';
7
+ import { PemKeyPair, type SymmetricKey } from '../crypto/declarations.js';
8
8
  import { DecoratedReadableStream } from './DecoratedReadableStream.js';
9
9
  import { type Chunker } from '../../../src/seekable.js';
10
10
  import { AssertionConfig, AssertionVerificationKeys } from '../assertions.js';
@@ -516,7 +516,7 @@ class EncryptParamsBuilder {
516
516
  }
517
517
  }
518
518
 
519
- export type DecryptKeyMiddleware = (key: Binary) => Promise<Binary>;
519
+ export type DecryptKeyMiddleware = (key: SymmetricKey) => Promise<SymmetricKey>;
520
520
 
521
521
  export type DecryptStreamMiddleware = (
522
522
  stream: DecoratedReadableStream
@@ -19,12 +19,7 @@ import { OIDCRefreshTokenProvider } from '../../../src/auth/oidc-refreshtoken-pr
19
19
  import { OIDCExternalJwtProvider } from '../../../src/auth/oidc-externaljwt-provider.js';
20
20
  import { CryptoService } from '../crypto/declarations.js';
21
21
  import { type AuthProvider, HttpRequest, withHeaders } from '../../../src/auth/auth.js';
22
- import {
23
- getPlatformUrlFromKasEndpoint,
24
- pemToCryptoPublicKey,
25
- rstrip,
26
- validateSecureUrl,
27
- } from '../../../src/utils.js';
22
+ import { getPlatformUrlFromKasEndpoint, rstrip, validateSecureUrl } from '../../../src/utils.js';
28
23
 
29
24
  import {
30
25
  type DecryptParams,
@@ -42,13 +37,11 @@ import { DecoratedReadableStream } from './DecoratedReadableStream.js';
42
37
  import {
43
38
  fetchKeyAccessServers,
44
39
  type KasPublicKeyInfo,
45
- keyAlgorithmToPublicKeyAlgorithm,
46
40
  OriginAllowList,
47
41
  } from '../../../src/access.js';
48
42
  import { ConfigurationError } from '../../../src/errors.js';
49
- import { Binary } from '../binary.js';
50
43
  import { AesGcmCipher } from '../ciphers/aes-gcm-cipher.js';
51
- import { toCryptoKeyPair } from '../crypto/crypto-utils.js';
44
+ import { type KeyPair, type SymmetricKey } from '../crypto/declarations.js';
52
45
  import * as defaultCryptoService from '../crypto/index.js';
53
46
  import {
54
47
  type AttributeObject,
@@ -69,24 +62,23 @@ const defaultClientConfig = { oidcOrigin: '', cryptoService: defaultCryptoServic
69
62
 
70
63
  const getFirstTwoBytes = async (chunker: Chunker) => new TextDecoder().decode(await chunker(0, 2));
71
64
 
72
- async function algorithmFromPEM(pem: string) {
73
- const k: CryptoKey = await pemToCryptoPublicKey(pem);
74
- return keyAlgorithmToPublicKeyAlgorithm(k);
65
+ async function algorithmFromPEM(pem: string, cryptoService: CryptoService) {
66
+ const keyInfo = await cryptoService.parsePublicKeyPem(pem);
67
+ return keyInfo.algorithm;
75
68
  }
76
69
 
77
- // Convert a PEM string to a CryptoKey
70
+ // Convert a PEM string to KasPublicKeyInfo
78
71
  export const resolveKasInfo = async (
79
72
  pem: string,
80
73
  uri: string,
74
+ cryptoService: CryptoService,
81
75
  kid?: string
82
76
  ): Promise<KasPublicKeyInfo> => {
83
- const k: CryptoKey = await pemToCryptoPublicKey(pem);
84
- const algorithm = keyAlgorithmToPublicKeyAlgorithm(k);
77
+ const keyInfo = await cryptoService.parsePublicKeyPem(pem);
85
78
  return {
86
- key: Promise.resolve(k),
87
79
  publicKey: pem,
88
80
  url: uri,
89
- algorithm,
81
+ algorithm: keyInfo.algorithm,
90
82
  kid: kid,
91
83
  };
92
84
  };
@@ -132,7 +124,7 @@ export interface ClientConfig {
132
124
  /// oauth client id; used to generate oauth authProvider
133
125
  clientId?: string;
134
126
  dpopEnabled?: boolean;
135
- dpopKeys?: Promise<CryptoKeyPair>;
127
+ dpopKeys?: Promise<KeyPair>;
136
128
  kasEndpoint: string;
137
129
  /**
138
130
  * Service to use to look up ABAC. Used during autoconfigure. Defaults to
@@ -177,28 +169,23 @@ export interface ClientConfig {
177
169
  */
178
170
  export async function createSessionKeys({
179
171
  authProvider,
180
- // FIXME use cryptoservice to generate keys again
181
172
  cryptoService,
182
173
  dpopKeys,
183
174
  }: {
184
175
  authProvider?: AuthProvider;
185
176
  cryptoService: CryptoService;
186
- dpopKeys?: Promise<CryptoKeyPair>;
187
- }): Promise<CryptoKeyPair> {
188
- let signingKeys: CryptoKeyPair;
177
+ dpopKeys?: Promise<KeyPair>;
178
+ }): Promise<KeyPair> {
179
+ let signingKeys: KeyPair;
189
180
  if (dpopKeys) {
190
181
  signingKeys = await dpopKeys;
191
182
  } else {
192
- const keys = await cryptoService.generateSigningKeyPair();
193
- // signingKeys = await crypto.subtle.generateKey(rsaPkcs1Sha256(), true, ['sign']);
194
- signingKeys = await toCryptoKeyPair(keys);
183
+ // generateSigningKeyPair returns opaque KeyPair
184
+ signingKeys = await cryptoService.generateSigningKeyPair();
195
185
  }
196
186
 
197
187
  // This will contact the auth server and forcibly refresh the auth token claims,
198
188
  // binding the token and the (new) pubkey together.
199
- // Note that we base64 encode the PEM string here as a quick workaround, simply because
200
- // a formatted raw PEM string isn't a valid header value and sending it raw makes keycloak's
201
- // header parser barf. There are more subtle ways to solve this, but this works for now.
202
189
  if (authProvider) {
203
190
  await authProvider?.updateClientPublicKey(signingKeys);
204
191
  }
@@ -301,7 +288,8 @@ const putKasKeyIntoCache = (
301
288
  cache: KasKeyInfoCache,
302
289
  kasKey: Omit<SimpleKasKey, 'publicKey'> & {
303
290
  publicKey: Exclude<SimpleKasKey['publicKey'], undefined>;
304
- }
291
+ },
292
+ cryptoService: CryptoService
305
293
  ): ReturnType<typeof fetchKasPublicKey> => {
306
294
  const algorithmString = algorithmEnumValueToString(kasKey.publicKey.algorithm);
307
295
  const cachedEntry = findEntryInCache(cache, kasKey.kasUri, algorithmString, kasKey.publicKey.kid);
@@ -309,12 +297,9 @@ const putKasKeyIntoCache = (
309
297
  return cachedEntry;
310
298
  }
311
299
  const keyInfoPromise = (async function () {
312
- const keyPromise = pemToCryptoPublicKey(kasKey.publicKey.pem);
313
- const key = await keyPromise;
314
- const algorithm = keyAlgorithmToPublicKeyAlgorithm(key);
300
+ const keyInfo = await cryptoService.parsePublicKeyPem(kasKey.publicKey.pem);
315
301
  return {
316
- algorithm: algorithm,
317
- key: keyPromise,
302
+ algorithm: keyInfo.algorithm,
318
303
  kid: kasKey.publicKey.kid,
319
304
  publicKey: kasKey.publicKey.pem,
320
305
  url: kasKey.kasUri,
@@ -371,7 +356,7 @@ export class Client {
371
356
  /**
372
357
  * Session binding keys. Used for DPoP and signed request bodies.
373
358
  */
374
- readonly dpopKeys: Promise<CryptoKeyPair>;
359
+ readonly dpopKeys: Promise<KeyPair>;
375
360
 
376
361
  readonly dpopEnabled: boolean;
377
362
 
@@ -453,18 +438,24 @@ export class Client {
453
438
  //browser-based OIDC login and authentication process against the OIDC endpoint using their chosen method,
454
439
  //and provide us with a valid refresh token/clientId obtained from that process.
455
440
  if (clientConfig.refreshToken) {
456
- this.authProvider = new OIDCRefreshTokenProvider({
457
- clientId: clientConfig.clientId,
458
- refreshToken: clientConfig.refreshToken,
459
- oidcOrigin: clientConfig.oidcOrigin,
460
- });
441
+ this.authProvider = new OIDCRefreshTokenProvider(
442
+ {
443
+ clientId: clientConfig.clientId,
444
+ refreshToken: clientConfig.refreshToken,
445
+ oidcOrigin: clientConfig.oidcOrigin,
446
+ },
447
+ this.cryptoService
448
+ );
461
449
  } else if (clientConfig.externalJwt) {
462
450
  //Are we exchanging a JWT previously issued by a trusted external entity (e.g. Google) for a bearer token?
463
- this.authProvider = new OIDCExternalJwtProvider({
464
- clientId: clientConfig.clientId,
465
- externalJwt: clientConfig.externalJwt,
466
- oidcOrigin: clientConfig.oidcOrigin,
467
- });
451
+ this.authProvider = new OIDCExternalJwtProvider(
452
+ {
453
+ clientId: clientConfig.clientId,
454
+ externalJwt: clientConfig.externalJwt,
455
+ oidcOrigin: clientConfig.oidcOrigin,
456
+ },
457
+ this.cryptoService
458
+ );
468
459
  }
469
460
  }
470
461
  this.dpopKeys = createSessionKeys({
@@ -509,22 +500,27 @@ export class Client {
509
500
  metadata,
510
501
  mimeType = 'unknown',
511
502
  windowSize = DEFAULT_SEGMENT_SIZE,
512
- keyMiddleware = defaultKeyMiddleware,
503
+ keyMiddleware: keyMiddlewareOpt,
513
504
  splitPlan: preconfiguredSplitPlan,
514
505
  streamMiddleware = async (stream: DecoratedReadableStream) => stream,
515
506
  tdfSpecVersion,
516
507
  wrappingKeyAlgorithm,
517
508
  } = opts;
509
+ const keyMiddleware = keyMiddlewareOpt ?? (() => defaultKeyMiddleware(this.cryptoService));
518
510
  const scope = opts.scope ?? { attributes: [], dissem: [] };
519
511
 
520
512
  for (const attributeValue of scope.attributeValues || []) {
521
513
  for (const kasKey of attributeValue.kasKeys) {
522
514
  if (kasKey.publicKey !== undefined) {
523
- await putKasKeyIntoCache(this.kasKeyInfoCache, {
524
- // TypeScript is silly and cannot infer that publicKey is not undefined, without re-referencing it like this, even though we checked already.
525
- ...kasKey,
526
- publicKey: kasKey.publicKey,
527
- });
515
+ await putKasKeyIntoCache(
516
+ this.kasKeyInfoCache,
517
+ {
518
+ // TypeScript is silly and cannot infer that publicKey is not undefined, without re-referencing it like this, even though we checked already.
519
+ ...kasKey,
520
+ publicKey: kasKey.publicKey,
521
+ },
522
+ this.cryptoService
523
+ );
528
524
  }
529
525
  }
530
526
  }
@@ -594,11 +590,15 @@ export class Client {
594
590
  for (const attributeValue of attributeValues) {
595
591
  for (const kasKey of effectiveKasKeys(attributeValue)) {
596
592
  if (kasKey.publicKey !== undefined) {
597
- await putKasKeyIntoCache(this.kasKeyInfoCache, {
598
- // TypeScript is silly and cannot infer that publicKey is not undefined, without re-referencing it like this, even though we checked already.
599
- ...kasKey,
600
- publicKey: kasKey.publicKey,
601
- });
593
+ await putKasKeyIntoCache(
594
+ this.kasKeyInfoCache,
595
+ {
596
+ // TypeScript is silly and cannot infer that publicKey is not undefined, without re-referencing it like this, even though we checked already.
597
+ ...kasKey,
598
+ publicKey: kasKey.publicKey,
599
+ },
600
+ this.cryptoService
601
+ );
602
602
  }
603
603
  }
604
604
  }
@@ -606,7 +606,7 @@ export class Client {
606
606
  const detailedPlan = plan(attributeValues);
607
607
  for (const item of detailedPlan) {
608
608
  if ('kid' in item.kas) {
609
- const pemAlgorithm = await algorithmFromPEM(item.kas.pem);
609
+ const pemAlgorithm = await algorithmFromPEM(item.kas.pem, this.cryptoService);
610
610
  const kasPublicKeyInfo = await this._doFetchKasKeyWithCache(
611
611
  this.kasKeyInfoCache,
612
612
  item.kas.kasUri,
@@ -694,7 +694,7 @@ export class Client {
694
694
  }
695
695
  encryptionInformation.keyAccess = await Promise.all(
696
696
  splitPlan.map(async ({ kas, kid, pem, sid }) => {
697
- const algorithm = await algorithmFromPEM(pem);
697
+ const algorithm = await algorithmFromPEM(pem, this.cryptoService);
698
698
  if (algorithm !== wrappingKeyAlgorithm) {
699
699
  console.warn(
700
700
  `Mismatched wrapping key algorithm: [${algorithm}] is not requested type, [${wrappingKeyAlgorithm}]`
@@ -722,6 +722,7 @@ export class Client {
722
722
  publicKey: pem,
723
723
  metadata,
724
724
  sid,
725
+ cryptoService: this.cryptoService,
725
726
  });
726
727
  })
727
728
  );
@@ -765,7 +766,7 @@ export class Client {
765
766
  async decrypt({
766
767
  source,
767
768
  allowList,
768
- keyMiddleware = async (key: Binary) => key,
769
+ keyMiddleware = async (key: SymmetricKey) => key,
769
770
  streamMiddleware = async (stream: DecoratedReadableStream) => stream,
770
771
  assertionVerificationKeys,
771
772
  noVerifyAssertions,
@@ -1,5 +1,5 @@
1
1
  import { base64 } from '../../../src/encodings/index.js';
2
- import { type AnyKeyPair, type PemKeyPair } from './declarations.js';
2
+ import { type PemKeyPair } from './declarations.js';
3
3
  import { rsaPkcs1Sha256 } from './index.js';
4
4
 
5
5
  /**
@@ -73,7 +73,10 @@ export const removePemFormatting = (input: string): string => {
73
73
  const PEMRE =
74
74
  /-----BEGIN\s((?:RSA\s)?(?:PUBLIC\sKEY|PRIVATE\sKEY|CERTIFICATE))-----[\s0-9A-Za-z+/=]+-----END\s\1-----/;
75
75
 
76
- export const isPemKeyPair = (i: AnyKeyPair): i is PemKeyPair => {
76
+ /**
77
+ * Type guard to check if a key pair is a PemKeyPair.
78
+ */
79
+ export const isPemKeyPair = (i: PemKeyPair | CryptoKeyPair): i is PemKeyPair => {
77
80
  const { privateKey, publicKey } = i;
78
81
  if (typeof privateKey !== 'string' || typeof publicKey !== 'string') {
79
82
  return false;
@@ -89,7 +92,10 @@ export const isPemKeyPair = (i: AnyKeyPair): i is PemKeyPair => {
89
92
  return true;
90
93
  };
91
94
 
92
- export const isCryptoKeyPair = (i: AnyKeyPair): i is CryptoKeyPair => {
95
+ /**
96
+ * Type guard to check if a key pair is a CryptoKeyPair.
97
+ */
98
+ export const isCryptoKeyPair = (i: PemKeyPair | CryptoKeyPair): i is CryptoKeyPair => {
93
99
  const { privateKey, publicKey } = i;
94
100
  if (typeof privateKey !== 'object' || typeof publicKey !== 'object') {
95
101
  return false;
@@ -100,12 +106,13 @@ export const isCryptoKeyPair = (i: AnyKeyPair): i is CryptoKeyPair => {
100
106
  return privateKey.type === 'private' && publicKey.type === 'public';
101
107
  };
102
108
 
103
- export const toCryptoKeyPair = async (input: AnyKeyPair): Promise<CryptoKeyPair> => {
104
- if (isCryptoKeyPair(input)) {
105
- return input;
106
- }
109
+ /**
110
+ * Convert a PemKeyPair to CryptoKeyPair for internal use.
111
+ * This is needed when interfacing with APIs that still require CryptoKey objects.
112
+ */
113
+ export const toCryptoKeyPair = async (input: PemKeyPair): Promise<CryptoKeyPair> => {
107
114
  if (!isPemKeyPair(input)) {
108
- throw new Error('internal: generated invalid keypair');
115
+ throw new Error('internal: invalid PEM keypair');
109
116
  }
110
117
  const k = [input.publicKey, input.privateKey]
111
118
  .map(removePemFormatting)