From 4c10e3e7245ca523a0c49e321fd2be9493adb52d Mon Sep 17 00:00:00 2001 From: Local Dev Date: Thu, 22 Oct 2026 00:10:19 +0300 Subject: [PATCH] hermes: lift scrypt maxmem so Create account doesn't throw MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit N=2^15 r=8 p=1 needs 128 * N * r = ~32 MiB. Node's default maxmem for scryptSync is exactly 32 MiB, so the derive call throws MEMORY_LIMIT_EXCEEDED on the first create-account click. Pass maxmem: 128 MiB explicitly so the ceiling is above the KDF's working set with headroom. Applies to both wrap and unwrap paths; wrap params carry the KDF cost inline so changing the N here would invalidate existing backups, but unwrap already reads N from the blob — the maxmem lift is the only needed change. --- main.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/main.js b/main.js index 97ee13c5..31df4e27 100644 --- a/main.js +++ b/main.js @@ -10147,8 +10147,10 @@ const HERMES_SCRYPT = { N: 1 << 15, r: 8, p: 1, keyLen: 32 }; function hermesWrapMnemonic(mnemonic, password) { const salt = nodeCrypto.randomBytes(16); + // N=2^15 r=8 p=1 needs ~32 MiB; Node's default maxmem is 32 MiB on-the-nose, + // which throws MEMORY_LIMIT_EXCEEDED. Lift the ceiling explicitly. const key = nodeCrypto.scryptSync(String(password), salt, HERMES_SCRYPT.keyLen, - { N: HERMES_SCRYPT.N, r: HERMES_SCRYPT.r, p: HERMES_SCRYPT.p }); + { N: HERMES_SCRYPT.N, r: HERMES_SCRYPT.r, p: HERMES_SCRYPT.p, maxmem: 128 * 1024 * 1024 }); const nonce = nodeCrypto.randomBytes(12); const cipher = nodeCrypto.createCipheriv("aes-256-gcm", key, nonce); const ct = Buffer.concat([cipher.update(String(mnemonic), "utf8"), cipher.final()]); @@ -10169,7 +10171,7 @@ function hermesUnwrapMnemonic(wrap, password) { } const salt = Buffer.from(wrap.kdf.salt, "hex"); const key = nodeCrypto.scryptSync(String(password), salt, HERMES_SCRYPT.keyLen, - { N: wrap.kdf.N, r: wrap.kdf.r, p: wrap.kdf.p }); + { N: wrap.kdf.N, r: wrap.kdf.r, p: wrap.kdf.p, maxmem: 128 * 1024 * 1024 }); const nonce = Buffer.from(wrap.nonce, "hex"); const decipher = nodeCrypto.createDecipheriv("aes-256-gcm", key, nonce); decipher.setAuthTag(Buffer.from(wrap.tag, "hex"));