npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

paseto-kit

v0.2.1

Published

Complete, runtime-agnostic PASETO v3/v4 + full PASERK for JS/TS. Successor to panva/paseto.

Readme

paseto-kit

npm CI license

The complete, runtime-agnostic PASETO v3/v4 + full PASERK library for JavaScript & TypeScript.

A maintained successor to the archived panva/paseto. Unlike other current libraries, paseto-kit ships v4 tokens and full PASERK key management (wrapping, password-wrapping, sealing, key IDs) — built on audited @noble primitives, running unmodified in Node, Deno, Bun, browsers, and edge runtimes.

⚠️ Pre-1.0. The v4 protocol and all 11 PASERK types pass the official test vectors, but the library has not yet had an independent security audit. Review before production use.

Why paseto-kit?

| | panva/paseto | paseto-ts | paseto-kit | |---|:---:|:---:|:---:| | Maintained | ❌ archived | ✅ | ✅ | | v4 local + public | ✅ | ✅ | ✅ | | v3 (NIST) local + public | ✅ | ❌ | ✅ | | PASERK key serialization | ✅ | partial | ✅ | | PASERK wrapping (local-wrap/secret-wrap) | ✅ | ❌ | ✅ | | PASERK password (local-pw/secret-pw) | ✅ | ❌ | ✅ | | PASERK seal | ✅ | ❌ | ✅ | | PASERK key IDs (lid/pid/sid) | ✅ | ❌ | ✅ | | Runtime-agnostic (Node/Deno/Bun/browser/edge) | Node only | ✅ | ✅ |

Install

npm install paseto-kit

Zero runtime dependencies beyond @noble/ciphers, @noble/hashes, @noble/curves. Requires Node ≥ 20 (for the global WebCrypto CSPRNG), or any modern browser, Deno, Bun, or edge runtime.

Quickstart

v4.local — symmetric encryption

import { generateLocalKey, encrypt, decrypt } from 'paseto-kit';

const key = generateLocalKey();
const token = encrypt(key, { sub: 'user-123', exp: '2026-12-31T00:00:00Z' });

const { payload } = decrypt(key, token, { validate: { exp: true } });
// payload -> { sub: 'user-123', exp: '2026-12-31T00:00:00Z' }

v4.public — asymmetric signatures

import { generateKeyPair, sign, verify } from 'paseto-kit';

const { secretKey, publicKey } = generateKeyPair();
const signed = sign(secretKey, { role: 'admin' });

const { payload } = verify(publicKey, signed);
// payload -> { role: 'admin' }

Claims validation

decrypt(key, token, {
  validate: { exp: true, nbf: true, iss: 'my-api', aud: 'mobile', clockToleranceSec: 30 },
});
// throws ClaimError on any failed check

Footers & implicit assertions

const token = encrypt(key, { a: 1 }, { footer: 'key-id-1', assertion: 'tenant-42' });
decrypt(key, token, { assertion: 'tenant-42' }); // assertion must match; footer is authenticated, not encrypted

PASERK — key management

import {
  toPaserk, fromPaserk, keyId,
  wrapKey, unwrapKey,
  wrapWithPassword, unwrapWithPassword,
  sealKey, unsealKey,
  generateLocalKey, generateKeyPair,
} from 'paseto-kit';

const key = generateLocalKey();

// Serialize / deserialize
const s = toPaserk(key);           // "k4.local.…"
const back = fromPaserk(s);        // LocalKey

// Stable key identifier (safe to log)
keyId(key);                        // "k4.lid.…"

// Wrap a key with another symmetric key
const wrapped = wrapKey(key, generateLocalKey());   // "k4.local-wrap.pie.…"

// Wrap a key with a password (Argon2id)
const pw = wrapWithPassword(key, 'correct horse battery staple');  // "k4.local-pw.…"
const key2 = unwrapWithPassword(pw, 'correct horse battery staple');

// Seal a key for a recipient's public key (X25519)
const { secretKey, publicKey } = generateKeyPair();
const sealed = sealKey(key, publicKey);             // "k4.seal.…"
const key3 = unsealKey(sealed, secretKey);

PASETO v3 (NIST)

Need the NIST/FIPS-friendly variant (P-384 / AES-CTR / HMAC-SHA384)? Use the v3 namespace — same shape as the top-level v4 API, with its own key types.

import { v3 } from 'paseto-kit';

const key = v3.generateLocalKey();
const token = v3.encrypt(key, { sub: 'user-123' });   // "v3.local.…"
v3.decrypt(key, token, { validate: { exp: true } });

const { secretKey, publicKey } = v3.generateKeyPair(); // P-384
v3.verify(publicKey, v3.sign(secretKey, { role: 'admin' }));

// Full v3 PASERK too: v3.toPaserk, v3.keyId, v3.wrapKey, v3.wrapWithPassword, v3.sealKey, …

Top-level encrypt/decrypt/sign/verify remain v4. A v4 key never works on a v3 token (and vice versa) — enforced by distinct key types.

Migrating from panva/paseto

| panva/paseto (V4) | paseto-kit | |---|---| | V4.encrypt(payload, key, { footer, assertion }) | encrypt(key, payload, { footer, assertion }) | | V4.decrypt(token, key, { assertion }) | decrypt(key, token, { assertion, validate }) | | V4.sign(payload, secretKey, { footer, assertion }) | sign(secretKey, payload, { footer, assertion }) | | V4.verify(token, publicKey, { assertion }) | verify(publicKey, token, { assertion, validate }) | | generateKeys('local' \| 'public') | generateLocalKey() / generateKeyPair() | | separate paserk package | built in (toPaserk, wrapKey, sealKey, …) |

Key differences: the key is the first argument; claim validation is explicit via { validate }; keys are typed (LocalKey / SecretKey / PublicKey).

Performance

Representative throughput (npm run bench, Node 22, Apple Silicon — your numbers will vary):

| Operation | ops/sec | |---|--:| | v4.local encrypt / decrypt | ~50,000 | | v4.public sign (Ed25519) | ~5,000 | | v4.public verify | ~1,100 | | v3.local encrypt / decrypt | ~29,000 | | v3.public sign / verify (P-384) | ~1,600 / ~300 |

Security

  • Built on audited @noble/* primitives — no hand-rolled crypto, only spec assembly.
  • Constant-time authentication-tag and footer comparison.
  • Conformance to the official PASETO and PASERK test vectors is enforced in CI.
  • Footers are authenticated but not encrypted — never put secrets in a footer.
  • -pw (password) is for human-memorable protection; -wrap is for machine keys.

See SECURITY.md to report vulnerabilities.

Roadmap

  • v4 (local + public) + full PASERK. ✅
  • v3 (NIST: P-384 / AES-CTR / HMAC-SHA384) + full v3 PASERK. ✅
  • Toward 1.0 — browser CI, benchmarks, and an independent security review.

License

MIT © Tareq El-Ali