noble-hashes
Audited, zero-dependency JS/TS implementation of SHA2, SHA3, BLAKE, HMAC, HKDF, PBKDF2, Scrypt and Argon2 that tree-shakes down to a few kilobytes per hash.
Repository Health
Technical Analysis
@noble/hashes is a minimal, audited implementation of cryptographic hash functions, MACs, and key derivation functions for JavaScript and TypeScript. It covers the SHA2 and SHA3 families (including SHAKE, cSHAKE, KMAC, and KangarooTwelve), the BLAKE1/2/3 family, legacy algorithms (SHA1, MD5, RIPEMD160), HMAC, and the KDFs HKDF, PBKDF2, Scrypt, Argon2, and an experimental ESKDF. Every algorithm lives in its own module with an ESM-only entry point, so bundlers exclude unused code and a single hash like sha256 ships at roughly 2.8KB gzipped.
The library was funded by the Ethereum Foundation, independently audited by Cure53 in 2022, and has since added regular AI-assisted self-audits plus continuous fuzzing in CI. It has zero runtime dependencies, PGP-signed commits, and provenance-verified npm releases through GitHub’s trusted publishing. It belongs to the broader noble cryptography suite alongside noble-curves and noble-ciphers, sharing the same emphasis on small, readable, dependency-free code that’s easy to audit line by line.
APIs follow a consistent shape across every module: a one-shot function call for simple cases (sha256(bytes)) and a create().update().digest() streaming interface for partial or chunked input, letting the same primitive hash up to 4GB per chunk across any number of chunks. A webcrypto.js wrapper mirrors the same API over the browser/Node built-in crypto.subtle for callers who prefer native implementations, and utils.js exposes hex/byte conversion helpers plus a CSPRNG-backed randomBytes.
What You Get
- SHA2 (sha224/256/384/512 and the 512/224, 512/256 variants) plus the full SHA3/Keccak family including SHAKE, cSHAKE, KMAC, TurboSHAKE and KangarooTwelve (KT128/KT256)
- BLAKE1, BLAKE2 (b/s), and BLAKE3 with keyed, salted, and context-personalized modes
- Legacy low-security hashes (SHA1, MD5, RIPEMD160) isolated in their own legacy.js module so they aren’t imported by accident
- Key derivation functions: HKDF, PBKDF2 (sync + async), Scrypt (sync + async, with progress callback and DoS-resistant maxmem), Argon2 (d/i/id), and an experimental ESKDF for deriving app-specific child keys
- HMAC with the same one-shot/streaming dual API as the hash functions
- A webcrypto.js wrapper offering an identical API backed by the platform’s native crypto.subtle
- Cryptographically secure randomBytes and hex/byte conversion utilities
Common Use Cases
- Hashing and integrity-checking data in Node.js, browsers, Deno, or React Native without native bindings
- Password hashing and key stretching with Scrypt or Argon2 before storing credentials
- Deriving symmetric keys from a shared secret via HKDF for use in encryption or signing schemes
- Computing HMACs to authenticate API requests or verify message integrity
- Building higher-level cryptographic protocols (signatures, key exchange) that need an audited, dependency-free hash primitive as a building block
Under The Hood
Architecture
A shared abstract base, HashMD in _md.ts, implements the Merkle-Damgard construction once; concrete hashes (SHA1, MD5, RIPEMD160 in legacy.ts, the SHA2 family in sha2.ts) subclass it and only override process, get, set, _cloneInto, destroy, and roundClean. SHA3/Keccak (sha3.ts, sha3-addons.ts) and BLAKE1/2/3 (blake1.ts, blake2.ts, blake3.ts) implement their own sponge/compression logic but reuse the same Hash interface and byte-handling primitives from utils.ts and the 64-bit word helpers in _u64.ts. KDFs (hkdf.ts, pbkdf2.ts, scrypt.ts, argon2.ts, eskdf.ts) are composed on top of the hash/HMAC primitives rather than reimplementing hashing. The root index.ts deliberately throws if imported directly, forcing every consumer through a specific subpath (sha2.js, blake3.js, etc.), which is what lets bundlers tree-shake unused algorithms out entirely. Changing the HashMD abstraction would ripple through every Merkle-Damgard hash, since SHA1, MD5, RIPEMD160 and the SHA2 family all extend the same six-method contract.
Tech Stack
TypeScript compiled straight through tsc with no bundler in the library build itself, zero runtime dependencies, and a minimal dev toolchain: the author’s own @paulmillr/jsbt build/benchmark/test helper, bismar for bundle-size checks, prettier, and @types/node. The package is ESM-only (type: module), targets Node >= 20.19, and declares a strict per-module exports map in package.json rather than a single entry point. Tests run through jsbt’s custom runner instead of Jest or Vitest. CI on GitHub Actions delegates to reusable workflows hosted in the author’s paulmillr/jsbt and paulmillr/cryptofuzz repositories, with separate jobs for standard tests, scheduled fuzzing, and slow DoS/ACVP/KDF suites.
Code Quality
The test/ directory holds over twenty dedicated files covering every algorithm (hashes.test.ts, blake.test.ts, keccak.test.ts, hmac.test.ts, kdf.test.ts, argon2.test.ts, webcrypto.test.ts, u64.test.ts, utils.test.ts, clone.test.ts), plus isolated slow suites for large inputs, DoS resistance, official ACVP/KAT vectors, and memory-intensive KDF parameters that are excluded from the default fast run. Tests check against official test vectors and cross-library chained hashing, with property-based coverage via fast-check and continuous fuzzing in CI. Source files carry detailed JSDoc with runnable @example blocks explaining non-obvious tradeoffs, such as why a specific call site must stay monomorphic for JIT scalar-replacement of secret-bearing state. Type safety is strict TypeScript, with custom generic helpers bridging typed-array API differences across TypeScript versions. Input validation is explicit (dedicated assertion helpers throw on malformed input) rather than silently swallowed.
API Design
Every algorithm follows the same dual shape: a one-shot call (sha256(bytes)) alongside a chained create().update(a).update(b).digest() form for partial or chunked input, so the mental model transfers across all fifteen-plus algorithms in the library. Low-security legacy hashes are isolated in their own legacy.js module specifically to avoid the accidental use of MD5 or SHA1. Options objects share consistent shapes across the family — dkLen, key, personalization, and salt mean the same thing whether the caller is using BLAKE2, BLAKE3, or a SHA3-addon function. A webcrypto.js wrapper exposes the identical function signatures over the platform’s native crypto.subtle, so switching implementations requires only an import change. Getting started needs a single subpath import and a function call, with no configuration or setup boilerplate.
Used by 6 apps in this directory
Documenso
Digital Signiture
Self-hosted, open-source DocuSign alternative with legally binding PDF signatures, multi-party workflows, and a full REST and tRPC API.
Enso
Analytics · Data Engineering · Low Code Platforms
A visual and textual programming platform for data prep and analysis where the node graph and the underlying Enso code are always perfectly in sync, built by an Alteryx co-founder on a GraalVM engine.
Epicenter
Knowledge Management · Note Taking · Developer Tools
A local-first monorepo led by Whispering, an open-source speech-to-text app, built on an MIT toolkit that turns your data into plain Markdown and SQLite files you own instead of a database you rent.
Orca
AI Agents · AI Code Assistants
An open-source Agent Development Environment that orchestrates fleets of parallel AI coding agents — Claude Code, Codex, Gemini and more — each running in its own isolated git worktree.
Traefik
Devops · Automation · Security
A cloud-native reverse proxy and load balancer that auto-configures itself from Docker, Kubernetes, and other orchestrators — zero manual routing required.
Webiny JS
Ecommerce · Blogging · CMS
Open-source, self-hosted CMS on AWS serverless — a TypeScript framework you extend with code, not a product you configure through a UI.