@opentdf/sdk 0.3.2-beta.2468 → 0.3.2-beta.3

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/src/access.ts CHANGED
@@ -3,7 +3,10 @@ import { ServiceError } from './errors.js';
3
3
  import { RewrapResponse } from './platform/kas/kas_pb.js';
4
4
  import { getPlatformUrlFromKasEndpoint, validateSecureUrl } from './utils.js';
5
5
 
6
- import { fetchKeyAccessServers as fetchKeyAccessServersRpc } from './access/access-rpc.js';
6
+ import {
7
+ fetchKasBasePubKey,
8
+ fetchKeyAccessServers as fetchKeyAccessServersRpc,
9
+ } from './access/access-rpc.js';
7
10
  import { fetchKeyAccessServers as fetchKeyAccessServersLegacy } from './access/access-fetch.js';
8
11
  import { fetchWrappedKey as fetchWrappedKeysRpc } from './access/access-rpc.js';
9
12
  import { fetchWrappedKey as fetchWrappedKeysLegacy } from './access/access-fetch.js';
@@ -39,30 +42,44 @@ export async function fetchWrappedKey(
39
42
  );
40
43
  }
41
44
 
42
- export type KasPublicKeyAlgorithm = 'ec:secp256r1' | 'rsa:2048';
45
+ export type KasPublicKeyAlgorithm =
46
+ | 'ec:secp256r1'
47
+ | 'ec:secp384r1'
48
+ | 'ec:secp521r1'
49
+ | 'rsa:2048'
50
+ | 'rsa:4096';
43
51
 
44
52
  export const isPublicKeyAlgorithm = (a: string): a is KasPublicKeyAlgorithm => {
45
53
  return a === 'ec:secp256r1' || a === 'rsa:2048';
46
54
  };
47
55
 
48
- export const keyAlgorithmToPublicKeyAlgorithm = (a: KeyAlgorithm): KasPublicKeyAlgorithm => {
56
+ export const keyAlgorithmToPublicKeyAlgorithm = (k: CryptoKey): KasPublicKeyAlgorithm => {
57
+ const a = k.algorithm;
49
58
  if (a.name === 'ECDSA' || a.name === 'ECDH') {
50
59
  const eca = a as EcKeyAlgorithm;
51
- if (eca.namedCurve === 'P-256') {
52
- return 'ec:secp256r1';
60
+ switch (eca.namedCurve) {
61
+ case 'P-256':
62
+ return 'ec:secp256r1';
63
+ case 'P-384':
64
+ return 'ec:secp384r1';
65
+ case 'P-521':
66
+ return 'ec:secp521r1';
67
+ default:
68
+ throw new Error(`unsupported EC curve: ${eca.namedCurve}`);
53
69
  }
54
- throw new Error(`unsupported EC curve: ${eca.namedCurve}`);
55
70
  }
56
- if (a.name === 'RSA-OAEP') {
71
+ if (a.name === 'RSA-OAEP' || a.name === 'RSASSA-PKCS1-v1_5') {
57
72
  const rsaa = a as RsaHashedKeyAlgorithm;
58
- if (rsaa.modulusLength === 2048) {
59
- // if (rsaa.hash.name !== 'RSASSA-PKCS1-v1_5') {
60
- // throw new Error(`unsupported RSA hash: ${rsaa.hash.name}`);
61
- // }
62
- if (rsaa.publicExponent.toString() !== '1,0,1') {
63
- throw new Error(`unsupported RSA public exponent: ${rsaa.publicExponent}`);
64
- }
65
- return 'rsa:2048';
73
+ if (rsaa.publicExponent.toString() !== '1,0,1') {
74
+ throw new Error(`unsupported RSA public exponent: ${rsaa.publicExponent}`);
75
+ }
76
+ switch (rsaa.modulusLength) {
77
+ case 2048:
78
+ return 'rsa:2048';
79
+ case 4096:
80
+ return 'rsa:4096';
81
+ default:
82
+ throw new Error(`unsupported RSA modulus length: ${rsaa.modulusLength}`);
66
83
  }
67
84
  }
68
85
  throw new Error(`unsupported key algorithm: ${a.name}`);
@@ -74,6 +91,14 @@ export const publicKeyAlgorithmToJwa = (a: KasPublicKeyAlgorithm): string => {
74
91
  return 'ES256';
75
92
  case 'rsa:2048':
76
93
  return 'RS256';
94
+ case 'rsa:4096':
95
+ return 'RS512';
96
+ case 'ec:secp384r1':
97
+ return 'ES384';
98
+ case 'ec:secp521r1':
99
+ return 'ES512';
100
+ default:
101
+ throw new Error(`unsupported public key algorithm: ${a}`);
77
102
  }
78
103
  };
79
104
 
@@ -122,17 +147,34 @@ export async function fetchKeyAccessServers(
122
147
  }
123
148
 
124
149
  /**
125
- * If we have KAS url but not public key we can fetch it from KAS, fetching
126
- * the value from `${kas}/kas_public_key`.
150
+ * Fetch the EC (secp256r1) public key for a KAS endpoint.
151
+ * @param kasEndpoint The KAS endpoint URL.
152
+ * @returns The public key information for the KAS endpoint.
127
153
  */
128
154
  export async function fetchECKasPubKey(kasEndpoint: string): Promise<KasPublicKeyInfo> {
129
155
  return fetchKasPubKey(kasEndpoint, 'ec:secp256r1');
130
156
  }
131
157
 
158
+ /**
159
+ * Fetch the public key for a KAS endpoint.
160
+ * This function will first try to fetch the base public key,
161
+ * then it will try to fetch the public key using the RPC method,
162
+ * and finally it will try to fetch the public key using the legacy method.
163
+ * If all attempts fail, it will return the error from RPC Public Key fetch.
164
+ * @param kasEndpoint The KAS endpoint URL.
165
+ * @param algorithm Optional algorithm to fetch the public key for.
166
+ * @returns The public key information.
167
+ */
132
168
  export async function fetchKasPubKey(
133
169
  kasEndpoint: string,
134
170
  algorithm?: KasPublicKeyAlgorithm
135
171
  ): Promise<KasPublicKeyInfo> {
172
+ try {
173
+ return await fetchKasBasePubKey(kasEndpoint);
174
+ } catch (e) {
175
+ console.log(e);
176
+ }
177
+
136
178
  return await tryPromisesUntilFirstSuccess(
137
179
  () => fetchKasPubKeyRpc(kasEndpoint, algorithm),
138
180
  () => fetchKasPubKeyLegacy(kasEndpoint, algorithm)
@@ -71,7 +71,7 @@ export async function keyAgreement(
71
71
  }
72
72
  ): Promise<CryptoKey> {
73
73
  for (const k of [privateKey, publicKey]) {
74
- const mechanism = keyAlgorithmToPublicKeyAlgorithm(k.algorithm);
74
+ const mechanism = keyAlgorithmToPublicKeyAlgorithm(k);
75
75
  if (mechanism !== 'ec:secp256r1') {
76
76
  throw new ConfigurationError(
77
77
  `${k.type} CryptoKey is expected to be of type ECDSA or ECDH, not [${k.algorithm?.name}]`
package/src/opentdf.ts CHANGED
@@ -335,7 +335,7 @@ export class OpenTDF {
335
335
  this.tdf3Client = new TDF3Client({
336
336
  authProvider,
337
337
  dpopKeys,
338
- kasEndpoint: 'https://disallow.all.invalid',
338
+ kasEndpoint: this.platformUrl || 'https://disallow.all.invalid',
339
339
  policyEndpoint,
340
340
  });
341
341
  this.dpopKeys =
@@ -522,14 +522,17 @@ class NanoTDFReader {
522
522
  r.header = nanotdf.header;
523
523
  return r;
524
524
  }
525
+ const platformUrl = this.opts.platformUrl || this.outer.platformUrl;
526
+ const kasEndpoint =
527
+ this.opts.allowedKASEndpoints?.[0] || platformUrl || 'https://disallow.all.invalid';
525
528
  const nc = new Client({
526
529
  allowedKases: this.opts.allowedKASEndpoints,
527
530
  authProvider: this.outer.authProvider,
528
531
  ignoreAllowList: this.opts.ignoreAllowlist,
529
532
  dpopEnabled: this.outer.dpopEnabled,
530
533
  dpopKeys: this.outer.dpopKeys,
531
- kasEndpoint: this.opts.allowedKASEndpoints?.[0] || 'https://disallow.all.invalid',
532
- platformUrl: this.opts.platformUrl || this.outer.platformUrl,
534
+ kasEndpoint,
535
+ platformUrl,
533
536
  });
534
537
  // TODO: The version number should be fetched from the API
535
538
  const version = '0.0.1';
@@ -691,9 +694,12 @@ class Collection {
691
694
  break;
692
695
  }
693
696
 
697
+ const kasEndpoint =
698
+ opts.defaultKASEndpoint || opts.platformUrl || 'https://disallow.all.invalid';
699
+
694
700
  this.client = new NanoTDFDatasetClient({
695
701
  authProvider,
696
- kasEndpoint: opts.defaultKASEndpoint ?? 'https://disallow.all.invalid',
702
+ kasEndpoint: kasEndpoint,
697
703
  maxKeyIterations: opts.maxKeyIterations,
698
704
  platformUrl: opts.platformUrl,
699
705
  });
package/src/version.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * Exposes the released version number of the `@opentdf/sdk` package
3
3
  */
4
- export const version = '0.3.2';
4
+ export const version = '0.3.2'; // x-release-please-version
5
5
 
6
6
  /**
7
7
  * A string name used to label requests as coming from this library client.
@@ -79,7 +79,7 @@ export const resolveKasInfo = async (
79
79
  kid?: string
80
80
  ): Promise<KasPublicKeyInfo> => {
81
81
  const k: CryptoKey = await pemToCryptoPublicKey(pem);
82
- const algorithm = keyAlgorithmToPublicKeyAlgorithm(k.algorithm);
82
+ const algorithm = keyAlgorithmToPublicKeyAlgorithm(k);
83
83
  return {
84
84
  key: Promise.resolve(k),
85
85
  publicKey: pem,
@@ -398,7 +398,7 @@ export class Client {
398
398
  keyMiddleware = defaultKeyMiddleware,
399
399
  streamMiddleware = async (stream: DecoratedReadableStream) => stream,
400
400
  tdfSpecVersion,
401
- wrappingKeyAlgorithm = 'rsa:2048',
401
+ wrappingKeyAlgorithm,
402
402
  } = opts;
403
403
  const scope = opts.scope ?? { attributes: [], dissem: [] };
404
404
 
@@ -462,7 +462,6 @@ export class Client {
462
462
  ? maxByteLimit
463
463
  : opts.byteLimit;
464
464
  const encryptionInformation = new SplitKey(new AesGcmCipher(this.cryptoService));
465
- // TODO KAS: check here
466
465
  const splits: SplitStep[] = splitPlan?.length
467
466
  ? splitPlan
468
467
  : [{ kas: opts.defaultKASEndpoint ?? this.kasEndpoint }];
package/tdf3/src/tdf.ts CHANGED
@@ -199,7 +199,7 @@ export async function fetchKasPublicKey(
199
199
  kas: string,
200
200
  algorithm?: KasPublicKeyAlgorithm
201
201
  ): Promise<KasPublicKeyInfo> {
202
- return fetchKasPubKeyV2(kas, algorithm || 'rsa:2048');
202
+ return fetchKasPubKeyV2(kas, algorithm);
203
203
  }
204
204
 
205
205
  export async function extractPemFromKeyString(