noble-ed25519
A 5KB, audited, dependency-free TypeScript implementation of Ed25519 EdDSA signatures for Node, browsers, and Deno.
Repository Health
Technical Analysis
@noble/ed25519 is the smallest widely-used JavaScript implementation of Ed25519 signing and verification, weighing in at roughly 3.7KB gzipped with zero runtime dependencies by default. It exposes four core operations — keygen, getPublicKey, sign, and verify — each available in both synchronous and asynchronous forms, and targets RFC8032, FIPS 186-5, and the consensus-friendly ZIP215 verification rules used by Zcash and other blockchain protocols.
The library is part of the broader noble cryptography suite (noble-curves, noble-hashes, noble-ciphers, noble-post-quantum) maintained by Paul Miller, all sharing the same design philosophy: minimal, highly readable, PGP-signed, and independently auditable code with no bundled hash function. To use synchronous signing, callers inject a SHA-512 implementation (typically @noble/hashes) into ed.hashes.sha512; the async API works out of the box via WebCrypto. The v1 codebase was independently audited by cure53 in 2022, and the project is continuously fuzzed in a separate repository.
Because it targets ed25519’s exact security properties — SUF-CMA (strong unforgeability under chosen-message attacks) and SBS (strongly-binding signatures / non-repudiation) — plus optional strict RFC8032 verification alongside the default ZIP215 mode, it’s a common choice for wallets, blockchain clients, and any application that needs consensus-critical or non-repudiable signature verification rather than just “a signing library that works.”
What You Get
- Four core primitives —
keygen()/keygenAsync(),getPublicKey()/getPublicKeyAsync(),sign()/signAsync(), andverify()/verifyAsync()— covering the full signing lifecycle - A
Pointclass exposing the underlying edwards25519 curve arithmetic (add,multiply,toAffine,fromBytes, torsion/order checks) for advanced use cases - Dual verification modes: default ZIP215 (consensus-friendly, matches Zcash/blockchain rules) or strict RFC8032/FIPS 186-5 via the
zip215: falseoption - A dependency-injection point for the hash function (
ed.hashes.sha512) so the sync API stays pluggable instead of bundling a hash implementation - Utility exports (
etc.bytesToHex,etc.hexToBytes,etc.randomBytes,utils.randomSecretKey,utils.getExtendedPublicKey) for common byte/hex plumbing - Distribution via both npm (
@noble/ed25519) and JSR (jsr:@noble/ed25519), plus documented React Native polyfill instructions forgetRandomValuesand SHA-512
Common Use Cases
- Cryptocurrency wallets and blockchain clients - signing and verifying transactions where ZIP215-compliant, consensus-critical verification behavior matters
- Lightweight auth tokens and API request signing - services that need EdDSA signatures without pulling in a large crypto SDK or native bindings
- Cross-runtime libraries - projects targeting Node, browser, Deno, and React Native from one dependency-light codebase
- Security-sensitive applications requiring an audited primitive - teams that specifically want a cure53-audited, fuzzed implementation over an unaudited alternative
- SSH and protocol implementations using Ed25519 keys - lower-level tooling that needs direct access to key generation and raw signature bytes
Under The Hood
Architecture
The entire implementation lives in a single ~1,150-line index.ts file with no internal module boundaries — a deliberate noble-family convention that trades conventional layering for single-file auditability. The file is organized into clearly delimited sections: byte/hex helpers (abytes, snapshotBytes, concatBytes, randomBytes), an immutable Point class implementing extended twisted-Edwards coordinates (X/Y/Z/T) with add/double/multiply/toAffine/fromBytes, a wNAF fixed-window (w=8) precomputation cache (Gpows) used whenever the base point G is multiplied, and the public keygen/getPublicKey/sign/verify surface (each with sync and async variants). Hash-function injection (ed.hashes.sha512) is the one explicit seam in an otherwise flat design: it lets the sync API exist without bundling a hash implementation, at the cost of throwing a descriptive error if the caller forgets to set it. If the curve constants (P, N, _d, Gx, Gy) were altered, all arithmetic would silently produce wrong results, so they’re frozen (Object.freeze) at module load.
Tech Stack
Pure TypeScript (type: module, ESM-only) with zero runtime dependencies declared in package.json. The single dev dependency relevant to functionality is @noble/hashes (2.4.0), used for SHA-512 in tests and to demonstrate sync-mode setup; other dev dependencies (@paulmillr/jsbt, bismar, prettier, typescript) handle build/benchmark/format tooling rather than runtime behavior. There is no bundler — the build script is a plain tsc compile, and tests run directly via node test/index.ts, relying on Node’s built-in TypeScript execution rather than ts-node or a test runner like Jest/Vitest. The package ships to both npm and JSR, and documents explicit polyfill requirements (react-native-get-random-values, injected SHA-512) for React Native, where WebCrypto isn’t available by default.
Code Quality
Testing is extensive and unusually rigorous for a library this size: dedicated suites cover point arithmetic (point.test.ts, ~23KB), signing (sign.test.ts), general spec conformance (ed25519.test.ts, ~19KB), hash injection (hashes.test.ts), and utilities (utils.test.ts), plus an acvp.test.ts suite that validates against NIST’s official ACVP test vectors — a level of spec-conformance testing rarely seen outside standards-body reference implementations. A vectors/ directory and compiled/ fixtures back these tests, and the project is additionally fuzzed in a companion paulmillr/fuzzing repository. Error handling is explicit and typed: a shared abytes() assertion helper throws descriptive TypeError/RangeError messages rather than swallowing bad input. The codebase is fully typed with exported helper types (Bytes, EdwardsOpts, AffinePoint, EdDSAVerifyOpts, plus TArg/TRet compatibility types bridging TypeScript 5.6 and 5.9+ Uint8Array generics), formatted with Prettier, and built with GitHub Actions workflows for test, fuzz, and release-with-provenance.
What Makes It Unique The project competes primarily on size, auditability, and precise security semantics rather than feature breadth. It advertises a 3.7KB gzipped footprint and zero mandatory runtime dependencies — the hash function is injected by the caller instead of bundled, keeping the dependency-free default true even where sync APIs are used. It explicitly documents and targets SUF-CMA and SBS security properties that it claims most other JS ed25519 libraries lack, and offers a first-class toggle between ZIP215 (consensus-friendly, blockchain-compatible) and strict RFC8032/FIPS 186-5 verification — a distinction that matters a great deal to consensus-critical software (wallets, chain clients) but is invisible in most general-purpose crypto libraries. Supply-chain hardening is treated as a first-order concern: signed commits, token-less trusted-publishing releases with verifiable provenance logs, and strictly pinned/minimized dependencies, backed by an independent cure53 audit of the v1 codebase and ongoing fuzzing infrastructure.
Used by 2 apps in this directory
Rocket.Chat
Team Chat
The secure, self-hosted team communications platform for organizations that cannot compromise on data sovereignty.
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.