sha.js

A pure JavaScript, streamable implementation of the SHA family of hash functions with a Node-crypto-like API.

Library
npm
v2.4.12
298stars
(MIT AND BSD-3-Clause)

Repository Health

Pre-computed score based on development activity, maintenance, community, maturity, and trend momentum.How we score it →
36/100Needs Attention
Development Activity0
Maintenance0
Community64
Maturity60
Momentum20

Technical Analysis

AI-assessed by reading the actual repository — architecture, code quality, innovation, and documentation.How we score it →
55/100Fair
Architecture68
Code Quality68
Innovation60
Learning Curve25

sha.js reimplements SHA-0, SHA-1, SHA-224, SHA-256, SHA-384, and SHA-512 entirely in JavaScript, with no native bindings and no dependency on Node’s built-in crypto module. It grew out of the browserify ecosystem as a polyfill so code written against Node’s hashing API could run unmodified in the browser, and it remains widely used today as a lightweight, dependency-light hashing primitive for any JavaScript runtime.

The API deliberately mirrors crypto.createHash(): call the exported factory with an algorithm name, then chain .update() calls and finish with .digest(), optionally requesting a specific string encoding. Each algorithm is also exposed as its own constructable class (shajs.sha256, etc.) for callers who prefer to instantiate directly rather than go through the string-keyed factory. Internally, all algorithms share a single base class that handles incremental block buffering, so adding or auditing a hash variant only requires implementing the compression function itself.

What You Get

  • A single factory function, require('sha.js')(algorithm), that returns a hash instance for any supported SHA variant by name
  • Per-algorithm constructors (shajs.sha256, shajs.sha1, shajs.sha224, shajs.sha384, shajs.sha512, plus legacy shajs.sha) for direct instantiation
  • Incremental hashing via .update(data, encoding), so input can be fed in chunks without buffering the whole payload in memory at once
  • A .digest(encoding) call that finalizes the hash and returns either a Buffer or an encoded string (e.g. 'hex')
  • A small CLI entry declared in package.json (bin.js) intended to hash stdin or a file from the command line

Common Use Cases

  • Bundling code for the browser (via browserify/webpack) that calls Node’s crypto.createHash with a SHA algorithm, without pulling in a native crypto shim
  • Computing checksums or content hashes incrementally for large inputs (files, streams) without loading the entire payload into memory
  • Supporting legacy or interoperability code paths that specifically need SHA-0 or SHA-1 output alongside modern SHA-2 variants
  • Acting as the underlying hash primitive inside other browserify-ecosystem crypto packages (e.g. HMAC or PBKDF2 implementations) that need a pure-JS SHA implementation to build on

Under The Hood

Architecture The library is built around a single template-method base class in hash.js: Hash(blockSize, finalSize) owns the incremental block-buffering logic (update) and padding/length-encoding finalization (digest), and defers the actual compression step to a _update/_hash pair that each algorithm module must implement. sha.js, sha1.js, sha224.js, sha256.js, sha384.js, and sha512.js each use inherits to extend that base class with their own round constants and compression function, and index.js is a thin factory that lowercases the requested algorithm name and looks up the matching subclass, also re-exporting each subclass directly for callers who want to new it themselves. Because every variant shares the same base class, a bug or behavior change in hash.js’s buffering/padding logic would propagate to all six algorithms simultaneously.

Tech Stack The library ships as plain CommonJS with no build step or bundler — files are required directly as published. Runtime dependencies are minimal and deliberately chosen for cross-version compatibility: inherits for prototype-based subclassing, safe-buffer so Buffer usage behaves consistently across old and new Node versions, and to-buffer to coerce arbitrary input into a Buffer. Development tooling includes tape for the test runner, eslint (pinned to a specific version) with the @ljharb/eslint-config shared config, hash-test-vectors for known-answer test data, and auto-changelog to generate CHANGELOG.md from commit history. GitHub Actions workflows run the test suite across a wide matrix of Node.js versions from very old to current.

Code Quality Tests in test/test.js and test/vectors.js run each algorithm against the hash-test-vectors known-answer corpus via tape, and test/hash.js separately unit-tests the base class’s block-buffering edge cases. CI runs npm run lint (ESLint) before the test suite as a pretest gate, and a posttest step runs npm audit for production dependencies. Error handling is minimal but explicit: the factory throws a clear error for an unrecognized algorithm name rather than failing silently. There are no type annotations (plain JavaScript, no TypeScript or JSDoc types). One quality gap: the package’s declared CLI entry point, bin.js, requires a ./browserify module that does not exist anywhere in the published source, so the CLI is effectively broken — this does not affect the library’s primary require('sha.js') usage path, which is unaffected.

API Design The public API is intentionally unsurprising: it mirrors Node’s built-in crypto.createHash(algorithm).update(data).digest(encoding) shape almost exactly, so anyone familiar with Node’s native crypto module can use sha.js with zero learning curve. Naming is consistent across algorithms (sha1, sha224, sha256, sha384, sha512), and getting started requires no configuration or setup beyond a single require() call. Documentation is limited to a short README with one usage example and a list of supported algorithms — there is no per-method API reference or dedicated examples directory beyond that.

Join founders buildingwith open source

Opinionated takes, migration guides, cost-saving tips, and insights from the open source ecosystem.

Subscribe on Substack
Join 750+ subscribers

Search