Skip to content

XOF hash function changed their default outputLength to zero byte #58913

Description

@antoinep92

Version

v22.14.0

Platform

Linux ### 6.15.2-arch1-1 #1 SMP PREEMPT_DYNAMIC Tue, 10 Jun 2025 21:32:33 +0000 x86_64 GNU/Linux

Subsystem

crypto

What steps will reproduce the bug?

Try to hash anything using a variable length hash function (e.g. shake128), without any options you get an empty buffer/string.

How often does it reproduce? Is there a required condition?

Reproducible, but I haven't dissected the exact version the default changed. I known it is somewhere between v14.21.3 and v22.14.0 and yes I realize this is a very large window 😕

What is the expected behavior? Why is that the expected behavior?

shake128 should default to outputLength = 16 as in earlier Node.JS versions. Other variable-length (XOF) hashes should also default to sensible non-zero length.

I believe it is sane to expect the following assertion:

const {getHashes, createHash } = require('crypto');
assert.equal( 0 , getHashes().filter( h => !createHash(h).digest().length ).length )

What do you see instead?

getHashes().filter( h => !createHash(h).digest().length ) == [ 'shake128', 'shake256' ]

Additional information

  • Node 12.8.0 introduced the outputLength option to crypto.createHash
  • In Node 14.21.3 and earlier, when the option is omitted, shake128 defaults to 16 bytes output
  • In Node 22.14.0 and later, the default is zero, which results in empty hashes:
> require('crypto').createHash('shake128').update('test').digest()
<Buffer >

There are two issues here:

  • It is not backward compatible, and unless I missed something this breaking change is not documented, which resulted in breaking our app when upgrading node
  • In general, defaulting to null length by default is very countrer-intuitive

Activity

  1. added
    cryptoIssues and PRs related to the crypto subsystem.
    on Jul 2, 2025
  2. panva commented on Jul 3, 2025

    @panva
    Member

    I'm not able to reproduce this issue with bundled OpenSSL

    $ node -p 'process.versions'
    {
      node: '22.14.0',
      acorn: '8.14.0',
      ada: '2.9.2',
      amaro: '0.3.0',
      ares: '1.34.4',
      brotli: '1.1.0',
      cjs_module_lexer: '1.4.1',
      cldr: '46.0',
      icu: '76.1',
      llhttp: '9.2.1',
      modules: '127',
      napi: '10',
      nbytes: '0.1.1',
      ncrypto: '0.0.1',
      nghttp2: '1.64.0',
      nghttp3: '1.6.0',
      ngtcp2: '1.10.0',
      openssl: '3.0.15+quic',
      simdjson: '3.10.1',
      simdutf: '6.0.3',
      sqlite: '3.47.2',
      tz: '2024b',
      undici: '6.21.1',
      unicode: '16.0',
      uv: '1.49.2',
      uvwasi: '0.0.21',
      v8: '12.4.254.21-node.22',
      zlib: '1.3.0.1-motley-82a5fec'
    }
    $ node -p "require('crypto').createHash('shake128').update('test').digest().byteLength"
    16
    

    But suspect this has to with using linked OpenSSL >= 3.4, @antoinep92 can you confirm?

  3. panva commented on Jul 3, 2025

    @panva
    Member

    The issue is not Node changing the default, it's OpenSSL.

    While we are testing on later OpenSSL versions I am unsure about how "supported" they actually are meant to be. I've identified the issue and opened a PR to work around the OpenSSL breaking change.

  4. antoinep92 commented on Jul 3, 2025

    @antoinep92
    Author

    But suspect this has to with using linked OpenSSL >= 3.4, @antoinep92 can you confirm?

    Hi @panva indeed I confirm I have OpenSSL 3.5 installed. Thanks for tracking this down and the PR 👍
    I haven't found any maximum supported version for OpenSSL either, but it makes sense that not all versions of all shared libs can be tested.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    confirmed-bugIssues and PRs for confirmed bugs.cryptoIssues and PRs related to the crypto subsystem.

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions