Skip to content

Zero-Knowledge Encryption ​

Veriprompt's zero-knowledge encryption lets you store prompts, AI responses, and sensitive metadata in fully encrypted form. When enabled, content is encrypted client-side before transmission and stored as opaque ciphertext that Veriprompt cannot read at rest.

Encryption at Rest vs. Execution

Zero-knowledge mode encrypts content at rest in the database. During gateway execution, encrypted payloads are decrypted in server memory, forwarded to the AI provider, and then wiped. If your threat model requires that the platform never accesses plaintext at all, use the encrypted storage endpoints without gateway execution and handle provider calls client-side.

How It Works ​

Client (your app/browser)                    Veriprompt Server
────────────────────────                     ──────────────────
1. Bootstrap keys            ──────────>     Provision & wrap keys
2. Encrypt prompt locally                    Store encrypted blob
3. Send encrypted payload    ──────────>     (ciphertext only at rest)
4. Retrieve encrypted blob   <──────────     Return encrypted payload
5. Decrypt locally                           Never stores plaintext

Key Principles ​

PrincipleWhat It Means
Encrypted at RestStored prompts and responses are AES-256-GCM ciphertext; the server cannot read them without the client key
Client-Side EncryptionEncryption and decryption happen on your device using the Client SDK
Hierarchical KeysCompany > Project > Prompt key hierarchy for granular control
Authenticated EncryptionAES-256-GCM ensures both confidentiality and integrity

Getting Started ​

1. Enable Zero-Knowledge Mode ​

An Account Owner or Admin enables ZK mode at the company level:

Admin Panel > Settings > Security > Zero-Knowledge Encryption > Enable

Or via API:

bash
curl -X PUT https://app.veriprompt.tech/api/v1/zero-knowledge/company \
  -H "Authorization: Bearer <session-token>" \
  -H "Content-Type: application/json" \
  -d '{"enabled": true}'

2. Bootstrap Client Keys ​

Before encrypting, your client needs encryption keys. Call the bootstrap endpoint with your client public key:

typescript
const response = await fetch('/api/v1/pzk/bootstrap', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    'Cookie': sessionCookie
  },
  body: JSON.stringify({
    action: 'initialize',
    clientPublicKey: myPublicKeyBase64,
    repositoryIds: ['repo-id-1']  // optional: specific repos
  })
});

const { keys, action } = await response.json();
// keys is an array of KeyBootstrapResponse objects:
// { keyId, encryptedKey, algorithm, expiresAt, repositoryId?, serverPublicKey, handshakeAlgorithm }

3. Encrypt and Store Prompts ​

Encrypt your prompt content locally, then store the ciphertext via the API:

typescript
// Encrypt locally using AES-256-GCM
const iv = crypto.getRandomValues(new Uint8Array(12));
const ciphertext = await crypto.subtle.encrypt(
  { name: 'AES-GCM', iv },
  repositoryKey,
  new TextEncoder().encode(promptContent)
);

// Store encrypted prompt
const res = await fetch('/api/v1/pzk/encrypted-prompts', {
  method: 'POST',
  headers: {
    'Authorization': 'Bearer <your-api-key>',
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    repositoryId: 'repo-public-id',
    encryptedUserPrompt: {
      alg: 'AES-GCM',
      iv: base64Encode(iv),
      ct: base64Encode(ciphertext),
      tag: base64Encode(tag)           // optional if included in ct
    },
    encryptedSystemPrompt: { ... },    // optional
    encryptedName: { ... },            // optional encrypted name
    encryptionAlg: 'AES-GCM',
    encryptionKeyRef: keys[0].keyId,
    promptHash: await sha256Hex(promptContent),
    tags: ['production'],
    category: 'summarization'
  })
});

const { ok, prompt } = await res.json();
// prompt.promptId is your lookup key

4. Retrieve and Decrypt ​

typescript
const res = await fetch(
  `/api/v1/pzk/encrypted-prompts?promptId=${promptId}`,
  { headers: { 'Authorization': 'Bearer <your-api-key>' } }
);

const { prompt } = await res.json();
// prompt.encryptedUserPrompt contains { alg, iv, ct, tag }
const plaintext = await decryptAesGcm(repositoryKey, prompt.encryptedUserPrompt);

Key Hierarchy ​

Veriprompt uses a hierarchical key structure:

Company Master Key (CMK)
  |
  +-- Repository Encryption Key (REK)
  |     |
  |     +-- Prompt content encrypted with REK
  |     +-- Response content encrypted with REK
  |
  +-- Repository Encryption Key (REK)
        +-- ...
  • Company Master Key: Generated when ZK mode is initialized. Protected by the KMS provider.
  • Repository Keys: Derived per repository. Distributed to authorized team members via key shares.
  • Key Wrapping: Keys are wrapped with your client public key during bootstrap so only your client can unwrap them.

Key Rotation ​

Keys can be rotated on demand:

bash
curl -X POST https://app.veriprompt.tech/api/v1/pzk/bootstrap \
  -H "Cookie: <session-cookie>" \
  -H "Content-Type: application/json" \
  -d '{"action": "rotate", "clientPublicKey": "<your-public-key>"}'

During rotation:

  1. A new key version is generated
  2. Existing encrypted data remains accessible via the old key (grace period)
  3. New encryptions use the new key
  4. Old keys are retired after the grace period

Collaboration & Key Sharing ​

Team members can access shared encrypted prompts via key shares:

bash
# List key shares received by the current user
curl "https://app.veriprompt.tech/api/v1/pzk/shares?role=received&status=active" \
  -H "Cookie: <session-cookie>"

# Share an encryption key with a team member
curl -X POST https://app.veriprompt.tech/api/v1/pzk/shares \
  -H "Cookie: <session-cookie>" \
  -H "Content-Type: application/json" \
  -d '{
    "encryptionKeyId": "<key-uuid>",
    "recipientUserId": "<user-uuid>",
    "scope": "read",
    "expiresAt": "2026-12-31T23:59:59Z",
    "notes": "Sharing for Q1 review"
  }'

If you omit the envelope field, the server generates a wrapped envelope using the recipient's registered public key. You can also supply a pre-wrapped envelope for full client-side key management.

Project-Level Configuration ​

Zero-knowledge settings can be configured per project:

bash
# Check project ZK status
curl https://app.veriprompt.tech/api/v1/zero-knowledge/projects/{projectId} \
  -H "Cookie: <session-cookie>"

# Enable ZK for a specific project
curl -X PUT https://app.veriprompt.tech/api/v1/zero-knowledge/projects/{projectId} \
  -H "Cookie: <session-cookie>" \
  -H "Content-Type: application/json" \
  -d '{"enabled": true}'

Encrypted AI Responses ​

AI responses can be stored in encrypted form alongside their execution metadata:

bash
curl -X POST https://app.veriprompt.tech/api/v1/pzk/encrypted-responses \
  -H "Authorization: Bearer <api-key>" \
  -H "Content-Type: application/json" \
  -d '{
    "executionId": "exec-uuid",
    "promptId": "prompt-public-id",
    "provider": "openai",
    "model": "gpt-4",
    "inputTokens": 150,
    "outputTokens": 300,
    "totalTokens": 450,
    "costCents": 12,
    "executionTime": 2500,
    "encryptionAlg": "AES-GCM",
    "encryptedContent": {
      "alg": "AES-GCM",
      "iv": "<base64>",
      "ct": "<base64>",
      "tag": "<base64>"
    },
    "encryptionKeyRef": "<key-id>"
  }'

Security Guarantees ​

GuaranteeDetail
Encryption at restAES-256-GCM authenticated encryption for all stored content
Key wrappingKeys wrapped with session-specific client public key during bootstrap
Hash identificationSHA-256 hashes identify prompts without exposing content
Audit trailAll key operations logged (bootstrap, rotation, sharing, creation)
KMS backendPluggable provider (local dev, AWS KMS, Azure Key Vault)

When to Use Zero-Knowledge ​

Use CaseRecommendation
Regulated industries (HIPAA, SOC2)Strongly recommended
Customer-facing applicationsRecommended
Internal development/testingOptional
PrototypingNot needed

Limitations ​

  • Server-side search: The server cannot search plaintext content of encrypted prompts. Use promptId or metadata for lookups.
  • Gateway execution: When using the gateway execute endpoint with encrypted prompts, decryption occurs briefly in server memory before forwarding to the AI provider. For maximum isolation, call providers directly from your client.
  • Performance: Client-side encryption adds a small latency overhead (typically <10ms).
  • Collaboration: Key sharing requires recipients to have registered their public key, or you must supply a pre-wrapped envelope.