Add encryption your own servers can’t read

A zero-knowledge, post-quantum storage API for developers. Encrypt in your client with open-source @shieldfive/crypto, store the ciphertext with us — we hold only ciphertext and never your keys.

Free developer tier · EU-hosted · open-source crypto core

Quickstart

Encrypt on the device, store the ciphertext, fetch it back, decrypt on the device. The API only ever handles ciphertext.

// 1. Encrypt on the device with the open-source core (npm i @shieldfive/crypto)
import { xchachaV1, randomBytes, bytesToBase64 } from '@shieldfive/crypto'

const key = randomBytes(32)                      // your key — never sent to us
const { blob } = await xchachaV1.encryptBytes(
  new TextEncoder().encode('patient record #42'),
  { contentKey: key },
)
const ciphertext = bytesToBase64(new Uint8Array(await blob.arrayBuffer()))

// 2. Store the CIPHERTEXT (we never see plaintext or your key)
const stored = await fetch('https://shieldfive.com/api/v1/blobs', {
  method: 'POST',
  headers: {
    'authorization': 'Bearer ' + process.env.SHIELDFIVE_API_KEY,
    'content-type': 'application/json',
  },
  body: JSON.stringify({ ciphertext, meta: { record: 42 } }),
}).then((r) => r.json())          // -> { id, storedBytes, quotaBytes }

// 3. Retrieve + decrypt on the device
const got = await fetch('https://shieldfive.com/api/v1/blobs/' + stored.id, {
  headers: { 'authorization': 'Bearer ' + process.env.SHIELDFIVE_API_KEY },
}).then((r) => r.json())

const plaintext = await xchachaV1.decryptToBytes({
  blob: new Blob([Uint8Array.from(atob(got.ciphertext), (c) => c.charCodeAt(0))]),
  contentKey: key,
})

Endpoints: POST /api/v1/blobs · GET /api/v1/blobs/:id · DELETE /api/v1/blobs/:id — each authed with your Bearer API key.

The API receives only ciphertext

Your app encrypts before anything is sent. We store ciphertext + wrapped keys keyed by your project and never the unwrapped keys, so a breach of our storage exposes only ciphertext.

Post-quantum, open source

The crypto is the same open-source @shieldfive/crypto that runs the rest of ShieldFive — a hybrid of ML-KEM-1024 and XChaCha20-Poly1305. Audit it before you ship it.

No key server to run

Your users’ keys stay on their devices. You store wrapped keys alongside the ciphertext. There is no plaintext key infrastructure for you to operate or protect.

Free to start

Create a project, mint an API key, and store up to 100 MB of ciphertext per project — no card. Usage-based higher tiers are on the roadmap.

Get an API key — free

Questions

How is this zero-knowledge if it’s a hosted API?
The encryption happens in your client with @shieldfive/crypto, before the ciphertext is sent. The API receives and stores ciphertext + wrapped keys only — it never receives plaintext or unwrapped keys, and never decrypts.
What does it cost?
The MVP is a free developer tier with a hard byte quota (100 MB stored per project), EU-hosted, hashed API keys shown once. Usage-based billing for higher limits is on the roadmap.
What happens if a user loses their key?
Because no key ever reaches us and nothing is stored in plaintext, a lost key means the ciphertext can’t be decrypted by anyone — including us. Key custody is the developer’s responsibility; that’s what makes it zero-knowledge.
Is there a separate SDK to install?
Today the “SDK” is the open-source @shieldfive/crypto library plus two HTTP calls, as shown above. A dedicated convenience SDK is planned but not required to build.