Hi,
I noticed two scrypt behaviors in the Workers crypto compatibility layer currently diverge from Node.js.
Issue 1: Wrong error code
When invalid parameters are passed to scrypt, Node.js throws ERR_CRYPTO_INVALID_SCRYPT_PARAMS with a .code property set accordingly. Workers instead throws a generic Error with the message Scrypt failed and no .code property at all.
Here is a reproduction:
import crypto from 'node:crypto';
export default {
async fetch() {
try {
crypto.scryptSync('pw', 'salt', 64, { N: 3, r: 8, p: 1 });
} catch(e) {
return new Response('code: ' + e.code + '\nmessage: ' + e.message);
}
}
}
Running this in Node.js produces:
ERR_CRYPTO_INVALID_SCRYPT_PARAMS
message: Invalid scrypt params
Running the same code in Workers produces:
code: undefined
message: Scrypt failed
Issue 2: maxmem set to zero behaves opposite to Node.js
Node.js treats maxmem: 0 as an invalid parameter and throws ERR_CRYPTO_INVALID_SCRYPT_PARAMS. Workers accepts maxmem: 0 and allows the operation to succeed.
crypto.scryptSync('pw', 'salt', 64, { N: 32768, r: 8, p: 1, maxmem: 0 });
In Node.js this throws. In Workers it succeeds. When maxmem is set to a valid value like 33MB, both Node.js and Workers succeed as expected.
Root cause
The implementation in src/node/internal/crypto_scrypt.ts discards the error code and the OpenSSL error stack when propagating BoringSSL failures up to JavaScript.
Environment
Component: src/node/internal/crypto_scrypt.ts
Node.js version tested: v24.12.0
Reproduced on: Workers playground
Hi,
I noticed two scrypt behaviors in the Workers crypto compatibility layer currently diverge from Node.js.
Issue 1: Wrong error code
When invalid parameters are passed to scrypt, Node.js throws ERR_CRYPTO_INVALID_SCRYPT_PARAMS with a .code property set accordingly. Workers instead throws a generic Error with the message Scrypt failed and no .code property at all.
Here is a reproduction:
import crypto from 'node:crypto';
export default {
async fetch() {
try {
crypto.scryptSync('pw', 'salt', 64, { N: 3, r: 8, p: 1 });
} catch(e) {
return new Response('code: ' + e.code + '\nmessage: ' + e.message);
}
}
}
Running this in Node.js produces:
ERR_CRYPTO_INVALID_SCRYPT_PARAMS
message: Invalid scrypt params
Running the same code in Workers produces:
code: undefined
message: Scrypt failed
Issue 2: maxmem set to zero behaves opposite to Node.js
Node.js treats maxmem: 0 as an invalid parameter and throws ERR_CRYPTO_INVALID_SCRYPT_PARAMS. Workers accepts maxmem: 0 and allows the operation to succeed.
crypto.scryptSync('pw', 'salt', 64, { N: 32768, r: 8, p: 1, maxmem: 0 });
In Node.js this throws. In Workers it succeeds. When maxmem is set to a valid value like 33MB, both Node.js and Workers succeed as expected.
Root cause
The implementation in src/node/internal/crypto_scrypt.ts discards the error code and the OpenSSL error stack when propagating BoringSSL failures up to JavaScript.
Environment
Component: src/node/internal/crypto_scrypt.ts
Node.js version tested: v24.12.0
Reproduced on: Workers playground