CipherStashDocs

Getting started

Go from zero to encrypted in under 5 minutes with the interactive setup wizard

Getting started

This guide takes you from zero to encrypting data in under 5 minutes.

Prerequisites

Quick start

Initialize your project

Run the init wizard:

npx @cipherstash/stack init

The wizard will:

  • Ask which database connection method you're using (Drizzle ORM, Supabase JS, Prisma, or Raw SQL)
  • Let you build an encryption schema interactively or use a placeholder
  • Generate your encryption client file (default: src/encryption/index.ts)
  • Install @cipherstash/stack-forge as a devDependency for database tooling

Add your credentials

Sign up at cipherstash.com/signup and follow the onboarding to get your credentials. Save them to .env:

CS_WORKSPACE_CRN=    # The workspace identifier
CS_CLIENT_ID=        # The client identifier
CS_CLIENT_KEY=       # Key material used with ZeroKMS
CS_CLIENT_ACCESS_KEY= # API key for CipherStash API

See Configuration for all options.

Set up your database

Run the interactive setup to install EQL in your PostgreSQL database:

npx stash-forge setup

Or use stash-forge install directly for non-interactive setup with flags like --drizzle or --supabase. See Install and upgrade EQL for all options.

Encrypt your first value

The init wizard generated your schema and client. Now use them to encrypt data:

import { users } from "./encryption/schema"
import { client } from "./encryption"

const encryptResult = await client.encrypt("[email protected]", {
  column: users.email,
  table: users,
})

if (encryptResult.failure) {
  console.error(encryptResult.failure.type, encryptResult.failure.message)
} else {
  console.log("Encrypted:", encryptResult.data)
}

Run it:

npx tsx src/index.ts

The result is a JSON payload (called a CipherCell) ready for database storage:

// Success
{ data: { c: '\\x61202020202020472aaf602219d48c4a...' } }

// Failure
{ failure: { type: 'EncryptionError', message: '...' } }

Decrypt data

const decryptResult = await client.decrypt(encryptResult.data)

if (decryptResult.failure) {
  console.error(decryptResult.failure.message)
} else {
  console.log("Plaintext:", decryptResult.data) // "[email protected]"
}

For encrypting and decrypting multiple values or entire objects, see Encrypt and decrypt for bulk operations like bulkEncryptModels and bulkDecryptModels.

Store in a database

Store encrypted data in any database that supports JSONB:

For searchable encryption in PostgreSQL, use the eql_v2_encrypted column type (installed by EQL in Step 3). See Searchable encryption for details.

CREATE TABLE users (
  id SERIAL PRIMARY KEY,
  email jsonb NOT NULL
);

Manual setup

If you prefer not to use the init wizard, you can set up manually:

Install the SDK

npm install @cipherstash/stack

If you're using Bun, version 1.3 or later is required.

Define your schema

Create src/encryption/schema.ts:

import { encryptedTable, encryptedColumn } from "@cipherstash/stack/schema"

export const users = encryptedTable("users", {
  email: encryptedColumn("email")
    .equality()
    .freeTextSearch()
    .orderAndRange(),
})

See Schema definition for all index types.

Initialize the client

Create src/encryption/index.ts:

import { Encryption } from "@cipherstash/stack"
import { users } from "./schema"

export const client = await Encryption({ schemas: [users] })

Then continue from Step 2 (credentials) above.

@cipherstash/stack includes a native FFI module. You must exclude it from bundlers like Webpack, esbuild, or Next.js. See Bundling for details.

Next steps

On this page