@learncard/sss-key-manager 0.1.20 → 0.1.22
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/README.md +157 -16
- package/dist/api-client.d.ts +49 -0
- package/dist/api-client.d.ts.map +1 -0
- package/dist/atomic-operations.d.ts +101 -0
- package/dist/atomic-operations.d.ts.map +1 -0
- package/dist/auth-coordinator.d.ts +10 -0
- package/dist/auth-coordinator.d.ts.map +1 -0
- package/dist/crypto.d.ts +31 -0
- package/dist/crypto.d.ts.map +1 -0
- package/dist/index.d.ts +26 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/key-manager.d.ts +30 -0
- package/dist/key-manager.d.ts.map +1 -0
- package/dist/passkey.d.ts +23 -0
- package/dist/passkey.d.ts.map +1 -0
- package/dist/qr-crypto.d.ts +56 -0
- package/dist/qr-crypto.d.ts.map +1 -0
- package/dist/qr-login.d.ts +122 -0
- package/dist/qr-login.d.ts.map +1 -0
- package/dist/recovery-phrase.d.ts +14 -0
- package/dist/recovery-phrase.d.ts.map +1 -0
- package/dist/sss-key-manager.cjs.development.js +230 -6
- package/dist/sss-key-manager.cjs.development.js.map +2 -2
- package/dist/sss-key-manager.cjs.production.min.js +6 -6
- package/dist/sss-key-manager.cjs.production.min.js.map +3 -3
- package/dist/sss-key-manager.esm.js +230 -6
- package/dist/sss-key-manager.esm.js.map +2 -2
- package/dist/sss-strategy.d.ts +82 -0
- package/dist/sss-strategy.d.ts.map +1 -0
- package/dist/sss.d.ts +15 -0
- package/dist/sss.d.ts.map +1 -0
- package/dist/storage.d.ts +46 -0
- package/dist/storage.d.ts.map +1 -0
- package/dist/types.d.ts +155 -0
- package/dist/types.d.ts.map +1 -0
- package/package.json +5 -6
- package/src/crypto.ts +9 -14
- package/src/recovery-phrase.ts +7 -4
- package/dist/sss-key-manager.d.ts +0 -898
package/README.md
CHANGED
|
@@ -8,14 +8,14 @@ This package provides a secure, self-hosted alternative to Web3Auth Single Facto
|
|
|
8
8
|
|
|
9
9
|
## Features
|
|
10
10
|
|
|
11
|
-
-
|
|
12
|
-
-
|
|
13
|
-
-
|
|
14
|
-
-
|
|
15
|
-
-
|
|
16
|
-
-
|
|
17
|
-
-
|
|
18
|
-
-
|
|
11
|
+
- **Key Splitting**: Split ed25519 private keys into 3 shares with 2-of-3 threshold
|
|
12
|
+
- **Device Storage**: Encrypted local storage using AES-GCM with IndexedDB
|
|
13
|
+
- **Server Storage**: Encrypted auth share stored on server with envelope encryption
|
|
14
|
+
- **Recovery Methods**:
|
|
15
|
+
- Password-based (Argon2id KDF)
|
|
16
|
+
- Passkey/WebAuthn PRF (coming soon)
|
|
17
|
+
- Backup file export/import
|
|
18
|
+
- **Migration**: Seamless migration from Web3Auth SFA
|
|
19
19
|
|
|
20
20
|
## Installation
|
|
21
21
|
|
|
@@ -115,19 +115,19 @@ const privateKey = await keyManager.recover({
|
|
|
115
115
|
|
|
116
116
|
## Security Model
|
|
117
117
|
|
|
118
|
-
-
|
|
119
|
-
-
|
|
120
|
-
-
|
|
121
|
-
-
|
|
118
|
+
- **Device Share**: Encrypted with non-extractable AES-GCM key stored in IndexedDB
|
|
119
|
+
- **Auth Share**: Server-side envelope encryption (DEK + KMS-encrypted DEK)
|
|
120
|
+
- **Recovery Share**: Password-based uses Argon2id KDF with secure parameters
|
|
121
|
+
- **Threshold**: Any 2 of 3 shares can reconstruct the key
|
|
122
122
|
|
|
123
123
|
## Auth Provider Support
|
|
124
124
|
|
|
125
125
|
The package is designed to work with any authentication provider:
|
|
126
126
|
|
|
127
|
-
-
|
|
128
|
-
-
|
|
129
|
-
-
|
|
130
|
-
-
|
|
127
|
+
- Firebase Authentication (default for production)
|
|
128
|
+
- SuperTokens (recommended for self-hosting/local dev)
|
|
129
|
+
- Keycloak (enterprise SSO)
|
|
130
|
+
- Any OIDC-compliant provider
|
|
131
131
|
|
|
132
132
|
## API Reference
|
|
133
133
|
|
|
@@ -167,6 +167,147 @@ Exports an encrypted backup file.
|
|
|
167
167
|
|
|
168
168
|
Returns the current security level based on configured recovery methods.
|
|
169
169
|
|
|
170
|
+
## Four shares
|
|
171
|
+
|
|
172
|
+
`SSS_TOTAL_SHARES = 4` and `SSS_THRESHOLD = 2`: any two shares reconstruct the private key, while one share alone reveals nothing about it.
|
|
173
|
+
|
|
174
|
+
| Share | Where it lives | Purpose |
|
|
175
|
+
| -------------- | ---------------------------------------------------------------------------------- | ---------------------------------- |
|
|
176
|
+
| Device share | Local IndexedDB | Same-device sign-in |
|
|
177
|
+
| Auth share | LearnCard API server, encrypted at rest | Authenticated sign-in and recovery |
|
|
178
|
+
| Recovery share | Passkey-protected server record, offline phrase, or password-encrypted backup file | User-controlled recovery |
|
|
179
|
+
| Email share | Recovery email backup, encrypted before delivery | Optional additional recovery path |
|
|
180
|
+
|
|
181
|
+
Passkeys protect the recovery share using a key derived from WebAuthn PRF output. A recovery phrase encodes the share as a mnemonic; a backup file encrypts it using Argon2id password derivation and AES-GCM, with its salt and KDF parameters stored in the file.
|
|
182
|
+
|
|
183
|
+
### Server-side encryption
|
|
184
|
+
|
|
185
|
+
The `lca-api` service derives an AES-256-GCM key from its server `SEED` using HKDF-SHA256, with salt `lca-auth-share-encryption` and info `v1`. Each auth-share encryption uses a fresh 12-byte IV; the stored ciphertext includes the 16-byte authentication tag.
|
|
186
|
+
|
|
187
|
+
This implementation encrypts the share directly with the derived key. It does **not** generate a per-share Data Encryption Key (DEK) wrapped by a separate Key Encryption Key (KEK): the `encryptedDek` field holds the format marker `server-v1`, not a wrapped DEK. Password backup encryption and server auth-share encryption are separate mechanisms.
|
|
188
|
+
|
|
189
|
+
## Key Types
|
|
190
|
+
|
|
191
|
+
### ContactMethod
|
|
192
|
+
|
|
193
|
+
Identifies a user by their primary contact method:
|
|
194
|
+
|
|
195
|
+
```typescript
|
|
196
|
+
type ContactMethodType = 'email' | 'phone';
|
|
197
|
+
|
|
198
|
+
interface ContactMethod {
|
|
199
|
+
type: ContactMethodType;
|
|
200
|
+
value: string;
|
|
201
|
+
}
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
### SecurityLevel
|
|
205
|
+
|
|
206
|
+
Describes how well-protected a user's key is:
|
|
207
|
+
|
|
208
|
+
```typescript
|
|
209
|
+
type SecurityLevel = 'basic' | 'enhanced' | 'advanced';
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
- **basic** — device + server share only (no recovery method)
|
|
213
|
+
- **enhanced** — at least one recovery method configured
|
|
214
|
+
- **advanced** — multiple recovery methods configured
|
|
215
|
+
|
|
216
|
+
### RecoveryInput
|
|
217
|
+
|
|
218
|
+
What the user provides to recover their key:
|
|
219
|
+
|
|
220
|
+
```typescript
|
|
221
|
+
type RecoveryInput =
|
|
222
|
+
| { method: 'passkey'; credentialId: string }
|
|
223
|
+
| { method: 'phrase'; phrase: string }
|
|
224
|
+
| { method: 'backup'; fileContents: string; password: string }
|
|
225
|
+
| { method: 'email'; emailShare: string };
|
|
226
|
+
```
|
|
227
|
+
|
|
228
|
+
### RecoverySetupInput
|
|
229
|
+
|
|
230
|
+
What the user provides to set up a new recovery method:
|
|
231
|
+
|
|
232
|
+
```typescript
|
|
233
|
+
type RecoverySetupInput =
|
|
234
|
+
| { method: 'passkey' }
|
|
235
|
+
| { method: 'phrase' }
|
|
236
|
+
| { method: 'backup'; password: string; did: string }
|
|
237
|
+
| { method: 'email' };
|
|
238
|
+
```
|
|
239
|
+
|
|
240
|
+
### BackupFile
|
|
241
|
+
|
|
242
|
+
The JSON structure of a downloadable backup file:
|
|
243
|
+
|
|
244
|
+
```typescript
|
|
245
|
+
interface BackupFile {
|
|
246
|
+
version: 1;
|
|
247
|
+
createdAt: string;
|
|
248
|
+
primaryDid: string;
|
|
249
|
+
shareVersion?: number;
|
|
250
|
+
encryptedShare: {
|
|
251
|
+
ciphertext: string;
|
|
252
|
+
iv: string;
|
|
253
|
+
salt: string;
|
|
254
|
+
kdfParams: {
|
|
255
|
+
algorithm: 'argon2id';
|
|
256
|
+
timeCost: number;
|
|
257
|
+
memoryCost: number;
|
|
258
|
+
parallelism: number;
|
|
259
|
+
};
|
|
260
|
+
};
|
|
261
|
+
}
|
|
262
|
+
```
|
|
263
|
+
|
|
264
|
+
## SSSStrategy
|
|
265
|
+
|
|
266
|
+
The main class that implements `KeyDerivationStrategy`. It is typically instantiated by the AuthCoordinator, not directly by application code.
|
|
267
|
+
|
|
268
|
+
### Configuration
|
|
269
|
+
|
|
270
|
+
```typescript
|
|
271
|
+
interface SSSStrategyConfig {
|
|
272
|
+
serverUrl: string;
|
|
273
|
+
enableEmailBackupShare?: boolean;
|
|
274
|
+
}
|
|
275
|
+
```
|
|
276
|
+
|
|
277
|
+
| Option | Default | Description |
|
|
278
|
+
| ------------------------ | ------- | ---------------------------------------------------------------------- |
|
|
279
|
+
| `serverUrl` | — | Base URL of the lca-api server (e.g., `https://api.example.com/api`) |
|
|
280
|
+
| `enableEmailBackupShare` | `false` | Automatically send a backup share to the user's email during key setup |
|
|
281
|
+
|
|
282
|
+
### Key Methods
|
|
283
|
+
|
|
284
|
+
| Method | Purpose |
|
|
285
|
+
| -------------------------------------------------- | --------------------------------------------------------------------- |
|
|
286
|
+
| `fetchServerKeyStatus(token, providerType)` | Check if a key record exists on the server for the authenticated user |
|
|
287
|
+
| `setupNewKey(token, providerType, signVp)` | Generate a new key, split it, store shares on device and server |
|
|
288
|
+
| `reconstructKey(token, providerType)` | Reconstruct the key from device share + auth share |
|
|
289
|
+
| `recoverKey(token, providerType, input)` | Recover the key using a recovery method + auth share |
|
|
290
|
+
| `hasLocalKey()` | Check if a device share exists in IndexedDB |
|
|
291
|
+
| `clearLocalKey()` | Remove the device share from IndexedDB |
|
|
292
|
+
| `setupRecoveryMethod(params)` | Set up a new recovery method (passkey, phrase, backup, email) |
|
|
293
|
+
| `getAvailableRecoveryMethods(token, providerType)` | List the user's configured recovery methods |
|
|
294
|
+
|
|
295
|
+
## API Client
|
|
296
|
+
|
|
297
|
+
The `api-client.ts` module provides a typed fetch wrapper for all lca-api `/keys/*` and `/qr-login/*` routes. It is used internally by the SSS strategy but can also be used directly:
|
|
298
|
+
|
|
299
|
+
```typescript
|
|
300
|
+
import { createApiClient } from '@learncard/sss-key-manager';
|
|
301
|
+
|
|
302
|
+
const client = createApiClient({ serverUrl: 'https://api.example.com/api' });
|
|
303
|
+
|
|
304
|
+
const status = await client.getAuthShare({
|
|
305
|
+
authToken: token,
|
|
306
|
+
providerType: 'firebase',
|
|
307
|
+
contactMethod: { type: 'email', value: 'user@example.com' },
|
|
308
|
+
});
|
|
309
|
+
```
|
|
310
|
+
|
|
170
311
|
## License
|
|
171
312
|
|
|
172
313
|
MIT
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* API client for SSS Key Manager server routes
|
|
3
|
+
*/
|
|
4
|
+
import type { AuthProvider, ServerEncryptedShare, RecoveryMethodInfo, EncryptedShare, SecurityLevel } from './types';
|
|
5
|
+
export interface GetAuthShareResponse {
|
|
6
|
+
authShare: ServerEncryptedShare | null;
|
|
7
|
+
primaryDid: string | null;
|
|
8
|
+
securityLevel: SecurityLevel;
|
|
9
|
+
recoveryMethods: RecoveryMethodInfo[];
|
|
10
|
+
keyProvider: 'web3auth' | 'sss';
|
|
11
|
+
maskedRecoveryEmail?: string | null;
|
|
12
|
+
}
|
|
13
|
+
export interface StoreAuthShareInput {
|
|
14
|
+
authShare: ServerEncryptedShare;
|
|
15
|
+
primaryDid: string;
|
|
16
|
+
securityLevel?: SecurityLevel;
|
|
17
|
+
}
|
|
18
|
+
export interface StoreRecoveryShareInput {
|
|
19
|
+
type: 'passkey' | 'backup' | 'phrase' | 'email';
|
|
20
|
+
encryptedShare?: EncryptedShare;
|
|
21
|
+
credentialId?: string;
|
|
22
|
+
shareVersion?: number;
|
|
23
|
+
}
|
|
24
|
+
export interface ApiClientConfig {
|
|
25
|
+
serverUrl: string;
|
|
26
|
+
authProvider: AuthProvider;
|
|
27
|
+
}
|
|
28
|
+
export declare class SSSApiClient {
|
|
29
|
+
private serverUrl;
|
|
30
|
+
private authProvider;
|
|
31
|
+
constructor(config: ApiClientConfig);
|
|
32
|
+
private getAuthHeaders;
|
|
33
|
+
private getContactMethodFromUser;
|
|
34
|
+
getAuthShare(): Promise<GetAuthShareResponse | null>;
|
|
35
|
+
storeAuthShare(input: StoreAuthShareInput): Promise<void>;
|
|
36
|
+
addRecoveryMethod(input: StoreRecoveryShareInput): Promise<void>;
|
|
37
|
+
getRecoveryShare(type: 'passkey' | 'backup' | 'phrase' | 'email', credentialId?: string): Promise<{
|
|
38
|
+
encryptedShare?: EncryptedShare;
|
|
39
|
+
shareVersion?: number;
|
|
40
|
+
} | null>;
|
|
41
|
+
markMigrated(): Promise<void>;
|
|
42
|
+
sendEmailBackupShare(emailShare: string, overrideEmail?: string): Promise<void>;
|
|
43
|
+
addRecoveryEmail(email: string): Promise<void>;
|
|
44
|
+
verifyRecoveryEmail(code: string): Promise<{
|
|
45
|
+
maskedEmail: string;
|
|
46
|
+
}>;
|
|
47
|
+
deleteUserKey(): Promise<void>;
|
|
48
|
+
}
|
|
49
|
+
//# sourceMappingURL=api-client.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"api-client.d.ts","sourceRoot":"","sources":["../src/api-client.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EACR,YAAY,EAGZ,oBAAoB,EACpB,kBAAkB,EAClB,cAAc,EACd,aAAa,EAChB,MAAM,SAAS,CAAC;AAEjB,MAAM,WAAW,oBAAoB;IACjC,SAAS,EAAE,oBAAoB,GAAG,IAAI,CAAC;IACvC,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,aAAa,EAAE,aAAa,CAAC;IAC7B,eAAe,EAAE,kBAAkB,EAAE,CAAC;IACtC,WAAW,EAAE,UAAU,GAAG,KAAK,CAAC;IAChC,mBAAmB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CACvC;AAED,MAAM,WAAW,mBAAmB;IAChC,SAAS,EAAE,oBAAoB,CAAC;IAChC,UAAU,EAAE,MAAM,CAAC;IACnB,aAAa,CAAC,EAAE,aAAa,CAAC;CACjC;AAED,MAAM,WAAW,uBAAuB;IACpC,IAAI,EAAE,SAAS,GAAG,QAAQ,GAAG,QAAQ,GAAG,OAAO,CAAC;IAChD,cAAc,CAAC,EAAE,cAAc,CAAC;IAChC,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,YAAY,CAAC,EAAE,MAAM,CAAC;CACzB;AAED,MAAM,WAAW,eAAe;IAC5B,SAAS,EAAE,MAAM,CAAC;IAClB,YAAY,EAAE,YAAY,CAAC;CAC9B;AAED,qBAAa,YAAY;IACrB,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,YAAY,CAAe;gBAEvB,MAAM,EAAE,eAAe;YAKrB,cAAc;YAQd,wBAAwB;IAahC,YAAY,IAAI,OAAO,CAAC,oBAAoB,GAAG,IAAI,CAAC;IAoBpD,cAAc,CAAC,KAAK,EAAE,mBAAmB,GAAG,OAAO,CAAC,IAAI,CAAC;IAkBzD,iBAAiB,CAAC,KAAK,EAAE,uBAAuB,GAAG,OAAO,CAAC,IAAI,CAAC;IAkBhE,gBAAgB,CAClB,IAAI,EAAE,SAAS,GAAG,QAAQ,GAAG,QAAQ,GAAG,OAAO,EAC/C,YAAY,CAAC,EAAE,MAAM,GACtB,OAAO,CAAC;QAAE,cAAc,CAAC,EAAE,cAAc,CAAC;QAAC,YAAY,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC;IA+BvE,YAAY,IAAI,OAAO,CAAC,IAAI,CAAC;IAe7B,oBAAoB,CAAC,UAAU,EAAE,MAAM,EAAE,aAAa,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAgC/E,gBAAgB,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAgB9C,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC;QAAE,WAAW,EAAE,MAAM,CAAA;KAAE,CAAC;IAkBnE,aAAa,IAAI,OAAO,CAAC,IAAI,CAAC;CAcvC"}
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Atomic Share Operations
|
|
3
|
+
*
|
|
4
|
+
* Provides verified split operations and atomic updates with rollback capability.
|
|
5
|
+
* These functions ensure that private keys can NEVER be lost due to partial failures.
|
|
6
|
+
*/
|
|
7
|
+
import { type SSSShares } from './sss';
|
|
8
|
+
export interface AtomicSplitResult {
|
|
9
|
+
privateKey: string;
|
|
10
|
+
shares: SSSShares;
|
|
11
|
+
verified: boolean;
|
|
12
|
+
}
|
|
13
|
+
export interface AtomicUpdateOptions {
|
|
14
|
+
previousDeviceShare?: string;
|
|
15
|
+
previousAuthShare?: string;
|
|
16
|
+
onRollback?: (reason: string) => void;
|
|
17
|
+
}
|
|
18
|
+
export interface StorageOperations {
|
|
19
|
+
storeDevice: (share: string) => Promise<void>;
|
|
20
|
+
storeAuth: (share: string) => Promise<void>;
|
|
21
|
+
getDevice?: () => Promise<string | null>;
|
|
22
|
+
getAuth?: () => Promise<string | null>;
|
|
23
|
+
}
|
|
24
|
+
export declare class ShareVerificationError extends Error {
|
|
25
|
+
readonly combination: string;
|
|
26
|
+
readonly expected: string;
|
|
27
|
+
readonly got: string;
|
|
28
|
+
constructor(message: string, combination: string, expected: string, got: string);
|
|
29
|
+
}
|
|
30
|
+
export declare class AtomicUpdateError extends Error {
|
|
31
|
+
readonly phase: 'split' | 'verify' | 'store_device' | 'store_auth' | 'verify_stored';
|
|
32
|
+
readonly rolledBack: boolean;
|
|
33
|
+
readonly cause?: Error | undefined;
|
|
34
|
+
constructor(message: string, phase: 'split' | 'verify' | 'store_device' | 'store_auth' | 'verify_stored', rolledBack: boolean, cause?: Error | undefined);
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Split a private key into shares and verify ALL combinations reconstruct correctly.
|
|
38
|
+
*
|
|
39
|
+
* This function will NOT return until verification passes. If verification fails,
|
|
40
|
+
* it throws an error - no shares are ever returned that don't reconstruct the key.
|
|
41
|
+
*
|
|
42
|
+
* @param privateKey - The private key to split (hex string)
|
|
43
|
+
* @returns Verified shares that are guaranteed to reconstruct the key
|
|
44
|
+
* @throws ShareVerificationError if any share combination fails verification
|
|
45
|
+
*/
|
|
46
|
+
export declare function splitAndVerify(privateKey: string): Promise<AtomicSplitResult>;
|
|
47
|
+
/**
|
|
48
|
+
* Atomically update shares with rollback on failure.
|
|
49
|
+
*
|
|
50
|
+
* This function ensures that either:
|
|
51
|
+
* 1. Both device and auth shares are updated successfully, OR
|
|
52
|
+
* 2. The previous state is restored (rollback)
|
|
53
|
+
*
|
|
54
|
+
* The operation flow:
|
|
55
|
+
* 1. Generate and verify new shares
|
|
56
|
+
* 2. Store device share locally
|
|
57
|
+
* 3. Store auth share on server
|
|
58
|
+
* 4. If step 3 fails, rollback step 2
|
|
59
|
+
*
|
|
60
|
+
* @param privateKey - The private key to split
|
|
61
|
+
* @param storage - Storage operations for device and auth shares
|
|
62
|
+
* @param options - Options including previous shares for rollback
|
|
63
|
+
* @returns The new verified shares
|
|
64
|
+
* @throws AtomicUpdateError with rollback status
|
|
65
|
+
*/
|
|
66
|
+
export declare function atomicShareUpdate(privateKey: string, storage: StorageOperations, options?: AtomicUpdateOptions): Promise<SSSShares>;
|
|
67
|
+
/**
|
|
68
|
+
* Verify that stored shares can reconstruct the expected private key.
|
|
69
|
+
*
|
|
70
|
+
* This is a health check that should be run after recovery or on login
|
|
71
|
+
* to ensure the user's shares are in a consistent state.
|
|
72
|
+
*
|
|
73
|
+
* @param storage - Storage operations to retrieve shares
|
|
74
|
+
* @param expectedDid - The expected DID (used to verify the reconstructed key)
|
|
75
|
+
* @param didFromPrivateKey - Function to derive DID from private key
|
|
76
|
+
* @returns Object with health status and details
|
|
77
|
+
*/
|
|
78
|
+
export declare function verifyStoredShares(storage: Pick<StorageOperations, 'getDevice' | 'getAuth'>, expectedDid: string, didFromPrivateKey: (privateKey: string) => Promise<string>): Promise<{
|
|
79
|
+
healthy: boolean;
|
|
80
|
+
hasDeviceShare: boolean;
|
|
81
|
+
hasAuthShare: boolean;
|
|
82
|
+
didMatches: boolean;
|
|
83
|
+
error?: string;
|
|
84
|
+
}>;
|
|
85
|
+
/**
|
|
86
|
+
* Create a recovery operation that atomically updates all shares.
|
|
87
|
+
*
|
|
88
|
+
* This is used during recovery when we reconstruct from recovery+auth shares
|
|
89
|
+
* and need to generate a new device share.
|
|
90
|
+
*
|
|
91
|
+
* @param recoveryShare - The decrypted recovery share
|
|
92
|
+
* @param authShareData - The auth share from server
|
|
93
|
+
* @param storage - Storage operations
|
|
94
|
+
* @param options - Atomic update options
|
|
95
|
+
* @returns The reconstructed private key and new shares
|
|
96
|
+
*/
|
|
97
|
+
export declare function atomicRecovery(recoveryShare: string, authShareData: string, storage: StorageOperations, options?: AtomicUpdateOptions): Promise<{
|
|
98
|
+
privateKey: string;
|
|
99
|
+
newShares: SSSShares;
|
|
100
|
+
}>;
|
|
101
|
+
//# sourceMappingURL=atomic-operations.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"atomic-operations.d.ts","sourceRoot":"","sources":["../src/atomic-operations.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAA0C,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAE/E,MAAM,WAAW,iBAAiB;IAC9B,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,SAAS,CAAC;IAClB,QAAQ,EAAE,OAAO,CAAC;CACrB;AAED,MAAM,WAAW,mBAAmB;IAChC,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,UAAU,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC;CACzC;AAED,MAAM,WAAW,iBAAiB;IAC9B,WAAW,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC9C,SAAS,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC5C,SAAS,CAAC,EAAE,MAAM,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;IACzC,OAAO,CAAC,EAAE,MAAM,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;CAC1C;AAED,qBAAa,sBAAuB,SAAQ,KAAK;aAGzB,WAAW,EAAE,MAAM;aACnB,QAAQ,EAAE,MAAM;aAChB,GAAG,EAAE,MAAM;gBAH3B,OAAO,EAAE,MAAM,EACC,WAAW,EAAE,MAAM,EACnB,QAAQ,EAAE,MAAM,EAChB,GAAG,EAAE,MAAM;CAKlC;AAED,qBAAa,iBAAkB,SAAQ,KAAK;aAGpB,KAAK,EAAE,OAAO,GAAG,QAAQ,GAAG,cAAc,GAAG,YAAY,GAAG,eAAe;aAC3E,UAAU,EAAE,OAAO;aACnB,KAAK,CAAC,EAAE,KAAK;gBAH7B,OAAO,EAAE,MAAM,EACC,KAAK,EAAE,OAAO,GAAG,QAAQ,GAAG,cAAc,GAAG,YAAY,GAAG,eAAe,EAC3E,UAAU,EAAE,OAAO,EACnB,KAAK,CAAC,EAAE,KAAK,YAAA;CAKpC;AAED;;;;;;;;;GASG;AACH,wBAAsB,cAAc,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,iBAAiB,CAAC,CA+BnF;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAsB,iBAAiB,CACnC,UAAU,EAAE,MAAM,EAClB,OAAO,EAAE,iBAAiB,EAC1B,OAAO,GAAE,mBAAwB,GAClC,OAAO,CAAC,SAAS,CAAC,CAuDpB;AAED;;;;;;;;;;GAUG;AACH,wBAAsB,kBAAkB,CACpC,OAAO,EAAE,IAAI,CAAC,iBAAiB,EAAE,WAAW,GAAG,SAAS,CAAC,EACzD,WAAW,EAAE,MAAM,EACnB,iBAAiB,EAAE,CAAC,UAAU,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,GAC3D,OAAO,CAAC;IACP,OAAO,EAAE,OAAO,CAAC;IACjB,cAAc,EAAE,OAAO,CAAC;IACxB,YAAY,EAAE,OAAO,CAAC;IACtB,UAAU,EAAE,OAAO,CAAC;IACpB,KAAK,CAAC,EAAE,MAAM,CAAC;CAClB,CAAC,CA6CD;AAED;;;;;;;;;;;GAWG;AACH,wBAAsB,cAAc,CAChC,aAAa,EAAE,MAAM,EACrB,aAAa,EAAE,MAAM,EACrB,OAAO,EAAE,iBAAiB,EAC1B,OAAO,GAAE,mBAAwB,GAClC,OAAO,CAAC;IACP,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,SAAS,CAAC;CACxB,CAAC,CAWD"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @deprecated AuthCoordinator has moved to learn-card-base/auth-coordinator.
|
|
3
|
+
* This file is kept only as a stub during migration.
|
|
4
|
+
* Import from 'learn-card-base' instead:
|
|
5
|
+
*
|
|
6
|
+
* ```ts
|
|
7
|
+
* import { AuthCoordinator, createAuthCoordinator } from 'learn-card-base';
|
|
8
|
+
* ```
|
|
9
|
+
*/
|
|
10
|
+
//# sourceMappingURL=auth-coordinator.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auth-coordinator.d.ts","sourceRoot":"","sources":["../src/auth-coordinator.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG"}
|
package/dist/crypto.d.ts
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cryptographic utilities for SSS Key Manager
|
|
3
|
+
*/
|
|
4
|
+
export interface KdfParams {
|
|
5
|
+
algorithm: 'argon2id';
|
|
6
|
+
timeCost: number;
|
|
7
|
+
memoryCost: number;
|
|
8
|
+
parallelism: number;
|
|
9
|
+
}
|
|
10
|
+
export declare const DEFAULT_KDF_PARAMS: KdfParams;
|
|
11
|
+
export declare function bufferToBase64(buf: ArrayBuffer): string;
|
|
12
|
+
export declare function base64ToBuffer(b64: string): Uint8Array<ArrayBuffer>;
|
|
13
|
+
export declare function hexToBytes(hex: string): Uint8Array<ArrayBuffer>;
|
|
14
|
+
export declare function bytesToHex(bytes: Uint8Array): string;
|
|
15
|
+
export declare function deriveKeyFromPassword(password: string, salt: Uint8Array, params?: KdfParams): Promise<Uint8Array<ArrayBuffer>>;
|
|
16
|
+
export declare function encryptWithPassword(plaintext: string, password: string): Promise<{
|
|
17
|
+
ciphertext: string;
|
|
18
|
+
iv: string;
|
|
19
|
+
salt: string;
|
|
20
|
+
kdfParams: KdfParams;
|
|
21
|
+
}>;
|
|
22
|
+
export declare function decryptWithPassword(ciphertext: string, iv: string, salt: string, password: string, params?: KdfParams): Promise<string>;
|
|
23
|
+
export declare function encryptShare(share: string, key: CryptoKey, aad?: string): Promise<{
|
|
24
|
+
encryptedData: string;
|
|
25
|
+
iv: string;
|
|
26
|
+
}>;
|
|
27
|
+
export declare function decryptShare(encryptedData: string, iv: string, key: CryptoKey, aad?: string): Promise<string>;
|
|
28
|
+
export declare function generateAesKey(): Promise<CryptoKey>;
|
|
29
|
+
export declare function generateRandomBytes(length: number): Uint8Array;
|
|
30
|
+
export declare function generateEd25519PrivateKey(): Promise<string>;
|
|
31
|
+
//# sourceMappingURL=crypto.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"crypto.d.ts","sourceRoot":"","sources":["../src/crypto.ts"],"names":[],"mappings":"AAAA;;GAEG;AASH,MAAM,WAAW,SAAS;IACtB,SAAS,EAAE,UAAU,CAAC;IACtB,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;CACvB;AAED,eAAO,MAAM,kBAAkB,EAAE,SAKhC,CAAC;AAEF,wBAAgB,cAAc,CAAC,GAAG,EAAE,WAAW,GAAG,MAAM,CAOvD;AAED,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG,UAAU,CAAC,WAAW,CAAC,CAOnE;AAED,wBAAgB,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,UAAU,CAAC,WAAW,CAAC,CAM/D;AAED,wBAAgB,UAAU,CAAC,KAAK,EAAE,UAAU,GAAG,MAAM,CAIpD;AAED,wBAAsB,qBAAqB,CACvC,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,UAAU,EAChB,MAAM,GAAE,SAA8B,GACvC,OAAO,CAAC,UAAU,CAAC,WAAW,CAAC,CAAC,CAWlC;AAED,wBAAsB,mBAAmB,CACrC,SAAS,EAAE,MAAM,EACjB,QAAQ,EAAE,MAAM,GACjB,OAAO,CAAC;IAAE,UAAU,EAAE,MAAM,CAAC;IAAC,EAAE,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,SAAS,CAAA;CAAE,CAAC,CA2BjF;AAED,wBAAsB,mBAAmB,CACrC,UAAU,EAAE,MAAM,EAClB,EAAE,EAAE,MAAM,EACV,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,MAAM,EAChB,MAAM,GAAE,SAA8B,GACvC,OAAO,CAAC,MAAM,CAAC,CAuBjB;AAED,wBAAsB,YAAY,CAC9B,KAAK,EAAE,MAAM,EACb,GAAG,EAAE,SAAS,EACd,GAAG,CAAC,EAAE,MAAM,GACb,OAAO,CAAC;IAAE,aAAa,EAAE,MAAM,CAAC;IAAC,EAAE,EAAE,MAAM,CAAA;CAAE,CAAC,CAehD;AAED,wBAAsB,YAAY,CAC9B,aAAa,EAAE,MAAM,EACrB,EAAE,EAAE,MAAM,EACV,GAAG,EAAE,SAAS,EACd,GAAG,CAAC,EAAE,MAAM,GACb,OAAO,CAAC,MAAM,CAAC,CAkBjB;AAED,wBAAsB,cAAc,IAAI,OAAO,CAAC,SAAS,CAAC,CAKzD;AAED,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,MAAM,GAAG,UAAU,CAE9D;AAED,wBAAsB,yBAAyB,IAAI,OAAO,CAAC,MAAM,CAAC,CAGjE"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @learncard/sss-key-manager
|
|
3
|
+
*
|
|
4
|
+
* Shamir Secret Sharing key manager for LearnCard - replaces Web3Auth SFA
|
|
5
|
+
*/
|
|
6
|
+
export { SSSKeyManager, createSSSKeyManager } from './key-manager';
|
|
7
|
+
export { SSSApiClient } from './api-client';
|
|
8
|
+
export { splitPrivateKey, reconstructPrivateKey, reconstructFromShares, SSS_TOTAL_SHARES, SSS_THRESHOLD, } from './sss';
|
|
9
|
+
export { storeDeviceShare, getDeviceShare, hasDeviceShare, deleteDeviceShare, clearAllShares, listAllDeviceShares, storeShareVersion, getShareVersion, isPublicComputerMode, setPublicComputerMode, createAdaptiveStorage, } from './storage';
|
|
10
|
+
export type { DeviceShareEntry } from './storage';
|
|
11
|
+
export { encryptWithPassword, decryptWithPassword, deriveKeyFromPassword, generateEd25519PrivateKey, hexToBytes, bytesToHex, bufferToBase64, base64ToBuffer, DEFAULT_KDF_PARAMS, } from './crypto';
|
|
12
|
+
export { createPasskeyCredential, deriveKeyFromPasskey, encryptShareWithPasskey, decryptShareWithPasskey, isWebAuthnSupported, isPRFSupported, } from './passkey';
|
|
13
|
+
export type { PasskeyCredential, PasskeyEncryptedShare } from './passkey';
|
|
14
|
+
export { shareToRecoveryPhrase, recoveryPhraseToShare, generateRecoveryPhrase, validateRecoveryPhrase, countWords, } from './recovery-phrase';
|
|
15
|
+
export type { RecoveryPhraseData } from './recovery-phrase';
|
|
16
|
+
export { splitAndVerify, atomicShareUpdate, verifyStoredShares, atomicRecovery, ShareVerificationError, AtomicUpdateError, } from './atomic-operations';
|
|
17
|
+
export type { AtomicSplitResult, AtomicUpdateOptions, StorageOperations, } from './atomic-operations';
|
|
18
|
+
export { createSSSStrategy } from './sss-strategy';
|
|
19
|
+
export type { SSSStorageFunctions, SSSStrategyConfig } from './sss-strategy';
|
|
20
|
+
export { generateEphemeralKeypair, encryptShareForTransfer, decryptShareFromTransfer, } from './qr-crypto';
|
|
21
|
+
export type { EphemeralKeypair, EncryptedSharePayload } from './qr-crypto';
|
|
22
|
+
export { createQrLoginSession, pollQrLoginSession, pollUntilApproved, getQrLoginSessionInfo, approveQrLoginSession, notifyDevicesForQrSession, } from './qr-login';
|
|
23
|
+
export type { QrLoginSession, QrLoginSessionInfo, QrLoginClientConfig, QrPayload, PollResult, NotifyDevicesResult, } from './qr-login';
|
|
24
|
+
export { AuthSessionError } from './types';
|
|
25
|
+
export type { SSSKeyManagerConfig, SSSKeyDerivationProvider, KeyDerivationProvider, KeyDerivationStrategy, SSSKeyDerivationStrategy, ServerKeyStatus, AuthProvider, AuthUser, AuthProviderType, ContactMethod, ContactMethodType, RecoveryMethod, RecoveryMethodType, RecoveryMethodInfo, RecoveryInput, RecoveryResult, RecoverySetupInput, RecoverySetupResult, PasskeyRecoveryMethod, BackupFileRecoveryMethod, RecoveryPhraseRecoveryMethod, SecurityLevel, BackupFile, EncryptedShare, ServerEncryptedShare, UserKeyRecord, AuthProviderMapping, } from './types';
|
|
26
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,aAAa,EAAE,mBAAmB,EAAE,MAAM,eAAe,CAAC;AACnE,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAE5C,OAAO,EACH,eAAe,EACf,qBAAqB,EACrB,qBAAqB,EACrB,gBAAgB,EAChB,aAAa,GAChB,MAAM,OAAO,CAAC;AAEf,OAAO,EACH,gBAAgB,EAChB,cAAc,EACd,cAAc,EACd,iBAAiB,EACjB,cAAc,EACd,mBAAmB,EACnB,iBAAiB,EACjB,eAAe,EACf,oBAAoB,EACpB,qBAAqB,EACrB,qBAAqB,GACxB,MAAM,WAAW,CAAC;AAEnB,YAAY,EAAE,gBAAgB,EAAE,MAAM,WAAW,CAAC;AAElD,OAAO,EACH,mBAAmB,EACnB,mBAAmB,EACnB,qBAAqB,EACrB,yBAAyB,EACzB,UAAU,EACV,UAAU,EACV,cAAc,EACd,cAAc,EACd,kBAAkB,GACrB,MAAM,UAAU,CAAC;AAElB,OAAO,EACH,uBAAuB,EACvB,oBAAoB,EACpB,uBAAuB,EACvB,uBAAuB,EACvB,mBAAmB,EACnB,cAAc,GACjB,MAAM,WAAW,CAAC;AAEnB,YAAY,EAAE,iBAAiB,EAAE,qBAAqB,EAAE,MAAM,WAAW,CAAC;AAE1E,OAAO,EACH,qBAAqB,EACrB,qBAAqB,EACrB,sBAAsB,EACtB,sBAAsB,EACtB,UAAU,GACb,MAAM,mBAAmB,CAAC;AAE3B,YAAY,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AAE5D,OAAO,EACH,cAAc,EACd,iBAAiB,EACjB,kBAAkB,EAClB,cAAc,EACd,sBAAsB,EACtB,iBAAiB,GACpB,MAAM,qBAAqB,CAAC;AAE7B,YAAY,EACR,iBAAiB,EACjB,mBAAmB,EACnB,iBAAiB,GACpB,MAAM,qBAAqB,CAAC;AAE7B,OAAO,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AAEnD,YAAY,EAAE,mBAAmB,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AAE7E,OAAO,EACH,wBAAwB,EACxB,uBAAuB,EACvB,wBAAwB,GAC3B,MAAM,aAAa,CAAC;AAErB,YAAY,EAAE,gBAAgB,EAAE,qBAAqB,EAAE,MAAM,aAAa,CAAC;AAE3E,OAAO,EACH,oBAAoB,EACpB,kBAAkB,EAClB,iBAAiB,EACjB,qBAAqB,EACrB,qBAAqB,EACrB,yBAAyB,GAC5B,MAAM,YAAY,CAAC;AAEpB,YAAY,EACR,cAAc,EACd,kBAAkB,EAClB,mBAAmB,EACnB,SAAS,EACT,UAAU,EACV,mBAAmB,GACtB,MAAM,YAAY,CAAC;AAMpB,OAAO,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAC;AAE3C,YAAY,EACR,mBAAmB,EACnB,wBAAwB,EACxB,qBAAqB,EACrB,qBAAqB,EACrB,wBAAwB,EACxB,eAAe,EACf,YAAY,EACZ,QAAQ,EACR,gBAAgB,EAChB,aAAa,EACb,iBAAiB,EACjB,cAAc,EACd,kBAAkB,EAClB,kBAAkB,EAClB,aAAa,EACb,cAAc,EACd,kBAAkB,EAClB,mBAAmB,EACnB,qBAAqB,EACrB,wBAAwB,EACxB,4BAA4B,EAC5B,aAAa,EACb,UAAU,EACV,cAAc,EACd,oBAAoB,EACpB,aAAa,EACb,mBAAmB,GACtB,MAAM,SAAS,CAAC"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SSS Key Manager - Main class
|
|
3
|
+
*/
|
|
4
|
+
import type { SSSKeyManagerConfig, SSSKeyDerivationProvider, RecoveryMethod, RecoveryMethodInfo, SecurityLevel, BackupFile } from './types';
|
|
5
|
+
export declare class SSSKeyManager implements SSSKeyDerivationProvider {
|
|
6
|
+
readonly name = "sss";
|
|
7
|
+
private config;
|
|
8
|
+
private apiClient;
|
|
9
|
+
private initialized;
|
|
10
|
+
private currentPrivateKey;
|
|
11
|
+
constructor(config: SSSKeyManagerConfig);
|
|
12
|
+
isInitialized(): boolean;
|
|
13
|
+
hasLocalKey(): Promise<boolean>;
|
|
14
|
+
connect(): Promise<string>;
|
|
15
|
+
disconnect(): Promise<void>;
|
|
16
|
+
setupNewKey(): Promise<string>;
|
|
17
|
+
setupWithKey(privateKey: string, primaryDid?: string): Promise<void>;
|
|
18
|
+
migrate(privateKey: string): Promise<void>;
|
|
19
|
+
canMigrate(): Promise<boolean>;
|
|
20
|
+
addRecoveryMethod(method: RecoveryMethod): Promise<void>;
|
|
21
|
+
generateRecoveryPhrase(): Promise<string>;
|
|
22
|
+
getRecoveryMethods(): Promise<RecoveryMethodInfo[]>;
|
|
23
|
+
recover(method: RecoveryMethod): Promise<string>;
|
|
24
|
+
getSecurityLevel(): Promise<SecurityLevel>;
|
|
25
|
+
exportBackup(password: string): Promise<BackupFile>;
|
|
26
|
+
clearLocalData(): Promise<void>;
|
|
27
|
+
deleteAccount(): Promise<void>;
|
|
28
|
+
}
|
|
29
|
+
export declare function createSSSKeyManager(config: SSSKeyManagerConfig): SSSKeyManager;
|
|
30
|
+
//# sourceMappingURL=key-manager.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"key-manager.d.ts","sourceRoot":"","sources":["../src/key-manager.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EACR,mBAAmB,EACnB,wBAAwB,EACxB,cAAc,EACd,kBAAkB,EAClB,aAAa,EACb,UAAU,EAEb,MAAM,SAAS,CAAC;AA4BjB,qBAAa,aAAc,YAAW,wBAAwB;IAC1D,QAAQ,CAAC,IAAI,SAAS;IAEtB,OAAO,CAAC,MAAM,CAAsB;IACpC,OAAO,CAAC,SAAS,CAAe;IAChC,OAAO,CAAC,WAAW,CAAS;IAC5B,OAAO,CAAC,iBAAiB,CAAuB;gBAEpC,MAAM,EAAE,mBAAmB;IAQvC,aAAa,IAAI,OAAO;IAIlB,WAAW,IAAI,OAAO,CAAC,OAAO,CAAC;IAI/B,OAAO,IAAI,OAAO,CAAC,MAAM,CAAC;IA4B1B,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAK3B,WAAW,IAAI,OAAO,CAAC,MAAM,CAAC;IAM9B,YAAY,CAAC,UAAU,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAqBpE,OAAO,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAK1C,UAAU,IAAI,OAAO,CAAC,OAAO,CAAC;IAK9B,iBAAiB,CAAC,MAAM,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC;IAqCxD,sBAAsB,IAAI,OAAO,CAAC,MAAM,CAAC;IAWzC,kBAAkB,IAAI,OAAO,CAAC,kBAAkB,EAAE,CAAC;IAKnD,OAAO,CAAC,MAAM,EAAE,cAAc,GAAG,OAAO,CAAC,MAAM,CAAC;IA2FhD,gBAAgB,IAAI,OAAO,CAAC,aAAa,CAAC;IAK1C,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC;IAuBnD,cAAc,IAAI,OAAO,CAAC,IAAI,CAAC;IAM/B,aAAa,IAAI,OAAO,CAAC,IAAI,CAAC;CAMvC;AAED,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,mBAAmB,GAAG,aAAa,CAE9E"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* WebAuthn Passkey utilities for SSS recovery
|
|
3
|
+
* Uses the PRF (Pseudo-Random Function) extension to derive encryption keys
|
|
4
|
+
*/
|
|
5
|
+
export interface PasskeyCredential {
|
|
6
|
+
credentialId: string;
|
|
7
|
+
publicKey: string;
|
|
8
|
+
transports?: AuthenticatorTransport[];
|
|
9
|
+
}
|
|
10
|
+
export interface PasskeyEncryptedShare {
|
|
11
|
+
encryptedData: string;
|
|
12
|
+
iv: string;
|
|
13
|
+
credentialId: string;
|
|
14
|
+
}
|
|
15
|
+
declare function isWebAuthnSupported(): boolean;
|
|
16
|
+
declare function isPRFSupported(): Promise<boolean>;
|
|
17
|
+
export declare function createPasskeyCredential(userId: string, userName: string): Promise<PasskeyCredential>;
|
|
18
|
+
export declare function deriveKeyFromPasskey(credentialId: string): Promise<CryptoKey>;
|
|
19
|
+
export declare function encryptShareWithPasskey(share: string, credentialId: string): Promise<PasskeyEncryptedShare>;
|
|
20
|
+
export declare function decryptShareWithPasskey(encryptedShare: PasskeyEncryptedShare): Promise<string>;
|
|
21
|
+
export declare function listStoredPasskeys(): Promise<PasskeyCredential[]>;
|
|
22
|
+
export { isWebAuthnSupported, isPRFSupported };
|
|
23
|
+
//# sourceMappingURL=passkey.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"passkey.d.ts","sourceRoot":"","sources":["../src/passkey.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAIH,MAAM,WAAW,iBAAiB;IAC9B,YAAY,EAAE,MAAM,CAAC;IACrB,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,sBAAsB,EAAE,CAAC;CACzC;AAED,MAAM,WAAW,qBAAqB;IAClC,aAAa,EAAE,MAAM,CAAC;IACtB,EAAE,EAAE,MAAM,CAAC;IACX,YAAY,EAAE,MAAM,CAAC;CACxB;AAOD,iBAAS,mBAAmB,IAAI,OAAO,CAItC;AAED,iBAAe,cAAc,IAAI,OAAO,CAAC,OAAO,CAAC,CAShD;AAED,wBAAsB,uBAAuB,CACzC,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,MAAM,GACjB,OAAO,CAAC,iBAAiB,CAAC,CAgE5B;AAED,wBAAsB,oBAAoB,CACtC,YAAY,EAAE,MAAM,GACrB,OAAO,CAAC,SAAS,CAAC,CAkDpB;AAED,wBAAsB,uBAAuB,CACzC,KAAK,EAAE,MAAM,EACb,YAAY,EAAE,MAAM,GACrB,OAAO,CAAC,qBAAqB,CAAC,CAiBhC;AAED,wBAAsB,uBAAuB,CACzC,cAAc,EAAE,qBAAqB,GACtC,OAAO,CAAC,MAAM,CAAC,CAcjB;AAED,wBAAsB,kBAAkB,IAAI,OAAO,CAAC,iBAAiB,EAAE,CAAC,CAevE;AAED,OAAO,EAAE,mBAAmB,EAAE,cAAc,EAAE,CAAC"}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* QR Login Crypto Helpers
|
|
3
|
+
*
|
|
4
|
+
* X25519 ECDH key exchange + AES-256-GCM encryption for cross-device
|
|
5
|
+
* share transfer. Uses the Web Crypto API exclusively — no external deps.
|
|
6
|
+
*
|
|
7
|
+
* Flow:
|
|
8
|
+
* Device B generates an ephemeral X25519 keypair, shares the public key.
|
|
9
|
+
* Device A derives a shared secret via ECDH, encrypts the device share
|
|
10
|
+
* with AES-256-GCM, and sends the ciphertext.
|
|
11
|
+
* Device B decrypts with the same derived shared secret.
|
|
12
|
+
*/
|
|
13
|
+
export interface EphemeralKeypair {
|
|
14
|
+
/** Base64-encoded X25519 public key (sent to server / encoded in QR) */
|
|
15
|
+
publicKey: string;
|
|
16
|
+
/** Raw CryptoKey — kept in memory on Device B, never leaves the device */
|
|
17
|
+
privateKey: CryptoKey;
|
|
18
|
+
}
|
|
19
|
+
export interface EncryptedSharePayload {
|
|
20
|
+
/** Base64-encoded AES-256-GCM ciphertext */
|
|
21
|
+
ciphertext: string;
|
|
22
|
+
/** Base64-encoded 12-byte IV */
|
|
23
|
+
iv: string;
|
|
24
|
+
/** Base64-encoded ephemeral public key of the *sender* (Device A) */
|
|
25
|
+
senderPublicKey: string;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Generate an ephemeral X25519 keypair for the new device (Device B).
|
|
29
|
+
* The public key is shared via QR / short code; the private key stays in memory.
|
|
30
|
+
*/
|
|
31
|
+
export declare const generateEphemeralKeypair: () => Promise<EphemeralKeypair>;
|
|
32
|
+
/**
|
|
33
|
+
* Encrypt a device share for transfer to Device B.
|
|
34
|
+
*
|
|
35
|
+
* Called by Device A (the logged-in device):
|
|
36
|
+
* 1. Generates its own ephemeral X25519 keypair
|
|
37
|
+
* 2. Derives a shared secret from its private key + Device B's public key
|
|
38
|
+
* 3. Encrypts the share with AES-256-GCM
|
|
39
|
+
* 4. Returns the ciphertext + IV + Device A's ephemeral public key
|
|
40
|
+
*
|
|
41
|
+
* @param deviceShare - Plaintext device share to encrypt
|
|
42
|
+
* @param recipientPublicKey - Base64-encoded X25519 public key from Device B
|
|
43
|
+
*/
|
|
44
|
+
export declare const encryptShareForTransfer: (deviceShare: string, recipientPublicKey: string) => Promise<EncryptedSharePayload>;
|
|
45
|
+
/**
|
|
46
|
+
* Decrypt a device share received from Device A.
|
|
47
|
+
*
|
|
48
|
+
* Called by Device B (the new device):
|
|
49
|
+
* 1. Derives the shared secret from its private key + Device A's public key
|
|
50
|
+
* 2. Decrypts the ciphertext with AES-256-GCM
|
|
51
|
+
*
|
|
52
|
+
* @param payload - The encrypted payload from Device A
|
|
53
|
+
* @param recipientPrivateKey - Device B's ephemeral private CryptoKey
|
|
54
|
+
*/
|
|
55
|
+
export declare const decryptShareFromTransfer: (payload: EncryptedSharePayload, recipientPrivateKey: CryptoKey) => Promise<string>;
|
|
56
|
+
//# sourceMappingURL=qr-crypto.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"qr-crypto.d.ts","sourceRoot":"","sources":["../src/qr-crypto.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAQH,MAAM,WAAW,gBAAgB;IAC7B,wEAAwE;IACxE,SAAS,EAAE,MAAM,CAAC;IAElB,0EAA0E;IAC1E,UAAU,EAAE,SAAS,CAAC;CACzB;AAED,MAAM,WAAW,qBAAqB;IAClC,4CAA4C;IAC5C,UAAU,EAAE,MAAM,CAAC;IAEnB,gCAAgC;IAChC,EAAE,EAAE,MAAM,CAAC;IAEX,qEAAqE;IACrE,eAAe,EAAE,MAAM,CAAC;CAC3B;AAMD;;;GAGG;AACH,eAAO,MAAM,wBAAwB,QAAa,OAAO,CAAC,gBAAgB,CAoBzE,CAAC;AAsEF;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,uBAAuB,GAChC,aAAa,MAAM,EACnB,oBAAoB,MAAM,KAC3B,OAAO,CAAC,qBAAqB,CAsB/B,CAAC;AAEF;;;;;;;;;GASG;AACH,eAAO,MAAM,wBAAwB,GACjC,SAAS,qBAAqB,EAC9B,qBAAqB,SAAS,KAC/B,OAAO,CAAC,MAAM,CAiBhB,CAAC"}
|