@majikah/majik-key 0.2.10 → 0.2.11

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.
@@ -21,6 +21,12 @@ export interface MajikKeyJSON {
21
21
  encryptedMlDsaSecretKey?: string;
22
22
  mnemonicLanguage?: MnemonicLanguage;
23
23
  }
24
+ export interface MajikKeyDangerousJSON extends MajikKeyJSON {
25
+ privateKeyBase64: string;
26
+ mlKemSecretKeyBase64: string;
27
+ edSecretKeyBase64: string;
28
+ mlDsaSecretKeyBase64: string;
29
+ }
24
30
  export interface MajikKeyMetadata {
25
31
  id: string;
26
32
  fingerprint: string;
@@ -23,7 +23,7 @@
23
23
  */
24
24
  import { MajikContact, MajikContactMeta } from "@majikah/majik-contact";
25
25
  import { KDF_VERSION } from "./core/crypto/constants";
26
- import type { MajikKeyJSON, MajikKeyMetadata, MnemonicJSON } from "./core/types";
26
+ import type { MajikKeyDangerousJSON, MajikKeyJSON, MajikKeyMetadata, MnemonicJSON } from "./core/types";
27
27
  import { MajikMessageIdentity } from "./core/database/system/identity";
28
28
  import { MajikUser } from "@thezelijah/majik-user";
29
29
  import { MnemonicLanguage } from "./core/crypto/wordlist";
@@ -142,6 +142,20 @@ export declare class MajikKey {
142
142
  get hasSigningKeys(): boolean;
143
143
  static create(mnemonic: string, passphrase: string, label?: string, mnemonicLanguage?: MnemonicLanguage): Promise<MajikKey>;
144
144
  static fromJSON(json: MajikKeyJSON | string): MajikKey;
145
+ /**
146
+ * Export a fully unlocked MajikKey with all raw private keys.
147
+ * ⚠️ DANGEROUS — output contains unencrypted private key material.
148
+ * Only use for server-side secrets injection.
149
+ * Never log, store in a database, or transmit over the network.
150
+ */
151
+ toDangerousJSON(): MajikKeyDangerousJSON;
152
+ /**
153
+ * Reconstruct a fully unlocked MajikKey from a dangerous JSON export.
154
+ * ⚠️ DANGEROUS — input contains unencrypted private key material.
155
+ * Intended for server-side use only (e.g. TSA signing key loaded from Cloudflare Secrets).
156
+ * No KDF is involved — reconstruction is instant.
157
+ */
158
+ static fromDangerousJSON(json: MajikKeyDangerousJSON | string): MajikKey;
145
159
  toMnemonicJSON(mnemonic: string, passphrase?: string): MnemonicJSON;
146
160
  static fromMnemonicJSON(mnemonicJson: MnemonicJSON | string, passphrase: string, label?: string): Promise<MajikKey>;
147
161
  updateLabel(newLabel: string): this;
package/dist/majik-key.js CHANGED
@@ -271,6 +271,81 @@ export class MajikKey {
271
271
  throw new MajikKeyError("Failed to parse MajikKey from JSON", err);
272
272
  }
273
273
  }
274
+ /**
275
+ * Export a fully unlocked MajikKey with all raw private keys.
276
+ * ⚠️ DANGEROUS — output contains unencrypted private key material.
277
+ * Only use for server-side secrets injection.
278
+ * Never log, store in a database, or transmit over the network.
279
+ */
280
+ toDangerousJSON() {
281
+ if (this.isLocked)
282
+ throw new MajikKeyError("MajikKey must be unlocked to export dangerous JSON.");
283
+ if (!this._edSecretKey ||
284
+ !this._mlDsaSecretKey ||
285
+ !this._mlKemSecretKey ||
286
+ !this._privateKeyBase64)
287
+ throw new MajikKeyError("MajikKey is missing secret keys — re-import via importFromMnemonicBackup() first.");
288
+ return {
289
+ ...this.toJSON(),
290
+ privateKeyBase64: this._privateKeyBase64,
291
+ mlKemSecretKeyBase64: arrayToBase64(this._mlKemSecretKey),
292
+ edSecretKeyBase64: arrayToBase64(this._edSecretKey),
293
+ mlDsaSecretKeyBase64: arrayToBase64(this._mlDsaSecretKey),
294
+ };
295
+ }
296
+ /**
297
+ * Reconstruct a fully unlocked MajikKey from a dangerous JSON export.
298
+ * ⚠️ DANGEROUS — input contains unencrypted private key material.
299
+ * Intended for server-side use only (e.g. TSA signing key loaded from Cloudflare Secrets).
300
+ * No KDF is involved — reconstruction is instant.
301
+ */
302
+ static fromDangerousJSON(json) {
303
+ try {
304
+ const parsed = typeof json === "string" ? JSON.parse(json) : json;
305
+ if (!parsed.id ||
306
+ !parsed.fingerprint ||
307
+ !parsed.publicKey ||
308
+ !parsed.privateKeyBase64 ||
309
+ !parsed.edPublicKey ||
310
+ !parsed.edSecretKeyBase64 ||
311
+ !parsed.mlDsaPublicKey ||
312
+ !parsed.mlDsaSecretKeyBase64 ||
313
+ !parsed.mlKemPublicKey ||
314
+ !parsed.mlKemSecretKeyBase64)
315
+ throw new MajikKeyError("Invalid MajikKeyDangerousJSON — missing required fields");
316
+ const privateKeyBytes = base64ToUint8Array(parsed.privateKeyBase64);
317
+ const edPublicKey = base64ToUint8Array(parsed.edPublicKey);
318
+ const edSecretKey = base64ToUint8Array(parsed.edSecretKeyBase64);
319
+ const mlDsaPublicKey = base64ToUint8Array(parsed.mlDsaPublicKey);
320
+ const mlDsaSecretKey = base64ToUint8Array(parsed.mlDsaSecretKeyBase64);
321
+ const mlKemPublicKey = base64ToUint8Array(parsed.mlKemPublicKey);
322
+ const mlKemSecretKey = base64ToUint8Array(parsed.mlKemSecretKeyBase64);
323
+ return new MajikKey({
324
+ id: parsed.id,
325
+ fingerprint: parsed.fingerprint,
326
+ publicKey: { raw: base64ToUint8Array(parsed.publicKey) },
327
+ publicKeyBase64: parsed.publicKey,
328
+ privateKey: { raw: privateKeyBytes },
329
+ privateKeyBase64: parsed.privateKeyBase64,
330
+ encryptedPrivateKey: new ArrayBuffer(0),
331
+ encryptedPrivateKeyBase64: parsed.encryptedPrivateKey,
332
+ salt: parsed.salt,
333
+ backup: parsed.backup,
334
+ kdfVersion: parsed?.kdfVersion || KDF_VERSION.ARGON2ID,
335
+ mlKemPublicKey,
336
+ mlKemSecretKey,
337
+ edPublicKey,
338
+ edSecretKey,
339
+ mlDsaPublicKey,
340
+ mlDsaSecretKey,
341
+ });
342
+ }
343
+ catch (err) {
344
+ if (err instanceof MajikKeyError)
345
+ throw err;
346
+ throw new MajikKeyError("Failed to reconstruct MajikKey from dangerous JSON", err);
347
+ }
348
+ }
274
349
  // ── MnemonicJSON ─────────────────────────────────────────────────────────────
275
350
  toMnemonicJSON(mnemonic, passphrase) {
276
351
  if (this.isLocked)
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.2.10",
5
+ "version": "0.2.11",
6
6
  "license": "Apache-2.0",
7
7
  "author": "Zelijah",
8
8
  "main": "./dist/index.js",