@learncard/sss-key-manager 0.1.19 → 0.1.21

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.
Files changed (39) hide show
  1. package/dist/api-client.d.ts +49 -0
  2. package/dist/api-client.d.ts.map +1 -0
  3. package/dist/atomic-operations.d.ts +101 -0
  4. package/dist/atomic-operations.d.ts.map +1 -0
  5. package/dist/auth-coordinator.d.ts +10 -0
  6. package/dist/auth-coordinator.d.ts.map +1 -0
  7. package/dist/crypto.d.ts +31 -0
  8. package/dist/crypto.d.ts.map +1 -0
  9. package/dist/index.d.ts +26 -0
  10. package/dist/index.d.ts.map +1 -0
  11. package/dist/key-manager.d.ts +30 -0
  12. package/dist/key-manager.d.ts.map +1 -0
  13. package/dist/passkey.d.ts +23 -0
  14. package/dist/passkey.d.ts.map +1 -0
  15. package/dist/qr-crypto.d.ts +56 -0
  16. package/dist/qr-crypto.d.ts.map +1 -0
  17. package/dist/qr-login.d.ts +122 -0
  18. package/dist/qr-login.d.ts.map +1 -0
  19. package/dist/recovery-phrase.d.ts +14 -0
  20. package/dist/recovery-phrase.d.ts.map +1 -0
  21. package/dist/sss-key-manager.cjs.development.js +39 -3
  22. package/dist/sss-key-manager.cjs.development.js.map +2 -2
  23. package/dist/sss-key-manager.cjs.production.min.js +20 -20
  24. package/dist/sss-key-manager.cjs.production.min.js.map +3 -3
  25. package/dist/sss-key-manager.esm.js +39 -3
  26. package/dist/sss-key-manager.esm.js.map +2 -2
  27. package/dist/sss-strategy.d.ts +82 -0
  28. package/dist/sss-strategy.d.ts.map +1 -0
  29. package/dist/sss.d.ts +15 -0
  30. package/dist/sss.d.ts.map +1 -0
  31. package/dist/storage.d.ts +46 -0
  32. package/dist/storage.d.ts.map +1 -0
  33. package/dist/types.d.ts +155 -0
  34. package/dist/types.d.ts.map +1 -0
  35. package/package.json +8 -8
  36. package/src/crypto.ts +9 -14
  37. package/src/recovery-phrase.ts +7 -4
  38. package/src/sss-strategy.test.ts +404 -246
  39. package/dist/sss-key-manager.d.ts +0 -898
@@ -0,0 +1,82 @@
1
+ /**
2
+ * SSS Key Derivation Strategy
3
+ *
4
+ * Implements KeyDerivationStrategy using Shamir's Secret Sharing.
5
+ * This is the default key derivation strategy for LearnCard.
6
+ *
7
+ * The strategy owns:
8
+ * - Local key storage (IndexedDB device share)
9
+ * - Key splitting and reconstruction (SSS 2-of-4)
10
+ * - Server communication for auth shares
11
+ * - Optional email backup share delivery
12
+ * - Recovery method execution and setup
13
+ * - Storage cleanup knowledge
14
+ */
15
+ import type { SSSKeyDerivationStrategy } from './types';
16
+ export interface SSSStorageFunctions {
17
+ storeDeviceShare: (share: string, id?: string) => Promise<void>;
18
+ getDeviceShare: (id?: string) => Promise<string | null>;
19
+ hasDeviceShare: (id?: string) => Promise<boolean>;
20
+ clearAllShares: (id?: string) => Promise<void>;
21
+ storeShareVersion: (version: number, id?: string) => Promise<void>;
22
+ getShareVersion: (id?: string) => Promise<number | null>;
23
+ }
24
+ export interface SSSStrategyConfig {
25
+ /** Server URL for key share operations */
26
+ serverUrl: string;
27
+ /** Custom storage functions (defaults to IndexedDB) */
28
+ storage?: SSSStorageFunctions;
29
+ /**
30
+ * Whether to automatically send a backup share to the user's email
31
+ * during key setup and recovery. The share is relayed through the server
32
+ * but never persisted — fire-and-forget.
33
+ *
34
+ * Defaults to false. Controlled by VITE_ENABLE_EMAIL_BACKUP_SHARE env var.
35
+ */
36
+ enableEmailBackupShare?: boolean;
37
+ /**
38
+ * Tenant identifier forwarded as `X-Tenant-Id` on every server request.
39
+ * The lca-api uses this to brand recovery / OTP emails for the active
40
+ * tenant. Defaults to the server's fallback tenant (learncard) when unset.
41
+ */
42
+ tenantId?: string;
43
+ }
44
+ /**
45
+ * Format an email share with a 4-character hex version prefix.
46
+ *
47
+ * Example: version 12 + share "47dee4…" → "000c47dee4…"
48
+ *
49
+ * The 4-hex-digit prefix keeps the entire string as one contiguous
50
+ * hex blob, so double-clicking in an email selects the whole thing
51
+ * (no word-boundary characters like ":" to trip up selection).
52
+ */
53
+ export declare const VERSION_PREFIX_LEN = 4;
54
+ export declare const formatVersionedEmailShare: (emailShare: string, shareVersion: number) => string;
55
+ /**
56
+ * Parse a versioned email share string back into its components.
57
+ * Expects a 4-char hex version prefix followed by the hex share.
58
+ * Returns the raw hex share and the version number (if present).
59
+ */
60
+ export declare const parseVersionedEmailShare: (input: string) => {
61
+ share: string;
62
+ version: number | undefined;
63
+ };
64
+ /**
65
+ * Create an SSS key derivation strategy.
66
+ *
67
+ * @example
68
+ * ```ts
69
+ * const sssStrategy = createSSSStrategy({
70
+ * serverUrl: 'https://api.learncard.com',
71
+ * });
72
+ *
73
+ * // Use with AuthCoordinator
74
+ * const coordinator = createAuthCoordinator({
75
+ * authProvider,
76
+ * keyDerivation: sssStrategy,
77
+ * });
78
+ * ```
79
+ */
80
+ export declare function createSSSStrategy(config: SSSStrategyConfig): SSSKeyDerivationStrategy;
81
+ export type { SSSKeyDerivationStrategy };
82
+ //# sourceMappingURL=sss-strategy.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sss-strategy.d.ts","sourceRoot":"","sources":["../src/sss-strategy.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,KAAK,EACR,wBAAwB,EAU3B,MAAM,SAAS,CAAC;AA4BjB,MAAM,WAAW,mBAAmB;IAChC,gBAAgB,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE,CAAC,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAChE,cAAc,EAAE,CAAC,EAAE,CAAC,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;IACxD,cAAc,EAAE,CAAC,EAAE,CAAC,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;IAClD,cAAc,EAAE,CAAC,EAAE,CAAC,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC/C,iBAAiB,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE,CAAC,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACnE,eAAe,EAAE,CAAC,EAAE,CAAC,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;CAC5D;AAED,MAAM,WAAW,iBAAiB;IAC9B,0CAA0C;IAC1C,SAAS,EAAE,MAAM,CAAC;IAElB,uDAAuD;IACvD,OAAO,CAAC,EAAE,mBAAmB,CAAC;IAE9B;;;;;;OAMG;IACH,sBAAsB,CAAC,EAAE,OAAO,CAAC;IAEjC;;;;OAIG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;CACrB;AAmID;;;;;;;;GAQG;AACH,eAAO,MAAM,kBAAkB,IAAI,CAAC;AAEpC,eAAO,MAAM,yBAAyB,GAAI,YAAY,MAAM,EAAE,cAAc,MAAM,KAAG,MACT,CAAC;AAE7E;;;;GAIG;AACH,eAAO,MAAM,wBAAwB,GACjC,OAAO,MAAM,KACd;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,GAAG,SAAS,CAAA;CAY9C,CAAC;AAqGF;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,iBAAiB,GAAG,wBAAwB,CA8uBrF;AAED,YAAY,EAAE,wBAAwB,EAAE,CAAC"}
package/dist/sss.d.ts ADDED
@@ -0,0 +1,15 @@
1
+ /**
2
+ * Shamir Secret Sharing operations
3
+ */
4
+ export declare const SSS_TOTAL_SHARES = 4;
5
+ export declare const SSS_THRESHOLD = 2;
6
+ export interface SSSShares {
7
+ deviceShare: string;
8
+ authShare: string;
9
+ recoveryShare: string;
10
+ emailShare: string;
11
+ }
12
+ export declare function splitPrivateKey(privateKeyHex: string): Promise<SSSShares>;
13
+ export declare function reconstructPrivateKey(share1Hex: string, share2Hex: string): Promise<string>;
14
+ export declare function reconstructFromShares(shares: string[]): Promise<string>;
15
+ //# sourceMappingURL=sss.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sss.d.ts","sourceRoot":"","sources":["../src/sss.ts"],"names":[],"mappings":"AAAA;;GAEG;AAKH,eAAO,MAAM,gBAAgB,IAAI,CAAC;AAClC,eAAO,MAAM,aAAa,IAAI,CAAC;AAE/B,MAAM,WAAW,SAAS;IACtB,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,aAAa,EAAE,MAAM,CAAC;IACtB,UAAU,EAAE,MAAM,CAAC;CACtB;AAED,wBAAsB,eAAe,CAAC,aAAa,EAAE,MAAM,GAAG,OAAO,CAAC,SAAS,CAAC,CAW/E;AAED,wBAAsB,qBAAqB,CAAC,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAOjG;AAED,wBAAsB,qBAAqB,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC,CAS7E"}
@@ -0,0 +1,46 @@
1
+ /**
2
+ * Device-side storage for SSS shares
3
+ * Reuses patterns from webSecureStorage but specialized for SSS
4
+ */
5
+ export declare function storeDeviceShare(share: string, id?: string): Promise<void>;
6
+ /**
7
+ * Store the share version alongside a device share.
8
+ * Stored as a separate key `{id}:version` to avoid changing the encryption format.
9
+ */
10
+ export declare function storeShareVersion(version: number, id?: string): Promise<void>;
11
+ /**
12
+ * Retrieve the share version for a device share.
13
+ * Returns null if no version is stored (legacy shares).
14
+ */
15
+ export declare function getShareVersion(id?: string): Promise<number | null>;
16
+ export declare function getDeviceShare(id?: string): Promise<string | null>;
17
+ export declare function hasDeviceShare(id?: string): Promise<boolean>;
18
+ export declare function deleteDeviceShare(id?: string): Promise<void>;
19
+ export interface DeviceShareEntry {
20
+ id: string;
21
+ preview: string;
22
+ shareVersion?: number;
23
+ }
24
+ /**
25
+ * List all device shares stored in IndexedDB.
26
+ * Returns the storage key and a truncated preview for each share.
27
+ * Useful for debugging multi-account storage.
28
+ */
29
+ export declare function listAllDeviceShares(): Promise<DeviceShareEntry[]>;
30
+ export declare function isPublicComputerMode(): boolean;
31
+ export declare function setPublicComputerMode(enabled: boolean): void;
32
+ /**
33
+ * Create storage functions that dynamically route to sessionStorage (public
34
+ * computer mode) or IndexedDB (normal mode) based on the `lc-session-mode`
35
+ * flag in sessionStorage. Checked at call time, not at creation time.
36
+ */
37
+ export declare function createAdaptiveStorage(): {
38
+ storeDeviceShare: (share: string, id?: string) => Promise<void>;
39
+ getDeviceShare: (id?: string) => Promise<string | null>;
40
+ hasDeviceShare: (id?: string) => Promise<boolean>;
41
+ clearAllShares: (id?: string) => Promise<void>;
42
+ storeShareVersion: (version: number, id?: string) => Promise<void>;
43
+ getShareVersion: (id?: string) => Promise<number | null>;
44
+ };
45
+ export declare function clearAllShares(id?: string): Promise<void>;
46
+ //# sourceMappingURL=storage.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"storage.d.ts","sourceRoot":"","sources":["../src/storage.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAgJH,wBAAsB,gBAAgB,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE,GAAE,MAAgC,GAAG,OAAO,CAAC,IAAI,CAAC,CASzG;AAED;;;GAGG;AACH,wBAAsB,iBAAiB,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE,GAAE,MAAgC,GAAG,OAAO,CAAC,IAAI,CAAC,CAQ5G;AAED;;;GAGG;AACH,wBAAsB,eAAe,CAAC,EAAE,GAAE,MAAgC,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAYlG;AAED,wBAAsB,cAAc,CAAC,EAAE,GAAE,MAAgC,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAqCjG;AAED,wBAAsB,cAAc,CAAC,EAAE,GAAE,MAAgC,GAAG,OAAO,CAAC,OAAO,CAAC,CAG3F;AAED,wBAAsB,iBAAiB,CAAC,EAAE,GAAE,MAAgC,GAAG,OAAO,CAAC,IAAI,CAAC,CAU3F;AAED,MAAM,WAAW,gBAAgB;IAC7B,EAAE,EAAE,MAAM,CAAC;IACX,OAAO,EAAE,MAAM,CAAC;IAChB,YAAY,CAAC,EAAE,MAAM,CAAC;CACzB;AAED;;;;GAIG;AACH,wBAAsB,mBAAmB,IAAI,OAAO,CAAC,gBAAgB,EAAE,CAAC,CAoDvE;AAYD,wBAAgB,oBAAoB,IAAI,OAAO,CAO9C;AAED,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAU5D;AAiDD;;;;GAIG;AACH,wBAAgB,qBAAqB;8BAEH,MAAM,OAAO,MAAM;0BAKvB,MAAM;0BAKN,MAAM;0BAKN,MAAM;iCAKC,MAAM,OAAO,MAAM;2BAKzB,MAAM;EAKpC;AAED,wBAAsB,cAAc,CAAC,EAAE,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAsC/D"}
@@ -0,0 +1,155 @@
1
+ /**
2
+ * SSS Key Manager Types
3
+ *
4
+ * Re-exports provider-agnostic interfaces from @learncard/types
5
+ * and defines SSS-specific types (recovery shapes, backup files, etc.).
6
+ */
7
+ export { AuthSessionError, type AuthProviderType, type AuthUser, type AuthProvider, type RecoveryMethodInfo, type RecoveryResult, type ServerKeyStatus, type KeyDerivationStrategy, } from '@learncard/types';
8
+ import type { AuthProvider, AuthProviderType, KeyDerivationStrategy, RecoveryMethodInfo } from '@learncard/types';
9
+ export type ContactMethodType = 'email' | 'phone';
10
+ export interface ContactMethod {
11
+ type: ContactMethodType;
12
+ value: string;
13
+ }
14
+ export interface AuthProviderMapping {
15
+ type: AuthProviderType;
16
+ id: string;
17
+ }
18
+ export type SecurityLevel = 'basic' | 'enhanced' | 'advanced';
19
+ export declare const SecurityLevels: readonly SecurityLevel[];
20
+ /**
21
+ * SSS recovery method type identifiers.
22
+ * These are the specific recovery methods supported by the SSS strategy.
23
+ */
24
+ export type RecoveryMethodType = 'passkey' | 'backup' | 'phrase' | 'email';
25
+ export interface PasskeyRecoveryMethod {
26
+ type: 'passkey';
27
+ credentialId?: string;
28
+ }
29
+ export interface BackupFileRecoveryMethod {
30
+ type: 'backup';
31
+ fileContents: string;
32
+ password: string;
33
+ }
34
+ export interface RecoveryPhraseRecoveryMethod {
35
+ type: 'phrase';
36
+ phrase: string;
37
+ }
38
+ /** @deprecated Use RecoveryInput instead. Kept for legacy SSSKeyManager class. */
39
+ export type RecoveryMethod = PasskeyRecoveryMethod | BackupFileRecoveryMethod | RecoveryPhraseRecoveryMethod;
40
+ /**
41
+ * SSS-specific recovery input — what the user provides to recover their key.
42
+ */
43
+ export type RecoveryInput = {
44
+ method: 'passkey';
45
+ credentialId: string;
46
+ } | {
47
+ method: 'phrase';
48
+ phrase: string;
49
+ } | {
50
+ method: 'backup';
51
+ fileContents: string;
52
+ password: string;
53
+ } | {
54
+ method: 'email';
55
+ emailShare: string;
56
+ };
57
+ /**
58
+ * SSS-specific recovery setup input — what the user provides to set up a method.
59
+ */
60
+ export type RecoverySetupInput = {
61
+ method: 'passkey';
62
+ } | {
63
+ method: 'phrase';
64
+ } | {
65
+ method: 'backup';
66
+ password: string;
67
+ did: string;
68
+ } | {
69
+ method: 'email';
70
+ };
71
+ /**
72
+ * SSS-specific recovery setup result.
73
+ */
74
+ export type RecoverySetupResult = {
75
+ method: 'passkey';
76
+ credentialId: string;
77
+ } | {
78
+ method: 'phrase';
79
+ phrase: string;
80
+ } | {
81
+ method: 'backup';
82
+ backupFile: BackupFile;
83
+ } | {
84
+ method: 'email';
85
+ };
86
+ export interface EncryptedShare {
87
+ encryptedData: string;
88
+ iv: string;
89
+ salt?: string;
90
+ }
91
+ export interface ServerEncryptedShare {
92
+ encryptedData: string;
93
+ encryptedDek: string;
94
+ iv: string;
95
+ }
96
+ export interface UserKeyRecord {
97
+ contactMethod: ContactMethod;
98
+ authProviders: AuthProviderMapping[];
99
+ primaryDid: string;
100
+ linkedDids: string[];
101
+ keyProvider: 'web3auth' | 'sss';
102
+ authShare?: ServerEncryptedShare;
103
+ securityLevel: SecurityLevel;
104
+ recoveryMethods: RecoveryMethodInfo[];
105
+ migratedFromWeb3Auth: boolean;
106
+ migratedAt?: Date;
107
+ createdAt: Date;
108
+ updatedAt: Date;
109
+ }
110
+ export interface BackupFile {
111
+ version: 1;
112
+ createdAt: string;
113
+ primaryDid: string;
114
+ shareVersion?: number;
115
+ encryptedShare: {
116
+ ciphertext: string;
117
+ iv: string;
118
+ salt: string;
119
+ kdfParams: {
120
+ algorithm: 'argon2id';
121
+ timeCost: number;
122
+ memoryCost: number;
123
+ parallelism: number;
124
+ };
125
+ };
126
+ }
127
+ export interface SSSKeyManagerConfig {
128
+ serverUrl: string;
129
+ authProvider: AuthProvider;
130
+ deviceStorageKey?: string;
131
+ }
132
+ /**
133
+ * The SSS key derivation strategy — a KeyDerivationStrategy narrowed
134
+ * with SSS-specific recovery input/output types.
135
+ */
136
+ export type SSSKeyDerivationStrategy = KeyDerivationStrategy<RecoveryInput, RecoverySetupInput, RecoverySetupResult>;
137
+ /** @deprecated Use KeyDerivationStrategy instead. Kept for legacy SSSKeyManager class. */
138
+ export interface KeyDerivationProvider {
139
+ readonly name: string;
140
+ connect(): Promise<string>;
141
+ disconnect(): Promise<void>;
142
+ isInitialized(): boolean;
143
+ hasLocalKey(): Promise<boolean>;
144
+ canMigrate?(): Promise<boolean>;
145
+ migrate?(privateKey: string): Promise<void>;
146
+ }
147
+ /** @deprecated Use KeyDerivationStrategy instead. Kept for legacy SSSKeyManager class. */
148
+ export interface SSSKeyDerivationProvider extends KeyDerivationProvider {
149
+ addRecoveryMethod(method: RecoveryMethod): Promise<void>;
150
+ getRecoveryMethods(): Promise<RecoveryMethodInfo[]>;
151
+ recover(method: RecoveryMethod): Promise<string>;
152
+ getSecurityLevel(): Promise<SecurityLevel>;
153
+ exportBackup(password: string): Promise<BackupFile>;
154
+ }
155
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,20 +1,21 @@
1
1
  {
2
2
  "name": "@learncard/sss-key-manager",
3
- "version": "0.1.19",
3
+ "version": "0.1.21",
4
4
  "description": "Shamir Secret Sharing key manager for LearnCard - replaces Web3Auth SFA",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/sss-key-manager.esm.js",
7
- "types": "./dist/sss-key-manager.d.ts",
7
+ "types": "./dist/index.d.ts",
8
8
  "files": [
9
9
  "dist",
10
10
  "src"
11
11
  ],
12
12
  "scripts": {
13
- "build": "node ./scripts/build.mjs && shx cp ./scripts/mixedEntrypoint.js ./dist/index.js && dts-bundle-generator src/index.ts -o dist/sss-key-manager.d.ts --no-check",
13
+ "build": "node ./scripts/build.mjs && shx cp ./scripts/mixedEntrypoint.js ./dist/index.js && tsc --p tsconfig.json",
14
14
  "dev": "node ./scripts/build.mjs --watch",
15
15
  "test": "vitest run",
16
16
  "test:watch": "vitest",
17
- "typecheck": "tsc --noEmit"
17
+ "typecheck": "tsc --noEmit",
18
+ "test:coverage": "vitest run --coverage"
18
19
  },
19
20
  "author": "Learning Economy Foundation (www.learningeconomy.io)",
20
21
  "license": "MIT",
@@ -29,16 +30,15 @@
29
30
  "devDependencies": {
30
31
  "@esbuild-plugins/node-resolve": "^0.1.4",
31
32
  "@types/node": "^18.7.19",
32
- "dts-bundle-generator": "^6.10.0",
33
33
  "esbuild": "^0.27.1",
34
34
  "fake-indexeddb": "^6.2.5",
35
35
  "jsdom": "^24.0.0",
36
36
  "shx": "^0.3.4",
37
37
  "typescript": "^5.0.0",
38
- "vitest": "^1.0.0"
38
+ "vitest": "4.1.10"
39
39
  },
40
40
  "dependencies": {
41
- "@learncard/types": "5.18.1",
41
+ "@learncard/types": "5.18.3",
42
42
  "@noble/ed25519": "^2.0.0",
43
43
  "@scure/bip39": "^1.2.1",
44
44
  "hash-wasm": "^4.11.0",
@@ -55,7 +55,7 @@
55
55
  "exports": {
56
56
  ".": {
57
57
  "development": "./src/index.ts",
58
- "types": "./dist/sss-key-manager.d.ts",
58
+ "types": "./dist/index.d.ts",
59
59
  "import": "./dist/sss-key-manager.esm.js",
60
60
  "require": "./dist/index.js",
61
61
  "default": "./dist/sss-key-manager.esm.js"
package/src/crypto.ts CHANGED
@@ -32,7 +32,7 @@ export function bufferToBase64(buf: ArrayBuffer): string {
32
32
  return btoa(binary);
33
33
  }
34
34
 
35
- export function base64ToBuffer(b64: string): Uint8Array {
35
+ export function base64ToBuffer(b64: string): Uint8Array<ArrayBuffer> {
36
36
  const binary = atob(b64);
37
37
  const bytes = new Uint8Array(binary.length);
38
38
  for (let i = 0; i < binary.length; i++) {
@@ -41,7 +41,7 @@ export function base64ToBuffer(b64: string): Uint8Array {
41
41
  return bytes;
42
42
  }
43
43
 
44
- export function hexToBytes(hex: string): Uint8Array {
44
+ export function hexToBytes(hex: string): Uint8Array<ArrayBuffer> {
45
45
  const bytes = new Uint8Array(hex.length / 2);
46
46
  for (let i = 0; i < hex.length; i += 2) {
47
47
  bytes[i / 2] = parseInt(hex.slice(i, i + 2), 16);
@@ -59,7 +59,7 @@ export async function deriveKeyFromPassword(
59
59
  password: string,
60
60
  salt: Uint8Array,
61
61
  params: KdfParams = DEFAULT_KDF_PARAMS
62
- ): Promise<Uint8Array> {
62
+ ): Promise<Uint8Array<ArrayBuffer>> {
63
63
  const hash = await argon2id({
64
64
  password,
65
65
  salt: salt as unknown as Uint8Array,
@@ -69,7 +69,7 @@ export async function deriveKeyFromPassword(
69
69
  hashLength: ARGON2_HASH_LENGTH,
70
70
  outputType: 'binary',
71
71
  });
72
- return new Uint8Array(hash as ArrayBuffer);
72
+ return Uint8Array.from(hash);
73
73
  }
74
74
 
75
75
  export async function encryptWithPassword(
@@ -148,11 +148,7 @@ export async function encryptShare(
148
148
  encryptParams.additionalData = encoder.encode(aad);
149
149
  }
150
150
 
151
- const ciphertextBuffer = await crypto.subtle.encrypt(
152
- encryptParams,
153
- key,
154
- encoder.encode(share) as ArrayBuffer
155
- );
151
+ const ciphertextBuffer = await crypto.subtle.encrypt(encryptParams, key, encoder.encode(share));
156
152
 
157
153
  return {
158
154
  encryptedData: bufferToBase64(ciphertextBuffer),
@@ -186,11 +182,10 @@ export async function decryptShare(
186
182
  }
187
183
 
188
184
  export async function generateAesKey(): Promise<CryptoKey> {
189
- return crypto.subtle.generateKey(
190
- { name: 'AES-GCM', length: 256 },
191
- true,
192
- ['encrypt', 'decrypt']
193
- );
185
+ return crypto.subtle.generateKey({ name: 'AES-GCM', length: 256 }, true, [
186
+ 'encrypt',
187
+ 'decrypt',
188
+ ]);
194
189
  }
195
190
 
196
191
  export function generateRandomBytes(length: number): Uint8Array {
@@ -27,7 +27,7 @@ function bytesToBits(bytes: Uint8Array): string {
27
27
  .join('');
28
28
  }
29
29
 
30
- function bitsToBytes(bits: string): Uint8Array {
30
+ function bitsToBytes(bits: string): Uint8Array<ArrayBuffer> {
31
31
  const bytes = new Uint8Array(Math.ceil(bits.length / 8));
32
32
  for (let i = 0; i < bytes.length; i++) {
33
33
  bytes[i] = parseInt(bits.slice(i * 8, (i + 1) * 8).padEnd(8, '0'), 2);
@@ -35,7 +35,7 @@ function bitsToBytes(bits: string): Uint8Array {
35
35
  return bytes;
36
36
  }
37
37
 
38
- async function computeChecksum(data: Uint8Array): Promise<string> {
38
+ async function computeChecksum(data: Uint8Array<ArrayBuffer>): Promise<string> {
39
39
  const hash = await crypto.subtle.digest('SHA-256', data);
40
40
  const hashBits = bytesToBits(new Uint8Array(hash));
41
41
  const checksumLength = Math.floor(data.length / 4);
@@ -98,7 +98,7 @@ export async function recoveryPhraseToShare(phrase: string): Promise<string> {
98
98
 
99
99
  const checksumLength = Math.floor(dataByteCount / 4);
100
100
  const dataBitCount = dataByteCount * 8;
101
-
101
+
102
102
  const dataBits = bits.slice(0, dataBitCount);
103
103
  const checksumBits = bits.slice(dataBitCount, dataBitCount + checksumLength);
104
104
 
@@ -127,5 +127,8 @@ export async function validateRecoveryPhrase(phrase: string): Promise<boolean> {
127
127
  }
128
128
 
129
129
  export function countWords(phrase: string): number {
130
- return phrase.trim().split(/\s+/).filter(w => w.length > 0).length;
130
+ return phrase
131
+ .trim()
132
+ .split(/\s+/)
133
+ .filter(w => w.length > 0).length;
131
134
  }