Web Dev Tools

Crypto, JWT & Hashing

Tokens, password hashing, signing, encryption — what to actually use.

Use the platform first

  • Web Crypto API — built into Node 20+, Bun, Deno, Workers, browsers. Hashing, HMAC, AES-GCM, ECDSA, key generation, key derivation. Use this before reaching for a library.
  • crypto.randomUUID() — built-in UUID v4.
  • crypto.subtle.digest('SHA-256', …) — hashing.
  • crypto.subtle.importKey / sign / verify / encrypt / decrypt — full primitives.

JWT / JOSE

  • jose — modern JWT/JOSE library; Web Crypto-based; works on Node, Bun, Deno, Workers, browsers. The default.
  • jsonwebtoken — older Node-only; works on Workers via shims; less recommended for new code.
  • fast-jwt — high-performance Node-only.
  • @tsndr/cloudflare-worker-jwt — minimal Workers-friendly JWT.

Password hashing

  • @node-rs/argon2 — Argon2id via Rust binding; the gold standard for password hashing. The default for new Node apps.
  • @node-rs/bcrypt — Rust bcrypt; faster than bcrypt npm.
  • bcrypt / bcryptjs — bcrypt is fine; bcryptjs is pure JS (slow but Workers-compatible).
  • scrypt — built into Node's crypto.scrypt.
  • argon2 (npm) — Node-only argon2 binding.

For Workers / edge runtimes that can't load native modules: use @noble/hashes for argon2/scrypt or move auth to a separate Node service.

Signed cookies / sessions

  • iron-webcrypto — Iron-encrypted blobs; works everywhere; pairs nicely with cookie helpers.
  • @hono/cookie, Next.js cookies() — framework-bundled cookie helpers.
  • cookie-signature — older Node-only.

Random / IDs

  • crypto.randomUUID() — built-in UUID v4. Default.
  • nanoid — short URL-safe IDs; smaller than UUID.
  • uuid (npm) — full UUID library if you need v5/v7.
  • @paralleldrive/cuid2 — modern collision-resistant IDs.
  • ulid — sortable IDs; great for DB primary keys.
  • ksuid, xid — alternatives.

Modern crypto primitives

  • @noble/curves, @noble/hashes, @noble/ciphers — auditable, JS-only crypto. Use when Web Crypto doesn't have the algorithm you need (e.g., Ed25519 verify on older runtimes, BLS, secp256k1).
  • scure-base — encodings (base58, base64, hex).
  • PASETO via paseto (npm) — alternative to JWT; safer defaults.
  • JWE — for encrypted tokens; use jose.
  • JOSE = JWS + JWE + JWA + JWK — jose covers all of this.

TLS / certificate helpers

  • acme-client, greenlock — Let's Encrypt clients.
  • Caddy — server-level auto-HTTPS with built-in ACME.
  • For the browser: WebCrypto plus your IdP — never hand-roll cert validation.

Don't roll your own

If you're tempted to implement password hashing, JWT signing, encryption, or session tokens by hand — don't. Use the libraries above. The list of bugs from hand-rolled crypto is endless.

Pick this if…

  • Default token library: jose.
  • Default password hashing: @node-rs/argon2 (Node) or argon2-via-@noble/hashes (Workers / Bun).
  • IDs in the DB: crypto.randomUUID() (UUID v4) or ulid (sortable).
  • Encrypted cookies / sessions: iron-webcrypto.
  • Need a primitive Web Crypto doesn't have: @noble/*.

On this page