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
- Node.js >= 18
- A CipherStash account. Sign up here.
Quick start
Initialize your project
Run the init wizard:
npx @cipherstash/stack initThe 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-forgeas 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 APISee Configuration for all options.
Set up your database
Run the interactive setup to install EQL in your PostgreSQL database:
npx stash-forge setupOr 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.tsThe 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/stackIf 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.