npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@noble/hashes

v2.4.0

Published

Audited & minimal 0-dependency JS implementation of SHA, RIPEMD, BLAKE, HMAC, HKDF, PBKDF & Scrypt

Readme

noble-hashes

Audited & minimal JS implementation of hash functions, MACs and KDFs.

  • 🔒 Audited by an independent security firm
  • 🪶 Minimal: 2.8KB (gzipped) sha256, unused code is excluded from your builds
  • 🏎 Fast: hand-optimized for caveats of JS engines
  • 🔍 Reliable: chained / ACVP tests ensure correctness
  • 🔁 No unrolled loops: makes it easier to verify and reduces source code size up to 5x
  • 🦘 Includes SHA, RIPEMD, BLAKE, HMAC, HKDF, PBKDF, Scrypt, Argon2
  • 🥈 Wrapper with identical API over native WebCrypto

The library's initial development was funded by Ethereum Foundation.

This library belongs to noble cryptography

noble cryptography — high-security, easily auditable set of contained cryptographic libraries and tools.

Usage

npm install @noble/hashes

deno add jsr:@noble/hashes

We support all major platforms and runtimes. For React Native, you may need a polyfill for getRandomValues. A standalone file noble-hashes.js is also available.

// import * from '@noble/hashes'; // Error: use sub-imports, to ensure small app size
import { sha256 } from '@noble/hashes/sha2.js';
const hash = sha256(Uint8Array.from([0xca, 0xfe, 0x01, 0x23]));

Implementations

Hash functions:

  • sha256(): receive & return Uint8Array
  • sha256.create().update(a).update(b).digest(): support partial updates
  • blake3.create({ context: 'e', dkLen: 32 }): can have options
  • support little-endian architecture; also experimentally big-endian
  • can hash up to 4GB per chunk, with any amount of chunks

sha2: sha256, sha384, sha512 and others

import { sha224, sha256, sha384, sha512, sha512_224, sha512_256 } from '@noble/hashes/sha2.js';
const res = sha256(Uint8Array.from([0xbc]));

sha3: FIPS, SHAKE, Keccak

import {
  sha3_224, sha3_256, sha3_384, sha3_512,
  keccak_224, keccak_256, keccak_384, keccak_512,
  shake128, shake256,
} from '@noble/hashes/sha3.js';
const s = sha3_256(Uint8Array.from([0x10, 0x20, 0x30]));
const shka = shake128(Uint8Array.from([0x10]), { dkLen: 512 });
const shkb = shake256(Uint8Array.from([0x30]), { dkLen: 512 });

sha3-addons: cSHAKE, KMAC, KT128, TurboSHAKE

import {
  cshake128, cshake256, kt128, kt256,
  keccakprg, kmac128, kmac256,
  parallelhash256, tuplehash256,
  turboshake128, turboshake256,
} from '@noble/hashes/sha3-addons.js';
const data = Uint8Array.from([0x10, 0x20, 0x30]);
const ec = cshake128(data, { personalization: new TextEncoder().encode('def') });
const et = turboshake256(data, { D: 0x05 });
// tuplehash(['ab', 'c']) !== tuplehash(['a', 'bc']) !== tuplehash([data])
const eu = tuplehash256([new TextEncoder().encode('ab'), new TextEncoder().encode('c')]);
// Not parallel in JS (similar to blake3 / kt128), added for compat
const ep = parallelhash256(data, { blockLen: 8 });
const ek = kmac256(Uint8Array.from([0xca]), data);
const ekt = kt128(data);
const p = keccakprg(254);
p.addEntropy();
const rand1b = p.randomBytes(32);

blake1, blake2, blake3

import { blake224, blake256, blake384, blake512 } from '@noble/hashes/blake1.js';
import { blake2b, blake2s } from '@noble/hashes/blake2.js';
import { blake3 } from '@noble/hashes/blake3.js';
const ab = Uint8Array.from([0x01]);
blake256(ab);

// blake2 advanced usage
const txt = new TextEncoder();
blake2s(ab, { key: new Uint8Array(32) }); // blake2b keys can be 64 bytes
blake2s(ab, { personalization: txt.encode('pers1234') }); // 16 bytes for blake2b
blake2s(ab, { salt: txt.encode('salt1234') }); // 16 bytes for blake2b

// blake3 advanced usage
blake3(ab, { dkLen: 256 });
blake3(ab, { key: new Uint8Array(32) });
blake3(ab, { context: txt.encode('application-name') });

legacy: sha1, md5, ripemd160

import { md5, ripemd160, sha1 } from '@noble/hashes/legacy.js';
const h = sha1(Uint8Array.from([0x10, 0x20, 0x30]));

hmac

import { hmac } from '@noble/hashes/hmac.js';
import { sha256 } from '@noble/hashes/sha2.js';
const key = new Uint8Array(32).fill(1);
const msg = new Uint8Array(32).fill(2);
const mac1 = hmac(sha256, key, msg);
const mac2 = hmac.create(sha256, key).update(msg).digest();

hkdf

import { hkdf } from '@noble/hashes/hkdf.js';
import { randomBytes } from '@noble/hashes/utils.js';
import { sha256 } from '@noble/hashes/sha2.js';
const inputKey = randomBytes(32);
const salt = randomBytes(32);
const info = new TextEncoder().encode('application-key');
const hk1 = hkdf(sha256, inputKey, salt, info, 32);

// == same as
import { extract, expand } from '@noble/hashes/hkdf.js';
const prk = extract(sha256, inputKey, salt);
const hk2 = expand(sha256, prk, info, 32);

pbkdf2

import { pbkdf2, pbkdf2Async } from '@noble/hashes/pbkdf2.js';
import { sha256 } from '@noble/hashes/sha2.js';
const pbkey1 = pbkdf2(sha256, 'password', 'salt', { c: 524288, dkLen: 32 });
const pbkey2 = await pbkdf2Async(sha256, 'password', 'salt', { c: 524288, dkLen: 32 });
const pbkey3 = await pbkdf2Async(sha256, Uint8Array.from([1, 2, 3]), Uint8Array.from([4, 5, 6]), {
  c: 524288,
  dkLen: 32,
});

scrypt

import { scrypt, scryptAsync } from '@noble/hashes/scrypt.js';
const scr1 = scrypt('password', 'salt', { N: 2 ** 16, r: 8, p: 1, dkLen: 32 });
const scr2 = await scryptAsync('password', 'salt', { N: 2 ** 16, r: 8, p: 1, dkLen: 32 });
const scr3 = await scryptAsync(Uint8Array.from([1, 2, 3]), Uint8Array.from([4, 5, 6]), {
  N: 2 ** 17,
  r: 8,
  p: 1,
  dkLen: 32,
  onProgress(percentage) {
    console.log('progress', percentage);
  },
  // maxmem: 128 * 8 * (2 ** 17 + 1 + 1), // 128 * r * (N + p + 1)
});
  • N, r, p are work factors. It is common to only adjust N, while keeping r: 8, p: 1. See the blog post. JS doesn't support parallelization, making increasing p meaningless.
  • dkLen is the length of output bytes e.g. 32 or 64
  • onProgress can be used with async version of the function to report progress to a user.
  • maxmem prevents DoS and defaults to 1GiB + 2KiB (2**30 + 2**11), enough for N: 2**20, r: 8, p: 1. It can be adjusted using formula: 128 * r * (N + p + 1)

On Apple M4, N: 2**16 takes 0.1s and 64MB RAM; each increment of N doubles both, up to N: 2**24 at 27s and 16GB. Mobile phones can be 1x-4x slower.

[!NOTE] We support N larger than 2**20 where available, however, not all JS engines support >= 2GB ArrayBuffer-s. When using such N, you'll need to manually adjust maxmem, using formula above. Other JS implementations don't support large N-s.

argon2

import { argon2d, argon2i, argon2id } from '@noble/hashes/argon2.js';
// Defaults to t=3, m=1GiB (specified in KiB), p=1, and a 1GiB maxmem limit.
const arg1 = argon2id('password', 'saltsalt');

[!WARNING] Argon2 can't be fast in JS, because there is no fast Uint64Array. It is suggested to use Scrypt instead. Being 5x slower than native code means brute-forcing attackers have bigger advantage.

eskdf

import { eskdf } from '@noble/hashes/eskdf.js';
const kdf = await eskdf('example-university', 'beginning-new-example');
console.log(kdf.fingerprint);
const key = kdf.deriveChildKey('aes', 0);
kdf.expire();

Experimental KDF for deriving application-specific child keys from a username + password pair, built on scrypt, pbkdf2 and hkdf with fixed work factors. Non-standard: prefer scrypt or argon2 for new designs.

webcrypto: friendly wrapper

import { sha256, sha384, sha512, hmac, hkdf, pbkdf2 } from '@noble/hashes/webcrypto.js';
import { randomBytes } from '@noble/hashes/utils.js';
const whash = await sha256(Uint8Array.from([0xca, 0xfe, 0x01, 0x23]));

const key = new Uint8Array(32).fill(1);
const msg = new Uint8Array(32).fill(2);
const wmac = await hmac(sha256, key, msg);

const inputKey = randomBytes(32);
const salt = randomBytes(32);
const info = new TextEncoder().encode('application-key');
const hk1 = await hkdf(sha256, inputKey, salt, info, 32);

const pbkey1 = await pbkdf2(sha256, 'password', 'salt', { c: 524288, dkLen: 32 });

A thin wrapper over built-in crypto.subtle, mirroring the noble-hashes API and validating inputs, in just 30+ lines of code. Webcrypto methods are always async.

utils

import { bytesToHex as toHex, randomBytes } from '@noble/hashes/utils.js';
console.log(toHex(randomBytes(32)));
  • bytesToHex will convert Uint8Array to a hex string
  • randomBytes(bytes) will produce cryptographically secure random Uint8Array of length bytes

Specs

Security

The library has been audited:

We've started regular AI-assisted self-audits in Apr 2026.

It is tested against official (ACVP / KAT) vectors, cross-library chained hashing, sliding-window length sweeps and property-based tests (fast-check), and is being fuzzed in CI.

If you see anything unusual: investigate and report.

Constant-timeness

We're targetting algorithmic constant time. JIT-compiler and Garbage Collector make "constant time" extremely hard to achieve timing attack resistance in a scripting language. Which means any other JS library can't have constant-timeness. Even statically typed Rust, a language without GC, makes it harder to achieve constant-time for some cases. If your goal is absolute security, don't use any JS lib — including bindings to native ones. Use low-level libraries & languages.

Memory dumping

The library shares state buffers between hash function calls. Library-owned working buffers are zeroed after use, including mutable UTF-8 copies created from password-KDF string inputs. However, if an attacker can read application memory, you are doomed in any case:

  • JS strings are immutable and can't be overwritten with zeros — e.g. a password passed to scrypt(password, salt) as a string stays in memory
  • Inputs & outputs are re-used across the application and stay in file buffers / memory anyway
  • await anything() writes all internal variables (including numbers) to memory, with no guarantee of when they get overwritten — plenty of time for an attacker to read them

Supply chain security

  • Commits are signed with PGP keys to prevent forgery. Be sure to verify the commit signatures
  • Releases are made transparently through token-less GitHub CI and Trusted Publishing. Be sure to verify the provenance logs for authenticity.
  • Rare releasing is practiced to minimize the need for re-audits by end-users.
  • Dependencies are minimized, strictly pinned, and changes are checked with npm-diff.
  • Dev dependencies are excluded from end-user installs; they’re only used for development and build steps.

For this package, there are 0 dependencies; and a few dev dependencies:

  • jsbt contains helpers for building, benchmarking & testing secure JS apps. It is developed by the same author
  • prettier, fast-check and typescript are used for code quality / test generation / ts compilation

Randomness

We rely on the built-in crypto.getRandomValues, which is considered a cryptographically secure PRNG.

Browsers have had weaknesses in the past - and could again - but implementing a userspace CSPRNG is even worse, as there’s no reliable userspace source of high-quality entropy.

Quantum computers

Cryptographically relevant quantum computer, if built, will allow to utilize Grover's algorithm to break hashes in 2^n/2 operations, instead of 2^n.

This means SHA256 should be replaced with SHA512, SHA3-256 with SHA3-512, SHAKE128 with SHAKE256 etc.

Australian ASD prohibits SHA256 and similar hashes after 2030.

Upgrading

Supported node.js versions:

  • v2: v20.19+ (ESM-only)
  • v1: v14.21+ (ESM & CJS)

v2.0 changelog:

  • The package is now ESM-only. ESM can finally be loaded from common.js on node v20.19+
  • .js extension must be used for all modules
    • Old: @noble/hashes/sha3
    • New: @noble/hashes/sha3.js
    • This simplifies working in browsers natively without transpilers
  • Only allow Uint8Array as hash inputs, prohibit string
    • Strict validation checks improve security
    • To replicate previous behavior, use utils.utf8ToBytes
  • Rename / remove some modules for consistency. Previously, sha384 resided in sha512, which was weird
    • sha256, sha512 => sha2.js (consistent with sha3.js)
    • blake2b, blake2s => blake2.js (consistent with blake3.js, blake1.js)
    • ripemd160, sha1, md5 => legacy.js (all low-security hashes are there)
    • _assert => utils.js
    • crypto internal module got removed: use built-in WebCrypto instead
  • Improve typescript types & option autocomplete
  • Bump compilation target from es2020 to es2022

Contributing & testing

npm install && npm run build && npm test will build the code and run tests.

There are additional slow suites: timing-based DoS tests npm run test:dos, multi-hour large-input tests npm run test:slow, ACVP LDT vectors npm run test:acvp, and memory-intensive KDF tests npm run test:ultra. The 9–17GiB scrypt cases require an explicitly provisioned machine and run separately with npm run test:ultra:scrypt.

test/misc directory contains unrolled implementations (sha3, argon2) and misc helper scripts.

Some hashes are outside of scope of the library:

See paulmillr.com/noble for useful resources, articles, documentation and demos related to the library.

Speed

npm run benchmark

Benchmarks measured on Apple M4.

The library could be 3x faster by utilizing loop unrolling. It isn't used because unrolling a) would increase bundle size b) make lib un-readable c) current perf is "fast enough" for most use-cases.

If you need truly exemplar performance, switch to awasm-noble, which does unrolling in an auditable way and allows to achieve 10GB/s BLAKE3.

# 32B
sha256 438 ns
sha512 1219 ns
sha3_256 1853 ns
sha3_512 1864 ns
kt128 1380 ns
kt256 1370 ns
turboshake128 1191 ns
blake256 1335 ns
blake2b 2186 ns
blake2s 1055 ns
blake3 981 ns
ripemd160 563 ns
md5 449 ns
sha1 507 ns
hmac(sha256) 1955 ns
hmac(sha512) 5126 ns
kmac256 6653 ns
blake3(key) 1120 ns

# 1MB
sha256 x 297 mib/sec
sha512 x 130 mib/sec
sha3_256 x 78.1 mib/sec
sha3_512 x 41.9 mib/sec
kt128 x 184 mib/sec
kt256 x 147 mib/sec
turboshake128 x 186 mib/sec
blake256 x 56.7 mib/sec
blake2b x 66.2 mib/sec
blake2s x 62.9 mib/sec
blake3 x 90 mib/sec
ripemd160 x 179 mib/sec
md5 x 275 mib/sec
sha1 x 417 mib/sec
hmac(sha256) x 290 mib/sec
hmac(sha512) x 129 mib/sec
kmac256 x 78.4 mib/sec
blake3(key) x 90.5 mib/sec

# KDF
hkdf(sha256) x 249,100 ops/sec @ 4015 ns/op
blake3(context) x 480,400 ops/sec @ 2081 ns/op
pbkdf2(sha256, c: 2 ** 18) x 5 ops/sec @ 199 ms/op
scrypt(n: 2 ** 19, r: 8, p: 1) x 1 ops/sec @ 751 ms/op
argon2id(t: 1, m: 128MB) x 3 ops/sec @ 276 ms/op

License

The MIT License (MIT)

Copyright (c) 2022 Paul Miller (https://paulmillr.com)

See LICENSE file.