tweetnacl-js
A JavaScript port of the audited TweetNaCl cryptographic library, providing public-key and secret-key encryption, signing, and hashing for Node.js and browsers.
Repository Health
Technical Analysis
TweetNaCl.js is a direct JavaScript port of Daniel J. Bernstein’s TweetNaCl, a compact C cryptography library, kept as close as possible to the original implementation while adding an idiomatic high-level API on top. It ships two builds: nacl.js, a minimal-diff port of the reference C code, and nacl-fast.js, the same primitives with hot paths replaced by faster implementations (used by default when the npm package is imported).
The library implements a small, deliberately narrow set of primitives — authenticated public-key encryption (box, x25519-xsalsa20-poly1305), authenticated secret-key encryption (secretbox, xsalsa20-poly1305), raw scalar multiplication (x25519), Ed25519 signatures, SHA-512 hashing, a secure random byte generator, and constant-time comparison. It was independently audited by Cure53 in 2017 with no security issues found, and is released into the public domain (Unlicense), making it a common low-level dependency for higher-level crypto and messaging libraries in the JavaScript ecosystem.
What You Get
- Public-key authenticated encryption (
nacl.box) implementing x25519-xsalsa20-poly1305, including a precomputed shared-key variant (box.before/box.after) for repeated exchanges with the same peer - Secret-key authenticated encryption (
nacl.secretbox) implementing xsalsa20-poly1305 for symmetric encrypt-and-authenticate use cases - Ed25519 digital signatures (
nacl.sign) with both combined and detached-signature modes, plus deterministic key-pair derivation from a seed - Raw X25519 scalar multiplication (
nacl.scalarMult) for protocols that need the elliptic-curve primitive directly rather than through box - SHA-512 hashing (
nacl.hash) and constant-time byte comparison (nacl.verify) to avoid timing side-channels when checking secrets - A pluggable PRNG hook (
nacl.setPRNG) and automatic use of WebCrypto, msCrypto, or Node’scrypto.randomBytesdepending on the runtime
Common Use Cases
- Encrypting messages between two parties who exchange public keys, without building a full protocol from scratch
- Signing and verifying data (releases, tokens, API payloads) with Ed25519 when a small, audited implementation is preferred over a larger crypto suite
- Deriving and comparing secrets (password-reset tokens, MAC values) using constant-time comparison to avoid timing attacks
- Acting as the low-level primitive layer underneath higher-level libraries (streaming encryption wrappers, ratchet/forward-secrecy implementations, sealed-box constructions) that need x25519/Ed25519/SHA-512 without pulling in a much larger dependency
- Running the same crypto code unmodified in both Node.js and browsers, since the API is pure JavaScript with no native bindings
Under The Hood
Architecture
The codebase is a single self-contained module (nacl.js, with nacl-fast.js as a drop-in faster variant) wrapped in an IIFE that attaches a nacl namespace to module.exports or window. Internally it’s organized in strict layers: low-level field-arithmetic helpers (gf, u64, L32, ld32/dl64/st32/ts64) at the bottom, then the crypto_* functions that mirror the original C API one-to-one (crypto_box, crypto_sign, crypto_hash, crypto_scalarmult, etc.), and finally the public nacl.box/nacl.secretbox/nacl.sign/nacl.hash object built at the top of the file as a thin, input-validating wrapper over those functions. There is no dependency injection or plugin system beyond nacl.setPRNG, which swaps the module-level randombytes closure — the one deliberate extension point in an otherwise fixed data flow (bytes in, bytes out, no allocation surprises since output buffers are pre-sized from documented length constants).
Tech Stack
The runtime library itself has zero production dependencies — it’s plain ES5 JavaScript operating on Uint8Array/Float64Array/Uint32Array typed arrays, dual-published as nacl.js/nacl.min.js and nacl-fast.js/nacl-fast.min.js (minified via uglify-js). Development tooling includes browserify to bundle browser tests, tape plus faucet for TAP-formatted test output, eslint for linting, and a test/c directory with a small Makefile-driven C harness used to cross-check JS outputs against the original TweetNaCl C implementation. TypeScript consumers get hand-written definitions in nacl.d.ts. There is no bundler config, no build step for the library itself beyond minification, and no runtime dependency tree to audit.
Code Quality
Testing is extensive and unusually rigorous for a crypto library: the test/ directory has one file per primitive (04-secretbox.js, 06-box.js, 08-sign.js, etc.), an API/type-checking suite (00-api.js) that asserts every exported function throws TypeError on wrong-shaped input, and a test/c cross-implementation suite that compiles the reference C code and diffs its output against the JS port byte-for-byte. Tests run against both the plain and fast builds via the NACL_SRC environment variable, and CI (Travis) exercises both. Naming and style follow the original C source closely (short variable names like x, y, k, h in the field-arithmetic layer) which trades readability for auditability against the reference implementation — a deliberate tradeoff for a security-critical port, documented in the file’s own header comments. There are no TypeScript source types (only hand-maintained .d.ts declarations) and no runtime type checking beyond the explicit TypeError guards in the public API surface.
What Makes It Unique
TweetNaCl.js’s distinguishing property is fidelity to a single, minimal, independently-audited C reference implementation rather than a large multi-primitive crypto toolkit — it intentionally implements only what TweetNaCl implements, ports it with minimum deviation, and lets the test/c suite prove behavioral equivalence against that C source. That narrow scope, combined with the 2017 Cure53 audit finding no vulnerabilities, is why it has become a common low-level dependency for other libraries (streaming encryption, ristretto255, forward-secrecy/ratchet implementations) that want an audited primitive layer rather than reimplementing curve arithmetic themselves.
Used by 7 apps in this directory
Cap
Team Chat · Video Conferencing
Open source Loom alternative with GPU-accelerated recording, instant share links, AI summaries, and full self-hosting via Docker Compose.
Infisical
Security · Devops
The open-source platform for secrets, certificates, privileged access, and AI agent security — all in one self-hostable system.
MentraOS
Developer Tools · AI Development
The open source operating system and SDK that lets developers build one app and run it across smart glasses from Even Realities, Vuzix, Mentra Live, and more.
Orca
AI Agents · AI Code Assistants
An open-source Agent Development Environment that orchestrates fleets of parallel AI coding agents — Claude Code, Codex, Gemini and more — each running in its own isolated git worktree.
paseo
AI Agents · AI Code Assistants
One unified interface to orchestrate Claude Code, Codex, Copilot, OpenCode, and Pi agents in parallel from desktop, mobile, or the terminal.
Postiz
Social Media · Automation
The agentic social media scheduler — AI-powered content creation, 33-platform posting, and team workflows, all self-hosted.
Rocket.Chat
Team Chat
The secure, self-hosted team communications platform for organizations that cannot compromise on data sovereignty.