Encrypted vault
When building applications that store highly sensitive personal records (such as tax forms, medical PDFs, or identity card scans), storing plaintext files on disk is a significant security risk.
Layeron Storage provides Zero-Knowledge Managed Encryption. By passing a Secret reference to your Bucket, the dedicated Storage Product Worker encrypts data on-the-fly before it is written to the underlying Cloudflare R2 bucket.
Code Implementation
Section titled “Code Implementation”This example demonstrates generating a secure 256-bit cryptographically random key, declaring an encrypted vault bucket, uploading a tax document, and downloading it decrypted.
import { backend } from "@layeron/core"import { secret, storage } from "@layeron/modules"
const app = backend()
// 1. Generate and Register a 256-bit cryptographically random keyconst vaultEncryptionKey = secret.random({ name: "vault-aes-key", bytes: 32, // 256-bit encryption key})
// 2. Declare the encrypted Bucketconst vaultBucket = storage.bucket({ name: "secure-vault", access: "private", encryption: { secret: { kind: "secret_ref", name: "vault-aes-key", }, algorithm: "aes-gcm-256", // Supported secure block cipher },})
// Register both the key and the bucketapp.use(vaultEncryptionKey)app.use(vaultBucket)
// 3. Route: Save sensitive PDF documentsapp.post("/api/vault/upload", async (request) => { const userId = "usr_100" const documentId = crypto.randomUUID() const rawPdfBytes = await request.arrayBuffer()
// The .put() method automatically encrypts the raw binary bytes using // the 'vault-aes-key' secret inside the Product Worker boundary. const uploadResult = await vaultBucket.put(`documents/${userId}/${documentId}.pdf`, rawPdfBytes, { contentType: "application/pdf", metadata: { ownerId: userId, uploadedAt: new Date().toISOString(), }, })
// The upload result returns standard metadata, but is marked as encrypted return Response.json({ status: "encrypted_and_stored", documentId, key: uploadResult.key, size: uploadResult.size, // Encrypted size includes encryption headers isEncrypted: !!uploadResult.encrypted, // True })})
// 4. Route: Download and decrypt PDF documentsapp.get("/api/vault/download/:documentId", async (request) => { const pathSegments = new URL(request.url).pathname.split("/") const documentId = pathSegments[4] const userId = "usr_100" const key = `documents/${userId}/${documentId}.pdf`
// Fetch the encrypted handle from storage const handle = await vaultBucket.get(key) if (!handle) { return new Response("Document not found", { status: 404 }) }
// The .bytes() call automatically decrypts the binary payload // inside the secure Product Worker boundary. const decryptedBytes = await handle.bytes()
return new Response(decryptedBytes, { headers: { "content-type": "application/pdf", "content-disposition": `attachment; filename="document-${documentId}.pdf"`, }, })})How It Works
Section titled “How It Works”- Automatic Cipher Envelope: Inside the Storage Product Worker, your raw bytes are passed into the Web Crypto API, encrypted using AES-GCM-256 with a randomly generated unique Initialization Vector (IV). The encrypted cipher-bytes and the IV are packed and stored in Cloudflare R2.
- Plaintext Isolation: The encryption key is injected securely into the worker environment using Cloudflare secrets binding. The key is never written to your database, never logged, and never leaves the execution memory space. Even if an attacker gains read-access to your raw R2 bucket, they will only see unreadable binary blobs.
- Implicit Decryption: Reading is completely seamless. Invoking
handle.bytes(),handle.text(), orhandle.json()on the returnedStorageReadHandleautomatically triggers the product worker to extract the IV, decrypt the payload, and return the original plaintext data to your route handler.