@majikah/majik-key 0.3.3 → 0.4.0

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 CHANGED
@@ -1,13 +1,16 @@
1
1
  # Majik Key
2
2
 
3
+ [![ZENODO](https://img.shields.io/badge/Read_the_Technical_Whitepaper_Here-1682D4?style=for-the-badge&logo=zenodo&logoColor=white)](https://doi.org/10.5281/zenodo.21339132)
3
4
 
4
5
 
5
6
  [![Developed by Zelijah](https://img.shields.io/badge/Developed%20by-Zelijah-red?logo=github&logoColor=white)](https://www.thezelijah.world) ![GitHub Sponsors](https://img.shields.io/github/sponsors/jedlsf?style=plastic&label=Sponsors&link=https%3A%2F%2Fgithub.com%2Fsponsors%2Fjedlsf)
6
7
 
7
- [![DOI](https://zenodo.org/badge/DOI/10.5281/zenodo.21339132.svg)](https://doi.org/10.5281/zenodo.21339132) ![npm](https://img.shields.io/npm/v/@majikah/majik-key) ![npm downloads](https://img.shields.io/npm/dm/@majikah/majik-key) ![TypeScript](https://img.shields.io/badge/TypeScript-Ready-blue) [![License](https://img.shields.io/badge/License-Apache_2.0-blue.svg)](https://opensource.org/licenses/Apache-2.0)
8
+
8
9
 
9
10
  **Majik Key** turns a single BIP-39 mnemonic into a complete cryptographic identity — encryption, classical + post-quantum signing, and (experimentally) Bitcoin and Solana keys — encrypted at rest and ready to plug into the rest of the Majikah ecosystem.
10
11
 
12
+ [![DOI](https://zenodo.org/badge/DOI/10.5281/zenodo.21339132.svg)](https://doi.org/10.5281/zenodo.21339132) ![npm](https://img.shields.io/npm/v/@majikah/majik-key) ![npm downloads](https://img.shields.io/npm/dm/@majikah/majik-key) ![TypeScript](https://img.shields.io/badge/TypeScript-Ready-blue) [![License](https://img.shields.io/badge/License-Apache_2.0-blue.svg)](https://opensource.org/licenses/Apache-2.0)
13
+
11
14
  ---
12
15
 
13
16
  ## Why Majik Key
@@ -1,16 +1,13 @@
1
+ import type { ED25519RawPublicKey, MajikKeyFingerprint, MLDSA87RawPublicKey, MLKEM768RawPublicKey, X25519RawKey } from "../types";
1
2
  export interface EncryptionIdentity {
2
- publicKey: {
3
- raw: Uint8Array;
4
- };
5
- privateKey: {
6
- raw: Uint8Array;
7
- };
8
- fingerprint: string;
9
- mlKemPublicKey: Uint8Array;
3
+ publicKey: X25519RawKey;
4
+ privateKey: X25519RawKey;
5
+ fingerprint: MajikKeyFingerprint;
6
+ mlKemPublicKey: MLKEM768RawPublicKey;
10
7
  mlKemSecretKey?: Uint8Array;
11
- edPublicKey: Uint8Array;
8
+ edPublicKey: ED25519RawPublicKey;
12
9
  edSecretKey: Uint8Array;
13
- mlDsaPublicKey: Uint8Array;
10
+ mlDsaPublicKey: MLDSA87RawPublicKey;
14
11
  mlDsaSecretKey: Uint8Array;
15
12
  }
16
13
  /**
@@ -41,9 +38,7 @@ export declare class EncryptionEngine {
41
38
  /**
42
39
  * Generates a SHA-256 fingerprint from a public key.
43
40
  */
44
- static fingerprintFromPublicKey(publicKey: CryptoKey | {
45
- raw: Uint8Array;
46
- }): Promise<string>;
41
+ static fingerprintFromPublicKey(publicKey: CryptoKey | X25519RawKey): Promise<string>;
47
42
  private static assertPublicKey;
48
43
  }
49
44
  export declare class CryptoError extends Error {
@@ -1,13 +1,21 @@
1
1
  import { MnemonicLanguage } from "./crypto/wordlist";
2
2
  /** ISO 8601 timestamp string, e.g. `"2026-07-11T00:00:00.000Z"`. */
3
3
  export type ISODateString = string;
4
- export type MajikMessageAccountID = string;
5
- export type MajikMessagePublicKey = string;
6
- export type MajikMessageChatID = string;
7
4
  /** Base64-encoded public key material. Safe to store, log, or transmit. */
8
5
  export type MajikKeyAddress = string;
9
6
  /** Base64-encoded SHA-256 digest of a MajikKey's X25519 public key. Doubles as the account `id`. */
10
7
  export type MajikKeyFingerprint = string;
8
+ export type ED25519PublicKey = string;
9
+ export type MLKEM768PublicKey = string;
10
+ export type MLDSA87PublicKey = string;
11
+ export type BitcoinPublicKey = string;
12
+ export type ED25519RawPublicKey = Uint8Array;
13
+ export type MLKEM768RawPublicKey = Uint8Array;
14
+ export type MLDSA87RawPublicKey = Uint8Array;
15
+ export type BitcoinRawPublicKey = Uint8Array;
16
+ export interface X25519RawKey {
17
+ raw: Uint8Array;
18
+ }
11
19
  /**
12
20
  * Safe, serializable snapshot of a MajikKey — what `toJSON()` / `toString()` produce.
13
21
  *
@@ -21,7 +29,7 @@ export type MajikKeyFingerprint = string;
21
29
  */
22
30
  export interface MajikKeyJSON {
23
31
  /** Account identifier. Equal to `fingerprint` for accounts created by this library. */
24
- id: string;
32
+ id: MajikKeyFingerprint;
25
33
  /** Human-readable, user-editable account name. */
26
34
  label: string;
27
35
  /** X25519 public key, base64. */
@@ -40,23 +48,23 @@ export interface MajikKeyJSON {
40
48
  */
41
49
  backup: string;
42
50
  /** Account creation time, ISO 8601. */
43
- timestamp: string;
51
+ timestamp: ISODateString;
44
52
  /** KDF used for every `encrypted*` field on this account: `1` = legacy PBKDF2 (read-only), `2` = Argon2id (current). Defaults to `1` if omitted. */
45
53
  kdfVersion?: number;
46
54
  /** ML-KEM-768 (FIPS-203) public key, base64. Post-quantum key encapsulation. */
47
- mlKemPublicKey?: string;
55
+ mlKemPublicKey?: MLKEM768PublicKey;
48
56
  /** AES-256-GCM-encrypted ML-KEM-768 secret key, base64. */
49
57
  encryptedMlKemSecretKey?: string;
50
58
  /** Ed25519 public key, base64. Classical signing — same keypair the X25519 identity key is converted from. */
51
- edPublicKey?: string;
59
+ edPublicKey?: ED25519PublicKey;
52
60
  /** AES-256-GCM-encrypted Ed25519 secret key, base64. */
53
61
  encryptedEdSecretKey?: string;
54
62
  /** ML-DSA-87 (FIPS-204) public key, base64. Post-quantum signing. */
55
- mlDsaPublicKey?: string;
63
+ mlDsaPublicKey?: MLDSA87PublicKey;
56
64
  /** AES-256-GCM-encrypted ML-DSA-87 secret key, base64. */
57
65
  encryptedMlDsaSecretKey?: string;
58
66
  /** @experimental secp256k1 Bitcoin public key, base64. Domain-separated BIP-32/84 derivation by default — see `MajikKeyBitcoinNamespace`. */
59
- btcPublicKey?: string;
67
+ btcPublicKey?: BitcoinPublicKey;
60
68
  /** @experimental AES-256-GCM-encrypted Bitcoin private key, base64. */
61
69
  encryptedBtcSecretKey?: string;
62
70
  /** BIP-39 wordlist language the original mnemonic was generated/validated against. Defaults to `"en"`. */
@@ -132,4 +140,5 @@ export interface MnemonicJSON {
132
140
  id: string;
133
141
  /** Optional passphrase, carried in plaintext for convenience during export/import. ⚠️ Not encrypted. */
134
142
  phrase?: string;
143
+ language?: MnemonicLanguage;
135
144
  }
@@ -23,11 +23,12 @@
23
23
  * installed, we throw a clear, actionable MajikKeyError instead of
24
24
  * failing module load.
25
25
  */
26
+ import { BitcoinRawPublicKey } from "../../types";
26
27
  export interface BitcoinKeypairMaterial {
27
28
  /** 32-byte secp256k1 private key. */
28
29
  privateKey: Uint8Array;
29
30
  /** 33-byte compressed secp256k1 public key. */
30
- publicKey: Uint8Array;
31
+ publicKey: BitcoinRawPublicKey;
31
32
  }
32
33
  export interface BitcoinDerivationOptions {
33
34
  /**
@@ -1,3 +1,4 @@
1
+ import { BitcoinRawPublicKey } from "../../types";
1
2
  /**
2
3
  * @experimental By default this is Majik's DOMAIN-SEPARATED Bitcoin key
3
4
  * (derived via `MAJIK_BITCOIN_DOMAIN_PATH`) — deterministic and fully
@@ -9,7 +10,7 @@
9
10
  */
10
11
  export interface MajikKeyBitcoinNamespace {
11
12
  /** 33-byte compressed secp256k1 public key. */
12
- readonly publicKey: Uint8Array;
13
+ readonly publicKey: BitcoinRawPublicKey;
13
14
  /** 32-byte secp256k1 private key. Handle with the same care as any private key. */
14
15
  readonly privateKey: Uint8Array;
15
16
  /** Native SegWit (bech32) address. Lazily loads @scure/btc-signer — throws if not installed. */
@@ -25,9 +25,10 @@
25
25
  * signing Ed25519 keypair AS-IS. Simpler, but means the same private
26
26
  * key secures two different protocols. Opt-in only.
27
27
  */
28
+ import { ED25519RawPublicKey } from "../../types";
28
29
  export interface SolanaKeypairMaterial {
29
30
  /** 32-byte Ed25519 / Solana public key. */
30
- publicKey: Uint8Array;
31
+ publicKey: ED25519RawPublicKey;
31
32
  /** 64-byte nacl-format secret key (32-byte seed || 32-byte public key). */
32
33
  secretKey: Uint8Array;
33
34
  }
@@ -1,10 +1,11 @@
1
+ import { ED25519RawPublicKey } from "../../types";
1
2
  /**
2
3
  * @experimental Web3 / blockchain integrations are experimental. This
3
4
  * namespace's shape may change without a major version bump.
4
5
  */
5
6
  export interface MajikKeySolanaNamespace {
6
7
  /** 32-byte Solana/Ed25519 public key. */
7
- readonly publicKey: Uint8Array;
8
+ readonly publicKey: ED25519RawPublicKey;
8
9
  /** 64-byte nacl-format secret key. Handle with the same care as any private key. */
9
10
  readonly secretKey: Uint8Array;
10
11
  /** Base58 Solana address — does not require @solana/kit. */
@@ -5,7 +5,7 @@
5
5
  */
6
6
  import { MajikContact, MajikContactMeta } from "@majikah/majik-contact";
7
7
  import { KDF_VERSION } from "./core/crypto/constants";
8
- import type { MajikKeyAddress, MajikKeyDangerousJSON, MajikKeyFingerprint, MajikKeyJSON, MajikKeyMetadata, MnemonicJSON } from "./core/types";
8
+ import type { BitcoinRawPublicKey, ED25519RawPublicKey, MajikKeyAddress, MajikKeyDangerousJSON, MajikKeyFingerprint, MajikKeyJSON, MajikKeyMetadata, MLDSA87RawPublicKey, MLKEM768RawPublicKey, MnemonicJSON, X25519RawKey } from "./core/types";
9
9
  import { MajikMessageIdentity } from "./core/database/system/identity";
10
10
  import { MajikUser } from "@thezelijah/majik-user";
11
11
  import { MnemonicLanguage } from "./core/crypto/wordlist";
@@ -24,17 +24,13 @@ import { MajikKeyWeb3Namespace, BitcoinDerivationOptions, BitcoinKeypairMaterial
24
24
  */
25
25
  export interface MajikKeyIdentity {
26
26
  /** Account identifier. Equal to `fingerprint` for accounts created by this library. */
27
- id: string;
28
- /** X25519 public key — native `CryptoKey` where WebCrypto supports it, otherwise a raw-bytes wrapper. */
29
- publicKey: {
30
- raw: Uint8Array;
31
- };
27
+ id: MajikKeyFingerprint;
28
+ /** X25519 public key */
29
+ publicKey: X25519RawKey;
32
30
  /** SHA-256 fingerprint of `publicKey`. */
33
31
  fingerprint: MajikKeyFingerprint;
34
32
  /** X25519 private key, decrypted into memory. ⚠️ Live key material — do not log or serialize directly. */
35
- privateKey: {
36
- raw: Uint8Array;
37
- };
33
+ privateKey: X25519RawKey;
38
34
  /** AES-256-GCM-encrypted X25519 private key (IV + ciphertext), as stored at rest. */
39
35
  encryptedPrivateKey: ArrayBuffer;
40
36
  /** Random salt used to derive the passphrase-based encryption key. Base64. */
@@ -106,9 +102,7 @@ export interface SerializedIdentity {
106
102
  */
107
103
  export interface MajikKeyConstructorOptions {
108
104
  id: string;
109
- publicKey: {
110
- raw: Uint8Array;
111
- };
105
+ publicKey: X25519RawKey;
112
106
  publicKeyBase64: MajikKeyAddress;
113
107
  fingerprint: MajikKeyFingerprint;
114
108
  encryptedPrivateKey: ArrayBuffer;
@@ -120,19 +114,17 @@ export interface MajikKeyConstructorOptions {
120
114
  timestamp?: Date;
121
115
  /** Defaults to legacy PBKDF2 (`KDF_VERSION.PBKDF2`) if omitted — see the private constructor. */
122
116
  kdfVersion?: KDF_VERSION;
123
- mlKemPublicKey: Uint8Array;
117
+ mlKemPublicKey: MLKEM768RawPublicKey;
124
118
  /** Present only when constructing an already-unlocked instance. ⚠️ Live key material. */
125
119
  mlKemSecretKey?: Uint8Array;
126
120
  encryptedMlKemSecretKey?: ArrayBuffer;
127
121
  encryptedMlKemSecretKeyBase64?: string;
128
122
  /** Present only when constructing an already-unlocked instance. ⚠️ Live key material. */
129
- privateKey?: {
130
- raw: Uint8Array;
131
- };
132
- edPublicKey?: Uint8Array;
123
+ privateKey?: X25519RawKey;
124
+ edPublicKey?: ED25519RawPublicKey;
133
125
  encryptedEdSecretKey?: ArrayBuffer;
134
126
  encryptedEdSecretKeyBase64?: string;
135
- mlDsaPublicKey?: Uint8Array;
127
+ mlDsaPublicKey?: MLDSA87RawPublicKey;
136
128
  encryptedMlDsaSecretKey?: ArrayBuffer;
137
129
  encryptedMlDsaSecretKeyBase64?: string;
138
130
  /** Present only when constructing an already-unlocked instance. ⚠️ Live key material. */
@@ -140,7 +132,7 @@ export interface MajikKeyConstructorOptions {
140
132
  /** Present only when constructing an already-unlocked instance. ⚠️ Live key material. */
141
133
  mlDsaSecretKey?: Uint8Array;
142
134
  /** @experimental secp256k1 Bitcoin public key. */
143
- btcPublicKey?: Uint8Array;
135
+ btcPublicKey?: BitcoinRawPublicKey;
144
136
  /** @experimental AES-256-GCM-encrypted Bitcoin private key. */
145
137
  encryptedBtcSecretKey?: ArrayBuffer;
146
138
  /** @experimental Base64 form of `encryptedBtcSecretKey`. */
@@ -220,13 +212,11 @@ export declare class MajikKey {
220
212
  private _encryptedBtcSecretKeyBase64?;
221
213
  private constructor();
222
214
  /** Account identifier. Equal to `fingerprint` for accounts created by this library. */
223
- get id(): string;
215
+ get id(): MajikKeyFingerprint;
224
216
  /** SHA-256 fingerprint of the X25519 public key. Stable identity anchor for the account. */
225
217
  get fingerprint(): MajikKeyFingerprint;
226
- /** X25519 public key — native `CryptoKey` where WebCrypto supports it, otherwise a raw-bytes wrapper. Always available, even when locked. */
227
- get publicKey(): CryptoKey | {
228
- raw: Uint8Array;
229
- };
218
+ /** X25519 public key. Always available, even when locked. */
219
+ get publicKey(): X25519RawKey;
230
220
  /** X25519 public key, base64-encoded. Always available, even when locked. */
231
221
  get publicKeyBase64(): MajikKeyAddress;
232
222
  /** Human-readable, user-editable account name. Update via `updateLabel()`. */
@@ -251,7 +241,7 @@ export declare class MajikKey {
251
241
  /** `true` if private key material is currently decrypted in memory. The inverse of `isLocked`. */
252
242
  get isUnlocked(): boolean;
253
243
  /** ML-KEM-768 (FIPS-203) public key. Post-quantum key encapsulation. Always available, even when locked. */
254
- get mlKemPublicKey(): Uint8Array;
244
+ get mlKemPublicKey(): MLKEM768RawPublicKey;
255
245
  /** ML-KEM-768 secret key. `undefined` unless the account is unlocked. ⚠️ Live key material — prefer `getMlKemSecretKey()` if you want a thrown error instead of `undefined` on locked accounts. */
256
246
  get mlKemSecretKey(): Uint8Array | undefined;
257
247
  /** `true` if this account has ML-KEM-768 keys (i.e. is post-quantum-encryption capable). `false` means it's a legacy account pending migration. */
@@ -263,7 +253,7 @@ export declare class MajikKey {
263
253
  * has no stored Bitcoin key material (e.g. it predates Web3 support and
264
254
  * hasn't been re-imported via `importFromMnemonicBackup()`).
265
255
  */
266
- get btcPublicKey(): Uint8Array | undefined;
256
+ get btcPublicKey(): BitcoinRawPublicKey | undefined;
267
257
  /** @experimental `true` if this account has a stored Bitcoin keypair. */
268
258
  get hasBitcoin(): boolean;
269
259
  /**
@@ -273,9 +263,9 @@ export declare class MajikKey {
273
263
  */
274
264
  get metadata(): MajikKeyMetadata;
275
265
  /** Ed25519 public key. Classical signing — same keypair the X25519 identity key is converted from. Always available, even when locked. */
276
- get edPublicKey(): Uint8Array | undefined;
266
+ get edPublicKey(): ED25519RawPublicKey | undefined;
277
267
  /** ML-DSA-87 (FIPS-204) public key. Post-quantum signing. Always available, even when locked. */
278
- get mlDsaPublicKey(): Uint8Array | undefined;
268
+ get mlDsaPublicKey(): MLDSA87RawPublicKey | undefined;
279
269
  /** `true` if this account has both Ed25519 and ML-DSA-87 signing keys. `false` means it's a legacy account pending migration. */
280
270
  get hasSigningKeys(): boolean;
281
271
  /**
@@ -331,9 +321,7 @@ export declare class MajikKey {
331
321
  lock(): this;
332
322
  unlock(passphrase: string): Promise<this>;
333
323
  verify(passphrase: string): Promise<boolean>;
334
- getPrivateKey(): CryptoKey | {
335
- raw: Uint8Array;
336
- };
324
+ getPrivateKey(): X25519RawKey;
337
325
  getPrivateKeyBase64(): string;
338
326
  getMlKemSecretKey(): Uint8Array;
339
327
  getEdSecretKey(): Uint8Array;
package/dist/majik-key.js CHANGED
@@ -125,7 +125,7 @@ export class MajikKey {
125
125
  get fingerprint() {
126
126
  return this._fingerprint;
127
127
  }
128
- /** X25519 public key — native `CryptoKey` where WebCrypto supports it, otherwise a raw-bytes wrapper. Always available, even when locked. */
128
+ /** X25519 public key. Always available, even when locked. */
129
129
  get publicKey() {
130
130
  return this._publicKey;
131
131
  }
@@ -478,6 +478,7 @@ export class MajikKey {
478
478
  id: this._backup,
479
479
  seed: seedStringToArray(mnemonic.trim()),
480
480
  phrase: passphrase?.trim() || undefined,
481
+ language: this._mnemonicLanguage,
481
482
  };
482
483
  }
483
484
  static async fromMnemonicJSON(mnemonicJson, passphrase, label, options = {
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "@majikah/majik-key",
3
3
  "type": "module",
4
4
  "description": "A post-quantum ready seed phrase account library for the Majikah ecosystem. Manages deterministic X25519 and ML-KEM-768 identities with Argon2id protection and seamless legacy account migration.",
5
- "version": "0.3.3",
5
+ "version": "0.4.0",
6
6
  "license": "Apache-2.0",
7
7
  "author": "Zelijah",
8
8
  "main": "./dist/index.js",
@@ -56,11 +56,11 @@
56
56
  },
57
57
  "dependencies": {
58
58
  "@majikah/majik-contact": "^0.0.6",
59
- "@noble/curves": "^2.2.0",
60
- "@noble/hashes": "^2.2.0",
61
- "@noble/post-quantum": "^0.6.1",
62
- "@scure/bip32": "^2.2.0",
63
- "@scure/bip39": "^2.2.0",
59
+ "@noble/curves": "^2.3.0",
60
+ "@noble/hashes": "^2.3.0",
61
+ "@noble/post-quantum": "^0.7.0",
62
+ "@scure/bip32": "^2.3.0",
63
+ "@scure/bip39": "^2.3.0",
64
64
  "@stablelib/aes": "^2.0.1",
65
65
  "@stablelib/ed25519": "^2.1.0",
66
66
  "@stablelib/gcm": "^2.0.1",
@@ -72,10 +72,10 @@
72
72
  "hash-wasm": "^4.12.0"
73
73
  },
74
74
  "devDependencies": {
75
- "@scure/btc-signer": "^2.2.0",
76
- "@solana/kit": "^7.0.0",
75
+ "@scure/btc-signer": "^2.3.0",
76
+ "@solana/kit": "^7.1.0",
77
77
  "@types/ed2curve": "^0.2.4",
78
- "@types/node": "^26.1.1",
78
+ "@types/node": "^26.2.0",
79
79
  "typescript": "^7.0.2",
80
80
  "vitest": "^4.1.10"
81
81
  },