@icp-sdk/vetkeys 0.5.0-beta.0 → 0.6.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,11 +1,11 @@
1
- import { T as h, E as f, D as g, a as v } from "./index-BUXhtQhx.mjs";
2
- import { A as m } from "./actor-4fotMNaR.mjs";
1
+ import { TransportSecretKey as v, EncryptedVetKey as f, DerivedPublicKey as g, DerivedKeyMaterial as m } from "./index.es.js";
2
+ import { A as w } from "./actor-CFYb2LZx.mjs";
3
3
  function y(r) {
4
4
  return new Promise((e, t) => {
5
5
  r.oncomplete = r.onsuccess = () => e(r.result), r.onabort = r.onerror = () => t(r.error);
6
6
  });
7
7
  }
8
- function w(r, e) {
8
+ function h(r, e) {
9
9
  let t;
10
10
  const n = () => {
11
11
  if (t)
@@ -14,21 +14,59 @@ function w(r, e) {
14
14
  return a.onupgradeneeded = () => a.result.createObjectStore(e), t = y(a), t.then((i) => {
15
15
  i.onclose = () => t = void 0;
16
16
  }, () => {
17
+ t = void 0;
17
18
  }), t;
18
19
  };
19
20
  return (a, i) => n().then((s) => i(s.transaction(e, a).objectStore(e)));
20
21
  }
21
- let u;
22
- function d() {
23
- return u || (u = w("keyval-store", "keyval")), u;
22
+ let _;
23
+ function p() {
24
+ return _ || (_ = h("keyval-store", "keyval")), _;
24
25
  }
25
- function k(r, e = d()) {
26
+ function k(r, e = p()) {
26
27
  return e("readonly", (t) => y(t.get(r)));
27
28
  }
28
- function E(r, e, t = d()) {
29
+ function E(r, e, t = p()) {
29
30
  return t("readwrite", (n) => (n.put(e, r), y(n.transaction)));
30
31
  }
31
- const V = ({ IDL: r }) => {
32
+ function V(r = p()) {
33
+ return r("readwrite", (e) => (e.clear(), y(e.transaction)));
34
+ }
35
+ class K {
36
+ #e = /* @__PURE__ */ new Map();
37
+ get(e) {
38
+ return Promise.resolve(this.#e.get(e));
39
+ }
40
+ set(e, t) {
41
+ return this.#e.set(e, t), Promise.resolve();
42
+ }
43
+ clear() {
44
+ return this.#e.clear(), Promise.resolve();
45
+ }
46
+ }
47
+ class C {
48
+ #e;
49
+ /**
50
+ * @param dbName - IndexedDB database name. Defaults to `"ic-vetkeys"`. This
51
+ * is the isolation knob: give each identity its own database name (e.g.
52
+ * `` `vetkeys-${principal}` ``) so one identity's persisted keys are never
53
+ * served to another. The object store name is fixed, because `idb-keyval`
54
+ * supports only a single object store per database.
55
+ */
56
+ constructor(e = "ic-vetkeys") {
57
+ this.#e = h(e, "derived-key-material");
58
+ }
59
+ async get(e) {
60
+ return k(e, this.#e);
61
+ }
62
+ async set(e, t) {
63
+ await E(e, t, this.#e);
64
+ }
65
+ async clear() {
66
+ await V(this.#e);
67
+ }
68
+ }
69
+ const A = ({ IDL: r }) => {
32
70
  const e = r.Record({ inner: r.Vec(r.Nat8) }), t = r.Variant({
33
71
  Read: r.Null,
34
72
  ReadWrite: r.Null,
@@ -47,7 +85,7 @@ const V = ({ IDL: r }) => {
47
85
  }), o = r.Variant({
48
86
  Ok: r.Opt(t),
49
87
  Err: r.Text
50
- }), _ = r.Variant({ Ok: r.Vec(e), Err: r.Text });
88
+ }), u = r.Variant({ Ok: r.Vec(e), Err: r.Text });
51
89
  return r.Service({
52
90
  get_accessible_shared_map_names: r.Func(
53
91
  [],
@@ -112,7 +150,7 @@ const V = ({ IDL: r }) => {
112
150
  [a],
113
151
  []
114
152
  ),
115
- remove_map_values: r.Func([r.Principal, e], [_], []),
153
+ remove_map_values: r.Func([r.Principal, e], [u], []),
116
154
  remove_user: r.Func(
117
155
  [r.Principal, e, r.Principal],
118
156
  [o],
@@ -125,10 +163,10 @@ const V = ({ IDL: r }) => {
125
163
  )
126
164
  });
127
165
  };
128
- class U {
166
+ class R {
129
167
  actor;
130
168
  constructor(e, t) {
131
- this.actor = m.createActor(V, {
169
+ this.actor = w.createActor(A, {
132
170
  agent: e,
133
171
  canisterId: t
134
172
  });
@@ -184,7 +222,7 @@ class U {
184
222
  return this.actor.remove_user(e, t, n);
185
223
  }
186
224
  }
187
- class F {
225
+ class O {
188
226
  /**
189
227
  * The client instance for interacting with the EncryptedMaps canister.
190
228
  */
@@ -193,18 +231,44 @@ class F {
193
231
  * The cached verification key for validating encrypted VetKeys.
194
232
  */
195
233
  verificationKey = void 0;
234
+ /**
235
+ * Cache backing the per-map derived key material handles.
236
+ */
237
+ #e;
196
238
  /**
197
239
  * Creates a new instance of the EncryptedMaps client.
198
240
  *
241
+ * @param canisterClient - The client used to talk to the EncryptedMaps canister.
242
+ * @param options - Optional configuration.
243
+ * @param options.cache - Strategy for caching derived key material. Defaults to
244
+ * {@link InMemoryDerivedKeyMaterialCache} (in-memory only, never persisted).
245
+ * Pass {@link IndexedDbDerivedKeyMaterialCache} to persist across page reloads —
246
+ * see the security note in the class description.
247
+ *
199
248
  * @example
200
249
  * ```ts
201
250
  * import { EncryptedMaps } from "@icp-sdk/vetkeys/encrypted_maps";
202
251
  *
203
252
  * const encryptedMaps = new EncryptedMaps(encryptedMapsClientInstance);
204
253
  * ```
254
+ *
255
+ * @example Opt into persistent caching, namespaced per identity
256
+ * ```ts
257
+ * import {
258
+ * EncryptedMaps,
259
+ * IndexedDbDerivedKeyMaterialCache,
260
+ * } from "@icp-sdk/vetkeys/encrypted_maps";
261
+ *
262
+ * const encryptedMaps = new EncryptedMaps(encryptedMapsClientInstance, {
263
+ * // Namespace the store per identity so one identity's cached keys are
264
+ * // never served to another on the same origin.
265
+ * cache: new IndexedDbDerivedKeyMaterialCache(`vetkeys-${myPrincipal}`),
266
+ * });
267
+ * // Remember to call encryptedMaps.clearCache() on logout / identity change.
268
+ * ```
205
269
  */
206
- constructor(e) {
207
- this.canisterClient = e;
270
+ constructor(e, t) {
271
+ this.canisterClient = e, this.#e = t?.cache ?? new K();
208
272
  }
209
273
  /**
210
274
  * Retrieves a list of maps that were shared with the user and the user still has access to.
@@ -240,13 +304,13 @@ class F {
240
304
  for (const [n, a] of e) {
241
305
  const i = Uint8Array.from(n[1].inner), s = [];
242
306
  for (const [l, o] of a) {
243
- const _ = Uint8Array.from(l.inner), p = await this.decryptFor(
307
+ const u = Uint8Array.from(l.inner), d = await this.decryptFor(
244
308
  n[0],
245
309
  i,
246
- _,
310
+ u,
247
311
  Uint8Array.from(o.inner)
248
312
  );
249
- s.push([_, p]);
313
+ s.push([u, d]);
250
314
  }
251
315
  t.push([
252
316
  [n[0], Uint8Array.from(n[1].inner)],
@@ -268,13 +332,13 @@ class F {
268
332
  s,
269
333
  l
270
334
  ] of n.keyvals) {
271
- const o = Uint8Array.from(s.inner), _ = await this.decryptFor(
335
+ const o = Uint8Array.from(s.inner), u = await this.decryptFor(
272
336
  n.map_owner,
273
337
  a,
274
338
  o,
275
339
  Uint8Array.from(l.inner)
276
340
  );
277
- i.push([o, _]);
341
+ i.push([o, u]);
278
342
  }
279
343
  t.push({
280
344
  accessControl: n.access_control,
@@ -342,13 +406,13 @@ class F {
342
406
  ]);
343
407
  const i = new Array();
344
408
  for (const [s, l] of n.Ok) {
345
- const o = Uint8Array.from(s.inner), _ = await this.decryptFor(
409
+ const o = Uint8Array.from(s.inner), u = await this.decryptFor(
346
410
  e,
347
411
  t,
348
412
  o,
349
413
  Uint8Array.from(l.inner)
350
414
  );
351
- i.push([o, _]);
415
+ i.push([o, u]);
352
416
  }
353
417
  return i;
354
418
  }
@@ -567,7 +631,7 @@ class F {
567
631
  * @throws Error if the operation fails
568
632
  */
569
633
  async getDerivedKeyMaterial(e, t) {
570
- const n = h.random(), a = await this.canisterClient.get_encrypted_vetkey(
634
+ const n = v.random(), a = await this.canisterClient.get_encrypted_vetkey(
571
635
  e,
572
636
  c(t),
573
637
  c(n.publicKeyBytes())
@@ -579,10 +643,10 @@ class F {
579
643
  e.toUint8Array().length,
580
644
  ...e.toUint8Array(),
581
645
  ...t
582
- ]), o = f.deserialize(i), _ = g.deserialize(s);
646
+ ]), o = f.deserialize(i), u = g.deserialize(s);
583
647
  return await o.decryptAndVerify(
584
648
  n,
585
- _,
649
+ u,
586
650
  l
587
651
  ).asDerivedKeyMaterial();
588
652
  }
@@ -623,28 +687,50 @@ class F {
623
687
  * @returns Promise resolving to the derived key material
624
688
  */
625
689
  async getDerivedKeyMaterialOrFetchIfNeeded(e, t) {
626
- const n = new Uint8Array(t), a = await k([
627
- e.toString(),
628
- n
629
- ]);
690
+ const n = M(e, t), a = await this.#e.get(n);
630
691
  if (a)
631
- return await v.fromCryptoKey(
692
+ return await m.fromCryptoKey(
632
693
  a
633
694
  );
634
695
  const i = await this.getDerivedKeyMaterial(
635
696
  e,
636
697
  t
637
698
  );
638
- return await E(
639
- [e.toString(), n],
699
+ return await this.#e.set(
700
+ n,
640
701
  i.getCryptoKey()
641
702
  ), i;
642
703
  }
704
+ /**
705
+ * Clears all cached derived key material.
706
+ *
707
+ * Strongly recommended on logout or whenever the authenticated identity
708
+ * changes: the cache belongs to a single identity, so clearing it (or
709
+ * discarding the `EncryptedMaps` instance) prevents one identity's key
710
+ * material from being served to another, and drops the still-usable
711
+ * decryption capability that otherwise lingers. This matters most with
712
+ * {@link IndexedDbDerivedKeyMaterialCache}, where cached key handles persist
713
+ * across sessions until cleared.
714
+ */
715
+ async clearCache() {
716
+ await this.#e.clear();
717
+ }
718
+ }
719
+ function M(r, e) {
720
+ return `${r.toString()}|${F(e)}`;
721
+ }
722
+ function F(r) {
723
+ let e = "";
724
+ for (const t of r)
725
+ e += t.toString(16).padStart(2, "0");
726
+ return e;
643
727
  }
644
728
  function c(r) {
645
729
  return { inner: r };
646
730
  }
647
731
  export {
648
- U as DefaultEncryptedMapsClient,
649
- F as EncryptedMaps
732
+ R as DefaultEncryptedMapsClient,
733
+ O as EncryptedMaps,
734
+ K as InMemoryDerivedKeyMaterialCache,
735
+ C as IndexedDbDerivedKeyMaterialCache
650
736
  };