
Company News
Free Business Plan Upgrades for Open Source Maintainers
Open source maintainers are under more pressure than ever. We're raising our open source program from the Team plan to the Business plan, free.
@noble/hashes
Advanced tools
Audited & minimal 0-dependency JS implementation of SHA, RIPEMD, BLAKE, HMAC, HKDF, PBKDF & Scrypt
Audited & minimal JS implementation of hash functions, MACs and KDFs.
The library's initial development was funded by Ethereum Foundation.
noble cryptography — high-security, easily auditable set of contained cryptographic libraries and tools.
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 as noble_sha256 } from '@noble/hashes/sha2.js';
const hash = noble_sha256(Uint8Array.from([0xca, 0xfe, 0x01, 0x23]));
// Available modules
import { sha256, sha384, sha512, sha224, sha512_224, sha512_256 } from '@noble/hashes/sha2.js';
import {
sha3_256, sha3_512,
keccak_256, keccak_512,
shake128, shake256,
} from '@noble/hashes/sha3.js';
import {
cshake256, turboshake256, kmac256, tuplehash256,
kt128, kt256, keccakprg,
} from '@noble/hashes/sha3-addons.js';
import { blake3 } from '@noble/hashes/blake3.js';
import { blake2b, blake2s } from '@noble/hashes/blake2.js';
import { blake256, blake512 } from '@noble/hashes/blake1.js';
import { sha1, md5, ripemd160 } from '@noble/hashes/legacy.js';
import { hmac } from '@noble/hashes/hmac.js';
import { hkdf } from '@noble/hashes/hkdf.js';
import { pbkdf2, pbkdf2Async } from '@noble/hashes/pbkdf2.js';
import { scrypt, scryptAsync } from '@noble/hashes/scrypt.js';
import { argon2d, argon2i, argon2id } from '@noble/hashes/argon2.js';
import { eskdf } from '@noble/hashes/eskdf.js';
import * as webcrypto from '@noble/hashes/webcrypto.js';
// const { sha256, sha384, sha512, hmac, hkdf, pbkdf2 } = webcrypto;
import * as utils from '@noble/hashes/utils.js';
const { bytesToHex, concatBytes, equalBytes, hexToBytes } = utils;
Hash functions:
sha256(): receive & return Uint8Arraysha256.create().update(a).update(b).digest(): support partial updatesblake3.create({ context: 'e', dkLen: 32 }): can have optionsimport { sha224, sha256, sha384, sha512, sha512_224, sha512_256 } from '@noble/hashes/sha2.js';
const res = sha256(Uint8Array.from([0xbc])); // basic
for (let hash of [sha256, sha384, sha512, sha224, sha512_224, sha512_256]) {
const arr = Uint8Array.from([0x10, 0x20, 0x30]);
const a = hash(arr);
const b = hash.create().update(arr).digest();
}
Check out RFC 6234 and the paper on truncated SHA512/256.
import {
sha3_224, sha3_256, sha3_384, sha3_512,
keccak_224, keccak_256, keccak_384, keccak_512,
shake128, shake256,
} from '@noble/hashes/sha3.js';
for (let hash of [
sha3_224, sha3_256, sha3_384, sha3_512,
keccak_224, keccak_256, keccak_384, keccak_512,
]) {
const arr = Uint8Array.from([0x10, 0x20, 0x30]);
const a = hash(arr);
const b = hash.create().update(arr).digest();
}
const shka = shake128(Uint8Array.from([0x10]), { dkLen: 512 });
const shkb = shake256(Uint8Array.from([0x30]), { dkLen: 512 });
Check out the differences between SHA-3 and Keccak
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 personalization = new TextEncoder().encode('def');
const ec1 = cshake128(data, { personalization });
const ec2 = cshake256(data, { personalization });
const et1 = turboshake128(data);
const et2 = turboshake256(data, { D: 0x05 });
// tuplehash(['ab', 'c']) !== tuplehash(['a', 'bc']) !== tuplehash([data])
const et3 = tuplehash256([new TextEncoder().encode('ab'), new TextEncoder().encode('c')]);
// Not parallel in JS (similar to blake3 / kt128), added for compat
const ep1 = parallelhash256(data, { blockLen: 8 });
const kk = Uint8Array.from([0xca]);
const ek10 = kmac128(kk, data);
const ek11 = kmac256(kk, data);
const ek12 = kt128(data); // kangarootwelve 128-bit
const ek13 = kt256(data); // kangarootwelve 256-bit
// pseudo-random generator, first argument is capacity. XKCP recommends 254 bits capacity for 128-bit security strength.
const p = keccakprg(254);
p.addEntropy(Uint8Array.from([1, 2, 3]));
const rand1b = p.randomBytes(32);
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';
for (let hash of [blake224, blake256, blake384, blake512, blake2b, blake2s, blake3]) {
const arr = Uint8Array.from([0x10, 0x20, 0x30]);
const a = hash(arr);
const b = hash.create().update(arr).digest();
}
// blake2 advanced usage
const ab = Uint8Array.from([0x01]);
const txt = new TextEncoder();
blake2s(ab);
blake2s(ab, { key: new Uint8Array(32) });
blake2s(ab, { personalization: txt.encode('pers1234') });
blake2s(ab, { salt: txt.encode('salt1234') });
blake2b(ab);
blake2b(ab, { key: new Uint8Array(64) });
blake2b(ab, { personalization: txt.encode('pers1234pers1234') });
blake2b(ab, { salt: txt.encode('salt1234salt1234') });
// blake3 advanced usage
blake3(ab);
blake3(ab, { dkLen: 256 });
blake3(ab, { key: new Uint8Array(32) });
blake3(ab, { context: txt.encode('application-name') });
SHA1 (RFC 3174), MD5 (RFC 1321) and RIPEMD160 (ISO/IEC 10118-3) legacy, weak hash functions. Don't use them in a new protocol. What "weak" means:
import { md5, ripemd160, sha1 } from '@noble/hashes/legacy.js';
for (let hash of [md5, ripemd160, sha1]) {
const arr = Uint8Array.from([0x10, 0x20, 0x30]);
const a = hash(arr);
const b = hash.create().update(arr).digest();
}
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();
Conforms to RFC 2104.
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);
Conforms to RFC 5869.
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,
});
Conforms to RFC 8018.
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 64onProgress can be used with async version of the function to report progress to a user.maxmem prevents DoS and is limited to 1GB + 1KB (2**30 + 2**10), but can be adjusted using formula: 128 * r * (N + p + 1)Time it takes to derive Scrypt key under different values of N (2**N) on Apple M4 (mobile phones can be 1x-4x slower):
| N pow | Time | RAM |
|---|---|---|
| 16 | 0.1s | 64MB |
| 17 | 0.2s | 128MB |
| 18 | 0.4s | 256MB |
| 19 | 0.8s | 512MB |
| 20 | 1.5s | 1GB |
| 21 | 3.1s | 2GB |
| 22 | 6.2s | 4GB |
| 23 | 13s | 8GB |
| 24 | 27s | 16GB |
[!NOTE] We support N larger than
2**20where available, however, not all JS engines support >= 2GB ArrayBuffer-s. When using such N, you'll need to manually adjustmaxmem, using formula above. Other JS implementations don't support large N-s.
import { argon2d, argon2i, argon2id } from '@noble/hashes/argon2.js';
const arg1 = argon2id('password', 'saltsalt', { t: 2, m: 65536, p: 1, maxmem: 2 ** 32 - 1 });
Argon2 RFC 9106 implementation.
[!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.
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.
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 });
Sometimes people want to use built-in crypto.subtle instead of pure JS implementation.
However, it has terrible API.
We simplify access to built-ins with API which mirrors noble-hashes. The overhead is minimal - just 30+ lines of code, which verify input correctness.
[!NOTE] Webcrypto methods are always async.
import { bytesToHex as toHex, randomBytes } from '@noble/hashes/utils.js';
console.log(toHex(randomBytes(32)));
bytesToHex will convert Uint8Array to a hex stringrandomBytes(bytes) will produce cryptographically secure random Uint8Array of length bytesThe library has been audited:
blake3, sha3-addons, sha1 and argon2, which have not been auditedIt 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 the separate repo.
If you see anything unusual: investigate and report.
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.
The library shares state buffers between hash function calls. The buffers are zeroed-out after each call. However, if an attacker can read application memory, you are doomed in any case:
scrypt(password, salt) where password and salt are stringsawait anything() will always write all internal variables (including numbers)
to memory. With async functions / Promises there are no guarantees when the code
chunk would be executed. Which means attacker can have plenty of time to read data from memoryFor this package, there are 0 dependencies; and a few dev dependencies:
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.
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.
Supported node.js versions:
v2.0 changelog:
.js extension must be used for all modules
@noble/hashes/sha3@noble/hashes/sha3.jsstring
utils.utf8ToBytessha256, 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.jscrypto internal module got removed: use built-in WebCrypto insteadtest/misc directory contains unrolled implementations (sha3, argon2) and misc helper scripts.
npm install && npm run build && npm test will build the code and run tests.npm run check / npm run format will run linter / fix linter issues.npm run benchmark will run benchmarksnpm run bundle will build single filenpm run test:dos,
multi-hour 4GB-input test npm run test:slow, ACVP vectors npm run test:acvp
and KDF vectors npm run test:kdf.
See our approach to testingSome hashes are outside of scope of the library:
See paulmillr.com/noble for useful resources, articles, documentation and demos related to the library.
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 x 2,016,129 ops/sec @ 496ns/op
sha512 x 740,740 ops/sec @ 1μs/op
sha3_256 x 287,686 ops/sec @ 3μs/op
sha3_512 x 288,267 ops/sec @ 3μs/op
kt128 x 476,190 ops/sec @ 2μs/op
blake2b x 410,340 ops/sec @ 2μs/op
blake2s x 942,507 ops/sec @ 1μs/op
blake3 x 1,006,036 ops/sec @ 994ns/op
ripemd160 x 1,410,437 ops/sec @ 709ns/op
md5 x 1,663,893 ops/sec @ 601ns/op
sha1 x 1,589,825 ops/sec @ 629ns/op
# 1MB
sha256 x 331 ops/sec @ 3ms/op
sha512 x 128 ops/sec @ 7ms/op
sha3_256 x 39 ops/sec @ 25ms/op
sha3_512 x 21 ops/sec @ 46ms/op
kt128 x 91 ops/sec @ 10ms/op
kt256 x 75 ops/sec @ 13ms/op
turboshake128 x 93 ops/sec @ 10ms/op
blake256 x 57 ops/sec @ 17ms/op
blake2b x 61 ops/sec @ 16ms/op
blake2s x 78 ops/sec @ 12ms/op
blake3 x 95 ops/sec @ 10ms/op
ripemd160 x 177 ops/sec @ 5ms/op
md5 x 250 ops/sec @ 3ms/op
sha1 x 416 ops/sec @ 2ms/op
# MAC
hmac(sha256) x 599,880 ops/sec @ 1μs/op
hmac(sha512) x 197,122 ops/sec @ 5μs/op
kmac256 x 87,981 ops/sec @ 11μs/op
blake3(key) x 796,812 ops/sec @ 1μs/op
# KDF
hkdf(sha256) x 259,942 ops/sec @ 3μs/op
blake3(context) x 424,808 ops/sec @ 2μs/op
pbkdf2(sha256, c: 2 ** 18) x 5 ops/sec @ 197ms/op
pbkdf2(sha512, c: 2 ** 18) x 1 ops/sec @ 630ms/op
scrypt(n: 2 ** 18, r: 8, p: 1) x 2 ops/sec @ 400ms/op
argon2id(t: 1, m: 256MB) 2881ms
The MIT License (MIT)
Copyright (c) 2022 Paul Miller (https://paulmillr.com)
See LICENSE file.
Crypto-js is a popular package that provides a variety of cryptographic algorithms including hash functions, HMAC, and encryption. It is similar to @noble/hashes but has a broader scope, including encryption and decryption methods.
Hash.js is a lightweight library of hash functions that includes implementations of SHA-1, SHA-256, and RIPEMD. It is similar to @noble/hashes in providing hash functions but is not as focused on security and performance.
Sha.js is a simple module that only implements SHA hash functions. It is similar to @noble/hashes in providing SHA hashing but does not include other hash functions like RIPEMD-160 or HMAC capabilities.
FAQs
Audited & minimal 0-dependency JS implementation of SHA, RIPEMD, BLAKE, HMAC, HKDF, PBKDF & Scrypt
The npm package @noble/hashes receives a total of 46,368,480 weekly downloads. As such, @noble/hashes popularity was classified as popular.
We found that @noble/hashes demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Company News
Open source maintainers are under more pressure than ever. We're raising our open source program from the Team plan to the Business plan, free.

Security News
The supply chain control that delays freshly published gems now covers lockfile generation and gem vendoring in Ruby projects.

Security News
During a UK cyber test, a Mythos 5 agent used sockpuppets, social engineering, and prompt injection to try to get a maintainer to merge malware.