noble-ed25519

A 5KB, audited, dependency-free TypeScript implementation of Ed25519 EdDSA signatures for Node, browsers, and Deno.

Library
npm
v3.2.0
520stars
MIT License

Repository Health

Pre-computed score based on development activity, maintenance, community, maturity, and trend momentum.How we score it →
74/100Good
Development Activity76
Maintenance68
Community64
Maturity60
Momentum28

Technical Analysis

AI-assessed by reading the actual repository — architecture, code quality, innovation, and documentation.How we score it →
83/100Excellent
Architecture90
Code Quality92
Innovation85
Learning Curve65

@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(), and verify()/verifyAsync() — covering the full signing lifecycle
  • A Point class 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: false option
  • 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 for getRandomValues and 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.

Join founders buildingwith open source

Opinionated takes, migration guides, cost-saving tips, and insights from the open source ecosystem.

Subscribe on Substack
Join 750+ subscribers

Search