@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,5 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { A as h } from "./actor-
|
|
1
|
+
import { TransportSecretKey as u, DerivedPublicKey as _, EncryptedVetKey as l } from "./index.es.js";
|
|
2
|
+
import { A as h } from "./actor-CFYb2LZx.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.
|
|
4
|
-
"packageManager": "pnpm@10.10.0",
|
|
3
|
+
"version": "0.6.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,26 +57,26 @@
|
|
|
58
57
|
"module": "dist/lib/index.es.js",
|
|
59
58
|
"typings": "dist/types/index.d.ts",
|
|
60
59
|
"dependencies": {
|
|
61
|
-
"@icp-sdk/core": "^
|
|
62
|
-
"idb-keyval": "^6.
|
|
60
|
+
"@icp-sdk/core": "^6.1.0",
|
|
61
|
+
"idb-keyval": "^6.3.0"
|
|
63
62
|
},
|
|
64
63
|
"devDependencies": {
|
|
64
|
+
"@eslint/js": "^9.39.5",
|
|
65
65
|
"@noble/curves": "^1.9.7",
|
|
66
66
|
"@noble/hashes": "^1.8.0",
|
|
67
|
-
"@
|
|
68
|
-
"@
|
|
69
|
-
"
|
|
70
|
-
"eslint": "^
|
|
71
|
-
"eslint-
|
|
72
|
-
"
|
|
73
|
-
"
|
|
74
|
-
"
|
|
75
|
-
"typedoc": "^0.28.3",
|
|
67
|
+
"@types/node": "^24.13.3",
|
|
68
|
+
"@vitest/coverage-v8": "^3.2.7",
|
|
69
|
+
"eslint": "^9.39.5",
|
|
70
|
+
"eslint-config-prettier": "^10.1.8",
|
|
71
|
+
"eslint-plugin-prettier": "^5.5.6",
|
|
72
|
+
"fake-indexeddb": "^6.2.5",
|
|
73
|
+
"prettier": "^3.9.6",
|
|
74
|
+
"typedoc": "^0.28.20",
|
|
76
75
|
"typescript": "^5.9.3",
|
|
77
|
-
"typescript-eslint": "^8.
|
|
78
|
-
"vite": "^7.
|
|
79
|
-
"vite-plugin-dts": "^4.5.
|
|
80
|
-
"vitest": "^3.
|
|
76
|
+
"typescript-eslint": "^8.68.0",
|
|
77
|
+
"vite": "^7.3.6",
|
|
78
|
+
"vite-plugin-dts": "^4.5.4",
|
|
79
|
+
"vitest": "^3.2.7"
|
|
81
80
|
},
|
|
82
81
|
"scripts": {
|
|
83
82
|
"build": "tsc && vite build",
|