@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.
- package/dist/lib/actor-CFYb2LZx.mjs +8929 -0
- package/dist/lib/encrypted_maps.es.js +121 -35
- package/dist/lib/index.es.js +3737 -18
- package/dist/lib/key_manager.es.js +2 -2
- 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 +16 -17
- package/dist/lib/actor-4fotMNaR.mjs +0 -5718
- package/dist/lib/index-BUXhtQhx.mjs +0 -3932
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { A as
|
|
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
|
|
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
|
|
22
|
-
function
|
|
23
|
-
return
|
|
22
|
+
let _;
|
|
23
|
+
function p() {
|
|
24
|
+
return _ || (_ = h("keyval-store", "keyval")), _;
|
|
24
25
|
}
|
|
25
|
-
function k(r, e =
|
|
26
|
+
function k(r, e = p()) {
|
|
26
27
|
return e("readonly", (t) => y(t.get(r)));
|
|
27
28
|
}
|
|
28
|
-
function E(r, e, t =
|
|
29
|
+
function E(r, e, t = p()) {
|
|
29
30
|
return t("readwrite", (n) => (n.put(e, r), y(n.transaction)));
|
|
30
31
|
}
|
|
31
|
-
|
|
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
|
-
}),
|
|
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
|
|
166
|
+
class R {
|
|
129
167
|
actor;
|
|
130
168
|
constructor(e, t) {
|
|
131
|
-
this.actor =
|
|
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
|
|
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
|
|
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([
|
|
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),
|
|
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),
|
|
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 =
|
|
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),
|
|
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 =
|
|
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
|
|
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
|
|
639
|
-
|
|
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
|
-
|
|
649
|
-
|
|
732
|
+
R as DefaultEncryptedMapsClient,
|
|
733
|
+
O as EncryptedMaps,
|
|
734
|
+
K as InMemoryDerivedKeyMaterialCache,
|
|
735
|
+
C as IndexedDbDerivedKeyMaterialCache
|
|
650
736
|
};
|