@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.
- 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 +39 -3
- package/dist/sss-key-manager.cjs.development.js.map +2 -2
- package/dist/sss-key-manager.cjs.production.min.js +20 -20
- package/dist/sss-key-manager.cjs.production.min.js.map +3 -3
- package/dist/sss-key-manager.esm.js +39 -3
- 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 +8 -8
- package/src/crypto.ts +9 -14
- package/src/recovery-phrase.ts +7 -4
- package/src/sss-strategy.test.ts +404 -246
- package/dist/sss-key-manager.d.ts +0 -898
|
@@ -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"}
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* QR Login Client
|
|
3
|
+
*
|
|
4
|
+
* High-level orchestrator for cross-device login via QR code or short code.
|
|
5
|
+
* Coordinates between the relay API and the ECDH crypto layer.
|
|
6
|
+
*
|
|
7
|
+
* Two roles:
|
|
8
|
+
* - **Requester** (Device B, new device): creates session, renders QR, polls
|
|
9
|
+
* - **Approver** (Device A, logged-in device): reads QR/code, encrypts share, approves
|
|
10
|
+
*/
|
|
11
|
+
import type { EphemeralKeypair } from './qr-crypto';
|
|
12
|
+
export interface QrLoginSession {
|
|
13
|
+
sessionId: string;
|
|
14
|
+
shortCode: string;
|
|
15
|
+
expiresInSeconds: number;
|
|
16
|
+
}
|
|
17
|
+
export interface QrLoginSessionInfo {
|
|
18
|
+
sessionId: string;
|
|
19
|
+
publicKey: string;
|
|
20
|
+
status: 'pending' | 'approved';
|
|
21
|
+
encryptedPayload?: string;
|
|
22
|
+
approverDid?: string;
|
|
23
|
+
}
|
|
24
|
+
export interface QrLoginClientConfig {
|
|
25
|
+
serverUrl: string;
|
|
26
|
+
}
|
|
27
|
+
export interface QrPayload {
|
|
28
|
+
/** Session ID for the relay */
|
|
29
|
+
sessionId: string;
|
|
30
|
+
/** Base64-encoded ephemeral X25519 public key */
|
|
31
|
+
publicKey: string;
|
|
32
|
+
/** Server URL for the relay */
|
|
33
|
+
serverUrl: string;
|
|
34
|
+
}
|
|
35
|
+
/** Result of polling — either still waiting or the device share is ready */
|
|
36
|
+
export type PollResult = {
|
|
37
|
+
status: 'pending';
|
|
38
|
+
} | {
|
|
39
|
+
status: 'approved';
|
|
40
|
+
deviceShare: string;
|
|
41
|
+
approverDid: string;
|
|
42
|
+
accountHint?: string;
|
|
43
|
+
shareVersion?: number;
|
|
44
|
+
};
|
|
45
|
+
/**
|
|
46
|
+
* Create a QR login session and generate the ephemeral keypair.
|
|
47
|
+
*
|
|
48
|
+
* Returns everything Device B needs to display a QR and start polling.
|
|
49
|
+
* The ephemeral private key is kept in memory — never serialized.
|
|
50
|
+
*/
|
|
51
|
+
export declare const createQrLoginSession: (config: QrLoginClientConfig) => Promise<{
|
|
52
|
+
session: QrLoginSession;
|
|
53
|
+
ephemeralKeypair: EphemeralKeypair;
|
|
54
|
+
qrPayload: QrPayload;
|
|
55
|
+
}>;
|
|
56
|
+
/**
|
|
57
|
+
* Poll a QR login session for approval.
|
|
58
|
+
*
|
|
59
|
+
* When Device A approves, this returns the decrypted device share.
|
|
60
|
+
*
|
|
61
|
+
* @param config - Server config
|
|
62
|
+
* @param sessionId - The session to poll
|
|
63
|
+
* @param ephemeralPrivateKey - Device B's ephemeral private key (for decryption)
|
|
64
|
+
*/
|
|
65
|
+
export declare const pollQrLoginSession: (config: QrLoginClientConfig, sessionId: string, ephemeralPrivateKey: CryptoKey) => Promise<PollResult>;
|
|
66
|
+
/**
|
|
67
|
+
* Convenience: poll in a loop until approved or timeout.
|
|
68
|
+
*
|
|
69
|
+
* @param config - Server config
|
|
70
|
+
* @param sessionId - The session to poll
|
|
71
|
+
* @param ephemeralPrivateKey - Device B's ephemeral private key
|
|
72
|
+
* @param intervalMs - Polling interval (default 2000ms)
|
|
73
|
+
* @param timeoutMs - Total timeout (default 120000ms)
|
|
74
|
+
* @param onPoll - Optional callback on each poll (for UI updates)
|
|
75
|
+
*/
|
|
76
|
+
export declare const pollUntilApproved: (config: QrLoginClientConfig, sessionId: string, ephemeralPrivateKey: CryptoKey, options?: {
|
|
77
|
+
intervalMs?: number;
|
|
78
|
+
timeoutMs?: number;
|
|
79
|
+
onPoll?: (attempt: number) => void;
|
|
80
|
+
signal?: AbortSignal;
|
|
81
|
+
}) => Promise<{
|
|
82
|
+
deviceShare: string;
|
|
83
|
+
approverDid: string;
|
|
84
|
+
accountHint?: string;
|
|
85
|
+
shareVersion?: number;
|
|
86
|
+
}>;
|
|
87
|
+
/**
|
|
88
|
+
* Fetch a QR login session's public key (for Device A to encrypt against).
|
|
89
|
+
*
|
|
90
|
+
* @param config - Server config
|
|
91
|
+
* @param lookup - Session ID or 6-digit short code
|
|
92
|
+
*/
|
|
93
|
+
export declare const getQrLoginSessionInfo: (config: QrLoginClientConfig, lookup: string) => Promise<QrLoginSessionInfo>;
|
|
94
|
+
/**
|
|
95
|
+
* Approve a QR login session by encrypting and pushing the device share.
|
|
96
|
+
*
|
|
97
|
+
* Called by Device A (the logged-in device).
|
|
98
|
+
*
|
|
99
|
+
* @param config - Server config
|
|
100
|
+
* @param sessionId - The session to approve
|
|
101
|
+
* @param deviceShare - Plaintext device share from Device A's local storage
|
|
102
|
+
* @param approverDid - DID of the approving device
|
|
103
|
+
* @param recipientPublicKey - Base64 X25519 public key from the session
|
|
104
|
+
* @param accountHint - Optional email or phone of the approver's account (sent to Device B as a login hint)
|
|
105
|
+
* @param shareVersion - Optional share version so Device B can fetch the matching auth share
|
|
106
|
+
*/
|
|
107
|
+
export declare const approveQrLoginSession: (config: QrLoginClientConfig, sessionId: string, deviceShare: string, approverDid: string, recipientPublicKey: string, accountHint?: string, shareVersion?: number) => Promise<void>;
|
|
108
|
+
export interface NotifyDevicesResult {
|
|
109
|
+
sent: boolean;
|
|
110
|
+
deviceCount: number;
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* Send a push notification to the authenticated user's other devices,
|
|
114
|
+
* prompting them to open the approver flow for the given QR session.
|
|
115
|
+
*
|
|
116
|
+
* Called by Device B (in needs_recovery) after creating a session.
|
|
117
|
+
* Requires the user's Firebase (or other auth provider) token.
|
|
118
|
+
*
|
|
119
|
+
* This is fire-and-forget — failure does not block the QR login flow.
|
|
120
|
+
*/
|
|
121
|
+
export declare const notifyDevicesForQrSession: (config: QrLoginClientConfig, sessionId: string, shortCode: string, authToken: string, providerType?: string) => Promise<NotifyDevicesResult>;
|
|
122
|
+
//# sourceMappingURL=qr-login.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"qr-login.d.ts","sourceRoot":"","sources":["../src/qr-login.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAUH,OAAO,KAAK,EAAE,gBAAgB,EAAyB,MAAM,aAAa,CAAC;AAM3E,MAAM,WAAW,cAAc;IAC3B,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,gBAAgB,EAAE,MAAM,CAAC;CAC5B;AAED,MAAM,WAAW,kBAAkB;IAC/B,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,SAAS,GAAG,UAAU,CAAC;IAC/B,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,WAAW,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,WAAW,mBAAmB;IAChC,SAAS,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,SAAS;IACtB,+BAA+B;IAC/B,SAAS,EAAE,MAAM,CAAC;IAElB,iDAAiD;IACjD,SAAS,EAAE,MAAM,CAAC;IAElB,+BAA+B;IAC/B,SAAS,EAAE,MAAM,CAAC;CACrB;AAED,4EAA4E;AAC5E,MAAM,MAAM,UAAU,GAChB;IAAE,MAAM,EAAE,SAAS,CAAA;CAAE,GACrB;IAAE,MAAM,EAAE,UAAU,CAAC;IAAC,WAAW,EAAE,MAAM,CAAC;IAAC,WAAW,EAAE,MAAM,CAAC;IAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAAC,YAAY,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC;AAoBpH;;;;;GAKG;AACH,eAAO,MAAM,oBAAoB,GAC7B,QAAQ,mBAAmB,KAC5B,OAAO,CAAC;IACP,OAAO,EAAE,cAAc,CAAC;IACxB,gBAAgB,EAAE,gBAAgB,CAAC;IACnC,SAAS,EAAE,SAAS,CAAC;CACxB,CAsBA,CAAC;AAEF;;;;;;;;GAQG;AACH,eAAO,MAAM,kBAAkB,GAC3B,QAAQ,mBAAmB,EAC3B,WAAW,MAAM,EACjB,qBAAqB,SAAS,KAC/B,OAAO,CAAC,UAAU,CAkCpB,CAAC;AAEF;;;;;;;;;GASG;AACH,eAAO,MAAM,iBAAiB,GAC1B,QAAQ,mBAAmB,EAC3B,WAAW,MAAM,EACjB,qBAAqB,SAAS,EAC9B,UAAU;IACN,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,MAAM,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;IACnC,MAAM,CAAC,EAAE,WAAW,CAAC;CACxB,KACF,OAAO,CAAC;IAAE,WAAW,EAAE,MAAM,CAAC;IAAC,WAAW,EAAE,MAAM,CAAC;IAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAAC,YAAY,CAAC,EAAE,MAAM,CAAA;CAAE,CAwCnG,CAAC;AAMF;;;;;GAKG;AACH,eAAO,MAAM,qBAAqB,GAC9B,QAAQ,mBAAmB,EAC3B,QAAQ,MAAM,KACf,OAAO,CAAC,kBAAkB,CAW5B,CAAC;AAEF;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,qBAAqB,GAC9B,QAAQ,mBAAmB,EAC3B,WAAW,MAAM,EACjB,aAAa,MAAM,EACnB,aAAa,MAAM,EACnB,oBAAoB,MAAM,EAC1B,cAAc,MAAM,EACpB,eAAe,MAAM,KACtB,OAAO,CAAC,IAAI,CAoBd,CAAC;AAMF,MAAM,WAAW,mBAAmB;IAChC,IAAI,EAAE,OAAO,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;CACvB;AAED;;;;;;;;GAQG;AACH,eAAO,MAAM,yBAAyB,GAClC,QAAQ,mBAAmB,EAC3B,WAAW,MAAM,EACjB,WAAW,MAAM,EACjB,WAAW,MAAM,EACjB,eAAc,MAAmB,KAClC,OAAO,CAAC,mBAAmB,CAqB7B,CAAC"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* BIP39 Recovery Phrase utilities for SSS recovery
|
|
3
|
+
* The recovery phrase directly encodes a share (not encryption)
|
|
4
|
+
*/
|
|
5
|
+
export interface RecoveryPhraseData {
|
|
6
|
+
phrase: string;
|
|
7
|
+
shareHex: string;
|
|
8
|
+
}
|
|
9
|
+
export declare function shareToRecoveryPhrase(shareHex: string): Promise<string>;
|
|
10
|
+
export declare function recoveryPhraseToShare(phrase: string): Promise<string>;
|
|
11
|
+
export declare function generateRecoveryPhrase(shareHex: string): Promise<RecoveryPhraseData>;
|
|
12
|
+
export declare function validateRecoveryPhrase(phrase: string): Promise<boolean>;
|
|
13
|
+
export declare function countWords(phrase: string): number;
|
|
14
|
+
//# sourceMappingURL=recovery-phrase.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"recovery-phrase.d.ts","sourceRoot":"","sources":["../src/recovery-phrase.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAIH,MAAM,WAAW,kBAAkB;IAC/B,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;CACpB;AAkCD,wBAAsB,qBAAqB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAc7E;AAED,wBAAsB,qBAAqB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAoD3E;AAED,wBAAsB,sBAAsB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,kBAAkB,CAAC,CAG1F;AAED,wBAAsB,sBAAsB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAO7E;AAED,wBAAgB,UAAU,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAKjD"}
|
|
@@ -197,6 +197,12 @@ var require_types_cjs_development = __commonJS({
|
|
|
197
197
|
LCNBoostClaimLinkSigningAuthorityValidator: /* @__PURE__ */ __name(() => LCNBoostClaimLinkSigningAuthorityValidator, "LCNBoostClaimLinkSigningAuthorityValidator"),
|
|
198
198
|
LCNBoostStatus: /* @__PURE__ */ __name(() => LCNBoostStatus, "LCNBoostStatus"),
|
|
199
199
|
LCNConnectionProfileValidator: /* @__PURE__ */ __name(() => LCNConnectionProfileValidator, "LCNConnectionProfileValidator"),
|
|
200
|
+
LCNConnectionPromptActionResultValidator: /* @__PURE__ */ __name(() => LCNConnectionPromptActionResultValidator, "LCNConnectionPromptActionResultValidator"),
|
|
201
|
+
LCNConnectionPromptActionStatusValidator: /* @__PURE__ */ __name(() => LCNConnectionPromptActionStatusValidator, "LCNConnectionPromptActionStatusValidator"),
|
|
202
|
+
LCNConnectionPromptMetadataValidator: /* @__PURE__ */ __name(() => LCNConnectionPromptMetadataValidator, "LCNConnectionPromptMetadataValidator"),
|
|
203
|
+
LCNConnectionPromptStatusValidator: /* @__PURE__ */ __name(() => LCNConnectionPromptStatusValidator, "LCNConnectionPromptStatusValidator"),
|
|
204
|
+
LCNConnectionPromptSurfaceValidator: /* @__PURE__ */ __name(() => LCNConnectionPromptSurfaceValidator, "LCNConnectionPromptSurfaceValidator"),
|
|
205
|
+
LCNConnectionPromptValidator: /* @__PURE__ */ __name(() => LCNConnectionPromptValidator, "LCNConnectionPromptValidator"),
|
|
200
206
|
LCNDomainOrOriginValidator: /* @__PURE__ */ __name(() => LCNDomainOrOriginValidator, "LCNDomainOrOriginValidator"),
|
|
201
207
|
LCNInboxContactMethodValidator: /* @__PURE__ */ __name(() => LCNInboxContactMethodValidator, "LCNInboxContactMethodValidator"),
|
|
202
208
|
LCNInboxStatusEnumValidator: /* @__PURE__ */ __name(() => LCNInboxStatusEnumValidator, "LCNInboxStatusEnumValidator"),
|
|
@@ -208,6 +214,7 @@ var require_types_cjs_development = __commonJS({
|
|
|
208
214
|
LCNNotificationDataValidator: /* @__PURE__ */ __name(() => LCNNotificationDataValidator, "LCNNotificationDataValidator"),
|
|
209
215
|
LCNNotificationInboxValidator: /* @__PURE__ */ __name(() => LCNNotificationInboxValidator, "LCNNotificationInboxValidator"),
|
|
210
216
|
LCNNotificationMessageValidator: /* @__PURE__ */ __name(() => LCNNotificationMessageValidator, "LCNNotificationMessageValidator"),
|
|
217
|
+
LCNNotificationMetadataValidator: /* @__PURE__ */ __name(() => LCNNotificationMetadataValidator, "LCNNotificationMetadataValidator"),
|
|
211
218
|
LCNNotificationTypeEnumValidator: /* @__PURE__ */ __name(() => LCNNotificationTypeEnumValidator, "LCNNotificationTypeEnumValidator"),
|
|
212
219
|
LCNNotificationValidator: /* @__PURE__ */ __name(() => LCNNotificationValidator, "LCNNotificationValidator"),
|
|
213
220
|
LCNProfileConnectionStatusEnum: /* @__PURE__ */ __name(() => LCNProfileConnectionStatusEnum, "LCNProfileConnectionStatusEnum"),
|
|
@@ -16232,6 +16239,31 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
16232
16239
|
isServiceProfile: true,
|
|
16233
16240
|
display: true
|
|
16234
16241
|
});
|
|
16242
|
+
var LCNConnectionPromptStatusValidator = external_exports.enum(["PENDING", "SKIPPED", "CONNECTED"]);
|
|
16243
|
+
var LCNConnectionPromptSurfaceValidator = external_exports.enum(["POST_CLAIM", "NOTIFICATION"]);
|
|
16244
|
+
var LCNConnectionPromptActionStatusValidator = external_exports.enum([
|
|
16245
|
+
"PENDING",
|
|
16246
|
+
"SKIPPED",
|
|
16247
|
+
"CONNECTED",
|
|
16248
|
+
"STALE"
|
|
16249
|
+
]);
|
|
16250
|
+
var LCNConnectionPromptValidator = external_exports.object({
|
|
16251
|
+
promptId: external_exports.string().uuid(),
|
|
16252
|
+
status: LCNConnectionPromptStatusValidator,
|
|
16253
|
+
surface: LCNConnectionPromptSurfaceValidator,
|
|
16254
|
+
triggerId: external_exports.string(),
|
|
16255
|
+
triggeredAt: external_exports.iso.datetime(),
|
|
16256
|
+
updatedAt: external_exports.iso.datetime(),
|
|
16257
|
+
counterpart: LCNPublicProfileValidator
|
|
16258
|
+
});
|
|
16259
|
+
var LCNConnectionPromptActionResultValidator = external_exports.object({
|
|
16260
|
+
promptId: external_exports.string().uuid(),
|
|
16261
|
+
status: LCNConnectionPromptActionStatusValidator
|
|
16262
|
+
});
|
|
16263
|
+
var LCNConnectionPromptMetadataValidator = external_exports.object({
|
|
16264
|
+
promptId: external_exports.string().uuid(),
|
|
16265
|
+
counterpartProfileId: external_exports.string()
|
|
16266
|
+
});
|
|
16235
16267
|
var LCNAuthedProfileValidator = LCNPublicProfileValidator.extend({
|
|
16236
16268
|
bio: LCNProfileValidator.shape.bio,
|
|
16237
16269
|
websiteLink: LCNProfileValidator.shape.websiteLink,
|
|
@@ -16240,7 +16272,8 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
16240
16272
|
did: LCNProfileValidator.shape.did
|
|
16241
16273
|
});
|
|
16242
16274
|
var LCNConnectionProfileValidator = LCNAuthedProfileValidator.extend({
|
|
16243
|
-
email: LCNProfileValidator.shape.email
|
|
16275
|
+
email: LCNProfileValidator.shape.email,
|
|
16276
|
+
connectedAt: external_exports.iso.datetime().optional().describe("When the viewer and this profile became connected.")
|
|
16244
16277
|
});
|
|
16245
16278
|
var LCNVisibleProfileValidator = external_exports.union([
|
|
16246
16279
|
LCNConnectionProfileValidator.strict(),
|
|
@@ -16796,12 +16829,15 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
16796
16829
|
}),
|
|
16797
16830
|
timestamp: external_exports.iso.datetime().optional()
|
|
16798
16831
|
});
|
|
16832
|
+
var LCNNotificationMetadataValidator = external_exports.object({
|
|
16833
|
+
connectionPrompt: LCNConnectionPromptMetadataValidator.optional()
|
|
16834
|
+
}).catchall(external_exports.unknown());
|
|
16799
16835
|
var LCNNotificationDataValidator = external_exports.object({
|
|
16800
16836
|
vcUris: external_exports.array(external_exports.string()).optional(),
|
|
16801
16837
|
vpUris: external_exports.array(external_exports.string()).optional(),
|
|
16802
16838
|
transaction: ConsentFlowTransactionValidator.optional(),
|
|
16803
16839
|
inbox: LCNNotificationInboxValidator.optional(),
|
|
16804
|
-
metadata:
|
|
16840
|
+
metadata: LCNNotificationMetadataValidator.optional()
|
|
16805
16841
|
}).loose();
|
|
16806
16842
|
var LCNNotificationValidator = external_exports.object({
|
|
16807
16843
|
type: LCNNotificationTypeEnumValidator,
|
|
@@ -17964,7 +18000,7 @@ async function deriveKeyFromPassword(password, salt, params = DEFAULT_KDF_PARAMS
|
|
|
17964
18000
|
hashLength: ARGON2_HASH_LENGTH,
|
|
17965
18001
|
outputType: "binary"
|
|
17966
18002
|
});
|
|
17967
|
-
return
|
|
18003
|
+
return Uint8Array.from(hash);
|
|
17968
18004
|
}
|
|
17969
18005
|
__name(deriveKeyFromPassword, "deriveKeyFromPassword");
|
|
17970
18006
|
async function encryptWithPassword(plaintext, password) {
|