@majikah/majik-key 0.1.3 → 0.1.5

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.
@@ -6,7 +6,7 @@ export interface EncryptionIdentity {
6
6
  raw: Uint8Array;
7
7
  };
8
8
  fingerprint: string;
9
- mlKemPublicKey?: Uint8Array;
9
+ mlKemPublicKey: Uint8Array;
10
10
  mlKemSecretKey?: Uint8Array;
11
11
  }
12
12
  /**
@@ -15,12 +15,6 @@ export interface EncryptionIdentity {
15
15
  * Core cryptographic engine.
16
16
  */
17
17
  export declare class EncryptionEngine {
18
- /**
19
- * Generates a random long-term identity keypair (X25519 only).
20
- * ML-KEM keys are not generated here since random identities
21
- * cannot be deterministically recovered from a mnemonic.
22
- */
23
- static generateIdentity(): Promise<EncryptionIdentity>;
24
18
  /**
25
19
  * Derive a complete identity from a BIP-39 mnemonic.
26
20
  *
@@ -11,33 +11,29 @@ export class EncryptionEngine {
11
11
  /* ================================
12
12
  * Identity
13
13
  * ================================ */
14
- /* ================================
15
- * Identity
16
- * ================================ */
17
- /**
18
- * Generates a random long-term identity keypair (X25519 only).
19
- * ML-KEM keys are not generated here since random identities
20
- * cannot be deterministically recovered from a mnemonic.
21
- */
22
- static async generateIdentity() {
23
- try {
24
- const ed = ed25519.generateKeyPair();
25
- const skCurve = ed2curve.convertSecretKey(ed.secretKey);
26
- const pkCurve = ed2curve.convertPublicKey(ed.publicKey);
27
- if (!skCurve || !pkCurve) {
28
- throw new CryptoError("Failed to convert Ed25519 keys to Curve25519");
29
- }
30
- const pkBytes = new Uint8Array(pkCurve);
31
- const skBytes = new Uint8Array(skCurve);
32
- const publicKey = { type: "public", raw: pkBytes };
33
- const privateKey = { type: "private", raw: skBytes };
34
- const fingerprint = fingerprintFromPublicRaw(pkBytes);
35
- return { publicKey, privateKey, fingerprint };
36
- }
37
- catch (err) {
38
- throw new CryptoError("Failed to generate identity", err);
39
- }
40
- }
14
+ // /**
15
+ // * Generates a random long-term identity keypair (X25519 only).
16
+ // * ML-KEM keys are not generated here since random identities
17
+ // * cannot be deterministically recovered from a mnemonic.
18
+ // */
19
+ // static async generateIdentity(): Promise<EncryptionIdentity> {
20
+ // try {
21
+ // const ed = ed25519.generateKeyPair();
22
+ // const skCurve = ed2curve.convertSecretKey(ed.secretKey);
23
+ // const pkCurve = ed2curve.convertPublicKey(ed.publicKey);
24
+ // if (!skCurve || !pkCurve) {
25
+ // throw new CryptoError("Failed to convert Ed25519 keys to Curve25519");
26
+ // }
27
+ // const pkBytes = new Uint8Array(pkCurve as Uint8Array);
28
+ // const skBytes = new Uint8Array(skCurve as Uint8Array);
29
+ // const publicKey = { type: "public", raw: pkBytes } as any;
30
+ // const privateKey = { type: "private", raw: skBytes } as any;
31
+ // const fingerprint = fingerprintFromPublicRaw(pkBytes);
32
+ // return { publicKey, privateKey, fingerprint };
33
+ // } catch (err) {
34
+ // throw new CryptoError("Failed to generate identity", err);
35
+ // }
36
+ // }
41
37
  /**
42
38
  * Derive a complete identity from a BIP-39 mnemonic.
43
39
  *
@@ -4,11 +4,11 @@ export interface MajikMessageIdentityJSON {
4
4
  id: string;
5
5
  user_id: string;
6
6
  public_key: string;
7
+ ml_key: string;
7
8
  phash: string;
8
9
  label: string;
9
10
  timestamp: string;
10
11
  restricted: boolean;
11
- kdfVersion?: number;
12
12
  }
13
13
  /**
14
14
  * MajikMessageIdentity
@@ -18,6 +18,7 @@ export declare class MajikMessageIdentity {
18
18
  private readonly _id;
19
19
  private readonly _userId;
20
20
  private readonly _publicKey;
21
+ private readonly _mlKey;
21
22
  private readonly _phash;
22
23
  private _label;
23
24
  private readonly _timestamp;
@@ -27,6 +27,7 @@ export class MajikMessageIdentity {
27
27
  _id;
28
28
  _userId;
29
29
  _publicKey;
30
+ _mlKey;
30
31
  _phash;
31
32
  _label;
32
33
  _timestamp;
@@ -38,6 +39,7 @@ export class MajikMessageIdentity {
38
39
  assertString(params.id, "id");
39
40
  assertString(params.userId, "user_id");
40
41
  assertString(params.publicKey, "public_key");
42
+ assertString(params.mlKey, "ml_key");
41
43
  assertString(params.phash, "phash");
42
44
  assertString(params.label, "label");
43
45
  assertISODate(params.timestamp, "timestamp");
@@ -45,6 +47,7 @@ export class MajikMessageIdentity {
45
47
  this._id = params.id;
46
48
  this._userId = params.userId;
47
49
  this._publicKey = params.publicKey;
50
+ this._mlKey = params.mlKey;
48
51
  this._phash = params.phash;
49
52
  this._label = params.label;
50
53
  this._timestamp = params.timestamp;
@@ -68,11 +71,12 @@ export class MajikMessageIdentity {
68
71
  assertString(label, "label");
69
72
  const timestamp = new Date().toISOString();
70
73
  const publicKey = account.publicKeyBase64;
71
- const phash = sha256(`${user.id}:${publicKey}:${account.id}`);
74
+ const phash = sha256(`${user.id}:${publicKey}:${account.id}:${account.mlKey}`);
72
75
  return new MajikMessageIdentity({
73
76
  id: account.id,
74
77
  userId: user.id,
75
78
  publicKey: publicKey,
79
+ mlKey: account.mlKey,
76
80
  phash,
77
81
  label,
78
82
  timestamp,
@@ -127,7 +131,7 @@ export class MajikMessageIdentity {
127
131
  * Detects tampering of id/public_key
128
132
  */
129
133
  validateIntegrity() {
130
- const expected = sha256(`${this._userId}:${this._publicKey}:${this._id}`);
134
+ const expected = sha256(`${this._userId}:${this._publicKey}:${this._id}:${this._mlKey}`);
131
135
  return expected === this._phash;
132
136
  }
133
137
  /**
@@ -136,7 +140,7 @@ export class MajikMessageIdentity {
136
140
  matches(userId, publicKey) {
137
141
  assertString(userId, "userId");
138
142
  assertString(publicKey, "publicKey");
139
- const hash = sha256(`${userId}:${publicKey}:${this._id}`);
143
+ const hash = sha256(`${userId}:${publicKey}:${this._id}:${this._mlKey}`);
140
144
  return hash === this._phash;
141
145
  }
142
146
  // ─────────────────────────────
@@ -147,6 +151,7 @@ export class MajikMessageIdentity {
147
151
  id: this._id,
148
152
  user_id: this._userId,
149
153
  public_key: this._publicKey,
154
+ ml_key: this._mlKey,
150
155
  phash: this._phash,
151
156
  label: this._label,
152
157
  timestamp: this._timestamp,
@@ -160,6 +165,7 @@ export class MajikMessageIdentity {
160
165
  id: obj.id,
161
166
  userId: obj.user_id,
162
167
  publicKey: obj.public_key,
168
+ mlKey: obj.ml_key,
163
169
  phash: obj.phash,
164
170
  label: obj.label,
165
171
  timestamp: obj.timestamp,
@@ -2,6 +2,7 @@ import { MajikMessageIdentityJSON } from "./database/system/identity";
2
2
  import { ISODateString } from "./types";
3
3
  export type SerializedMajikContact = Omit<MajikContactData, "publicKey"> & {
4
4
  publicKeyBase64: string;
5
+ mlKey: string;
5
6
  };
6
7
  export interface MajikContactMeta {
7
8
  label?: string;
@@ -16,6 +17,7 @@ export interface MajikContactData {
16
17
  raw: Uint8Array;
17
18
  };
18
19
  fingerprint: string;
20
+ mlKey: string;
19
21
  meta?: MajikContactMeta;
20
22
  majikah_registered?: boolean;
21
23
  }
@@ -24,6 +26,7 @@ export interface MajikContactCard {
24
26
  publicKey: string;
25
27
  fingerprint: string;
26
28
  label: string;
29
+ mlKey: string;
27
30
  }
28
31
  export declare class MajikContactError extends Error {
29
32
  cause?: unknown;
@@ -35,12 +38,13 @@ export declare class MajikContact {
35
38
  raw: Uint8Array;
36
39
  };
37
40
  readonly fingerprint: string;
41
+ readonly mlKey: string;
38
42
  meta: MajikContactMeta;
39
43
  private majikah_registered?;
40
44
  constructor(data: MajikContactData);
41
45
  static create(id: string, publicKey: CryptoKey | {
42
46
  raw: Uint8Array;
43
- }, fingerprint: string, meta?: Partial<MajikContactMeta>): MajikContact;
47
+ }, mlKey: string, fingerprint: string, meta?: Partial<MajikContactMeta>): MajikContact;
44
48
  private assertId;
45
49
  private assertPublicKey;
46
50
  private assertFingerprint;
@@ -1,6 +1,3 @@
1
- /* -------------------------------
2
- * Types
3
- * ------------------------------- */
4
1
  import { arrayBufferToBase64, base64ToArrayBuffer } from "./utils";
5
2
  /* -------------------------------
6
3
  * Errors
@@ -20,6 +17,7 @@ export class MajikContact {
20
17
  id;
21
18
  publicKey;
22
19
  fingerprint;
20
+ mlKey;
23
21
  meta;
24
22
  majikah_registered;
25
23
  constructor(data) {
@@ -29,6 +27,7 @@ export class MajikContact {
29
27
  this.id = data.id;
30
28
  this.publicKey = data.publicKey;
31
29
  this.fingerprint = data.fingerprint;
30
+ this.mlKey = data.mlKey;
32
31
  this.meta = {
33
32
  label: data.meta?.label || "",
34
33
  notes: data.meta?.notes || "",
@@ -37,12 +36,13 @@ export class MajikContact {
37
36
  updatedAt: data.meta?.updatedAt || new Date().toISOString(),
38
37
  };
39
38
  }
40
- static create(id, publicKey, fingerprint, meta) {
39
+ static create(id, publicKey, mlKey, fingerprint, meta) {
41
40
  return new MajikContact({
42
41
  id,
43
42
  publicKey,
44
43
  fingerprint,
45
44
  meta,
45
+ mlKey,
46
46
  });
47
47
  }
48
48
  assertId(id) {
@@ -145,6 +145,7 @@ export class MajikContact {
145
145
  meta: { ...this.meta },
146
146
  publicKeyBase64: await this.getPublicKeyBase64(),
147
147
  majikah_registered: this.majikah_registered,
148
+ mlKey: this.mlKey,
148
149
  };
149
150
  }
150
151
  /**
@@ -159,6 +160,7 @@ export class MajikContact {
159
160
  meta: serialized.meta,
160
161
  publicKey: { raw: publicKeyRaw },
161
162
  majikah_registered: serialized.majikah_registered,
163
+ mlKey: serialized.mlKey,
162
164
  });
163
165
  }
164
166
  catch (err) {
@@ -182,6 +184,7 @@ export class MajikContact {
182
184
  blocked: identityJSON.restricted,
183
185
  },
184
186
  majikah_registered: true,
187
+ mlKey: identityJSON.ml_key,
185
188
  };
186
189
  return new MajikContact(contactData);
187
190
  }
@@ -38,7 +38,7 @@ export interface MajikKeyIdentity {
38
38
  encryptedPrivateKey: ArrayBuffer;
39
39
  salt: string;
40
40
  kdfVersion: KDF_VERSION;
41
- mlKemPublicKey?: Uint8Array;
41
+ mlKemPublicKey: Uint8Array;
42
42
  mlKemSecretKey?: Uint8Array;
43
43
  }
44
44
  export interface SerializedIdentity {
@@ -62,7 +62,7 @@ export interface MajikKeyConstructorOptions {
62
62
  label?: string;
63
63
  timestamp?: Date;
64
64
  kdfVersion?: KDF_VERSION;
65
- mlKemPublicKey?: Uint8Array;
65
+ mlKemPublicKey: Uint8Array;
66
66
  mlKemSecretKey?: Uint8Array;
67
67
  encryptedMlKemSecretKey?: ArrayBuffer;
68
68
  encryptedMlKemSecretKeyBase64?: string;
@@ -83,7 +83,7 @@ export declare class MajikKey {
83
83
  private _salt;
84
84
  private _label;
85
85
  private _kdfVersion;
86
- private _mlKemPublicKey?;
86
+ private _mlKemPublicKey;
87
87
  private _mlKemSecretKey?;
88
88
  private _encryptedMlKemSecretKey?;
89
89
  private _encryptedMlKemSecretKeyBase64?;
package/dist/majik-key.js CHANGED
@@ -25,7 +25,7 @@ import { generateMnemonic } from "@scure/bip39";
25
25
  import { aesGcmDecrypt, aesGcmEncrypt, deriveKeyFromPassphraseArgon2, deriveKeyFromMnemonicArgon2, deriveKeyFromPassphrase, generateRandomBytes, IV_LENGTH, } from "./core/crypto/crypto-provider";
26
26
  import { EncryptionEngine } from "./core/crypto/encryption-engine";
27
27
  import { MajikContact } from "./core/majik-contact";
28
- import { arrayBufferToBase64, arrayToBase64, base64ToArrayBuffer, concatUint8Arrays, utf8ToBase64, base64ToUtf8, seedStringToArray, seedArrayToString, } from "./core/utils";
28
+ import { arrayBufferToBase64, arrayToBase64, base64ToArrayBuffer, concatUint8Arrays, utf8ToBase64, base64ToUtf8, seedStringToArray, seedArrayToString, base64ToUint8Array, } from "./core/utils";
29
29
  import { wordlist } from "@scure/bip39/wordlists/english";
30
30
  import { KDF_VERSION, KEY_ALGO, MAJIK_MNEMONIC_SALT, } from "./core/crypto/constants";
31
31
  import { MajikKeyValidator } from "./core/validator";
@@ -171,10 +171,7 @@ export class MajikKey {
171
171
  const anyParsed = parsed;
172
172
  const publicKeyBuffer = base64ToArrayBuffer(validated.publicKey);
173
173
  const encryptedPrivateKeyBuffer = base64ToArrayBuffer(validated.encryptedPrivateKey);
174
- let mlKemPublicKey;
175
- if (anyParsed.mlKemPublicKey) {
176
- mlKemPublicKey = new Uint8Array(base64ToArrayBuffer(anyParsed.mlKemPublicKey));
177
- }
174
+ const mlKemPublicKey = base64ToUint8Array(anyParsed.mlKemPublicKey);
178
175
  let encryptedMlKemSecretKey;
179
176
  let encryptedMlKemSecretKeyBase64;
180
177
  if (anyParsed.encryptedMlKemSecretKey) {
@@ -397,11 +394,13 @@ export class MajikKey {
397
394
  }
398
395
  }
399
396
  toContact() {
397
+ const mlKeyBase64 = arrayToBase64(this._mlKemPublicKey);
400
398
  return new MajikContact({
401
399
  id: this._id,
402
400
  publicKey: this._publicKey,
403
401
  fingerprint: this._fingerprint,
404
402
  meta: { label: this._label },
403
+ mlKey: mlKeyBase64,
405
404
  });
406
405
  }
407
406
  toKeyIdentity() {
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.1.3",
5
+ "version": "0.1.5",
6
6
  "license": "Apache-2.0",
7
7
  "author": "Zelijah",
8
8
  "main": "./dist/index.js",