88 * adapted for Aptos key types. Supports encrypting Ed25519, Secp256k1, and Secp256r1
99 * private keys with a password or key file using modern cryptography:
1010 *
11- * - KDF: scrypt (default), Argon2id (requires optional `hash-wasm` peer dependency ), or PBKDF2-HMAC-SHA256
11+ * - KDF: Argon2id (default when `hash-wasm` is installed), scrypt (fallback ), or PBKDF2-HMAC-SHA256
1212 * - Cipher: AES-256-GCM (authenticated encryption)
1313 *
1414 * AES-256-GCM provides both confidentiality and integrity in a single operation,
@@ -105,8 +105,8 @@ export type KeystoreKdfParams = Argon2idKdfParams | ScryptKdfParams | Pbkdf2KdfP
105105 * "cipher": "aes-256-gcm",
106106 * "cipherparams": { "iv": "...", "tag": "..." },
107107 * "ciphertext": "...",
108- * "kdf": "scrypt ",
109- * "kdfparams": { "n ": 131072 , "r ": 8 , "p ": 1 , "dklen": 32, "salt": "..." }
108+ * "kdf": "argon2id ",
109+ * "kdfparams": { "iterations ": 3 , "parallelism ": 4 , "memorySize ": 65536 , "dklen": 32, "salt": "..." }
110110 * }
111111 * }
112112 * ```
@@ -144,7 +144,7 @@ export interface AptosKeyStore {
144144 * Options for customizing keystore encryption.
145145 */
146146export interface KeystoreEncryptOptions {
147- /** KDF to use. Defaults to "scrypt". Use " argon2id" for stronger protection (requires `hash-wasm` peer dependency) . */
147+ /** KDF to use. Defaults to "argon2id" if `hash-wasm` is installed, otherwise "scrypt" . */
148148 kdf ?: KeystoreKdf ;
149149 /** Argon2id iterations (time cost). Defaults to 3. */
150150 argon2Iterations ?: number ;
@@ -180,13 +180,26 @@ function passwordToBytes(password: string | Uint8Array): Uint8Array {
180180 return password ;
181181}
182182
183- async function loadArgon2id ( ) : Promise < typeof import ( "hash-wasm" ) . argon2id > {
183+ async function tryLoadArgon2id ( ) : Promise < typeof import ( "hash-wasm" ) [ " argon2id" ] | null > {
184184 try {
185185 const mod = await import ( "hash-wasm" ) ;
186186 return mod . argon2id ;
187187 } catch {
188+ return null ;
189+ }
190+ }
191+
192+ async function loadArgon2id ( ) : Promise < typeof import ( "hash-wasm" ) [ "argon2id" ] > {
193+ const fn = await tryLoadArgon2id ( ) ;
194+ if ( ! fn ) {
188195 throw new Error ( 'Argon2id KDF requires the "hash-wasm" package. Install it with: npm install hash-wasm' ) ;
189196 }
197+ return fn ;
198+ }
199+
200+ async function resolveDefaultKdf ( ) : Promise < KeystoreKdf > {
201+ const argon2 = await tryLoadArgon2id ( ) ;
202+ return argon2 ? "argon2id" : "scrypt" ;
190203}
191204
192205async function deriveKey ( password : Uint8Array , kdf : KeystoreKdf , kdfparams : KeystoreKdfParams ) : Promise < Uint8Array > {
@@ -299,9 +312,9 @@ function createPrivateKey(bytes: Uint8Array, keyType: PrivateKeyVariants): Keyst
299312 * Supports all Aptos private key types (Ed25519, Secp256k1, Secp256r1).
300313 * The password can be a string (passphrase) or raw bytes (e.g., contents of a key file).
301314 *
302- * Uses AES-256-GCM authenticated encryption with scrypt key derivation by default.
303- * For stronger password protection, use `kdf: "argon2id"` (requires the optional
304- * `hash-wasm` peer dependency: `npm install hash-wasm`) .
315+ * Uses AES-256-GCM authenticated encryption. The default KDF is Argon2id when the
316+ * optional `hash-wasm` peer dependency is installed (`npm install hash-wasm`),
317+ * falling back to scrypt otherwise .
305318 *
306319 * @param args.privateKey - The private key to encrypt.
307320 * @param args.password - Password string or key-file bytes used to derive the encryption key.
@@ -312,18 +325,18 @@ function createPrivateKey(bytes: Uint8Array, keyType: PrivateKeyVariants): Keyst
312325 * ```typescript
313326 * import { Ed25519PrivateKey, encryptKeystore } from "@aptos-labs/ts-sdk";
314327 *
315- * // Default (scrypt) — no extra dependencies
328+ * // Uses argon2id if hash-wasm is installed, scrypt otherwise
316329 * const privateKey = Ed25519PrivateKey.generate();
317330 * const keystore = await encryptKeystore({
318331 * privateKey,
319332 * password: "my-secure-password",
320333 * });
321334 *
322- * // Argon2id — requires: npm install hash-wasm
323- * const keystoreArgon2 = await encryptKeystore({
335+ * // Explicitly request a KDF
336+ * const keystoreScrypt = await encryptKeystore({
324337 * privateKey,
325338 * password: "my-secure-password",
326- * options: { kdf: "argon2id " },
339+ * options: { kdf: "scrypt " },
327340 * });
328341 * ```
329342 */
@@ -333,8 +346,9 @@ export async function encryptKeystore(args: {
333346 options ?: KeystoreEncryptOptions ;
334347} ) : Promise < AptosKeyStore > {
335348 const { privateKey, password, options = { } } = args ;
349+ const defaultKdf = options . kdf ?? ( await resolveDefaultKdf ( ) ) ;
336350 const {
337- kdf = "scrypt" ,
351+ kdf = defaultKdf ,
338352 argon2Iterations = 3 ,
339353 argon2Parallelism = 4 ,
340354 argon2MemorySize = 65536 ,
0 commit comments