mrkeyoor.com_
Sat 08 Aug 21:01 UTC
npmSecurityupdated 08 Aug 2026

js-sha256

A dependency-free implementation of SHA-256, SHA-224 and their HMAC variants with the same small synchronous API in browsers and Node.js. It hashes strings as UTF-8 or accepts arrays, Uint8Array and ArrayBuffer, supports incremental updates, and can return hex, byte arrays or ArrayBuffer output. Version 1.0 uses Node's native crypto module on Node while shipping a JavaScript implementation for browsers, workers and direct script-tag use.

Verdict

A focused and recently modernized cross-runtime SHA-256 API, especially good when browser-side incremental hashing is the requirement. Skip it for Node-only code, password storage, or applications that can use Web Crypto directly.

API stability4/5The callable sha256 and sha224 objects, create/update flow, HMAC helpers and four output formats have existed for years, and the type declarations make that small contract easy to inspect. Version 1.0 did formalize new package exports, remove legacy generated entry points and make update-after-finalize throw. Those are sensible changes but mean older deep imports or accidental hasher reuse need attention during the major-version upgrade.
Docs3/5The README shows ESM, CommonJS, script-tag and AMD loading, then covers one-shot, incremental, HMAC, UTF-8, byte inputs and every output shape with known vectors. It is compact and accurate for the surface area. It does not explain security boundaries such as password hashing, constant-time comparison, secret handling or canonical serialization, and the migration implications of the new 1.0 export map live mainly in the changelog.
Maintenance5/5Version 1.0.0 was published on July 27, 2026 alongside the repository's latest push. Its changelog records dedicated distribution entry points, native Node crypto, artifact contract tests, Playwright worker tests and runtime coverage across Node 16, 18, 20, 22 and 24. The repository is not archived and had only three combined open issues and pull requests in the fetched GitHub snapshot, strong evidence of active focused upkeep.
Ecosystem4/5The package recorded 4,542,597 downloads in the measured week, supports ESM, CommonJS, browsers, Node and workers, and exposes familiar hash and HMAC forms that fit many protocols. Its scope is intentionally narrow, so there is no plugin ecosystem and consumers needing more algorithms must combine packages or switch libraries. Interoperability with standard SHA-256 is the ecosystem advantage, not package-specific extensions.

Use it if

  • You need one synchronous SHA-256 or SHA-224 API that works across Node, browsers and workers
  • You need incremental hashing for a file or stream but cannot rely on Web Crypto's one-shot digest API
  • You maintain browser code that consumes a UMD global, CommonJS and ESM from the same package
  • You need HMAC-SHA-256 with string or binary keys and several output formats without pulling in a general cryptography suite
Skip it if

Setup reality

npm install js-sha256 is the whole install, with no dependencies, peer packages, native compilation or runtime configuration. Version 1.0 has explicit package exports for ESM, CommonJS, Node and browser builds. Use named imports from the package root instead of old unpublished or improvised deep paths; the changelog says legacy generated entry points were removed. Node automatically receives an adapter backed by node:crypto, while browser imports execute the package's JavaScript core. The public calls are synchronous in both environments. Strings are encoded as UTF-8, so hash bytes directly when a protocol specifies exact octets or an existing text encoding. Incremental hashing does not open files or consume streams for you: read chunks, call update for each one, then select hex(), array(), digest() or arrayBuffer(). Calling an output method finalizes the hasher, and version 1.0 now throws if update is called afterward, so create a new instance for every message. HMAC keys receive the same string-or-bytes treatment as messages. The library does not generate keys, salt passwords, compare tags in constant time, canonicalize JSON, or protect secrets stored in frontend code. Those are application responsibilities, not missing setup flags.

Patterns

Hash a UTF-8 string with SHA-256hash-text

import { sha256 } from 'js-sha256';

const digest = sha256('Message to hash');
console.log(digest); // lowercase hexadecimal

String input is encoded as UTF-8. If a protocol defines a different encoding or exact bytes, encode it yourself and pass a Uint8Array.

Produce a SHA-224 digesthash-sha224

import { sha224 } from 'js-sha256';

const digest = sha224('Message to hash');
console.log(digest);

SHA-224 produces a shorter digest than SHA-256. Use the algorithm named by your protocol rather than choosing based only on output length.

Hash bytes without text conversionhash-binary-data

import { sha256 } from 'js-sha256';

const bytes = new Uint8Array([0xd3, 0xd4]);
const digest = sha256(bytes);

Uint8Array, ArrayBuffer and number[] are accepted. Passing bytes avoids accidental UTF-8 encoding of a string representation.

Return hex, bytes or an ArrayBufferchoose-output-format

const hex = sha256.hex(data);
const bytes = sha256.array(data);
const sameBytes = sha256.digest(data);
const buffer = sha256.arrayBuffer(data);

array and digest are aliases returning number[]. The default callable form and hex both return lowercase hexadecimal.

Hash a message in chunkshash-incrementally

const hash = sha256.create();
hash.update('Message');
hash.update(' to hash');
const digest = hash.hex();

An output call finalizes the instance. Version 1.0 throws if update is called after hex, array, digest or arrayBuffer.

Hash a browser File without one giant bufferhash-browser-file

async function hashFile(file: File) {
  const hash = sha256.create();
  const reader = file.stream().getReader();

  for (;;) {
    const { value, done } = await reader.read();
    if (done) break;
    hash.update(value);
  }

  return hash.hex();
}

The library supplies incremental updates, not file I/O. File.stream is a browser API and availability depends on the browser versions you support.

Hash a Node.js readable streamhash-node-stream

import { createReadStream } from 'node:fs';
import { sha256 } from 'js-sha256';

const hash = sha256.create();
for await (const chunk of createReadStream('archive.tar')) {
  hash.update(chunk);
}
console.log(hash.hex());

On Node, version 1.0 routes hashing through native node:crypto. The wrapper is not itself a Transform stream, so feed chunks in a loop.

Authenticate a message with HMAC-SHA-256create-hmac

const tag = sha256.hmac('secret-key', 'message');
console.log(tag);

A string key is UTF-8 encoded. Do not embed a real server secret in browser JavaScript, where every user can read it.

Build an HMAC from chunksstream-hmac

const mac = sha256.hmac.create(secretKeyBytes);
mac.update(headerBytes);
mac.update(bodyBytes);
const tagBytes = mac.array();

The chunk boundaries do not affect the result, but byte order does. Keep protocol framing explicit so different field combinations cannot become ambiguous.

Compare HMAC tags safely in Node.jsverify-hmac-node

import { timingSafeEqual } from 'node:crypto';

const expected = Buffer.from(sha256.hmac.array(secret, body));
const received = Buffer.from(receivedHex, 'hex');
const valid = received.length === expected.length &&
  timingSafeEqual(received, expected);

The package computes HMAC but does not provide verification. Compare equal-length byte strings with a constant-time primitive rather than === on hex strings.

Create a SHA-256 Subresource Integrity valuemake-sri-value

const bytes = new Uint8Array(await response.arrayBuffer());
const digest = new Uint8Array(sha256.arrayBuffer(bytes));
const base64 = btoa(String.fromCharCode(...digest));
const integrity = `sha256-${base64}`;

SRI uses base64, not the package's default hex output. Spreading 32 digest bytes is safe; do not use this spread technique for the full downloaded resource.

Hash deterministic JSON byteshash-canonical-json

const canonical = JSON.stringify({
  id: record.id,
  name: record.name,
  tags: [...record.tags].sort(),
});
const digest = sha256(canonical);

Hashing ordinary JSON does not create canonical JSON automatically. Fix field order, number formatting and array ordering according to your protocol before hashing.

Alternatives

PackageRegistryPick it when
@noble/hashesnpmChoose it for audited-style, dependency-free implementations covering SHA-2, SHA-3, BLAKE and password-oriented primitives
hash-wasmnpmChoose it for large browser inputs or a wider algorithm list where WebAssembly performance is worth the extra machinery
crypto-jsnpmChoose it only for compatibility with an existing CryptoJS WordArray codebase that already depends on its broader API