You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
AOT: crypto.createHash('sha1').digest() returns a number, not a Buffer #86
crypto.createHash(...).update(buf).digest() under the AOT binary returns a value with typeof === 'number' instead of a 20-byte Buffer. instanceof Uint8Array is false, .length is undefined.
Other Buffer-producing paths (Buffer.alloc, Buffer.from) work correctly from the same cross-module context, so this is specific to the crypto Hash wrapper.
Any protocol that needs SHA-1 / SHA-256 / SHA-512 digests in-process.
Workarounds are painful — you'd have to reimplement the hash by hand, which defeats the point of having crypto in the stdlib.
Hit in real code
@perry/mysql's auth plugins (src/auth/native-password.ts, src/auth/caching-sha2.ts) compute the auth-response via h.digest(). Under the AOT binary the digest buffer has length === 0 by the time it reaches the outer nativeScramble, so the driver ends up sending an empty auth_response field in HandshakeResponse41 and the server rejects with errno 1045 "Access denied (using password: NO)".
Same source, run under Bun or Node, authenticates correctly against MySQL 8.
Expected
hash.digest() returns a Buffer of length matching the algorithm (20 for SHA-1, 32 for SHA-256, 64 for SHA-512), with Buffer.isBuffer(d) === true and d instanceof Uint8Array === true.
Fixed in v0.5.97. New HashHandle in perry-stdlib/src/crypto.rs wraps sha1/sha256/sha512/md5 state behind the handle registry; js_crypto_create_hash returns a small-int handle NaN-boxed with POINTER_TAG, and common/dispatch.rs routes subsequent .update/.digest through dispatch_hash. Also wired js_stdlib_init_dispatch() into main's prologue so HANDLE_METHOD_DISPATCH is registered eagerly (was previously lazy via ensure_pump_registered, which never fired for sync-only programs). SHA-1('hello') now returns aaf4c61ddcc5e8a2dabede0f3b482cd9aea9434d.
Activity
proggeramlug commentedon Apr 18, 2026
Fixed in v0.5.97. New
HashHandleinperry-stdlib/src/crypto.rswraps sha1/sha256/sha512/md5 state behind the handle registry;js_crypto_create_hashreturns a small-int handle NaN-boxed with POINTER_TAG, andcommon/dispatch.rsroutes subsequent.update/.digestthroughdispatch_hash. Also wiredjs_stdlib_init_dispatch()into main's prologue soHANDLE_METHOD_DISPATCHis registered eagerly (was previously lazy viaensure_pump_registered, which never fired for sync-only programs). SHA-1('hello') now returnsaaf4c61ddcc5e8a2dabede0f3b482cd9aea9434d.fix: backfill v0.5.97/v0.5.98 source that v0.5.99 dispatch builds on