Skip to content

🐛 Bug Report Runtime APIs node:crypto: Hmac.prototype.digest silently returns empty Buffer on second call instead of throwing ERR_CRYPTO_HASH_FINALIZED #6921

Description

@Sertug17

Description

Calling hmac.digest() a second time silently returns an empty Buffer (or '')
instead of throwing ERR_CRYPTO_HASH_FINALIZED, diverging from both Node.js behavior
and the existing Hash.prototype.digest implementation in the same file.

Reproduction

import { createHmac } from 'node:crypto';

const hmac = createHmac('sha256', 'secret');
hmac.update('data');

const first  = hmac.digest('hex');   // correct HMAC
const second = hmac.digest('hex');   // should throw, but returns '' in workerd
console.log(second); // '' — silent wrong result

Expected behavior (Node.js v22)

The second hmac.digest() call throws:

Error [ERR_CRYPTO_HASH_FINALIZED]: Digest already called

Actual behavior (workerd)

Returns '' (empty string) or Buffer.from('') silently, producing a wrong result
without any indication of the error.

Root cause

In src/node/internal/crypto_hash.ts, Hash.prototype.digest correctly throws
ERR_CRYPTO_HASH_FINALIZED on a second call, but Hmac.prototype.digest has:

if (state[kFinalized]) {
  return !outputEncoding || outputEncoding === 'buffer'
    ? Buffer.from('')  // ← silently wrong
    : '';
}

Fix: Replace the early return with throw new ERR_CRYPTO_HASH_FINALIZED().

Impact

Silent data corruption callers get an empty HMAC value thinking it's correct.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions