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

@zoza/vault

v0.1.1

Published

Client-side field encryption for Zoza Vault — X25519 ECDH + HKDF-SHA256 + AES-256-GCM. Tokens never hit your servers in plaintext.

Downloads

198

Readme

@zoza/vault

Client-side field encryption. Your servers never touch plaintext. X25519 · HKDF-SHA256 · AES-256-GCM.

npm license

The Zoza Vault JavaScript SDK encrypts sensitive fields (card numbers, SSNs, health records, tokens, API keys) in the browser before they ever leave the user's machine. Ciphertext is stored in your database like any other string. Decryption happens only inside the Zoza backend, which holds the application private key in an HSM.

Design mirrors what Basis Theory, Evervault, VGS, and Skyflow ship — only difference is this one is fully auditable: all crypto code you're about to run is in this repo.

Install

npm install @zoza/vault

Or via CDN:

<script type="module">
  import { VaultClient } from 'https://esm.sh/@zoza/vault';
</script>

Quick start

import { VaultClient } from '@zoza/vault';

const vault = new VaultClient({ appId: 'app_a99b96dd23fb8414d17ec48df7984802' });

// Encrypts client-side. `token` is safe to store/log/transmit.
const token = await vault.encrypt('card_number', '4242 4242 4242 4242');
// → "zv1:<ephPub>.<iv>.<ct+tag>"

// Encrypt a whole object:
const body = await vault.encryptObject({
  card_number: '4242424242424242',
  cvv: '123',
  cardholder: 'Ada Lovelace',
});
// send `body` to your own server as normal — every field is a vault token

Your server then POSTs the token to vault-api.zoza.world to receive the plaintext, only when it's needed, and only from servers you've authorised.

Why another SDK?

| | Zoza Vault | Basis Theory | Evervault | |---|:---:|:---:|:---:| | Open-source SDK (MIT) | ✅ | ❌ | ❌ | | Self-host option | ✅ | ❌ | ❌ | | Public crypto spec | ✅ | partial | partial | | India DPDPA aware | ✅ | ❌ | ❌ |

The crypto scheme is specified byte-for-byte in src/crypto.ts and the whole client is under 300 lines of TypeScript. Auditable by one engineer in an afternoon.

Cryptographic scheme

For every encrypt() call:

  1. A fresh X25519 ephemeral key-pair is generated in the browser.
  2. ECDH against the application's public key produces a 32-byte shared secret. The ephemeral private key is discarded immediately.
  3. HKDF-SHA256 stretches the secret using ephPub as salt and "zoza-vault/v1/" + field as info, yielding a 32-byte AES key bound to the field name. (A token for ssn cannot be replayed as card_number.)
  4. AES-256-GCM encrypts the UTF-8 plaintext with a random 12-byte IV, the field name bound as Additional Authenticated Data.
  5. The output token packs ephPub · iv · ciphertext+tag as URL-safe base64, prefixed zv1:.

Decryption (server-side only) reverses the process using the application's private key.

Token wire format

zv1:<ephPub_b64url>.<iv_b64url>.<ct_and_tag_b64url>

| Field | Size | Purpose | |---|---|---| | ephPub | 32 B | X25519 ephemeral public key | | iv | 12 B | random, per-token | | ct+tag | N + 16 B | AES-GCM ciphertext + auth tag |

Storable in any TEXT column. URL-safe, no padding.

API

new VaultClient(opts)

| Option | Type | Notes | |---|---|---| | appId | string (required) | From zoza.world/developers/vault | | apiUrl | string | Default https://vault-api.zoza.world | | appPublicKey | Uint8Array \| string | Pre-fetched 32-byte key (hex or base64url) — skips the network round-trip | | fetch | typeof fetch | Override for runtimes without a global fetch |

vault.encrypt(field, plaintext) → Promise<string>

Returns a zv1: token.

vault.encryptObject(values) → Promise<{...}>

Encrypts every string value, preserves null / undefined.

Low-level helpers

import { encryptField, parseToken, decryptFieldWithPrivateKey } from '@zoza/vault';

decryptFieldWithPrivateKey() is only for self-hosted deployments where you legitimately hold the private key. Never embed a private key in client code.

Security properties

  • Forward secrecy per token — compromising one token's plaintext reveals nothing about any other token.
  • Field binding — both the HKDF info and the GCM AAD bind the key and ciphertext to the declared field, preventing cross-field replay.
  • No plaintext transit — even TLS-stripping MITMs see only ciphertext.
  • No SDK secret — the SDK is publicly visible, so leaking it is a non-event; security lives in the server's private key custody.

Known threat model boundaries are documented in SECURITY.md.

Running the tests

npm install
npm test

Tests run on Node ≥18 (uses the native WebCrypto) and cover round-trip encrypt/decrypt, field-binding, key mismatch, UTF-8, and token parsing.

License

MIT © Zoza