hash.update()
Feeds more data into a Hash object, returning the same object so calls can be chained.
hash.update(data[, inputEncoding])- Added in Node.js v0.1.92
Parameters
| Parameter | Type | Description |
|---|---|---|
$data | string | Buffer | TypedArray | DataView | The data to add to the hash. It is appended to everything passed in previous update() calls. |
$inputEncodingoptional | string= 'utf8' | The encoding of data when data is a string, for example 'utf8', 'hex', 'base64' or 'latin1'. Ignored entirely when data is a Buffer, TypedArray or DataView. |
Return value
HashThe same Hash instance, so update() calls can be chained and finished with digest().
Errors
Throws ERR_CRYPTO_HASH_FINALIZED if called after digest() has already been invoked on the same Hash object.
Changelog
- PHP v6.0.0The default inputEncoding changed from 'binary' (latin1) to 'utf8', so non-ASCII strings hashed without an explicit encoding produce different digests before and after Node 6.
hash.update() appends bytes to a Hash created by crypto.createHash(). It returns the same object, so calls chain. Crucially, the hash sees a single continuous byte stream: update('hello ').update('world') and update('hello world') produce byte-for-byte identical digests. Chunk boundaries are invisible to the algorithm.
When to reach for it
Call it repeatedly when data arrives incrementally — chunks from a read stream, rows from a database cursor, or several separate values you want folded into one fingerprint. There is no size limit and no need to concatenate anything yourself.
What trips people up
Two things. First, the object is spent once digest() is called; a further update() throws ERR_CRYPTO_HASH_FINALIZED. To hash a second value you must create a new Hash.
Second, because chunk boundaries vanish, concatenating fields without a separator makes different inputs collide. Hashing the pair ('ab', 'c') and the pair ('a', 'bc') gives the same digest. If your fields are attacker-controlled, join them with a delimiter that cannot appear in the data, or fold in each field's length, or you have handed an attacker a way to forge a matching fingerprint.
Also note inputEncoding is silently ignored for Buffer input — passing 'hex' alongside a Buffer does not decode it.
Example
When to use it
- Hashing a file chunk by chunk as it is read from disk
- Combining several request fields into one cache key or fingerprint
- Digesting rows streamed from a database cursor without buffering them all
- Decoding a hex or base64 string into raw bytes before hashing it
Frequently asked questions
Does calling hash.update() multiple times change the digest?
No. The hash treats every update() as part of one continuous byte stream, so update('hello ').update('world') gives exactly the same digest as update('hello world'). This is what makes streaming a large file safe.
Why does hash.update() throw ERR_CRYPTO_HASH_FINALIZED?
Because digest() has already been called on that Hash object, which finalises it permanently. Create a fresh object with crypto.createHash() for each value you want to hash — Hash instances are not reusable.
Do I need inputEncoding when passing a Buffer to hash.update()?
No, it is ignored completely for Buffer, TypedArray and DataView input since those are already raw bytes. It matters only for strings, where it defaults to 'utf8' and controls whether something like 'deadbeef' is hashed as eight characters or four decoded bytes.
More examples
The concatenation collision, and how to avoid it
The naive version prints true: two completely different (user, resource) pairs produce one digest, because the hash only ever saw the bytes 'alicebob/doc'. Length-prefixing each field makes the encoding unambiguous and the collision disappears.
const crypto = require('node:crypto');
function naive(user, resource) {
return crypto.createHash('sha256').update(user).update(resource).digest('hex');
}
// A separator that cannot appear in either field removes the ambiguity.
function safe(user, resource) {
const h = crypto.createHash('sha256');
for (const field of [user, resource]) {
h.update(String(Buffer.byteLength(field)));
h.update('