@majikah/majik-universal-id-client 0.0.1
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/core/contacts/majik-contact-directory.d.ts +37 -0
- package/dist/core/contacts/majik-contact-directory.js +191 -0
- package/dist/core/contacts/majik-contact.d.ts +89 -0
- package/dist/core/contacts/majik-contact.js +212 -0
- package/dist/core/crypto/constants.d.ts +56 -0
- package/dist/core/crypto/constants.js +51 -0
- package/dist/core/crypto/keystore.d.ts +228 -0
- package/dist/core/crypto/keystore.js +575 -0
- package/dist/core/identity.d.ts +63 -0
- package/dist/core/identity.js +177 -0
- package/dist/core/types.d.ts +86 -0
- package/dist/core/types.js +7 -0
- package/dist/core/utils/APITranscoder.d.ts +114 -0
- package/dist/core/utils/APITranscoder.js +305 -0
- package/dist/core/utils/idb-majik-system.d.ts +15 -0
- package/dist/core/utils/idb-majik-system.js +44 -0
- package/dist/core/utils/majik-file-utils.d.ts +16 -0
- package/dist/core/utils/majik-file-utils.js +153 -0
- package/dist/core/utils/utilities.d.ts +18 -0
- package/dist/core/utils/utilities.js +80 -0
- package/dist/index.d.ts +9 -0
- package/dist/index.js +8 -0
- package/dist/majik-universal-id-client.d.ts +757 -0
- package/dist/majik-universal-id-client.js +1618 -0
- package/package.json +55 -0
|
@@ -0,0 +1,228 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MajikKeyStore.ts
|
|
3
|
+
*
|
|
4
|
+
* IDB persistence + in-memory cache layer for MajikKey accounts.
|
|
5
|
+
* Replaces MajikKeyStore as the account storage backend for MajikMessage.
|
|
6
|
+
*
|
|
7
|
+
*/
|
|
8
|
+
import { MajikKey, SerializedIdentity } from "@majikah/majik-key";
|
|
9
|
+
/**
|
|
10
|
+
* The legacy SerializedIdentity shape from MajikKeyStore.
|
|
11
|
+
* Used only for reading old IDB records during migration.
|
|
12
|
+
*/
|
|
13
|
+
interface LegacySerializedIdentity {
|
|
14
|
+
id: string;
|
|
15
|
+
publicKey: string;
|
|
16
|
+
fingerprint: string;
|
|
17
|
+
encryptedPrivateKey?: string;
|
|
18
|
+
salt?: string;
|
|
19
|
+
}
|
|
20
|
+
export declare class MajikKeyStoreError extends Error {
|
|
21
|
+
cause?: unknown;
|
|
22
|
+
constructor(message: string, cause?: unknown);
|
|
23
|
+
}
|
|
24
|
+
export declare class MajikKeyStore {
|
|
25
|
+
private static _deviceID;
|
|
26
|
+
private static _dbPromise;
|
|
27
|
+
/**
|
|
28
|
+
* In-memory cache of all loaded MajikKey instances (locked or unlocked).
|
|
29
|
+
* Keyed by account ID. Unlocked state lives inside each MajikKey instance.
|
|
30
|
+
*/
|
|
31
|
+
private static _keys;
|
|
32
|
+
/**
|
|
33
|
+
* Optional callback invoked when UI needs to prompt for a passphrase.
|
|
34
|
+
* Should return the passphrase string or Promise<string>.
|
|
35
|
+
*/
|
|
36
|
+
static onUnlockRequested?: (id: string) => string | Promise<string>;
|
|
37
|
+
/**
|
|
38
|
+
* Initialize the store with a device/user ID.
|
|
39
|
+
* Must be called before any other method.
|
|
40
|
+
*/
|
|
41
|
+
static init(deviceID: string): void;
|
|
42
|
+
private static _getDB;
|
|
43
|
+
private static _put;
|
|
44
|
+
private static _get;
|
|
45
|
+
private static _getAll;
|
|
46
|
+
private static _delete;
|
|
47
|
+
private static _getLegacy;
|
|
48
|
+
private static _getAllLegacy;
|
|
49
|
+
/**
|
|
50
|
+
* Store a MajikKey in IDB and cache it in memory.
|
|
51
|
+
* The key must be unlocked (toKeyIdentity() is called to warm the memory cache).
|
|
52
|
+
* The full MajikKeyJSON is persisted — including ML-KEM keys and kdfVersion.
|
|
53
|
+
*/
|
|
54
|
+
static save(key: MajikKey): Promise<void>;
|
|
55
|
+
/**
|
|
56
|
+
* Load a MajikKey by ID. Checks memory cache first, then IDB, then legacy IDB.
|
|
57
|
+
* Returns null if not found anywhere.
|
|
58
|
+
*
|
|
59
|
+
* Loaded keys are LOCKED. Call unlock(id, passphrase) to unlock.
|
|
60
|
+
*/
|
|
61
|
+
static load(id: string): Promise<MajikKey | null>;
|
|
62
|
+
/**
|
|
63
|
+
* Load all MajikKeys from IDB (new store + legacy store merged).
|
|
64
|
+
* Legacy accounts are included but NOT migrated until explicitly unlocked.
|
|
65
|
+
*/
|
|
66
|
+
static loadAll(): Promise<MajikKey[]>;
|
|
67
|
+
static getAccount(id: string): Promise<MajikKey>;
|
|
68
|
+
/**
|
|
69
|
+
* Unlock a stored MajikKey with the given passphrase.
|
|
70
|
+
* Automatically dispatches to the correct KDF (PBKDF2 for old accounts, Argon2id for new).
|
|
71
|
+
* Updates the in-memory cache with the unlocked instance.
|
|
72
|
+
*/
|
|
73
|
+
static unlock(id: string, passphrase: string): Promise<MajikKey>;
|
|
74
|
+
/**
|
|
75
|
+
* Lock a MajikKey — clears private keys from memory.
|
|
76
|
+
*/
|
|
77
|
+
static lock(id: string): void;
|
|
78
|
+
/**
|
|
79
|
+
* Lock all loaded accounts.
|
|
80
|
+
*/
|
|
81
|
+
static lockAll(): void;
|
|
82
|
+
/**
|
|
83
|
+
* Get the private key of an unlocked account.
|
|
84
|
+
* Throws if not found or not unlocked — caller must call unlock() first.
|
|
85
|
+
*/
|
|
86
|
+
static getPrivateKey(idOrFingerprint: string): CryptoKey | {
|
|
87
|
+
raw: Uint8Array;
|
|
88
|
+
};
|
|
89
|
+
/**
|
|
90
|
+
* Get the ML-KEM secret key of an unlocked account.
|
|
91
|
+
* Returns undefined if the account has no ML-KEM keys (pre-migration).
|
|
92
|
+
*/
|
|
93
|
+
static getMlKemSecretKey(idOrFingerprint: string): Uint8Array | undefined;
|
|
94
|
+
/**
|
|
95
|
+
* Get a loaded MajikKey by ID or fingerprint.
|
|
96
|
+
*/
|
|
97
|
+
static get(idOrFingerprint: string): MajikKey | undefined;
|
|
98
|
+
/**
|
|
99
|
+
* List all currently loaded MajikKey instances (locked + unlocked).
|
|
100
|
+
*/
|
|
101
|
+
static list(): MajikKey[];
|
|
102
|
+
/**
|
|
103
|
+
* Check whether an account exists by ID or fingerprint.
|
|
104
|
+
* Checks memory cache first, then IDB.
|
|
105
|
+
*/
|
|
106
|
+
static has(idOrFingerprint: string): Promise<boolean>;
|
|
107
|
+
/**
|
|
108
|
+
* Validate whether a passphrase can decrypt the stored account.
|
|
109
|
+
* Does NOT unlock or mutate any state.
|
|
110
|
+
*/
|
|
111
|
+
static isPassphraseValid(id: string, passphrase: string): Promise<boolean>;
|
|
112
|
+
/**
|
|
113
|
+
* Delete an account from IDB and memory cache.
|
|
114
|
+
*/
|
|
115
|
+
static delete(id: string): Promise<void>;
|
|
116
|
+
/**
|
|
117
|
+
* Ensure an account is unlocked, prompting for passphrase if needed.
|
|
118
|
+
* Drop-in replacement for MajikMessage.ensureIdentityUnlocked().
|
|
119
|
+
*
|
|
120
|
+
* @param id - Account ID
|
|
121
|
+
* @param promptFn - Optional passphrase prompt function
|
|
122
|
+
* @returns The unlocked account's X25519 private key
|
|
123
|
+
*/
|
|
124
|
+
static ensureUnlocked(id: string, promptFn?: (id: string) => string | Promise<string>): Promise<CryptoKey | {
|
|
125
|
+
raw: Uint8Array;
|
|
126
|
+
}>;
|
|
127
|
+
/**
|
|
128
|
+
* Reconstruct a locked MajikKey from a MajikKeyStore SerializedIdentity.
|
|
129
|
+
*
|
|
130
|
+
* The legacy format has:
|
|
131
|
+
* - id, publicKey (base64), fingerprint
|
|
132
|
+
* - encryptedPrivateKey (base64, PBKDF2-encrypted)
|
|
133
|
+
* - salt (base64, 16 bytes)
|
|
134
|
+
* - NO: kdfVersion (implied PBKDF2), NO: ML-KEM keys, NO: label, NO: backup
|
|
135
|
+
*
|
|
136
|
+
* The resulting MajikKey will:
|
|
137
|
+
* - Have kdfVersion: PBKDF2 (so unlock() uses the correct KDF)
|
|
138
|
+
* - Have hasMlKem: false (until importFromMnemonicBackup() is called)
|
|
139
|
+
* - Be locked (private key not in memory)
|
|
140
|
+
*
|
|
141
|
+
* After unlock(), MajikMessage can call key.migrate(passphrase) to upgrade
|
|
142
|
+
* the KDF to Argon2id. For full ML-KEM upgrade, importFromMnemonicBackup()
|
|
143
|
+
* is required (mnemonic needed).
|
|
144
|
+
*
|
|
145
|
+
* This method is also the answer to your question: it's how MajikKey
|
|
146
|
+
* accepts a SerializedIdentity from the existing MajikKeyStore IDB.
|
|
147
|
+
*/
|
|
148
|
+
static fromLegacySerializedIdentity(si: LegacySerializedIdentity): MajikKey;
|
|
149
|
+
/**
|
|
150
|
+
* Migrate all legacy MajikKeyStore accounts to the new MajikKeyJSON format.
|
|
151
|
+
*
|
|
152
|
+
* Reads all records from the old "identities" IDB store, reconstructs
|
|
153
|
+
* them as MajikKey instances, and writes them to the new "majik-keys" store.
|
|
154
|
+
* Does NOT upgrade KDF or add ML-KEM keys — that requires the passphrase/mnemonic.
|
|
155
|
+
*
|
|
156
|
+
* Call this once on app startup after MajikKeyStore → MajikKeyStore transition.
|
|
157
|
+
* Safe to call multiple times (already-migrated accounts are skipped).
|
|
158
|
+
*/
|
|
159
|
+
static migrateAllLegacy(): Promise<{
|
|
160
|
+
migrated: number;
|
|
161
|
+
skipped: number;
|
|
162
|
+
}>;
|
|
163
|
+
/**
|
|
164
|
+
* Migrate a legacy MajikKeyStore account to the new MajikKeyJSON format.
|
|
165
|
+
*
|
|
166
|
+
* Reconstructs them as MajikKey instances, and writes them to the new "majik-keys" store.
|
|
167
|
+
* Does NOT upgrade KDF or add ML-KEM keys — that requires the passphrase/mnemonic.
|
|
168
|
+
*
|
|
169
|
+
* Call this once on app startup after MajikKeyStore → MajikKeyStore transition.
|
|
170
|
+
* Safe to call multiple times (already-migrated accounts are skipped).
|
|
171
|
+
*/
|
|
172
|
+
static migrate(identity: SerializedIdentity): Promise<{
|
|
173
|
+
success: boolean;
|
|
174
|
+
message: string;
|
|
175
|
+
}>;
|
|
176
|
+
/**
|
|
177
|
+
* Drop-in for MajikKeyStore.addMajikKey().
|
|
178
|
+
* Saves the FULL MajikKeyJSON to IDB (not just 5 fields).
|
|
179
|
+
*/
|
|
180
|
+
static addMajikKey(key: MajikKey): Promise<void>;
|
|
181
|
+
/**
|
|
182
|
+
* Drop-in for MajikKeyStore.unlockIdentity().
|
|
183
|
+
*/
|
|
184
|
+
static unlockIdentity(id: string, passphrase: string): Promise<MajikKey>;
|
|
185
|
+
/**
|
|
186
|
+
* Drop-in for MajikKeyStore.lockIdentity().
|
|
187
|
+
*/
|
|
188
|
+
static lockIdentity(id: string): void;
|
|
189
|
+
/**
|
|
190
|
+
* Drop-in for MajikKeyStore.hasIdentity().
|
|
191
|
+
*/
|
|
192
|
+
static hasIdentity(fingerprint: string): Promise<boolean>;
|
|
193
|
+
/**
|
|
194
|
+
* Drop-in for MajikKeyStore.isPassphraseValid().
|
|
195
|
+
*/
|
|
196
|
+
static isPassphraseValidFor(id: string, passphrase: string): Promise<boolean>;
|
|
197
|
+
/**
|
|
198
|
+
* Drop-in for MajikKeyStore.updatePassphrase().
|
|
199
|
+
* Correctly upgrades KDF to Argon2id on re-encryption (MajikKeyStore never did this).
|
|
200
|
+
*/
|
|
201
|
+
static updatePassphrase(id: string, currentPassphrase: string, newPassphrase: string): Promise<void>;
|
|
202
|
+
/**
|
|
203
|
+
* Drop-in for MajikKeyStore.listStoredIdentities().
|
|
204
|
+
* Returns all stored MajikKey instances (loaded from IDB if needed).
|
|
205
|
+
*/
|
|
206
|
+
static listStoredKeys(): Promise<MajikKey[]>;
|
|
207
|
+
/**
|
|
208
|
+
* Drop-in for MajikKeyStore.deleteIdentity().
|
|
209
|
+
*/
|
|
210
|
+
static deleteIdentity(id: string): Promise<void>;
|
|
211
|
+
static deleteAll(): Promise<void>;
|
|
212
|
+
/**
|
|
213
|
+
* Drop-in for MajikKeyStore.generateMnemonic().
|
|
214
|
+
*/
|
|
215
|
+
static generateMnemonic(strength?: 128 | 256): string;
|
|
216
|
+
/**
|
|
217
|
+
* Drop-in for MajikKeyStore.exportIdentityMnemonicBackup().
|
|
218
|
+
* The account must be unlocked.
|
|
219
|
+
*/
|
|
220
|
+
static exportMnemonicBackup(id: string, mnemonic: string): Promise<string>;
|
|
221
|
+
/**
|
|
222
|
+
* Drop-in for MajikKeyStore.importIdentityFromMnemonicBackup().
|
|
223
|
+
* Fully upgrades the account: Argon2id KDF + ML-KEM keys in one step.
|
|
224
|
+
*/
|
|
225
|
+
static importFromMnemonicBackup(backupBase64: string, mnemonic: string, passphrase: string, label?: string): Promise<MajikKey>;
|
|
226
|
+
private static _findKey;
|
|
227
|
+
}
|
|
228
|
+
export {};
|