@majikah/majik-key 0.7.0 → 1.0.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 +566 -175
- package/dist/core/backup/index.d.ts +4 -4
- package/dist/core/backup/index.js +3 -3
- package/dist/core/backup/majik-key-backup.d.ts +3 -3
- package/dist/core/backup/majik-key-backup.js +5 -5
- package/dist/core/backup/types.d.ts +1 -1
- package/dist/core/backup/utils.js +1 -1
- package/dist/core/backup/validator.d.ts +1 -1
- package/dist/core/backup/validator.js +1 -1
- package/dist/core/crypto/constants.d.ts +35 -11
- package/dist/core/crypto/constants.js +33 -11
- package/dist/core/crypto/crypto-provider.js +8 -8
- package/dist/core/crypto/encryption-engine.d.ts +7 -16
- package/dist/core/crypto/encryption-engine.js +27 -62
- package/dist/core/database/system/identity.d.ts +2 -2
- package/dist/core/database/system/identity.js +2 -2
- package/dist/core/keys/hkdf-recipe.d.ts +4 -0
- package/dist/core/keys/hkdf-recipe.js +26 -0
- package/dist/core/keys/key-id.d.ts +50 -0
- package/dist/core/keys/key-id.js +64 -0
- package/dist/core/keys/key-impls.d.ts +12 -0
- package/dist/core/keys/key-impls.js +163 -0
- package/dist/core/keys/key-store.d.ts +72 -0
- package/dist/core/keys/key-store.js +264 -0
- package/dist/core/keys/keypair-handle.d.ts +36 -0
- package/dist/core/keys/keypair-handle.js +43 -0
- package/dist/core/keys/registry.d.ts +16 -0
- package/dist/core/keys/registry.js +144 -0
- package/dist/core/keys/types.d.ts +47 -0
- package/dist/core/keys/types.js +1 -0
- package/dist/core/types.d.ts +12 -1
- package/dist/core/utils.d.ts +1 -1
- package/dist/core/utils.js +1 -1
- package/dist/core/validator.d.ts +1 -1
- package/dist/core/validator.js +1 -1
- package/dist/core/web3/bitcoin/bitcoin.d.ts +1 -1
- package/dist/core/web3/bitcoin/bitcoin.js +4 -4
- package/dist/core/web3/bitcoin/types.d.ts +1 -1
- package/dist/core/web3/ethereum/constants.d.ts +1 -0
- package/dist/core/web3/ethereum/constants.js +4 -0
- package/dist/core/web3/ethereum/ethereum.d.ts +21 -0
- package/dist/core/web3/ethereum/ethereum.js +91 -0
- package/dist/core/web3/ethereum/types.d.ts +32 -0
- package/dist/core/web3/ethereum/types.js +1 -0
- package/dist/core/web3/index.d.ts +10 -5
- package/dist/core/web3/index.js +7 -2
- package/dist/core/web3/solana/solana.d.ts +2 -2
- package/dist/core/web3/solana/solana.js +6 -6
- package/dist/core/web3/solana/types.d.ts +1 -1
- package/dist/core/web3/types.d.ts +4 -2
- package/dist/index.d.ts +13 -6
- package/dist/index.js +11 -5
- package/dist/majik-key.d.ts +179 -281
- package/dist/majik-key.js +622 -726
- package/package.json +20 -5
package/dist/majik-key.d.ts
CHANGED
|
@@ -2,104 +2,70 @@
|
|
|
2
2
|
* MajikKey.ts
|
|
3
3
|
* Seed phrase account library for the Majikah ecosystem.
|
|
4
4
|
*
|
|
5
|
+
* v0.8 — key REGISTRY. Every account stores a set of keypairs in a KeyStore,
|
|
6
|
+
* addressed by namespaced id (see core/keys/key-id.ts). The core four
|
|
7
|
+
* (classic:x25519, classic:ed25519, pq:ml-kem-768, pq:ml-dsa-87) are always
|
|
8
|
+
* present on new accounts; anything else is opt-in via `keys` / `addKeys()`.
|
|
9
|
+
*
|
|
10
|
+
* The pre-registry per-algorithm getters still work and are marked
|
|
11
|
+
* @deprecated: they are thin wrappers over the registry accessors.
|
|
12
|
+
*
|
|
13
|
+
* Derivation (all deterministic from the BIP-39 mnemonic) lives in
|
|
14
|
+
* core/keys/key-impls.ts. Frozen "legacy-v1" recipes are pinned by
|
|
15
|
+
* vectors/legacy-v1.vectors.json.
|
|
5
16
|
*/
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
11
|
-
import {
|
|
12
|
-
import {
|
|
17
|
+
import { MajikContactData, MajikContactMeta } from "@majikah/majik-contact/dist/types.js";
|
|
18
|
+
import { MajikContact } from "@majikah/majik-contact/dist/contacts/majik-contact.js";
|
|
19
|
+
import { KDF_VERSION } from "./core/crypto/constants.js";
|
|
20
|
+
import type { BitcoinRawPublicKey, ED25519RawPublicKey, MajikKeyAddress, MajikKeyDangerousJSON, MajikKeyFingerprint, MajikKeyJSON, MajikKeyMetadata, MLDSA87RawPublicKey, MLKEM768RawPublicKey, MnemonicJSON, X25519RawKey } from "./core/types.js";
|
|
21
|
+
import { MajikMessageIdentity } from "./core/database/system/identity.js";
|
|
22
|
+
import { MajikUser } from "@thezelijah/majik-user/dist/core/majik-user.js";
|
|
23
|
+
import { MnemonicLanguage } from "./core/crypto/wordlist.js";
|
|
24
|
+
import { MajikKeyWeb3Namespace, BitcoinDerivationOptions, BitcoinKeypairMaterial, SolanaKeypairMaterial, EthereumKeypairMaterial } from "./core/web3/index.js";
|
|
25
|
+
import { KeyFamily, KeyId } from "./core/keys/key-id.js";
|
|
26
|
+
import { KeyInfo, MajikKeypair } from "./core/keys/keypair-handle.js";
|
|
27
|
+
export { KeyId, KeyFamily, CORE_KEYS } from "./core/keys/key-id.js";
|
|
28
|
+
export { MajikKeypair } from "./core/keys/keypair-handle.js";
|
|
29
|
+
export type { KeyInfo } from "./core/keys/keypair-handle.js";
|
|
13
30
|
/**
|
|
14
|
-
* In-memory identity bundle for an *unlocked* MajikKey
|
|
15
|
-
*
|
|
16
|
-
* `
|
|
17
|
-
*
|
|
18
|
-
* `mlKemPublicKey`/`mlKemSecretKey` are required here because every account
|
|
19
|
-
* (even ones mid-migration) is expected to carry ML-KEM material by the time
|
|
20
|
-
* this shape is used. `ed*`, `mlDsa*`, and `btc*` are optional because
|
|
21
|
-
* accounts imported before those key types existed may not have them yet —
|
|
22
|
-
* check `hasSigningKeys` / `hasBitcoin` on the `MajikKey` instance before
|
|
23
|
-
* relying on them.
|
|
31
|
+
* In-memory identity bundle for an *unlocked* MajikKey. Returned by
|
|
32
|
+
* `toKeyIdentity()`. Kept for backward compatibility; prefer the registry
|
|
33
|
+
* accessors (`getKeypair()`, `getPublicKey()`, `getPrivateKey(id)`).
|
|
24
34
|
*/
|
|
25
35
|
export interface MajikKeyIdentity {
|
|
26
|
-
/** Account identifier. Equal to `fingerprint` for accounts created by this library. */
|
|
27
36
|
id: MajikKeyFingerprint;
|
|
28
|
-
/** X25519 public key */
|
|
29
37
|
publicKey: X25519RawKey;
|
|
30
|
-
/** SHA-256 fingerprint of `publicKey`. */
|
|
31
38
|
fingerprint: MajikKeyFingerprint;
|
|
32
|
-
/** X25519 private key, decrypted into memory. ⚠️ Live key material — do not log or serialize directly. */
|
|
33
39
|
privateKey: X25519RawKey;
|
|
34
|
-
/** AES-256-GCM-encrypted X25519 private key (IV + ciphertext), as stored at rest. */
|
|
35
40
|
encryptedPrivateKey: ArrayBuffer;
|
|
36
|
-
/** Random salt used to derive the passphrase-based encryption key. Base64. */
|
|
37
41
|
salt: string;
|
|
38
|
-
/** KDF used to encrypt the keys on this identity: `1` = legacy PBKDF2, `2` = Argon2id. */
|
|
39
42
|
kdfVersion: KDF_VERSION;
|
|
40
|
-
/** ML-KEM-768 (FIPS-203) public key. Post-quantum key encapsulation. */
|
|
41
43
|
mlKemPublicKey: Uint8Array;
|
|
42
|
-
/** ML-KEM-768 secret key, decrypted into memory. ⚠️ Live key material. */
|
|
43
44
|
mlKemSecretKey?: Uint8Array;
|
|
44
|
-
/** Ed25519 public key. Classical signing — same keypair the X25519 identity key is converted from. */
|
|
45
45
|
edPublicKey?: Uint8Array;
|
|
46
|
-
/** Ed25519 secret key, decrypted into memory. ⚠️ Live key material. */
|
|
47
46
|
edSecretKey?: Uint8Array;
|
|
48
|
-
/** ML-DSA-87 (FIPS-204) public key. Post-quantum signing. */
|
|
49
47
|
mlDsaPublicKey?: Uint8Array;
|
|
50
|
-
/** ML-DSA-87 secret key, decrypted into memory. ⚠️ Live key material. */
|
|
51
48
|
mlDsaSecretKey?: Uint8Array;
|
|
52
|
-
/** @experimental
|
|
49
|
+
/** @experimental */
|
|
53
50
|
btcPublicKey?: Uint8Array;
|
|
54
|
-
/** @experimental
|
|
51
|
+
/** @experimental */
|
|
55
52
|
btcSecretKey?: Uint8Array;
|
|
56
53
|
}
|
|
57
|
-
/**
|
|
58
|
-
* `MajikKeyIdentity` immediately after fresh derivation from a mnemonic —
|
|
59
|
-
* i.e. what `create()` and `importFromMnemonicBackup()` produce internally,
|
|
60
|
-
* before the result is wrapped into a `MajikKey` instance.
|
|
61
|
-
*
|
|
62
|
-
* Unlike the base `MajikKeyIdentity`, every `encrypted*` field here is
|
|
63
|
-
* required: a fresh derivation always re-derives and re-encrypts the full
|
|
64
|
-
* key set (ML-KEM, Ed25519, ML-DSA, and Bitcoin) in one pass, so there's no
|
|
65
|
-
* "partially migrated" state at this point in the flow.
|
|
66
|
-
*/
|
|
54
|
+
/** @deprecated Pre-registry shape. No longer produced; kept so existing type imports keep compiling. */
|
|
67
55
|
export type MajikKeyDerivedIdentity = MajikKeyIdentity & {
|
|
68
|
-
/** AES-256-GCM-encrypted ML-KEM-768 secret key, freshly re-encrypted. */
|
|
69
56
|
encryptedMlKemSecretKey: ArrayBuffer;
|
|
70
|
-
/** AES-256-GCM-encrypted Ed25519 secret key, freshly re-encrypted. */
|
|
71
57
|
encryptedEdSecretKey: ArrayBuffer;
|
|
72
|
-
/** AES-256-GCM-encrypted ML-DSA-87 secret key, freshly re-encrypted. */
|
|
73
58
|
encryptedMlDsaSecretKey: ArrayBuffer;
|
|
74
|
-
/** @experimental AES-256-GCM-encrypted Bitcoin secret key, freshly re-encrypted. */
|
|
75
59
|
encryptedBtcSecretKey?: ArrayBuffer;
|
|
76
60
|
};
|
|
77
|
-
/**
|
|
78
|
-
* Minimal identity export — just enough to identify the account and, if
|
|
79
|
-
* present, re-derive access to it. Lighter than `MajikKeyJSON`: no ML-KEM,
|
|
80
|
-
* Ed25519, ML-DSA, or Bitcoin fields at all. Produced by
|
|
81
|
-
* `toSerializedIdentity()` (unlocked keys only).
|
|
82
|
-
*/
|
|
83
61
|
export interface SerializedIdentity {
|
|
84
62
|
id: string;
|
|
85
|
-
/** X25519 public key, base64. */
|
|
86
63
|
publicKey: MajikKeyAddress;
|
|
87
64
|
fingerprint: MajikKeyFingerprint;
|
|
88
|
-
/** AES-256-GCM-encrypted X25519 private key, base64. Omitted in some contexts — check before use. */
|
|
89
65
|
encryptedPrivateKey?: string;
|
|
90
|
-
/** Base64 salt paired with `encryptedPrivateKey`. Omitted in some contexts — check before use. */
|
|
91
66
|
salt?: string;
|
|
92
67
|
}
|
|
93
|
-
/**
|
|
94
|
-
* Internal constructor payload for `MajikKey` — every static factory
|
|
95
|
-
* (`create()`, `fromJSON()`, `fromDangerousJSON()`, `importFromMnemonicBackup()`,
|
|
96
|
-
* etc.) builds one of these and passes it to the private constructor.
|
|
97
|
-
*
|
|
98
|
-
* You won't normally build this by hand; it's exported mainly for type
|
|
99
|
-
* inference around the factory methods. Fields mirror `MajikKeyJSON` plus
|
|
100
|
-
* the live (decrypted) counterparts where a factory is constructing an
|
|
101
|
-
* already-unlocked instance.
|
|
102
|
-
*/
|
|
68
|
+
/** @deprecated Pre-registry constructor payload. The constructor now takes a KeyStore. */
|
|
103
69
|
export interface MajikKeyConstructorOptions {
|
|
104
70
|
id: string;
|
|
105
71
|
publicKey: X25519RawKey;
|
|
@@ -108,18 +74,14 @@ export interface MajikKeyConstructorOptions {
|
|
|
108
74
|
encryptedPrivateKey: ArrayBuffer;
|
|
109
75
|
encryptedPrivateKeyBase64: string;
|
|
110
76
|
salt: string;
|
|
111
|
-
/** Encrypted mnemonic-verification blob — see `MajikKeyJSON.backup`. */
|
|
112
77
|
backup: string;
|
|
113
78
|
label?: string;
|
|
114
79
|
timestamp?: Date;
|
|
115
|
-
/** Defaults to legacy PBKDF2 (`KDF_VERSION.PBKDF2`) if omitted — see the private constructor. */
|
|
116
80
|
kdfVersion?: KDF_VERSION;
|
|
117
81
|
mlKemPublicKey: MLKEM768RawPublicKey;
|
|
118
|
-
/** Present only when constructing an already-unlocked instance. ⚠️ Live key material. */
|
|
119
82
|
mlKemSecretKey?: Uint8Array;
|
|
120
83
|
encryptedMlKemSecretKey?: ArrayBuffer;
|
|
121
84
|
encryptedMlKemSecretKeyBase64?: string;
|
|
122
|
-
/** Present only when constructing an already-unlocked instance. ⚠️ Live key material. */
|
|
123
85
|
privateKey?: X25519RawKey;
|
|
124
86
|
edPublicKey?: ED25519RawPublicKey;
|
|
125
87
|
encryptedEdSecretKey?: ArrayBuffer;
|
|
@@ -127,42 +89,38 @@ export interface MajikKeyConstructorOptions {
|
|
|
127
89
|
mlDsaPublicKey?: MLDSA87RawPublicKey;
|
|
128
90
|
encryptedMlDsaSecretKey?: ArrayBuffer;
|
|
129
91
|
encryptedMlDsaSecretKeyBase64?: string;
|
|
130
|
-
/** Present only when constructing an already-unlocked instance. ⚠️ Live key material. */
|
|
131
92
|
edSecretKey?: Uint8Array;
|
|
132
|
-
/** Present only when constructing an already-unlocked instance. ⚠️ Live key material. */
|
|
133
93
|
mlDsaSecretKey?: Uint8Array;
|
|
134
|
-
/** @experimental secp256k1 Bitcoin public key. */
|
|
135
94
|
btcPublicKey?: BitcoinRawPublicKey;
|
|
136
|
-
/** @experimental AES-256-GCM-encrypted Bitcoin private key. */
|
|
137
95
|
encryptedBtcSecretKey?: ArrayBuffer;
|
|
138
|
-
/** @experimental Base64 form of `encryptedBtcSecretKey`. */
|
|
139
96
|
encryptedBtcSecretKeyBase64?: string;
|
|
140
|
-
/** @experimental Present only when constructing an already-unlocked instance. ⚠️ Live key material. */
|
|
141
97
|
btcSecretKey?: Uint8Array;
|
|
142
98
|
mnemonicLanguage?: MnemonicLanguage;
|
|
143
99
|
}
|
|
100
|
+
/** Options for create(), fromMnemonicJSON() and importFromMnemonicBackup(). */
|
|
101
|
+
export interface MajikKeyCreateOptions {
|
|
102
|
+
mnemonicLanguage?: MnemonicLanguage;
|
|
103
|
+
/**
|
|
104
|
+
* Extra keypairs to create ON TOP of the core four (always included).
|
|
105
|
+
* Defaults to none. e.g. `keys: [KeyId.BTC]`.
|
|
106
|
+
*/
|
|
107
|
+
keys?: KeyId[];
|
|
108
|
+
/** @deprecated Use `keys: [KeyId.BTC]`. `true` adds `web3:btc`; omitted/false no longer derives it. */
|
|
109
|
+
deriveBitcoin?: boolean;
|
|
110
|
+
}
|
|
111
|
+
export interface MajikKeyToJSONOptions {
|
|
112
|
+
/**
|
|
113
|
+
* Also write the pre-registry flat fields (`encryptedMlKemSecretKey`, …)
|
|
114
|
+
* so older library versions / the Rust port can read the export.
|
|
115
|
+
* Defaults to TRUE in this release; planned to flip to false in the next major.
|
|
116
|
+
*/
|
|
117
|
+
legacy?: boolean;
|
|
118
|
+
}
|
|
144
119
|
/**
|
|
145
120
|
* MajikKey
|
|
146
121
|
* ---
|
|
147
|
-
*
|
|
148
|
-
*
|
|
149
|
-
*
|
|
150
|
-
* Every account stores FIVE keypairs, all deterministically derived from a
|
|
151
|
-
* single BIP-39 mnemonic:
|
|
152
|
-
* 1. X25519 (Curve25519) — fingerprint, contact identity, legacy message compat
|
|
153
|
-
* 2. ML-KEM-768 (FIPS-203) — post-quantum key encapsulation for v3 envelopes
|
|
154
|
-
* 3. Ed25519 — classical signing
|
|
155
|
-
* 4. ML-DSA-87 (FIPS-204) — post-quantum signing
|
|
156
|
-
* 5. Bitcoin (secp256k1) — BIP-32/84 HD key, domain-separated by default (experimental)
|
|
157
|
-
*
|
|
158
|
-
* All derived from the 64-byte BIP-39 seed:
|
|
159
|
-
* seed[0..32] → Ed25519 keypair — used directly for signing, AND converted
|
|
160
|
-
* to X25519 via ed2curve for the encryption/identity keypair
|
|
161
|
-
* (one Ed25519 keypair, two roles)
|
|
162
|
-
* seed[0..64] → ml_kem768.keygen(seed) — full seed, deterministic
|
|
163
|
-
* hash(seed || "MajikSignatureSeedDSA") → 32-byte seed → ml_dsa87.keygen()
|
|
164
|
-
* seed[0..64] → HDKey.fromMasterSeed(seed).derive(path) — BIP-32/84 Bitcoin key
|
|
165
|
-
*
|
|
122
|
+
* Registry of keypairs deterministically derived from one BIP-39 mnemonic.
|
|
123
|
+
* See core/keys/registry.ts for every supported algorithm and its status.
|
|
166
124
|
*/
|
|
167
125
|
export declare class MajikKey {
|
|
168
126
|
private readonly _id;
|
|
@@ -172,187 +130,162 @@ export declare class MajikKey {
|
|
|
172
130
|
private readonly _backup;
|
|
173
131
|
private readonly _timestamp;
|
|
174
132
|
private readonly _mnemonicLanguage;
|
|
175
|
-
private
|
|
176
|
-
private _encryptedPrivateKeyBase64;
|
|
133
|
+
private readonly _store;
|
|
177
134
|
private _salt;
|
|
178
135
|
private _label;
|
|
179
136
|
private _kdfVersion;
|
|
180
|
-
|
|
181
|
-
private _mlKemSecretKey?;
|
|
182
|
-
private _encryptedMlKemSecretKey?;
|
|
183
|
-
private _encryptedMlKemSecretKeyBase64?;
|
|
184
|
-
private _privateKey?;
|
|
185
|
-
private _edPublicKey?;
|
|
186
|
-
private _edSecretKey?;
|
|
187
|
-
private _encryptedEdSecretKey?;
|
|
188
|
-
private _encryptedEdSecretKeyBase64?;
|
|
189
|
-
private _mlDsaPublicKey?;
|
|
190
|
-
private _mlDsaSecretKey?;
|
|
191
|
-
private _encryptedMlDsaSecretKey?;
|
|
192
|
-
private _encryptedMlDsaSecretKeyBase64?;
|
|
193
|
-
/**
|
|
194
|
-
* @experimental
|
|
195
|
-
*/
|
|
137
|
+
/** @experimental derived view over classic:ed25519; cached while unlocked */
|
|
196
138
|
private _solanaKeypairMaterial?;
|
|
197
|
-
/**
|
|
198
|
-
* @experimental
|
|
199
|
-
*/
|
|
200
|
-
private _btcPublicKey?;
|
|
201
|
-
/**
|
|
202
|
-
* @experimental
|
|
203
|
-
*/
|
|
204
|
-
private _btcSecretKey?;
|
|
205
|
-
/**
|
|
206
|
-
* @experimental
|
|
207
|
-
*/
|
|
208
|
-
private _encryptedBtcSecretKey?;
|
|
209
|
-
/**
|
|
210
|
-
* @experimental
|
|
211
|
-
*/
|
|
212
|
-
private _encryptedBtcSecretKeyBase64?;
|
|
213
139
|
private constructor();
|
|
214
|
-
/** Account identifier. Equal to `fingerprint` for accounts created by this library. */
|
|
215
140
|
get id(): MajikKeyFingerprint;
|
|
216
|
-
/** SHA-256 fingerprint of the X25519 public key. Stable identity anchor for the account. */
|
|
217
141
|
get fingerprint(): MajikKeyFingerprint;
|
|
218
142
|
/** X25519 public key. Always available, even when locked. */
|
|
219
143
|
get publicKey(): X25519RawKey;
|
|
220
|
-
/** X25519 public key, base64-encoded. Always available, even when locked. */
|
|
221
144
|
get publicKeyBase64(): MajikKeyAddress;
|
|
222
|
-
/** Human-readable, user-editable account name. Update via `updateLabel()`. */
|
|
223
145
|
get label(): string;
|
|
224
|
-
/** BIP-39 wordlist language this account's mnemonic was generated/validated against. */
|
|
225
146
|
get mnemonicLanguage(): MnemonicLanguage;
|
|
226
|
-
/**
|
|
227
|
-
* Encrypted mnemonic-verification blob (base64 JSON). Decryptable only
|
|
228
|
-
* with the original mnemonic — used internally to verify a supplied
|
|
229
|
-
* mnemonic before `importFromMnemonicBackup()` re-derives the full
|
|
230
|
-
* identity. Not a general-purpose private-key backup.
|
|
231
|
-
*/
|
|
232
147
|
get backup(): string;
|
|
233
|
-
/** Account creation time. */
|
|
234
148
|
get timestamp(): Date;
|
|
235
|
-
/** KDF currently protecting every `encrypted*` field on this account: `1` = legacy PBKDF2, `2` = Argon2id. */
|
|
236
149
|
get kdfVersion(): KDF_VERSION;
|
|
237
|
-
/** `true` if this account is on the current KDF (Argon2id). `false` means it's still on legacy PBKDF2 — see `migrate()` or `importFromMnemonicBackup()`. */
|
|
238
150
|
get isArgon2id(): boolean;
|
|
239
|
-
/** `true` if private key material is currently purged from memory (i.e. `lock()` was called, or `unlock()` hasn't been called yet). */
|
|
240
151
|
get isLocked(): boolean;
|
|
241
|
-
/** `true` if private key material is currently decrypted in memory. The inverse of `isLocked`. */
|
|
242
152
|
get isUnlocked(): boolean;
|
|
243
|
-
/**
|
|
244
|
-
get
|
|
245
|
-
/**
|
|
246
|
-
get mlKemSecretKey(): Uint8Array | undefined;
|
|
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. */
|
|
248
|
-
get hasMlKem(): boolean;
|
|
249
|
-
/** `true` if this account is on Argon2id *and* has ML-KEM-768 keys — i.e. fully migrated, nothing left to upgrade. */
|
|
153
|
+
/** `true` if this account holds every key in CORE_KEYS. Legacy accounts may not — see `missingKeys()` / `addKeys()`. */
|
|
154
|
+
get isCoreComplete(): boolean;
|
|
155
|
+
/** `true` if this account is on Argon2id *and* has ML-KEM-768 keys. */
|
|
250
156
|
get isFullyUpgraded(): boolean;
|
|
157
|
+
/** Is this key present on the account? Works while locked. Derived views (web3:sol) count when their source key exists. */
|
|
158
|
+
hasKey(id: KeyId): boolean;
|
|
159
|
+
hasKeys(ids: readonly KeyId[]): boolean;
|
|
160
|
+
/** Which of `ids` (default: the core four) are NOT on this account. */
|
|
161
|
+
missingKeys(ids?: readonly KeyId[]): KeyId[];
|
|
162
|
+
/** Namespaced ids of every key available on this account, in canonical order. */
|
|
163
|
+
availableKeys(options?: {
|
|
164
|
+
family?: KeyFamily;
|
|
165
|
+
}): KeyId[];
|
|
166
|
+
/** Metadata for every available key. No secret material. */
|
|
167
|
+
listKeys(): KeyInfo[];
|
|
168
|
+
/** Every algorithm id this library version can create/enable. */
|
|
169
|
+
static supportedKeys(): KeyId[];
|
|
170
|
+
/** Public key bytes for `id`. Works while locked (derived views need an unlocked account). */
|
|
171
|
+
getPublicKey(id: KeyId): Uint8Array;
|
|
251
172
|
/**
|
|
252
|
-
*
|
|
253
|
-
*
|
|
254
|
-
* hasn't been re-imported via `importFromMnemonicBackup()`).
|
|
255
|
-
*/
|
|
256
|
-
get btcPublicKey(): BitcoinRawPublicKey | undefined;
|
|
257
|
-
/** @experimental `true` if this account has a stored Bitcoin keypair. */
|
|
258
|
-
get hasBitcoin(): boolean;
|
|
259
|
-
/**
|
|
260
|
-
* Lightweight, non-secret snapshot of this account's state — no key bytes
|
|
261
|
-
* at all, encrypted or otherwise. Useful for account pickers, dashboards,
|
|
262
|
-
* or anywhere you want to display status without touching key material.
|
|
173
|
+
* With no argument: the X25519 private key wrapper.
|
|
174
|
+
* @deprecated The no-argument form. Use `getPrivateKey(KeyId.X25519)`.
|
|
263
175
|
*/
|
|
264
|
-
|
|
265
|
-
/**
|
|
176
|
+
getPrivateKey(): X25519RawKey;
|
|
177
|
+
/** Secret key bytes for `id`. Throws if locked or absent. ⚠️ Live key material. */
|
|
178
|
+
getPrivateKey(id: KeyId): Uint8Array;
|
|
179
|
+
/** A live handle with `.public` / `.private` / `.publicBase64`. Reads through to the account, so it never goes stale across lock(). */
|
|
180
|
+
getKeypair(id: KeyId): MajikKeypair;
|
|
181
|
+
private _requireSecret;
|
|
182
|
+
/** @deprecated Use `getPublicKey(KeyId.ML_KEM_768)`. */
|
|
183
|
+
get mlKemPublicKey(): MLKEM768RawPublicKey;
|
|
184
|
+
/** @deprecated Use `getPrivateKey(KeyId.ML_KEM_768)`. */
|
|
185
|
+
get mlKemSecretKey(): Uint8Array | undefined;
|
|
186
|
+
/** @deprecated Use `hasKey(KeyId.ML_KEM_768)`. */
|
|
187
|
+
get hasMlKem(): boolean;
|
|
188
|
+
/** @deprecated Use `getPublicKey(KeyId.ED25519)`. */
|
|
266
189
|
get edPublicKey(): ED25519RawPublicKey | undefined;
|
|
267
|
-
/**
|
|
190
|
+
/** @deprecated Use `getPublicKey(KeyId.ML_DSA_87)`. */
|
|
268
191
|
get mlDsaPublicKey(): MLDSA87RawPublicKey | undefined;
|
|
269
|
-
/**
|
|
192
|
+
/** @deprecated Use `hasKeys([KeyId.ED25519, KeyId.ML_DSA_87])`. */
|
|
270
193
|
get hasSigningKeys(): boolean;
|
|
194
|
+
/** @experimental @deprecated Use `getPublicKey(KeyId.BTC)`. */
|
|
195
|
+
get btcPublicKey(): BitcoinRawPublicKey | undefined;
|
|
196
|
+
/** @experimental @deprecated Use `hasKey(KeyId.BTC)`. */
|
|
197
|
+
get hasBitcoin(): boolean;
|
|
198
|
+
/** @deprecated Use `getPrivateKey(KeyId.ML_KEM_768)`. */
|
|
199
|
+
getMlKemSecretKey(): Uint8Array;
|
|
200
|
+
/** @deprecated Use `getPrivateKey(KeyId.ED25519)`. */
|
|
201
|
+
getEdSecretKey(): Uint8Array;
|
|
202
|
+
/** @deprecated Use `getPrivateKey(KeyId.ML_DSA_87)`. */
|
|
203
|
+
getMlDsaSecretKey(): Uint8Array;
|
|
204
|
+
/** @experimental @deprecated Use `getPrivateKey(KeyId.BTC)`. */
|
|
205
|
+
getBtcSecretKey(): Uint8Array;
|
|
206
|
+
/** Non-secret snapshot of this account's state. */
|
|
207
|
+
get metadata(): MajikKeyMetadata;
|
|
271
208
|
/**
|
|
272
|
-
* Creates a brand-new MajikKey
|
|
209
|
+
* Creates a brand-new MajikKey from a BIP-39 mnemonic and returns it UNLOCKED.
|
|
210
|
+
*
|
|
211
|
+
* Always derives the core four (X25519, Ed25519, ML-KEM-768, ML-DSA-87).
|
|
212
|
+
* Pass `options.keys` for more, e.g. `{ keys: [KeyId.BTC] }`.
|
|
273
213
|
*
|
|
274
|
-
*
|
|
275
|
-
* ML-DSA-87, and a domain-separated Bitcoin key (see `MAJIK_BITCOIN_DOMAIN_PATH`)
|
|
276
|
-
* — encrypts every private key with Argon2id (KDF v2), and returns an
|
|
277
|
-
* **already-unlocked** instance (no `unlock()` call needed right after
|
|
278
|
-
* `create()`).
|
|
214
|
+
* ⚠️ Behavior change vs 0.7: Bitcoin is no longer derived by default.
|
|
279
215
|
*
|
|
280
|
-
* @
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
*
|
|
286
|
-
*
|
|
216
|
+
* @throws {MajikKeyError} on invalid mnemonic/passphrase/label or unusable key ids.
|
|
217
|
+
*/
|
|
218
|
+
static create(mnemonic: string, passphrase: string, label?: string, options?: MajikKeyCreateOptions): Promise<MajikKey>;
|
|
219
|
+
private static _resolveCreateKeys;
|
|
220
|
+
/**
|
|
221
|
+
* Parse a MajikKey from JSON. Accepts BOTH shapes:
|
|
222
|
+
* - registry JSON (has `keys`) → used as-is
|
|
223
|
+
* - legacy flat JSON (no `keys`) → auto-migrated in memory (no secrets, no
|
|
224
|
+
* passphrase, no mnemonic needed). Re-serialize with toJSON() to persist
|
|
225
|
+
* the upgraded shape.
|
|
287
226
|
*/
|
|
288
|
-
static create(mnemonic: string, passphrase: string, label?: string, options?: {
|
|
289
|
-
mnemonicLanguage?: MnemonicLanguage;
|
|
290
|
-
/** @experimental Set `false` to skip deriving the Bitcoin keypair. Defaults to `true` for backward compatibility. */
|
|
291
|
-
deriveBitcoin?: boolean;
|
|
292
|
-
}): Promise<MajikKey>;
|
|
293
227
|
static fromJSON(json: MajikKeyJSON | string): MajikKey;
|
|
228
|
+
private static _validateRegistryJSON;
|
|
294
229
|
/**
|
|
295
230
|
* Export a fully unlocked MajikKey with all raw private keys.
|
|
296
231
|
* ⚠️ DANGEROUS — output contains unencrypted private key material.
|
|
297
232
|
* Only use for server-side secrets injection.
|
|
298
|
-
* Never log, store in a database, or transmit over the network.
|
|
299
233
|
*/
|
|
300
234
|
toDangerousJSON(): MajikKeyDangerousJSON;
|
|
301
235
|
/**
|
|
302
236
|
* Reconstruct a fully unlocked MajikKey from a dangerous JSON export.
|
|
303
237
|
* ⚠️ DANGEROUS — input contains unencrypted private key material.
|
|
304
|
-
* Intended for server-side use only (e.g. TSA signing key loaded from Cloudflare Secrets).
|
|
305
238
|
* No KDF is involved — reconstruction is instant.
|
|
306
239
|
*/
|
|
307
240
|
static fromDangerousJSON(json: MajikKeyDangerousJSON | string): MajikKey;
|
|
308
241
|
toMnemonicJSON(mnemonic: string, passphrase?: string): MnemonicJSON;
|
|
309
|
-
static fromMnemonicJSON(mnemonicJson: MnemonicJSON | string, passphrase: string, label?: string, options?:
|
|
310
|
-
mnemonicLanguage?: MnemonicLanguage;
|
|
311
|
-
/** @experimental Set `false` to skip deriving the Bitcoin keypair. Defaults to `true` for backward compatibility. */
|
|
312
|
-
deriveBitcoin?: boolean;
|
|
313
|
-
}): Promise<MajikKey>;
|
|
242
|
+
static fromMnemonicJSON(mnemonicJson: MnemonicJSON | string, passphrase: string, label?: string, options?: MajikKeyCreateOptions): Promise<MajikKey>;
|
|
314
243
|
updateLabel(newLabel: string): this;
|
|
315
244
|
updatePassphrase(currentPassphrase: string, newPassphrase: string): Promise<this>;
|
|
316
245
|
/**
|
|
317
246
|
* Migrate KDF from PBKDF2 to Argon2id without changing passphrase.
|
|
318
|
-
*
|
|
247
|
+
* Does not add new key types — use addKeys() (requires the mnemonic).
|
|
319
248
|
*/
|
|
320
249
|
migrate(passphrase: string): Promise<this>;
|
|
250
|
+
/**
|
|
251
|
+
* Add keypairs this account doesn't have yet (new algorithms, or core keys
|
|
252
|
+
* missing on a legacy account). Requires the original MNEMONIC: new keys are
|
|
253
|
+
* derived from the seed, which is never stored. Also requires the current
|
|
254
|
+
* passphrase (to encrypt the new keys under the account's existing salt).
|
|
255
|
+
*
|
|
256
|
+
* Safe by construction: the mnemonic must reproduce this account's X25519
|
|
257
|
+
* key, and the passphrase must decrypt it, before anything is added.
|
|
258
|
+
* Keys already present are skipped. Account must be on Argon2id — call
|
|
259
|
+
* `migrate(passphrase)` first if `isArgon2id` is false.
|
|
260
|
+
*
|
|
261
|
+
* @returns the ids that were added
|
|
262
|
+
*/
|
|
263
|
+
addKeys(ids: readonly KeyId[], mnemonic: string, passphrase: string): Promise<KeyId[]>;
|
|
321
264
|
lock(): this;
|
|
265
|
+
/** One KDF run decrypts every key. Atomic: a failure leaves the account fully locked. */
|
|
322
266
|
unlock(passphrase: string): Promise<this>;
|
|
323
267
|
verify(passphrase: string): Promise<boolean>;
|
|
324
|
-
getPrivateKey()
|
|
268
|
+
/** @deprecated Use `getPrivateKey(KeyId.X25519)`. */
|
|
325
269
|
getPrivateKeyBase64(): string;
|
|
326
|
-
getMlKemSecretKey(): Uint8Array;
|
|
327
|
-
getEdSecretKey(): Uint8Array;
|
|
328
|
-
getMlDsaSecretKey(): Uint8Array;
|
|
329
270
|
/**
|
|
330
271
|
* Executes an operation against an already-unlocked MajikKey and
|
|
331
|
-
* automatically locks the key when the operation completes.
|
|
332
|
-
*
|
|
333
|
-
* The key is always locked after the operation, including when the
|
|
334
|
-
* operation throws or rejects.
|
|
335
|
-
*
|
|
336
|
-
* @param key - An already-unlocked MajikKey instance.
|
|
337
|
-
* @param operation - Synchronous or asynchronous operation to execute.
|
|
338
|
-
* @returns The result returned by the operation.
|
|
339
|
-
*
|
|
340
|
-
* @throws {MajikKeyError} If the key is locked.
|
|
341
|
-
* @throws {MajikKeyError} If `operation` is not a function.
|
|
342
|
-
*
|
|
343
|
-
* @example
|
|
344
|
-
* ```ts
|
|
345
|
-
* await key.unlock(passphrase);
|
|
346
|
-
*
|
|
347
|
-
* const signature = await MajikKey.withAutoLock(key, async (key) => {
|
|
348
|
-
* return sign(key.getEdSecretKey(), message);
|
|
349
|
-
* });
|
|
350
|
-
*
|
|
351
|
-
* // key.isLocked === true
|
|
352
|
-
* ```
|
|
272
|
+
* automatically locks the key when the operation completes (even on throw).
|
|
353
273
|
*/
|
|
354
274
|
static withAutoLock<T>(key: MajikKey, operation: (key: MajikKey) => T | Promise<T>): Promise<T>;
|
|
355
|
-
|
|
275
|
+
private _hasNonX25519Blobs;
|
|
276
|
+
/**
|
|
277
|
+
* Decrypt every blob under (current passphrase, current salt/KDF), re-encrypt
|
|
278
|
+
* under (new passphrase, fresh salt, Argon2id), then commit atomically.
|
|
279
|
+
* Does not need the account to be unlocked and never touches plaintext in memory.
|
|
280
|
+
*/
|
|
281
|
+
private _reencryptAll;
|
|
282
|
+
/**
|
|
283
|
+
* Serialize (safe at rest: only passphrase-encrypted secrets).
|
|
284
|
+
* Writes the registry (`keys`) AND, by default, the pre-registry flat fields
|
|
285
|
+
* for compatibility. Pass `{ legacy: false }` for registry-only output.
|
|
286
|
+
* (JSON.stringify passes a string here; that is treated as "defaults".)
|
|
287
|
+
*/
|
|
288
|
+
toJSON(options?: MajikKeyToJSONOptions | string): MajikKeyJSON;
|
|
356
289
|
toString(pretty?: boolean): string;
|
|
357
290
|
static generateMnemonic(strength?: 128 | 256, language?: MnemonicLanguage): Promise<string>;
|
|
358
291
|
static validateMnemonic(mnemonic: string): boolean;
|
|
@@ -371,97 +304,62 @@ export declare class MajikKey {
|
|
|
371
304
|
}): Promise<MajikMessageIdentity>;
|
|
372
305
|
exportMnemonicBackup(mnemonic: string): Promise<string>;
|
|
373
306
|
/**
|
|
374
|
-
* Import a MajikKey from a mnemonic-encrypted backup.
|
|
375
|
-
*
|
|
307
|
+
* Import a MajikKey from a mnemonic-encrypted backup. Re-derives the account
|
|
308
|
+
* from the mnemonic: the core four (plus `options.keys`) under a new passphrase.
|
|
376
309
|
*/
|
|
377
|
-
static importFromMnemonicBackup(backup: string, mnemonic: string, passphrase: string, label?: string, options?:
|
|
378
|
-
mnemonicLanguage?: MnemonicLanguage;
|
|
379
|
-
/** @experimental Set `false` to skip deriving the Bitcoin keypair. Defaults to `true` for backward compatibility. */
|
|
380
|
-
deriveBitcoin?: boolean;
|
|
381
|
-
}): Promise<MajikKey>;
|
|
310
|
+
static importFromMnemonicBackup(backup: string, mnemonic: string, passphrase: string, label?: string, options?: MajikKeyCreateOptions): Promise<MajikKey>;
|
|
382
311
|
private static _getWordlist;
|
|
383
312
|
/**
|
|
384
|
-
*
|
|
385
|
-
*
|
|
386
|
-
* @param options.deriveBitcoin - @experimental Set `false` to skip deriving the Bitcoin keypair. Defaults to `true`.
|
|
313
|
+
* Derive `ids` from the mnemonic and seal each secret under ONE Argon2id
|
|
314
|
+
* key (single salt, single KDF run). Returns an UNLOCKED store.
|
|
387
315
|
*/
|
|
388
|
-
private static
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
* Encrypt the ML-KEM secret key using the same Argon2id-derived key as X25519
|
|
392
|
-
* (same passphrase + same salt) but a DIFFERENT random IV. One Argon2id
|
|
393
|
-
* computation → two independently encrypted blobs.
|
|
394
|
-
*/
|
|
395
|
-
private static _encryptMlKemSecretKey;
|
|
396
|
-
private static _encryptSigningKey;
|
|
397
|
-
private static _decryptPrivateKey;
|
|
398
|
-
private static _decryptMlKemSecretKey;
|
|
399
|
-
private static _decryptSigningKey;
|
|
316
|
+
private static _deriveFromMnemonic;
|
|
317
|
+
/** One KDF run. kdfVersion 1 = legacy PBKDF2 (X25519 blob of old accounts only). */
|
|
318
|
+
private static _deriveVaultKey;
|
|
400
319
|
private static _verifyBackupDecryption;
|
|
401
320
|
private static _exportMnemonicBackup;
|
|
402
321
|
private static _deriveLegacyMnemonicKey;
|
|
403
|
-
private static _exportKeyToBase64;
|
|
404
|
-
/**
|
|
405
|
-
* @experimental
|
|
406
|
-
*/
|
|
407
|
-
getBtcSecretKey(): Uint8Array;
|
|
408
322
|
/**
|
|
409
323
|
* @experimental
|
|
410
324
|
*/
|
|
411
325
|
get web3(): MajikKeyWeb3Namespace | undefined;
|
|
412
|
-
/**
|
|
413
|
-
* @experimental True if this MajikKey can currently produce Bitcoin
|
|
414
|
-
* material (i.e. it's unlocked and has a Bitcoin secret key).
|
|
415
|
-
*/
|
|
326
|
+
/** @experimental True if this MajikKey can currently produce Bitcoin material (unlocked + has a Bitcoin key). */
|
|
416
327
|
get hasBitcoinKeypair(): boolean;
|
|
417
328
|
/**
|
|
418
|
-
* @experimental Raw Bitcoin keypair material
|
|
419
|
-
*
|
|
420
|
-
*
|
|
421
|
-
*
|
|
422
|
-
* NOTE: `{ standard: true }` re-derives from the raw seed on demand and is
|
|
423
|
-
* NOT the same key as `web3.bitcoin` (which is always the stored,
|
|
424
|
-
* domain-separated default) — it requires the mnemonic to reproduce again
|
|
425
|
-
* outside Majik, whereas the stored default does not.
|
|
329
|
+
* @experimental Raw Bitcoin keypair material for the stored (domain-separated)
|
|
330
|
+
* key. The REAL BIP-84 key needs the mnemonic:
|
|
331
|
+
* use `MajikKey.deriveStandardBitcoinFromMnemonic(mnemonic)`.
|
|
426
332
|
*/
|
|
427
333
|
getBitcoinKeypairMaterial(options?: BitcoinDerivationOptions): BitcoinKeypairMaterial;
|
|
428
|
-
/**
|
|
429
|
-
* @experimental Derive the REAL BIP-84 mainnet Bitcoin keypair straight
|
|
430
|
-
* from a mnemonic — for one-off export/verification. Does not require
|
|
431
|
-
* an unlocked MajikKey instance.
|
|
432
|
-
*/
|
|
334
|
+
/** @experimental Derive the REAL BIP-84 mainnet Bitcoin keypair straight from a mnemonic. */
|
|
433
335
|
static deriveStandardBitcoinFromMnemonic(mnemonic: string, mnemonicLanguage?: MnemonicLanguage): Promise<BitcoinKeypairMaterial>;
|
|
434
|
-
/**
|
|
435
|
-
* @experimental WIF export of the default (domain-separated) Bitcoin key.
|
|
436
|
-
*/
|
|
336
|
+
/** @experimental WIF export of the stored (domain-separated) Bitcoin key. */
|
|
437
337
|
getBitcoinWIF(options?: {
|
|
438
338
|
compressed?: boolean;
|
|
439
339
|
}): string;
|
|
340
|
+
/** @experimental True if this account has a stored Ethereum key (works while locked). */
|
|
341
|
+
get hasEthereum(): boolean;
|
|
440
342
|
/**
|
|
441
|
-
* @experimental
|
|
442
|
-
*
|
|
343
|
+
* @experimental EIP-55 Ethereum address (standard m/44'/60'/0'/0/0 — the same
|
|
344
|
+
* address MetaMask shows for this mnemonic). Public-only, so it works while locked.
|
|
443
345
|
*/
|
|
346
|
+
getEthereumAddress(): string;
|
|
347
|
+
/** @experimental Raw Ethereum keypair material. Requires an unlocked account. */
|
|
348
|
+
getEthereumKeypairMaterial(): EthereumKeypairMaterial;
|
|
349
|
+
/** @experimental 0x-prefixed private key hex, for wallet "import private key". */
|
|
350
|
+
getEthereumPrivateKeyHex(): string;
|
|
351
|
+
/** @experimental True if this MajikKey can currently produce a Solana keypair (unlocked + has Ed25519). */
|
|
444
352
|
get hasSolanaKeypair(): boolean;
|
|
445
353
|
private _getOrDeriveSolanaMaterial;
|
|
446
|
-
/**
|
|
447
|
-
* @experimental Raw Solana keypair material (public/secret key bytes).
|
|
448
|
-
* Pass `{ reuseMessageKey: true }` to reuse the MajikKey's message signing
|
|
449
|
-
* Ed25519 key directly instead of the domain-separated derivation.
|
|
450
|
-
*/
|
|
354
|
+
/** @experimental Raw Solana keypair material. `reuseMessageKey: true` reuses the message-signing Ed25519 key. */
|
|
451
355
|
getSolanaKeypairMaterial(options?: {
|
|
452
356
|
reuseMessageKey?: boolean;
|
|
453
357
|
}): SolanaKeypairMaterial;
|
|
454
|
-
/**
|
|
455
|
-
* @experimental Real @solana/kit Keypair instance. Lazily loads
|
|
456
|
-
* @solana/kit — throws a MajikKeyError with install instructions if
|
|
457
|
-
* it isn't present in the consuming project.
|
|
458
|
-
*/
|
|
358
|
+
/** @experimental Real @solana/kit Keypair instance (lazy-loads @solana/kit). */
|
|
459
359
|
getSolanaKeypair(options?: {
|
|
460
360
|
reuseMessageKey?: boolean;
|
|
461
361
|
}): Promise<any>;
|
|
462
|
-
/**
|
|
463
|
-
* @experimental Base58 Solana address. Does NOT require @solana/kit.
|
|
464
|
-
*/
|
|
362
|
+
/** @experimental Base58 Solana address. Does NOT require @solana/kit. */
|
|
465
363
|
getSolanaAddress(options?: {
|
|
466
364
|
reuseMessageKey?: boolean;
|
|
467
365
|
}): string;
|