@icp-sdk/vetkeys 0.5.0-beta.0 → 0.5.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.
- package/dist/lib/{actor-4fotMNaR.mjs → actor-CrGCNm9W.mjs} +831 -830
- package/dist/lib/encrypted_maps.es.js +120 -35
- package/dist/lib/key_manager.es.js +1 -1
- package/dist/types/encrypted_maps/cache.d.ts +95 -0
- package/dist/types/encrypted_maps/cache.test.d.ts +1 -0
- package/dist/types/encrypted_maps/index.d.ts +53 -1
- package/package.json +3 -4
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import { T as
|
|
2
|
-
import { A as
|
|
1
|
+
import { T as v, E as f, D as g, a as m } from "./index-BUXhtQhx.mjs";
|
|
2
|
+
import { A as w } from "./actor-CrGCNm9W.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
|
|
8
|
+
function h(r, e) {
|
|
9
9
|
let t;
|
|
10
10
|
const n = () => {
|
|
11
11
|
if (t)
|
|
@@ -18,17 +18,54 @@ function w(r, e) {
|
|
|
18
18
|
};
|
|
19
19
|
return (a, i) => n().then((s) => i(s.transaction(e, a).objectStore(e)));
|
|
20
20
|
}
|
|
21
|
-
let
|
|
22
|
-
function
|
|
23
|
-
return
|
|
21
|
+
let _;
|
|
22
|
+
function p() {
|
|
23
|
+
return _ || (_ = h("keyval-store", "keyval")), _;
|
|
24
24
|
}
|
|
25
|
-
function k(r, e =
|
|
25
|
+
function k(r, e = p()) {
|
|
26
26
|
return e("readonly", (t) => y(t.get(r)));
|
|
27
27
|
}
|
|
28
|
-
function E(r, e, t =
|
|
28
|
+
function E(r, e, t = p()) {
|
|
29
29
|
return t("readwrite", (n) => (n.put(e, r), y(n.transaction)));
|
|
30
30
|
}
|
|
31
|
-
|
|
31
|
+
function V(r = p()) {
|
|
32
|
+
return r("readwrite", (e) => (e.clear(), y(e.transaction)));
|
|
33
|
+
}
|
|
34
|
+
class K {
|
|
35
|
+
#e = /* @__PURE__ */ new Map();
|
|
36
|
+
get(e) {
|
|
37
|
+
return Promise.resolve(this.#e.get(e));
|
|
38
|
+
}
|
|
39
|
+
set(e, t) {
|
|
40
|
+
return this.#e.set(e, t), Promise.resolve();
|
|
41
|
+
}
|
|
42
|
+
clear() {
|
|
43
|
+
return this.#e.clear(), Promise.resolve();
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
class C {
|
|
47
|
+
#e;
|
|
48
|
+
/**
|
|
49
|
+
* @param dbName - IndexedDB database name. Defaults to `"ic-vetkeys"`. This
|
|
50
|
+
* is the isolation knob: give each identity its own database name (e.g.
|
|
51
|
+
* `` `vetkeys-${principal}` ``) so one identity's persisted keys are never
|
|
52
|
+
* served to another. The object store name is fixed, because `idb-keyval`
|
|
53
|
+
* supports only a single object store per database.
|
|
54
|
+
*/
|
|
55
|
+
constructor(e = "ic-vetkeys") {
|
|
56
|
+
this.#e = h(e, "derived-key-material");
|
|
57
|
+
}
|
|
58
|
+
async get(e) {
|
|
59
|
+
return k(e, this.#e);
|
|
60
|
+
}
|
|
61
|
+
async set(e, t) {
|
|
62
|
+
await E(e, t, this.#e);
|
|
63
|
+
}
|
|
64
|
+
async clear() {
|
|
65
|
+
await V(this.#e);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
const A = ({ IDL: r }) => {
|
|
32
69
|
const e = r.Record({ inner: r.Vec(r.Nat8) }), t = r.Variant({
|
|
33
70
|
Read: r.Null,
|
|
34
71
|
ReadWrite: r.Null,
|
|
@@ -47,7 +84,7 @@ const V = ({ IDL: r }) => {
|
|
|
47
84
|
}), o = r.Variant({
|
|
48
85
|
Ok: r.Opt(t),
|
|
49
86
|
Err: r.Text
|
|
50
|
-
}),
|
|
87
|
+
}), u = r.Variant({ Ok: r.Vec(e), Err: r.Text });
|
|
51
88
|
return r.Service({
|
|
52
89
|
get_accessible_shared_map_names: r.Func(
|
|
53
90
|
[],
|
|
@@ -112,7 +149,7 @@ const V = ({ IDL: r }) => {
|
|
|
112
149
|
[a],
|
|
113
150
|
[]
|
|
114
151
|
),
|
|
115
|
-
remove_map_values: r.Func([r.Principal, e], [
|
|
152
|
+
remove_map_values: r.Func([r.Principal, e], [u], []),
|
|
116
153
|
remove_user: r.Func(
|
|
117
154
|
[r.Principal, e, r.Principal],
|
|
118
155
|
[o],
|
|
@@ -125,10 +162,10 @@ const V = ({ IDL: r }) => {
|
|
|
125
162
|
)
|
|
126
163
|
});
|
|
127
164
|
};
|
|
128
|
-
class
|
|
165
|
+
class R {
|
|
129
166
|
actor;
|
|
130
167
|
constructor(e, t) {
|
|
131
|
-
this.actor =
|
|
168
|
+
this.actor = w.createActor(A, {
|
|
132
169
|
agent: e,
|
|
133
170
|
canisterId: t
|
|
134
171
|
});
|
|
@@ -184,7 +221,7 @@ class U {
|
|
|
184
221
|
return this.actor.remove_user(e, t, n);
|
|
185
222
|
}
|
|
186
223
|
}
|
|
187
|
-
class
|
|
224
|
+
class O {
|
|
188
225
|
/**
|
|
189
226
|
* The client instance for interacting with the EncryptedMaps canister.
|
|
190
227
|
*/
|
|
@@ -193,18 +230,44 @@ class F {
|
|
|
193
230
|
* The cached verification key for validating encrypted VetKeys.
|
|
194
231
|
*/
|
|
195
232
|
verificationKey = void 0;
|
|
233
|
+
/**
|
|
234
|
+
* Cache backing the per-map derived key material handles.
|
|
235
|
+
*/
|
|
236
|
+
#e;
|
|
196
237
|
/**
|
|
197
238
|
* Creates a new instance of the EncryptedMaps client.
|
|
198
239
|
*
|
|
240
|
+
* @param canisterClient - The client used to talk to the EncryptedMaps canister.
|
|
241
|
+
* @param options - Optional configuration.
|
|
242
|
+
* @param options.cache - Strategy for caching derived key material. Defaults to
|
|
243
|
+
* {@link InMemoryDerivedKeyMaterialCache} (in-memory only, never persisted).
|
|
244
|
+
* Pass {@link IndexedDbDerivedKeyMaterialCache} to persist across page reloads —
|
|
245
|
+
* see the security note in the class description.
|
|
246
|
+
*
|
|
199
247
|
* @example
|
|
200
248
|
* ```ts
|
|
201
249
|
* import { EncryptedMaps } from "@icp-sdk/vetkeys/encrypted_maps";
|
|
202
250
|
*
|
|
203
251
|
* const encryptedMaps = new EncryptedMaps(encryptedMapsClientInstance);
|
|
204
252
|
* ```
|
|
253
|
+
*
|
|
254
|
+
* @example Opt into persistent caching, namespaced per identity
|
|
255
|
+
* ```ts
|
|
256
|
+
* import {
|
|
257
|
+
* EncryptedMaps,
|
|
258
|
+
* IndexedDbDerivedKeyMaterialCache,
|
|
259
|
+
* } from "@icp-sdk/vetkeys/encrypted_maps";
|
|
260
|
+
*
|
|
261
|
+
* const encryptedMaps = new EncryptedMaps(encryptedMapsClientInstance, {
|
|
262
|
+
* // Namespace the store per identity so one identity's cached keys are
|
|
263
|
+
* // never served to another on the same origin.
|
|
264
|
+
* cache: new IndexedDbDerivedKeyMaterialCache(`vetkeys-${myPrincipal}`),
|
|
265
|
+
* });
|
|
266
|
+
* // Remember to call encryptedMaps.clearCache() on logout / identity change.
|
|
267
|
+
* ```
|
|
205
268
|
*/
|
|
206
|
-
constructor(e) {
|
|
207
|
-
this.canisterClient = e;
|
|
269
|
+
constructor(e, t) {
|
|
270
|
+
this.canisterClient = e, this.#e = t?.cache ?? new K();
|
|
208
271
|
}
|
|
209
272
|
/**
|
|
210
273
|
* Retrieves a list of maps that were shared with the user and the user still has access to.
|
|
@@ -240,13 +303,13 @@ class F {
|
|
|
240
303
|
for (const [n, a] of e) {
|
|
241
304
|
const i = Uint8Array.from(n[1].inner), s = [];
|
|
242
305
|
for (const [l, o] of a) {
|
|
243
|
-
const
|
|
306
|
+
const u = Uint8Array.from(l.inner), d = await this.decryptFor(
|
|
244
307
|
n[0],
|
|
245
308
|
i,
|
|
246
|
-
|
|
309
|
+
u,
|
|
247
310
|
Uint8Array.from(o.inner)
|
|
248
311
|
);
|
|
249
|
-
s.push([
|
|
312
|
+
s.push([u, d]);
|
|
250
313
|
}
|
|
251
314
|
t.push([
|
|
252
315
|
[n[0], Uint8Array.from(n[1].inner)],
|
|
@@ -268,13 +331,13 @@ class F {
|
|
|
268
331
|
s,
|
|
269
332
|
l
|
|
270
333
|
] of n.keyvals) {
|
|
271
|
-
const o = Uint8Array.from(s.inner),
|
|
334
|
+
const o = Uint8Array.from(s.inner), u = await this.decryptFor(
|
|
272
335
|
n.map_owner,
|
|
273
336
|
a,
|
|
274
337
|
o,
|
|
275
338
|
Uint8Array.from(l.inner)
|
|
276
339
|
);
|
|
277
|
-
i.push([o,
|
|
340
|
+
i.push([o, u]);
|
|
278
341
|
}
|
|
279
342
|
t.push({
|
|
280
343
|
accessControl: n.access_control,
|
|
@@ -342,13 +405,13 @@ class F {
|
|
|
342
405
|
]);
|
|
343
406
|
const i = new Array();
|
|
344
407
|
for (const [s, l] of n.Ok) {
|
|
345
|
-
const o = Uint8Array.from(s.inner),
|
|
408
|
+
const o = Uint8Array.from(s.inner), u = await this.decryptFor(
|
|
346
409
|
e,
|
|
347
410
|
t,
|
|
348
411
|
o,
|
|
349
412
|
Uint8Array.from(l.inner)
|
|
350
413
|
);
|
|
351
|
-
i.push([o,
|
|
414
|
+
i.push([o, u]);
|
|
352
415
|
}
|
|
353
416
|
return i;
|
|
354
417
|
}
|
|
@@ -567,7 +630,7 @@ class F {
|
|
|
567
630
|
* @throws Error if the operation fails
|
|
568
631
|
*/
|
|
569
632
|
async getDerivedKeyMaterial(e, t) {
|
|
570
|
-
const n =
|
|
633
|
+
const n = v.random(), a = await this.canisterClient.get_encrypted_vetkey(
|
|
571
634
|
e,
|
|
572
635
|
c(t),
|
|
573
636
|
c(n.publicKeyBytes())
|
|
@@ -579,10 +642,10 @@ class F {
|
|
|
579
642
|
e.toUint8Array().length,
|
|
580
643
|
...e.toUint8Array(),
|
|
581
644
|
...t
|
|
582
|
-
]), o = f.deserialize(i),
|
|
645
|
+
]), o = f.deserialize(i), u = g.deserialize(s);
|
|
583
646
|
return await o.decryptAndVerify(
|
|
584
647
|
n,
|
|
585
|
-
|
|
648
|
+
u,
|
|
586
649
|
l
|
|
587
650
|
).asDerivedKeyMaterial();
|
|
588
651
|
}
|
|
@@ -623,28 +686,50 @@ class F {
|
|
|
623
686
|
* @returns Promise resolving to the derived key material
|
|
624
687
|
*/
|
|
625
688
|
async getDerivedKeyMaterialOrFetchIfNeeded(e, t) {
|
|
626
|
-
const n =
|
|
627
|
-
e.toString(),
|
|
628
|
-
n
|
|
629
|
-
]);
|
|
689
|
+
const n = M(e, t), a = await this.#e.get(n);
|
|
630
690
|
if (a)
|
|
631
|
-
return await
|
|
691
|
+
return await m.fromCryptoKey(
|
|
632
692
|
a
|
|
633
693
|
);
|
|
634
694
|
const i = await this.getDerivedKeyMaterial(
|
|
635
695
|
e,
|
|
636
696
|
t
|
|
637
697
|
);
|
|
638
|
-
return await
|
|
639
|
-
|
|
698
|
+
return await this.#e.set(
|
|
699
|
+
n,
|
|
640
700
|
i.getCryptoKey()
|
|
641
701
|
), i;
|
|
642
702
|
}
|
|
703
|
+
/**
|
|
704
|
+
* Clears all cached derived key material.
|
|
705
|
+
*
|
|
706
|
+
* Strongly recommended on logout or whenever the authenticated identity
|
|
707
|
+
* changes: the cache belongs to a single identity, so clearing it (or
|
|
708
|
+
* discarding the `EncryptedMaps` instance) prevents one identity's key
|
|
709
|
+
* material from being served to another, and drops the still-usable
|
|
710
|
+
* decryption capability that otherwise lingers. This matters most with
|
|
711
|
+
* {@link IndexedDbDerivedKeyMaterialCache}, where cached key handles persist
|
|
712
|
+
* across sessions until cleared.
|
|
713
|
+
*/
|
|
714
|
+
async clearCache() {
|
|
715
|
+
await this.#e.clear();
|
|
716
|
+
}
|
|
717
|
+
}
|
|
718
|
+
function M(r, e) {
|
|
719
|
+
return `${r.toString()}|${F(e)}`;
|
|
720
|
+
}
|
|
721
|
+
function F(r) {
|
|
722
|
+
let e = "";
|
|
723
|
+
for (const t of r)
|
|
724
|
+
e += t.toString(16).padStart(2, "0");
|
|
725
|
+
return e;
|
|
643
726
|
}
|
|
644
727
|
function c(r) {
|
|
645
728
|
return { inner: r };
|
|
646
729
|
}
|
|
647
730
|
export {
|
|
648
|
-
|
|
649
|
-
|
|
731
|
+
R as DefaultEncryptedMapsClient,
|
|
732
|
+
O as EncryptedMaps,
|
|
733
|
+
K as InMemoryDerivedKeyMaterialCache,
|
|
734
|
+
C as IndexedDbDerivedKeyMaterialCache
|
|
650
735
|
};
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { T as u, D as _, E as l } from "./index-BUXhtQhx.mjs";
|
|
2
|
-
import { A as h } from "./actor-
|
|
2
|
+
import { A as h } from "./actor-CrGCNm9W.mjs";
|
|
3
3
|
const g = ({ IDL: e }) => {
|
|
4
4
|
const r = e.Record({ inner: e.Vec(e.Nat8) }), t = e.Variant({ Ok: r, Err: e.Text }), s = e.Variant({
|
|
5
5
|
Read: e.Null,
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module @icp-sdk/vetkeys/encrypted_maps
|
|
3
|
+
*
|
|
4
|
+
* @description Caching strategies for derived key material. See
|
|
5
|
+
* {@link DerivedKeyMaterialCache}.
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* Strategy for caching the per-map derived key material handles used by
|
|
9
|
+
* {@link EncryptedMaps}.
|
|
10
|
+
*
|
|
11
|
+
* Deriving key material requires a canister round-trip and threshold
|
|
12
|
+
* cryptography, so it is cached and reused. The cached value is a
|
|
13
|
+
* non-extractable {@link CryptoKey} handle: its raw bytes can never be read
|
|
14
|
+
* back (`crypto.subtle.exportKey` throws), but the handle can still be *used*
|
|
15
|
+
* to decrypt. Where that handle lives therefore matters for security — see the
|
|
16
|
+
* provided implementations.
|
|
17
|
+
*
|
|
18
|
+
* Cache entries are keyed by an opaque string derived from the map owner and
|
|
19
|
+
* map name. Derived key material is per map, not per caller, so the key does
|
|
20
|
+
* not encode the identity. Isolating one identity's cached keys from another's
|
|
21
|
+
* on the same origin is therefore a property of the cache instance: use a fresh
|
|
22
|
+
* cache per identity (the in-memory default is naturally per-instance), or give
|
|
23
|
+
* a persistent cache a per-identity namespace (see
|
|
24
|
+
* {@link IndexedDbDerivedKeyMaterialCache}).
|
|
25
|
+
*/
|
|
26
|
+
export interface DerivedKeyMaterialCache {
|
|
27
|
+
/**
|
|
28
|
+
* Returns the cached key handle for the given key, or `undefined` on a miss.
|
|
29
|
+
*/
|
|
30
|
+
get(key: string): Promise<CryptoKey | undefined>;
|
|
31
|
+
/**
|
|
32
|
+
* Stores a key handle under the given key.
|
|
33
|
+
*/
|
|
34
|
+
set(key: string, value: CryptoKey): Promise<void>;
|
|
35
|
+
/**
|
|
36
|
+
* Removes every cached key handle.
|
|
37
|
+
*
|
|
38
|
+
* Call this on logout or whenever the authenticated identity changes to
|
|
39
|
+
* avoid leaving usable decryption capability behind.
|
|
40
|
+
*/
|
|
41
|
+
clear(): Promise<void>;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Default {@link DerivedKeyMaterialCache} that keeps key handles in memory only.
|
|
45
|
+
*
|
|
46
|
+
* Nothing is written to disk, so the cache is discarded when the page is
|
|
47
|
+
* reloaded or the tab is closed and there is no at-rest exposure. The trade-off
|
|
48
|
+
* is one extra key derivation per map per page load.
|
|
49
|
+
*/
|
|
50
|
+
export declare class InMemoryDerivedKeyMaterialCache implements DerivedKeyMaterialCache {
|
|
51
|
+
#private;
|
|
52
|
+
get(key: string): Promise<CryptoKey | undefined>;
|
|
53
|
+
set(key: string, value: CryptoKey): Promise<void>;
|
|
54
|
+
clear(): Promise<void>;
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Opt-in {@link DerivedKeyMaterialCache} that persists key handles in IndexedDB.
|
|
58
|
+
*
|
|
59
|
+
* Key handles survive page reloads, avoiding repeated key derivation, but this
|
|
60
|
+
* is a deliberate security trade-off: the persisted handle is non-extractable
|
|
61
|
+
* (its raw bytes cannot be stolen), yet any same-origin code — e.g. via XSS, a
|
|
62
|
+
* malicious extension, or a shared browser profile — can read the handle and
|
|
63
|
+
* use it to decrypt the user's data without an authenticated session, for as
|
|
64
|
+
* long as it remains stored.
|
|
65
|
+
*
|
|
66
|
+
* Prefer {@link InMemoryDerivedKeyMaterialCache} (the default) unless you need
|
|
67
|
+
* cross-reload persistence and accept this exposure. When using this cache, be
|
|
68
|
+
* sure to call {@link EncryptedMaps.clearCache} on logout or identity change.
|
|
69
|
+
*
|
|
70
|
+
* Because the cache key does not encode the identity, **give the store a
|
|
71
|
+
* per-identity namespace** to keep one identity's persisted keys from being
|
|
72
|
+
* served to another on the same origin — e.g. include the caller's principal in
|
|
73
|
+
* the database name:
|
|
74
|
+
*
|
|
75
|
+
* ```ts
|
|
76
|
+
* new IndexedDbDerivedKeyMaterialCache(`vetkeys-${principal}`);
|
|
77
|
+
* ```
|
|
78
|
+
*
|
|
79
|
+
* A dedicated IndexedDB store is used, so {@link clear} only removes entries
|
|
80
|
+
* written by this cache and never touches other application data.
|
|
81
|
+
*/
|
|
82
|
+
export declare class IndexedDbDerivedKeyMaterialCache implements DerivedKeyMaterialCache {
|
|
83
|
+
#private;
|
|
84
|
+
/**
|
|
85
|
+
* @param dbName - IndexedDB database name. Defaults to `"ic-vetkeys"`. This
|
|
86
|
+
* is the isolation knob: give each identity its own database name (e.g.
|
|
87
|
+
* `` `vetkeys-${principal}` ``) so one identity's persisted keys are never
|
|
88
|
+
* served to another. The object store name is fixed, because `idb-keyval`
|
|
89
|
+
* supports only a single object store per database.
|
|
90
|
+
*/
|
|
91
|
+
constructor(dbName?: string);
|
|
92
|
+
get(key: string): Promise<CryptoKey | undefined>;
|
|
93
|
+
set(key: string, value: CryptoKey): Promise<void>;
|
|
94
|
+
clear(): Promise<void>;
|
|
95
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import { Principal } from '@icp-sdk/core/principal';
|
|
2
2
|
import { DerivedKeyMaterial } from '../utils/utils';
|
|
3
|
+
import { DerivedKeyMaterialCache } from './cache';
|
|
3
4
|
import { AccessRights, ByteBuf } from '../declarations/ic_vetkeys_manager_canister/ic_vetkeys_manager_canister.did.js';
|
|
4
5
|
export { DefaultEncryptedMapsClient } from './encrypted_maps_canister';
|
|
6
|
+
export { type DerivedKeyMaterialCache, InMemoryDerivedKeyMaterialCache, IndexedDbDerivedKeyMaterialCache, } from './cache';
|
|
5
7
|
export type { AccessRights, ByteBuf, } from '../declarations/ic_vetkeys_manager_canister/ic_vetkeys_manager_canister.did.js';
|
|
6
8
|
/**
|
|
7
9
|
* The **EncryptedMaps** frontend library facilitates interaction with an [**EncryptedMaps-enabled canister**](https://docs.rs/ic-vetkeys/latest/ic_vetkeys/encrypted_maps/struct.EncryptedMaps.html) on the **Internet Computer (ICP)**.
|
|
@@ -19,9 +21,23 @@ export type { AccessRights, ByteBuf, } from '../declarations/ic_vetkeys_manager_
|
|
|
19
21
|
*
|
|
20
22
|
* - **Access Rights** should be carefully managed to prevent unauthorized access.
|
|
21
23
|
* - VetKeys should be decrypted **only in trusted environments** such as user browsers to prevent leaks.
|
|
24
|
+
* - Derived key material is cached **in memory by default** ({@link InMemoryDerivedKeyMaterialCache}),
|
|
25
|
+
* so it never touches disk and is discarded on page reload. Persisting it across
|
|
26
|
+
* reloads with {@link IndexedDbDerivedKeyMaterialCache} is an explicit, opt-in trade-off:
|
|
27
|
+
* the persisted handle is non-extractable, but any same-origin code can use it to decrypt
|
|
28
|
+
* without an authenticated session for as long as it is stored.
|
|
29
|
+
* - The cache belongs to a single authenticated identity. Identity lifecycle is the
|
|
30
|
+
* caller's responsibility, so to avoid serving one identity's key material to another
|
|
31
|
+
* on the same origin:
|
|
32
|
+
* - with the in-memory default, use a **fresh `EncryptedMaps` instance per identity**
|
|
33
|
+
* (or call {@link EncryptedMaps.clearCache} on logout / identity change);
|
|
34
|
+
* - with {@link IndexedDbDerivedKeyMaterialCache}, give the store a **per-identity
|
|
35
|
+
* namespace** (e.g. include the caller's principal in the database name) so entries
|
|
36
|
+
* are physically separated, and call {@link EncryptedMaps.clearCache} on logout.
|
|
22
37
|
*
|
|
23
38
|
*/
|
|
24
39
|
export declare class EncryptedMaps {
|
|
40
|
+
#private;
|
|
25
41
|
/**
|
|
26
42
|
* The client instance for interacting with the EncryptedMaps canister.
|
|
27
43
|
*/
|
|
@@ -33,14 +49,38 @@ export declare class EncryptedMaps {
|
|
|
33
49
|
/**
|
|
34
50
|
* Creates a new instance of the EncryptedMaps client.
|
|
35
51
|
*
|
|
52
|
+
* @param canisterClient - The client used to talk to the EncryptedMaps canister.
|
|
53
|
+
* @param options - Optional configuration.
|
|
54
|
+
* @param options.cache - Strategy for caching derived key material. Defaults to
|
|
55
|
+
* {@link InMemoryDerivedKeyMaterialCache} (in-memory only, never persisted).
|
|
56
|
+
* Pass {@link IndexedDbDerivedKeyMaterialCache} to persist across page reloads —
|
|
57
|
+
* see the security note in the class description.
|
|
58
|
+
*
|
|
36
59
|
* @example
|
|
37
60
|
* ```ts
|
|
38
61
|
* import { EncryptedMaps } from "@icp-sdk/vetkeys/encrypted_maps";
|
|
39
62
|
*
|
|
40
63
|
* const encryptedMaps = new EncryptedMaps(encryptedMapsClientInstance);
|
|
41
64
|
* ```
|
|
65
|
+
*
|
|
66
|
+
* @example Opt into persistent caching, namespaced per identity
|
|
67
|
+
* ```ts
|
|
68
|
+
* import {
|
|
69
|
+
* EncryptedMaps,
|
|
70
|
+
* IndexedDbDerivedKeyMaterialCache,
|
|
71
|
+
* } from "@icp-sdk/vetkeys/encrypted_maps";
|
|
72
|
+
*
|
|
73
|
+
* const encryptedMaps = new EncryptedMaps(encryptedMapsClientInstance, {
|
|
74
|
+
* // Namespace the store per identity so one identity's cached keys are
|
|
75
|
+
* // never served to another on the same origin.
|
|
76
|
+
* cache: new IndexedDbDerivedKeyMaterialCache(`vetkeys-${myPrincipal}`),
|
|
77
|
+
* });
|
|
78
|
+
* // Remember to call encryptedMaps.clearCache() on logout / identity change.
|
|
79
|
+
* ```
|
|
42
80
|
*/
|
|
43
|
-
constructor(canisterClient: EncryptedMapsClient
|
|
81
|
+
constructor(canisterClient: EncryptedMapsClient, options?: {
|
|
82
|
+
cache?: DerivedKeyMaterialCache;
|
|
83
|
+
});
|
|
44
84
|
/**
|
|
45
85
|
* Retrieves a list of maps that were shared with the user and the user still has access to.
|
|
46
86
|
*
|
|
@@ -255,6 +295,18 @@ export declare class EncryptedMaps {
|
|
|
255
295
|
* @returns Promise resolving to the derived key material
|
|
256
296
|
*/
|
|
257
297
|
getDerivedKeyMaterialOrFetchIfNeeded(mapOwner: Principal, mapName: Uint8Array): Promise<DerivedKeyMaterial>;
|
|
298
|
+
/**
|
|
299
|
+
* Clears all cached derived key material.
|
|
300
|
+
*
|
|
301
|
+
* Strongly recommended on logout or whenever the authenticated identity
|
|
302
|
+
* changes: the cache belongs to a single identity, so clearing it (or
|
|
303
|
+
* discarding the `EncryptedMaps` instance) prevents one identity's key
|
|
304
|
+
* material from being served to another, and drops the still-usable
|
|
305
|
+
* decryption capability that otherwise lingers. This matters most with
|
|
306
|
+
* {@link IndexedDbDerivedKeyMaterialCache}, where cached key handles persist
|
|
307
|
+
* across sessions until cleared.
|
|
308
|
+
*/
|
|
309
|
+
clearCache(): Promise<void>;
|
|
258
310
|
}
|
|
259
311
|
/**
|
|
260
312
|
* Interface for map data structure.
|
package/package.json
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@icp-sdk/vetkeys",
|
|
3
|
-
"version": "0.5.0
|
|
4
|
-
"packageManager": "pnpm@10.10.0",
|
|
3
|
+
"version": "0.5.0",
|
|
5
4
|
"author": "DFINITY Stiftung",
|
|
6
5
|
"description": "JavaScript and TypeScript library to use Internet Computer vetKeys",
|
|
7
6
|
"homepage": "https://internetcomputer.org/docs/building-apps/network-features/vetkeys/introduction",
|
|
@@ -58,7 +57,7 @@
|
|
|
58
57
|
"module": "dist/lib/index.es.js",
|
|
59
58
|
"typings": "dist/types/index.d.ts",
|
|
60
59
|
"dependencies": {
|
|
61
|
-
"@icp-sdk/core": "^5.
|
|
60
|
+
"@icp-sdk/core": "^5.4.0",
|
|
62
61
|
"idb-keyval": "^6.2.1"
|
|
63
62
|
},
|
|
64
63
|
"devDependencies": {
|
|
@@ -77,7 +76,7 @@
|
|
|
77
76
|
"typescript-eslint": "^8.59.0",
|
|
78
77
|
"vite": "^7.0.8",
|
|
79
78
|
"vite-plugin-dts": "^4.5.3",
|
|
80
|
-
"vitest": "^3.
|
|
79
|
+
"vitest": "^3.2.6"
|
|
81
80
|
},
|
|
82
81
|
"scripts": {
|
|
83
82
|
"build": "tsc && vite build",
|