Skip to content

fix(crypto): sha224/sha384, base64 digest, and Buffer hash input#1393

Merged
proggeramlug merged 1 commit into
mainfrom
feat/crypto-hashing-1352-1357
May 22, 2026
Merged

fix(crypto): sha224/sha384, base64 digest, and Buffer hash input#1393
proggeramlug merged 1 commit into
mainfrom
feat/crypto-hashing-1352-1357

Conversation

@proggeramlug
Copy link
Copy Markdown
Contributor

Three fixes in the createHash / createHmac digest path. The hex + string-input inline fast path (SCRAM / #214 / #1076) is left unchanged; the fixes either add runtime algorithms or route the previously-mishandled cases to the runtime handle dispatch (dispatch_hash), which was already correct for them.

Fixes

  • sha224 / sha384 (node:crypto — add createHash sha224 / sha384 #1357) — added to the runtime HashState enum, js_crypto_create_hash, and dispatch_hash. createHash('sha224'|'sha384') previously returned undefined, so the chained .update() threw Cannot read properties of undefined.
  • digest('base64'|'base64url') (node:crypto — hash.digest('base64'|'base64url') ignores the encoding #1352) — the inline sha256/md5/hmac-sha256 fast path only emits hex (or a raw-byte Buffer for the no-arg form), so it silently returned hex for any other encoding. The fast path is now narrowed to hex / no-arg only; every other encoding falls through to dispatch_hash, which honors base64/base64url.
  • update(Buffer) / createHmac(_, Buffer) (node:crypto — createHash().update(Buffer) hashes the wrong representation #1354) — the fast path unboxed inputs as *StringHeader and hashed the UTF-8 string bytes, reading the wrong bytes for a Buffer/Uint8Array (different header layout). Buffer-typed inputs — inline Buffer.from(...) / crypto.randomBytes(...) and Buffer/Uint8Array-typed locals/fields — now route to the handle dispatch, whose bytes_from_ptr reads either layout.

Validation

Byte-for-byte parity against node --experimental-strip-types:

  • digest('base64') / digest('base64url') for hash + hmac
  • update(Buffer) (local var) and createHmac(_, Buffer.from(...)) (inline)
  • sha224 / sha384 hex + base64
  • Regression unchanged: sha256/md5/hmac hex, no-arg Buffer digest length, standalone const h = createHash(...) form, dynamic (const alg) hash/hmac, incremental .update().update().

Not included

digest() (no-arg) Buffer .toString('hex') / numeric indexing (#1353) is a separate type-inference issue — the no-arg digest() result isn't statically typed as a Buffer, so .toString('hex') and buf[0] mis-dispatch. It affects the runtime handle path too and is unchanged by this PR; it'll be addressed separately.

Closes #1352
Closes #1354
Closes #1357

Three fixes in the createHash/createHmac digest path:

- sha224 / sha384 (#1357): add both to the runtime HashState enum,
  js_crypto_create_hash, and dispatch_hash. createHash('sha224'|'sha384')
  previously returned undefined, crashing on the chained .update().

- digest('base64'|'base64url') (#1352): the inline sha256/md5/hmac fast
  path only emits hex (or a raw-byte Buffer for the no-arg form), so it
  silently returned hex for any other encoding. Narrow the fast path to
  hex / no-arg only; every other encoding falls through to the runtime
  handle dispatch, whose dispatch_hash already honors base64/base64url.

- update(Buffer) / createHmac(_, Buffer) (#1354): the fast path unboxed
  inputs as *StringHeader and hashed the UTF-8 string bytes, which reads
  the wrong bytes for a Buffer/Uint8Array (different header layout). Route
  Buffer-typed inputs (inline Buffer.from(...)/randomBytes(...) and
  Buffer/Uint8Array-typed locals) to the handle dispatch, whose
  bytes_from_ptr reads either layout.

The hex + string-input fast path (SCRAM / #214 / #1076) is unchanged.
Verified byte-for-byte against `node --experimental-strip-types` for
base64/base64url (hash + hmac), Buffer input (local + inline), sha224/384,
plus regression on hex/no-arg-Buffer/standalone/dynamic-alg forms.

Closes #1352
Closes #1354
Closes #1357
@proggeramlug proggeramlug merged commit 5563242 into main May 22, 2026
9 checks passed
@proggeramlug proggeramlug deleted the feat/crypto-hashing-1352-1357 branch May 22, 2026 14:31
proggeramlug added a commit that referenced this pull request May 22, 2026
…sweep (#1414)

Rolls up 26 PRs that merged to main post-v0.5.1023 without version
bumps:

- node:crypto gap-fixes (#1386 #1393 #1394 #1402 #1405): randomInt,
  timingSafeEqual, getHashes/getCiphers, sha224/sha384, base64 digest,
  Buffer hash input, no-arg digest() → Buffer, pbkdf2Sync digest arg,
  scryptSync.
- node:perf_hooks (#1321 + #1328 #1342 coverage): performance + User
  Timing + PerformanceObserver native impl, granular node-suite +
  edge-case coverage.
- #1090 GC checkpoint runtime work (#1324).
- #1311 geisterhand on iOS (#1316 #1383 #1384 #1385).
- #1312 process.env.X (unset) is nullish undefined (#1314).
- #1319 thread-safety hardening for cross-thread runtime statics.
- #1322 exact-head GC evidence packet.
- #1323 wasm timers dispatch through mem_call bridge (#1329).
- #1317 node:timers/promises shadow-segfault fix (#1326).
- #1330 node:process suite (#1331).
- #1292 bcrypt.hash() returns String (#1307).
- #1293 fastify .json()/.body external-fastify dispatch (#1308).
- #1296 app pattern performance gaps.
- #1297 diagnostics_channel parity.
- #1301 iOS App Groups capability (#1313).
- #1318 #1325 os/methods/modern-methods static dispatch.
- #1315 expanded Node parity test coverage.
- #1382 ui-ios stdlib pump for async fetch.
- #1392 ui-wasm reactive state + setText (#1404).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

1 participant