@majikah/majik-key 0.1.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/README.md ADDED
@@ -0,0 +1,911 @@
1
+ # Majik Key
2
+
3
+ [![Developed by Zelijah](https://img.shields.io/badge/Developed%20by-Zelijah-red?logo=github&logoColor=white)](https://thezelijah.world) ![GitHub Sponsors](https://img.shields.io/github/sponsors/jedlsf?style=plastic&label=Sponsors&link=https%3A%2F%2Fgithub.com%2Fsponsors%2Fjedlsf)
4
+
5
+ **Majik Key** is a seed phrase account library for creating, managing, and parsing mnemonic-based cryptographic accounts (Majik Keys). Generate deterministic key pairs from BIP39 seed phrases with simple, developer-friendly APIs.
6
+
7
+ ![npm](https://img.shields.io/npm/v/@majikah/majik-key) ![npm downloads](https://img.shields.io/npm/dm/@majikah/majik-key) ![npm bundle size](https://img.shields.io/bundlephobia/min/%40thezelijah%2Fmajik-key) [![License](https://img.shields.io/badge/License-Apache_2.0-blue.svg)](https://opensource.org/licenses/Apache-2.0) ![TypeScript](https://img.shields.io/badge/TypeScript-Ready-blue)
8
+
9
+
10
+
11
+ ---
12
+ - [Majik Key](#majik-key)
13
+ - [Overview](#overview)
14
+ - [What is a Majik Key?](#what-is-a-majik-key)
15
+ - [Use Cases](#use-cases)
16
+ - [Features](#features)
17
+ - [Security First](#security-first)
18
+ - [BIP39 Compliance](#bip39-compliance)
19
+ - [Developer Friendly](#developer-friendly)
20
+ - [Import/Export](#importexport)
21
+ - [Interoperability](#interoperability)
22
+ - [Installation](#installation)
23
+ - [Quick Start](#quick-start)
24
+ - [API Reference](#api-reference)
25
+ - [Static Methods](#static-methods)
26
+ - [`MajikKey.create(mnemonic, passphrase, label?)`](#majikkeycreatemnemonic-passphrase-label)
27
+ - [`MajikKey.fromJSON(json)`](#majikkeyfromjsonjson)
28
+ - [`MajikKey.fromMnemonicJSON(mnemonicJson, passphrase, label?)`](#majikkeyfrommnemonicjsonmnemonicjson-passphrase-label)
29
+ - [`MajikKey.importFromMnemonicBackup(backup, mnemonic, passphrase, label?)`](#majikkeyimportfrommnemonicbackupbackup-mnemonic-passphrase-label)
30
+ - [`MajikKey.generateMnemonic(strength?)`](#majikkeygeneratemnemonicstrength)
31
+ - [`MajikKey.validateMnemonic(mnemonic)`](#majikkeyvalidatemnemonicmnemonic)
32
+ - [Instance Methods](#instance-methods)
33
+ - [`unlock(passphrase)`](#unlockpassphrase)
34
+ - [`lock()`](#lock)
35
+ - [`verify(passphrase)`](#verifypassphrase)
36
+ - [`updateLabel(newLabel)`](#updatelabelnewlabel)
37
+ - [`updatePassphrase(currentPassphrase, newPassphrase)`](#updatepassphrasecurrentpassphrase-newpassphrase)
38
+ - [`getPrivateKey()`](#getprivatekey)
39
+ - [`getPrivateKeyBase64()`](#getprivatekeybase64)
40
+ - [`toJSON()`](#tojson)
41
+ - [`toString(pretty?)`](#tostringpretty)
42
+ - [`toMnemonicJSON(mnemonic, passphrase?)`](#tomnemonicjsonmnemonic-passphrase)
43
+ - [`exportMnemonicBackup(mnemonic)`](#exportmnemonicbackupmnemonic)
44
+ - [`toContact()`](#tocontact)
45
+ - [`toMajikMessageIdentity(user, options?)`](#tomajikmessageidentityuser-options)
46
+ - [Getters](#getters)
47
+ - [`id: string`](#id-string)
48
+ - [`fingerprint: string`](#fingerprint-string)
49
+ - [`publicKey: CryptoKey | { raw: Uint8Array }`](#publickey-cryptokey---raw-uint8array-)
50
+ - [`publicKeyBase64: string`](#publickeybase64-string)
51
+ - [`label: string`](#label-string)
52
+ - [`backup: string`](#backup-string)
53
+ - [`timestamp: Date`](#timestamp-date)
54
+ - [`isLocked: boolean`](#islocked-boolean)
55
+ - [`isUnlocked: boolean`](#isunlocked-boolean)
56
+ - [`metadata: MajikKeyMetadata`](#metadata-majikkeymetadata)
57
+ - [Usage Examples](#usage-examples)
58
+ - [Example 1: Create and Manage a Key](#example-1-create-and-manage-a-key)
59
+ - [Example 2: Lock/Unlock Pattern](#example-2-lockunlock-pattern)
60
+ - [Example 3: Backup and Recovery](#example-3-backup-and-recovery)
61
+ - [Example 4: Update Passphrase](#example-4-update-passphrase)
62
+ - [Example 5: Verify Passphrase](#example-5-verify-passphrase)
63
+ - [Integration with Majik Message](#integration-with-majik-message)
64
+ - [Importing to Majik Message](#importing-to-majik-message)
65
+ - [Converting to Majik Message Identity](#converting-to-majik-message-identity)
66
+ - [Security Considerations](#security-considerations)
67
+ - [Best Practices](#best-practices)
68
+ - [Security Features](#security-features)
69
+ - [What NOT to Do](#what-not-to-do)
70
+ - [What TO Do](#what-to-do)
71
+ - [Tips \& Reminders](#tips--reminders)
72
+ - [For Developers](#for-developers)
73
+ - [For Users](#for-users)
74
+ - [Related Projects](#related-projects)
75
+ - [Majik Message](#majik-message)
76
+ - [Contributing](#contributing)
77
+ - [License](#license)
78
+ - [Author](#author)
79
+ - [About the Developer](#about-the-developer)
80
+ - [Contact](#contact)
81
+
82
+
83
+ ---
84
+
85
+ ## Overview
86
+
87
+ **Majik Key** is a comprehensive library for managing seed phrase-based cryptographic accounts. It provides a secure, intuitive way to create, store, and manage mnemonic-based identities with built-in encryption, backup, and recovery features.
88
+
89
+ ### What is a Majik Key?
90
+
91
+ A Majik Key is a seed phrase account that:
92
+ - Derives cryptographic key pairs from BIP39 mnemonic phrases
93
+ - Encrypts private keys at rest with a user-defined passphrase
94
+ - Supports secure backup and recovery via mnemonic encryption
95
+ - Provides locked/unlocked state management for enhanced security
96
+ - Is fully compatible with **Majik Message** and other Majikah products
97
+
98
+ ### Use Cases
99
+
100
+ - **Majik Message Integration**: Create seed phrase accounts that can be imported directly into Majik Message
101
+ - **Cryptographic Identity Management**: Manage multiple identities with deterministic key derivation
102
+ - **Secure Messaging**: Generate signing keys for end-to-end encrypted communication
103
+ - **Blockchain Applications**: Create wallet-like accounts from mnemonic phrases
104
+ - **Majikah Ecosystem**: Use across all Majikah products and services
105
+
106
+ ---
107
+
108
+ ## Features
109
+
110
+ ### Security First
111
+ - **Encrypted at Rest**: Private keys are encrypted with PBKDF2-derived keys (200,000 iterations)
112
+ - **AES-GCM Encryption**: Industry-standard authenticated encryption
113
+ - **Locked/Unlocked States**: Private keys only exist in memory when explicitly unlocked
114
+ - **Per-Identity Salts**: Each account uses a unique salt for encryption
115
+
116
+ ### BIP39 Compliance
117
+ - **Standard Mnemonic Generation**: Generate 12 or 24-word seed phrases
118
+ - **Mnemonic Validation**: Built-in BIP39 validation
119
+ - **Deterministic Key Derivation**: Same mnemonic always produces the same keys
120
+
121
+ ### Developer Friendly
122
+ - **TypeScript Support**: Full type definitions included
123
+ - **Simple API**: Intuitive CRUD operations
124
+ - **Error Handling**: Comprehensive error messages with `MajikKeyError`
125
+ - **Method Chaining**: Fluent API for common operations
126
+
127
+ ### Import/Export
128
+ - **JSON Serialization**: Safe storage format (no private keys exposed)
129
+ - **Mnemonic Backup**: Export/import encrypted backups using mnemonic phrases
130
+ - **MnemonicJSON Format**: Compatible format for seed phrase storage
131
+
132
+ ### Interoperability
133
+ - **Majik Message Compatible**: Seamlessly import/export to Majik Message
134
+ - **Majik Contact Integration**: Convert keys to contact format
135
+ - **Majikah Ecosystem**: Works across all Majikah products
136
+
137
+ ---
138
+
139
+ ## Installation
140
+
141
+ ```bash
142
+ # Using npm
143
+ npm install @majikah/majik-key
144
+
145
+ ```
146
+
147
+ ---
148
+
149
+ ## Quick Start
150
+
151
+ ```ts
152
+ import { MajikKey } from '@majikah/majik-key';
153
+
154
+ // Generate a new mnemonic
155
+ const mnemonic = MajikKey.generateMnemonic(); // 12 words
156
+ console.log('Save this mnemonic:', mnemonic);
157
+
158
+ // Create a new Majik Key (unlocked state)
159
+ const key = await MajikKey.create(
160
+ mnemonic,
161
+ 'my-secure-passphrase',
162
+ 'My First Key'
163
+ );
164
+
165
+ console.log('Key ID:', key.id);
166
+ console.log('Fingerprint:', key.fingerprint);
167
+ console.log('Is Unlocked:', key.isUnlocked); // true
168
+
169
+ // Lock the key (clear private keys from memory)
170
+ key.lock();
171
+ console.log('Is Locked:', key.isLocked); // true
172
+
173
+ // Unlock when needed
174
+ await key.unlock('my-secure-passphrase');
175
+ console.log('Is Unlocked:', key.isUnlocked); // true
176
+
177
+ // Access private key (only when unlocked)
178
+ const privateKey = key.getPrivateKey();
179
+ const privateKeyBase64 = key.getPrivateKeyBase64();
180
+
181
+ // Save to storage (private keys never included)
182
+ const json = key.toJSON();
183
+ localStorage.setItem('myKey', JSON.stringify(json));
184
+
185
+ // Load from storage (locked state)
186
+ const loadedKey = MajikKey.fromJSON(json);
187
+ await loadedKey.unlock('my-secure-passphrase');
188
+ ```
189
+
190
+ ---
191
+
192
+ ## API Reference
193
+
194
+ ### Static Methods
195
+
196
+ #### `MajikKey.create(mnemonic, passphrase, label?)`
197
+ Create a new Majik Key from a mnemonic phrase.
198
+
199
+ **Parameters:**
200
+ - `mnemonic: string` - BIP39 mnemonic phrase (12-24 words)
201
+ - `passphrase: string` - Passphrase to encrypt the private key at rest
202
+ - `label?: string` - Optional label for the key
203
+
204
+ **Returns:** `Promise<MajikKey>` - A new unlocked MajikKey instance
205
+
206
+ **Example:**
207
+ ```ts
208
+ const mnemonic = 'witch collapse practice feed shame open despair creek road again ice least';
209
+ const key = await MajikKey.create(mnemonic, 'my-password', 'Personal Account');
210
+
211
+ ```
212
+
213
+ ---
214
+
215
+ #### `MajikKey.fromJSON(json)`
216
+ Load a Majik Key from JSON (locked state).
217
+
218
+ **Parameters:**
219
+ - `json: MajikKeyJSON | string` - JSON object or string
220
+
221
+ **Returns:** `MajikKey` - A locked MajikKey instance
222
+
223
+ **Example:**
224
+ ```ts
225
+ const json = localStorage.getItem('myKey');
226
+ const key = MajikKey.fromJSON(json);
227
+ await key.unlock('my-password');
228
+ ```
229
+
230
+ ---
231
+
232
+ #### `MajikKey.fromMnemonicJSON(mnemonicJson, passphrase, label?)`
233
+ Create a Majik Key from MnemonicJSON format.
234
+
235
+ **Parameters:**
236
+ - `mnemonicJson: MnemonicJSON | string` - MnemonicJSON object or string
237
+ - `passphrase: string` - Passphrase to encrypt the key at rest
238
+ - `label?: string` - Optional label for the key
239
+
240
+ **Returns:** `Promise<MajikKey>` - A new unlocked MajikKey instance
241
+
242
+ **Example:**
243
+ ```ts
244
+ const mnemonicData = {
245
+ id: 'backup-id',
246
+ seed: ['word1', 'word2', ...],
247
+ phrase: 'optional-encryption-phrase'
248
+ };
249
+
250
+ const key = await MajikKey.fromMnemonicJSON(mnemonicData, 'my-password');
251
+ ```
252
+
253
+ ---
254
+
255
+ #### `MajikKey.importFromMnemonicBackup(backup, mnemonic, passphrase, label?)`
256
+ Import a Majik Key from a mnemonic-encrypted backup.
257
+
258
+ **Parameters:**
259
+ - `backup: string` - Base64-encoded backup string
260
+ - `mnemonic: string` - The mnemonic phrase used to encrypt the backup
261
+ - `passphrase: string` - Passphrase to encrypt the imported key
262
+ - `label?: string` - Optional label for the key
263
+
264
+ **Returns:** `Promise<MajikKey>` - A new unlocked MajikKey instance
265
+
266
+ **Example:**
267
+ ```ts
268
+ const backupString = 'eT8xY2F...'; // From exportMnemonicBackup()
269
+ const key = await MajikKey.importFromMnemonicBackup(
270
+ backupString,
271
+ mnemonic,
272
+ 'new-password',
273
+ 'Restored Account'
274
+ );
275
+ ```
276
+
277
+ ---
278
+
279
+ #### `MajikKey.generateMnemonic(strength?)`
280
+ Generate a new BIP39 mnemonic phrase.
281
+
282
+ **Parameters:**
283
+ - `strength?: 128 | 256` - Entropy strength (128 = 12 words, 256 = 24 words). Default: 128
284
+
285
+ **Returns:** `string` - A new mnemonic phrase
286
+
287
+ **Example:**
288
+ ```ts
289
+ const mnemonic12 = MajikKey.generateMnemonic(); // 12 words
290
+ const mnemonic24 = MajikKey.generateMnemonic(256); // 24 words
291
+ ```
292
+
293
+ ---
294
+
295
+ #### `MajikKey.validateMnemonic(mnemonic)`
296
+ Validate a BIP39 mnemonic phrase.
297
+
298
+ **Parameters:**
299
+ - `mnemonic: string` - Mnemonic phrase to validate
300
+
301
+ **Returns:** `boolean` - true if valid, false otherwise
302
+
303
+ **Example:**
304
+ ```ts
305
+ const isValid = MajikKey.validateMnemonic('witch collapse practice...');
306
+ ```
307
+
308
+ ---
309
+
310
+ ### Instance Methods
311
+
312
+ #### `unlock(passphrase)`
313
+ Unlock the Majik Key by decrypting the private key.
314
+
315
+ **Parameters:**
316
+ - `passphrase: string` - Passphrase to decrypt the private key
317
+
318
+ **Returns:** `Promise<this>` - This instance for chaining
319
+
320
+ **Throws:** `MajikKeyError` if passphrase is incorrect or key is already unlocked
321
+
322
+ **Example:**
323
+ ```ts
324
+ await key.unlock('my-password');
325
+ ```
326
+
327
+ ---
328
+
329
+ #### `lock()`
330
+ Lock the Majik Key by clearing private keys from memory.
331
+
332
+ **Returns:** `this` - This instance for chaining
333
+
334
+ **Example:**
335
+ ```ts
336
+ key.lock();
337
+ ```
338
+
339
+ ---
340
+
341
+ #### `verify(passphrase)`
342
+ Verify that a passphrase can decrypt the private key.
343
+
344
+ **Parameters:**
345
+ - `passphrase: string` - Passphrase to verify
346
+
347
+ **Returns:** `Promise<boolean>` - true if valid, false otherwise
348
+
349
+ **Example:**
350
+ ```ts
351
+ const isValid = await key.verify('my-password');
352
+ ```
353
+
354
+ ---
355
+
356
+ #### `updateLabel(newLabel)`
357
+ Update the label of the Majik Key.
358
+
359
+ **Parameters:**
360
+ - `newLabel: string` - New label value
361
+
362
+ **Returns:** `this` - This instance for chaining
363
+
364
+ **Example:**
365
+ ```ts
366
+ key.updateLabel('Work Account');
367
+ ```
368
+
369
+ ---
370
+
371
+ #### `updatePassphrase(currentPassphrase, newPassphrase)`
372
+ Change the passphrase used to encrypt the private key.
373
+
374
+ **Parameters:**
375
+ - `currentPassphrase: string` - Current passphrase
376
+ - `newPassphrase: string` - New passphrase
377
+
378
+ **Returns:** `Promise<this>` - This instance for chaining
379
+
380
+ **Throws:** `MajikKeyError` if current passphrase is incorrect
381
+
382
+ **Example:**
383
+ ```ts
384
+ await key.updatePassphrase('old-password', 'new-password');
385
+ ```
386
+
387
+ ---
388
+
389
+ #### `getPrivateKey()`
390
+ Get the private key (only when unlocked).
391
+
392
+ **Returns:** `CryptoKey | { raw: Uint8Array }` - The private key
393
+
394
+ **Throws:** `MajikKeyError` if the key is locked
395
+
396
+ **Example:**
397
+ ```ts
398
+ const privateKey = key.getPrivateKey();
399
+ ```
400
+
401
+ ---
402
+
403
+ #### `getPrivateKeyBase64()`
404
+ Get the private key as base64 (only when unlocked).
405
+
406
+ **Returns:** `string` - The private key in base64 format
407
+
408
+ **Throws:** `MajikKeyError` if the key is locked
409
+
410
+ **Example:**
411
+ ```ts
412
+ const privateKeyBase64 = key.getPrivateKeyBase64();
413
+ ```
414
+
415
+ ---
416
+
417
+ #### `toJSON()`
418
+ Export to JSON format (safe for storage).
419
+
420
+ **Returns:** `MajikKeyJSON` - JSON representation (private keys never included)
421
+
422
+ **Example:**
423
+ ```ts
424
+ const json = key.toJSON();
425
+ localStorage.setItem('myKey', JSON.stringify(json));
426
+ ```
427
+
428
+ ---
429
+
430
+ #### `toString(pretty?)`
431
+ Export to JSON string.
432
+
433
+ **Parameters:**
434
+ - `pretty?: boolean` - Whether to pretty-print. Default: false
435
+
436
+ **Returns:** `string` - JSON string representation
437
+
438
+ **Example:**
439
+ ```ts
440
+ const jsonString = key.toString(true);
441
+ ```
442
+
443
+ ---
444
+
445
+ #### `toMnemonicJSON(mnemonic, passphrase?)`
446
+ Export to MnemonicJSON format.
447
+
448
+ **Parameters:**
449
+ - `mnemonic: string` - The BIP39 mnemonic phrase
450
+ - `passphrase?: string` - Optional passphrase
451
+
452
+ **Returns:** `MnemonicJSON` - MnemonicJSON object
453
+
454
+ **Throws:** `MajikKeyError` if the key is locked
455
+
456
+ **Example:**
457
+ ```ts
458
+ const mnemonicData = key.toMnemonicJSON(mnemonic, 'encryption-phrase');
459
+ ```
460
+
461
+ ---
462
+
463
+ #### `exportMnemonicBackup(mnemonic)`
464
+ Export a mnemonic-encrypted backup.
465
+
466
+ **Parameters:**
467
+ - `mnemonic: string` - The original mnemonic phrase
468
+
469
+ **Returns:** `Promise<string>` - Base64-encoded backup string
470
+
471
+ **Throws:** `MajikKeyError` if the key is locked
472
+
473
+ **Example:**
474
+ ```ts
475
+ const backup = await key.exportMnemonicBackup(mnemonic);
476
+ ```
477
+
478
+ ---
479
+
480
+ #### `toContact()`
481
+ Create a MajikContact from this Majik Key.
482
+
483
+ **Returns:** `MajikContact` - A MajikContact instance
484
+
485
+ **Example:**
486
+ ```ts
487
+ const contact = key.toContact();
488
+ ```
489
+
490
+ ---
491
+
492
+ #### `toMajikMessageIdentity(user, options?)`
493
+ Convert to MajikMessageIdentity for use in Majik Message.
494
+
495
+ **Parameters:**
496
+ - `user: MajikUser` - MajikUser instance
497
+ - `options?: { label?: string, restricted?: boolean }` - Optional configuration
498
+
499
+ **Returns:** `Promise<MajikMessageIdentity>` - MajikMessageIdentity instance
500
+
501
+ **Example:**
502
+ ```ts
503
+ const identity = await key.toMajikMessageIdentity(user, {
504
+ label: 'My Account',
505
+ restricted: false
506
+ });
507
+ ```
508
+
509
+ ---
510
+
511
+ ### Getters
512
+
513
+ #### `id: string`
514
+ The unique identifier (fingerprint).
515
+
516
+ #### `fingerprint: string`
517
+ The cryptographic fingerprint.
518
+
519
+ #### `publicKey: CryptoKey | { raw: Uint8Array }`
520
+ The public key.
521
+
522
+ #### `publicKeyBase64: string`
523
+ The public key in base64 format.
524
+
525
+ #### `label: string`
526
+ The user-defined label.
527
+
528
+ #### `backup: string`
529
+ The mnemonic backup identifier.
530
+
531
+ #### `timestamp: Date`
532
+ The creation timestamp.
533
+
534
+ #### `isLocked: boolean`
535
+ Whether the key is currently locked.
536
+
537
+ #### `isUnlocked: boolean`
538
+ Whether the key is currently unlocked.
539
+
540
+ #### `metadata: MajikKeyMetadata`
541
+ Safe metadata object (no sensitive data).
542
+
543
+ **Example:**
544
+ ```ts
545
+ console.log(key.metadata);
546
+ // {
547
+ // id: 'fingerprint-id',
548
+ // fingerprint: 'fingerprint-id',
549
+ // label: 'My Key',
550
+ // timestamp: Date,
551
+ // isLocked: false
552
+ // }
553
+ ```
554
+
555
+ ---
556
+
557
+ ## Usage Examples
558
+
559
+ ### Example 1: Create and Manage a Key
560
+
561
+ ```ts
562
+ import { MajikKey } from '@majikah/majik-key';
563
+
564
+ async function createKey() {
565
+ // Generate mnemonic
566
+ const mnemonic = MajikKey.generateMnemonic();
567
+ console.log('🔑 Save this mnemonic safely:', mnemonic);
568
+
569
+ // Create key
570
+ const key = await MajikKey.create(
571
+ mnemonic,
572
+ 'secure-passphrase',
573
+ 'Personal Account'
574
+ );
575
+
576
+ console.log('✅ Key created!');
577
+ console.log('ID:', key.id);
578
+ console.log('Fingerprint:', key.fingerprint);
579
+ console.log('Label:', key.label);
580
+
581
+ // Save to storage
582
+ const json = key.toJSON();
583
+ localStorage.setItem('myKey', JSON.stringify(json));
584
+
585
+ return { key, mnemonic };
586
+ }
587
+
588
+ createKey();
589
+ ```
590
+
591
+ ---
592
+
593
+ ### Example 2: Lock/Unlock Pattern
594
+
595
+ ```ts
596
+ import { MajikKey } from '@majikah/majik-key';
597
+
598
+ async function secureLockPattern() {
599
+ const json = localStorage.getItem('myKey');
600
+ const key = MajikKey.fromJSON(json);
601
+
602
+ // Key is locked by default when loaded from JSON
603
+ console.log('Locked:', key.isLocked); // true
604
+
605
+ try {
606
+ // This will throw an error
607
+ const privateKey = key.getPrivateKey();
608
+ } catch (error) {
609
+ console.log('❌ Cannot access private key when locked');
610
+ }
611
+
612
+ // Unlock to use private key
613
+ await key.unlock('secure-passphrase');
614
+ console.log('Unlocked:', key.isUnlocked); // true
615
+
616
+ // Now we can access private keys
617
+ const privateKey = key.getPrivateKey();
618
+ const privateKeyBase64 = key.getPrivateKeyBase64();
619
+
620
+ // Use the key for cryptographic operations
621
+ // ...
622
+
623
+ // Lock again when done
624
+ key.lock();
625
+ console.log('🔒 Key locked again');
626
+ }
627
+
628
+ secureLockPattern();
629
+ ```
630
+
631
+ ---
632
+
633
+ ### Example 3: Backup and Recovery
634
+
635
+ ```ts
636
+ import { MajikKey } from '@majikah/majik-key';
637
+
638
+ async function backupAndRecover() {
639
+ const mnemonic = MajikKey.generateMnemonic();
640
+ const key = await MajikKey.create(mnemonic, 'password123', 'Original Key');
641
+
642
+ //Download as Blob JSON File
643
+
644
+ const jsonData = await key.toMnemonicJSON(mnemonic, 'password123');
645
+ const jsonString = JSON.stringify(jsonData);
646
+ const blob = new Blob([jsonString], {
647
+ type: "application/json;charset=utf-8",
648
+ });
649
+ downloadBlob(
650
+ blob,
651
+ "json",
652
+ `${label} | ${key.id} | SEED KEY`,
653
+ );
654
+
655
+
656
+
657
+ // Later... recover from backup
658
+
659
+ //Parse the downloaded JSON into this object
660
+ const jsonData: MnemonicJSON = {
661
+ id: "abc123",
662
+ seed: ["word1", "word2", ...],
663
+ phrase: 'password123',
664
+ };
665
+
666
+ const recoveredKey = await MajikKey.importFromMnemonicBackup(
667
+ jsonData.id,
668
+ seedArrayToString(jsonData.seed),
669
+ jsonData.phrase,
670
+ 'Recovered Key'
671
+ );
672
+
673
+ console.log('✅ Key recovered!');
674
+ console.log('Same fingerprint:', key.fingerprint === recoveredKey.fingerprint);
675
+ }
676
+
677
+ backupAndRecover();
678
+ ```
679
+
680
+
681
+ ---
682
+
683
+ ### Example 4: Update Passphrase
684
+
685
+ ```ts
686
+ import { MajikKey } from '@majikah/majik-key';
687
+
688
+ async function changePassphrase() {
689
+ const json = localStorage.getItem('myKey');
690
+ const key = MajikKey.fromJSON(json);
691
+
692
+ // Must unlock first
693
+ await key.unlock('old-password');
694
+
695
+ // Change passphrase
696
+ await key.updatePassphrase('old-password', 'new-secure-password');
697
+ console.log('✅ Passphrase updated!');
698
+
699
+ // Save updated key
700
+ localStorage.setItem('myKey', JSON.stringify(key.toJSON()));
701
+
702
+ // Verify new passphrase works
703
+ key.lock();
704
+ await key.unlock('new-secure-password');
705
+ console.log('✅ New passphrase verified!');
706
+ }
707
+
708
+ changePassphrase();
709
+ ```
710
+
711
+ ---
712
+
713
+ ### Example 5: Verify Passphrase
714
+
715
+ ```ts
716
+ import { MajikKey } from '@majikah/majik-key';
717
+
718
+ async function verifyPassphrase() {
719
+ const json = localStorage.getItem('myKey');
720
+ const key = MajikKey.fromJSON(json);
721
+
722
+ // Verify without unlocking
723
+ const isValid = await key.verify('user-entered-password');
724
+
725
+ if (isValid) {
726
+ console.log('✅ Passphrase is correct');
727
+ await key.unlock('user-entered-password');
728
+ // Proceed with operations...
729
+ } else {
730
+ console.log('❌ Invalid passphrase');
731
+ // Show error to user
732
+ }
733
+ }
734
+
735
+ verifyPassphrase();
736
+ ```
737
+
738
+ ---
739
+
740
+ ## Integration with Majik Message
741
+
742
+ Majik Key is fully compatible with **Majik Message** as its seed phrase account implementation. Keys created with Majik Key can be directly imported into Majik Message.
743
+
744
+ ### Importing to Majik Message
745
+
746
+ ```ts
747
+ import { MajikKey } from '@majikah/majik-key';
748
+
749
+ async function importToMajikMessage() {
750
+ // Create or load a Majik Key
751
+ const mnemonic = MajikKey.generateMnemonic();
752
+ const key = await MajikKey.create(mnemonic, 'password', 'Message Account');
753
+
754
+ // Export to MnemonicJSON format for Majik Message
755
+ const mnemonicData = key.toMnemonicJSON(mnemonic, 'password');
756
+ const jsonString = JSON.stringify(mnemonicData);
757
+
758
+ // Download this blob as a JSON locally
759
+ const blob = new Blob([jsonString], {
760
+ type: "application/json;charset=utf-8",
761
+ });
762
+
763
+ // This mnemonicData can be imported directly into Majik Message
764
+ // as a seed phrase account
765
+ console.log('Import the saved JSON to Majik Message:', mnemonicData);
766
+ }
767
+ ```
768
+
769
+ ### Converting to Majik Message Identity
770
+
771
+ ```ts
772
+ import { MajikKey } from '@majikah/majik-key';
773
+ import { MajikUser } from '@thezelijah/majik-user';
774
+
775
+ async function createMessageIdentity() {
776
+ const mnemonic = MajikKey.generateMnemonic();
777
+ const key = await MajikKey.create(mnemonic, 'password', 'Message Identity');
778
+
779
+ // Create/parse a MajikUser instance
780
+ const user = new MajikUser({
781
+ username: 'myusername',
782
+ // ... other user properties
783
+ });
784
+
785
+ // Convert to Majik Message Identity
786
+ const identity = await key.toMajikMessageIdentity(user, {
787
+ label: 'My Message Account',
788
+ restricted: false
789
+ });
790
+
791
+ console.log('Majik Message Identity created:', identity);
792
+ }
793
+ ```
794
+
795
+ ---
796
+
797
+ ## Security Considerations
798
+
799
+ ### Best Practices
800
+
801
+ 1. **Never expose mnemonics**: Treat mnemonic phrases like passwords. Never log, transmit, or store them unencrypted.
802
+
803
+ 2. **Use strong passphrases**: Choose passphrases with high entropy (mix of letters, numbers, symbols).
804
+
805
+ 3. **Lock when not in use**: Always lock keys when private key access is not needed.
806
+
807
+ 4. **Secure storage**: Store JSON exports in secure locations (encrypted databases, secure storage APIs).
808
+
809
+ 5. **Backup mnemonics**: Store mnemonic phrases in multiple secure locations (password manager, paper backup, hardware wallet).
810
+
811
+ ### Security Features
812
+
813
+ - **PBKDF2 Key Derivation**: 200,000 iterations with SHA-256
814
+ - **AES-GCM Encryption**: Authenticated encryption with random IVs
815
+ - **Per-Identity Salts**: Unique salt for each key prevents rainbow table attacks
816
+ - **No Private Key Exposure**: Private keys never included in JSON exports
817
+ - **Memory Management**: Private keys cleared from memory when locked
818
+
819
+ ### What NOT to Do
820
+
821
+ ❌ **DON'T** store mnemonics in code or version control
822
+ ❌ **DON'T** transmit mnemonics over insecure channels
823
+ ❌ **DON'T** use weak passphrases like "password123"
824
+ ❌ **DON'T** share mnemonics or passphrases with anyone
825
+ ❌ **DON'T** screenshot or photograph mnemonics
826
+
827
+ ### What TO Do
828
+
829
+ ✅ **DO** use password managers for mnemonic storage
830
+ ✅ **DO** write mnemonics on paper and store securely
831
+ ✅ **DO** use hardware security modules when possible
832
+ ✅ **DO** test recovery procedures before relying on them
833
+ ✅ **DO** keep multiple encrypted backups in different locations
834
+
835
+ ---
836
+
837
+ ### Tips & Reminders
838
+
839
+ #### For Developers
840
+
841
+ - **Remember**: Always validate user input before creating or unlocking keys.
842
+
843
+ - **Security**: Never log sensitive data (mnemonics, private keys, passphrases) in production.
844
+
845
+ - **Performance**: Lock keys when not in use to free memory and reduce attack surface.
846
+
847
+ - **Testing**: Test backup/recovery procedures in development before deploying to production.
848
+
849
+ - **Dependencies**: Keep `@scure/bip39` and other crypto dependencies up to date.
850
+
851
+ #### For Users
852
+
853
+ - **Backup**: Always keep multiple backups of your mnemonic phrase in secure locations.
854
+
855
+ - **Passphrase**: Use a strong, unique passphrase for each Majik Key.
856
+
857
+ - **Recovery**: Test your ability to recover keys from backups before you need to.
858
+
859
+ - **Organization**: Use meaningful labels to identify different keys.
860
+ - **Loss Prevention**: Losing your mnemonic phrase means permanent loss of access to your key.
861
+
862
+ ---
863
+
864
+ ## Related Projects
865
+
866
+ ### [Majik Message](https://message.majikah.solutions)
867
+ Secure messaging platform using Majik Keys
868
+
869
+ [Read more about Majik Message here](https://majikah.solutions/products/majik-message)
870
+
871
+ [![Majik Message Thumbnail](https://gydzizwxtftlmsdaiouw.supabase.co/storage/v1/object/public/bucket-majikah-public/main/Majikah_MajikMessage_SocialCard.webp)](https://message.majikah.solutions)
872
+
873
+ > Click the image to try Majik Message live.
874
+
875
+ [Read Docs](https://majikah.solutions/products/majik-message/docs)
876
+
877
+
878
+ Also available on [Microsoft Store](https://apps.microsoft.com/detail/9pmjgvzzjspn) for free.
879
+
880
+ [Official Repository](https://github.com/Majikah/majik-message)
881
+ [SDK Library](https://www.npmjs.com/package/@majikah/majik-message)
882
+
883
+ ---
884
+
885
+ ## Contributing
886
+
887
+ If you want to contribute or help extend support to more platforms, reach out via email. All contributions are welcome!
888
+
889
+ ---
890
+
891
+ ## License
892
+
893
+ [Apache-2.0](LICENSE) — free for personal and commercial use.
894
+
895
+ ---
896
+ ## Author
897
+
898
+ Made with 💙 by [@thezelijah](https://github.com/jedlsf)
899
+
900
+ ## About the Developer
901
+
902
+ - **Developer**: Josef Elijah Fabian
903
+ - **GitHub**: [https://github.com/jedlsf](https://github.com/jedlsf)
904
+ - **Project Repository**: [https://github.com/jedlsf/majik-key](https://github.com/jedlsf/majik-key)
905
+
906
+ ---
907
+
908
+ ## Contact
909
+
910
+ - **Business Email**: [business@thezelijah.world](mailto:business@thezelijah.world)
911
+ - **Official Website**: [https://www.thezelijah.world](https://www.thezelijah.world)