noble-hashes
repository·main·Indexed 21 days ago
https://github.com/paulmillr/noble-hashesAn audited, minimal, 0-dependency JavaScript implementation of cryptographic primitives including SHA-2, SHA-3, BLAKE (1, 2, 3), RIPEMD, HMAC, HKDF, PBKDF2, and Scrypt. Designed for high security and auditability, it features hand-optimized code for JS engines and supports both one-shot hashing and streaming updates via .create().
What's inside @noble/hashes
- noble-hashes is a minimal, audited, and high-performance JavaScript implementation of various cryptographic primitives, including hash functions, Message Authentication Codes (MACs), and Key Derivation Functions (KDFs). It is designed for high security and auditability, featuring hand-optimized code for JS engines and a small footprint (approx. 2.7KB gzipped for SHA-256).
Security and Constant-timeness considerations
mainConstant-timeness
The library targets algorithmic constant time. However, because it is a JavaScript library, achieving true constant-time resistance is extremely difficult due to the behavior of JIT compilers and Garbage Collectors. If your application requires absolute timing attack resistance, it is recommended to use low-level languages (like Rust or C) and libraries rather than JavaScript.
Memory Safety
The library attempts to mitigate memory exposure by sharing state buffers and zeroing them out after each call. However, users should be aware of several inherent JavaScript risks:
- Immutable Strings: If sensitive data (like passwords) is handled as a JS
string, it cannot be zeroed out in memory. - Async Execution: Using
awaitcan write internal variables to memory, and there are no guarantees regarding when code chunks execute, potentially leaving data exposed for an attacker to read. - Input Buffers: Data from files or reused application buffers may persist in memory.
- Immutable Strings: If sensitive data (like passwords) is handled as a JS
Install @noble/hashes
mainYou can install the library using npm or add it via JSR for Deno. For React Native environments, you may need to provide a polyfill for
getRandomValues(e.g.,react-native-get-random-values). A standalonenoble-hashes.jsfile is also available for direct use.npm install @noble/hashes deno add jsr:@noble/hashesVerify noble-hashes supply chain security
mainTo ensure the integrity of the code you are using, follow these verification steps:
- Verify Commit Signatures: All commits are signed with PGP keys. Check signatures to prevent forgery.
- Verify Releases: Releases are made via token-less GitHub CI and Trusted Publishing. Verify the provenance logs for authenticity.
- Dependency Check: The package has 0 production dependencies, minimizing supply-chain risk.
Upgrade to noble-hashes v2.x
mainWhen upgrading to version 2.0 or later, note the following breaking changes:
- ESM-only: The package is now ESM-only. On Node.js v20.19+, ESM can be loaded from CommonJS.
- Explicit Extensions: You must use the
.jsextension for all module imports to ensure compatibility with native browsers without transpilers.- Old:
@noble/hashes/sha3 - New:
@noble/hashes/sha3.js
- Old:
- Strict Input Types: Only
Uint8Arrayis allowed as hash input. Passing astringwill result in a validation error. To convert strings to bytes, useutils.utf8ToBytes. - Module Reorganization:
sha256,sha512$\rightarrow$@noble/hashes/sha2.jsblake2b,blake2s$\rightarrow$@noble/hashes/blake2.jsripemd160,sha1,md5$\rightarrow$@noble/hashes/legacy.js_assert$\rightarrow$@noble/hashes/utils.js
- WebCrypto: The internal
cryptomodule has been removed; use the built-in WebCrypto API instead. - TypeScript: Compilation target has been bumped from
es2020toes2022.
Use sub-imports for @noble/hashes to optimize bundle size
mainTo ensure small application sizes, do not use
import * from '@noble/hashes'. Instead, use specific sub-imports for the modules you need (e.g.,@noble/hashes/sha2.js,@noble/hashes/sha3.js, etc.).// Error: do not do this // import * from '@noble/hashes'; // Correct: use sub-imports import { sha256 as noble_sha256 } from '@noble/hashes/sha2.js'; const hash = noble_sha256(Uint8Array.from([0xca, 0xfe, 0x01, 0x23]));Use BLAKE3 as an Extendable Output Function (XOF)
mainBLAKE3 supports variable-length output. If you need more bytes than the default digest length, you can use the XOF features.
- Via
blake3()helper: Set thedkLenproperty in the options object. - Via
_BLAKE3instance: After callingupdate(), you can call.xof(bytes)to get a specific number of bytes, or.xofInto(out)to write the output into an existingUint8Array.
- Via
Use Blake1 hash functions
mainBlake1 is a legacy hash function. It is rarely used today; it is recommended to use
blake2orblake3instead. The library provides four variants:blake224,blake256,blake384, andblake512. Each function can be used to hash a single message or to create a hasher instance for incremental updates.import { blake256 } from '@noble/hashes/blake1'; // Single-shot hashing const digest = blake256(new Uint8Array([97, 98, 99])); // Incremental hashing const hasher = blake256(); hasher.update(new Uint8Array([97, 98])); hasher.update(new Uint8Array([99])); const finalDigest = hasher.digest();Import submodules from @noble/hashes
mainThe root module of
@noble/hashescannot be imported directly. To use the library, you must import specific hash functions, MACs, or KDFs from their respective submodules. This ensures a minimal bundle size by only including the code you actually need.Common submodules include:
@noble/hashes/sha2.js: SHA-2 family (sha256, sha384, etc.)@noble/hashes/sha3.js: SHA-3 and Keccak (sha3_256, keccak_256, shake128, etc.)@noble/hashes/sha3-addons.js: SHA-3 extensions (cshake, kmac, etc.)@noble/hashes/blake3.js: BLAKE3@noble/hashes/blake2.js: BLAKE2 (blake2b, blake2s)@noble/hashes/hmac.js: HMAC@noble/hashes/hkdf.js: HKDF@noble/hashes/pbkdf2.js: PBKDF2@noble/hashes/scrypt.js: scrypt@noble/hashes/legacy.js: Legacy hashes (md5, ripemd160, sha1)@noble/hashes/utils.js: Utility functions
import { sha256 } from '@noble/hashes/sha2.js'; import { sha3_256 } from '@noble/hashes/sha3.js'; import { blake3 } from '@noble/hashes/blake3.js'; import { hmac } from '@noble/hashes/hmac.js';Run noble-hashes benchmarks
mainTo measure the performance of the hash implementations on your machine, run the following command:
npm run benchmarkUse ESKDF (Experimental)
mainThe
eskdf.jsmodule is an experimental KDF for deriving application-specific child keys from a username + password pair. It is built on scrypt, pbkdf2, and hkdf with fixed work factors.Note: This is non-standard. For new designs, prefer Scrypt or Argon2.
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();Use Argon2 for password-based key derivation
mainThe
argon2.jsmodule implements Argon2 (RFC 9106).Warning: Argon2 can be slow in JS because there is no fast
Uint64Array. It is suggested to use Scrypt instead, as being 5x slower than native code gives brute-force attackers a larger advantage.import { argon2d, argon2i, argon2id } from '@noble/hashes/argon2.js'; const arg1 = argon2id('password', 'saltsalt', { t: 2, m: 65536, p: 1, maxmem: 2 ** 32 - 1 });