Document Upload With Client-Side Encryption
Upload an encrypted document, wrap its key material, wait for enclave processing, and verify searchability.
Documents are encrypted before upload. Literal stores encrypted content, wrapped keys, blind index tokens, and operational metadata. The application server does not receive document plaintext, plaintext metadata, or plaintext search terms.
Prerequisites
Before starting, the client needs:
- An active access token.
- Client-side cryptography for authenticated encryption, key wrapping, and blind index token generation.
- The current platform public key for platform-wrapped document keys.
See Authentication and Platform Keys.
Overview
| Step | Where | Output |
|---|---|---|
| Get platform key | Literal → client | public key for platform wrapping |
| Reserve slot | Literal → client | document ID and commitment nonce |
| Encrypt locally | client | encrypted content, encrypted metadata, wrapped keys, blind tokens |
| Create record | client → Literal | document metadata record in pending_upload |
| Upload content | client → Literal | encrypted binary content |
| Process | enclave | verification artifacts and encrypted outputs |
| Verify searchability | client + Literal | encrypted search results |
Endpoint sequence:
GET /v1/public-keys/serverPOST /v1/documents/reservationsPOST /v1/documentsPUT /v1/documents/{id}/contentGET /v1/documents/{id}POST /v1/search
Use the API Reference for exact request fields, response bodies, and errors.
Step 1 — Get The Platform Public Key
The client fetches the current platform public key before encryption. This key is used to wrap the document encryption key for enclave processing.
Endpoint: GET /v1/public-keys/server
Cache the key and refresh it when key rotation requires a new one. See Platform Keys.
Step 2 — Reserve A Document Slot
Reservation gives the client a server-authoritative document ID and a commitment nonce that binds encryption to this specific upload. The reservation expires in 5 minutes.
Two-phase upload gives Literal a server-authoritative document ID before encryption and binds the encrypted content to that reservation through the commitment nonce.
Reserve before encrypting. The commitment_nonce from the reservation must be included in the
encryption AAD so the ciphertext is bound to this document slot.
Endpoint: POST /v1/documents/reservations
Use the reservation’s document ID as the reservation_id in Step 4.
Step 3 — Encrypt The Document Locally
The client performs five operations before creating the document record.
Generate A Document Encryption Key
Create a fresh, random symmetric encryption key for this document. Every document has its own unique key — no two documents share a key.
Encrypt Content And Metadata
Encrypt the document bytes and the document metadata (title, filename, type, tags) separately using the document encryption key with authenticated encryption. Include the commitment_nonce from Step 2 and the key-wrapping timestamp (wrap_ts) in the AEAD authentication context to bind the ciphertext to this specific upload.
Wrap The Document Key
Wrap the document encryption key twice:
- With the document holder’s personal master key, so the holder can decrypt the document later.
- With the platform public key from Step 1, so the secure enclave can process the document.
Both wraps target the same plaintext document key. Literal stores both wrapped copies but does not receive the unwrapped key.
Generate Blind Index Tokens
Generate one-way cryptographic tokens for each searchable value (document type, text content, dates, tags). Each token is computed using the personal search key and a normalization step that ensures consistent matching. See Encrypted Search and Key Hierarchy for the underlying model.
Prepare Upload Metadata
Compute the owner and document tokens for blind routing, capture the wrapping timestamp, and select a coarse size bucket for the encrypted content. These values accompany the document record in Step 4.
Step 4 — Create The Document Record
The create request stores the encrypted document metadata and access material. It includes:
- the reservation ID
- encrypted metadata
- document key wrapped for personal access
- document key wrapped for platform/enclave processing
- owner and document tokens for blind routing
- optional personal search tokens
- size bucket and wrapping timestamp
Endpoint: POST /v1/documents
After this step, the record is created in pending_upload and waits for the encrypted content upload.
Step 5 — Upload Encrypted Content
Upload the encrypted document bytes as binary content.
Endpoint: PUT /v1/documents/{id}/content
The upload must include the encrypted bytes and a valid content length. After upload, the document enters the processing queue.
The maximum upload size is 100 MB. The 10 MB threshold affects download behavior only; it does not change upload behavior.
During processing, the secure enclave unwraps the document key, temporarily decrypts the document, performs verification and seal generation, and returns encrypted outputs. The application server stores those outputs but does not receive document plaintext.
Step 6 — Confirm Enclave Processing
After upload, the document moves through several processing states automatically. Poll the document status to track progress.
Endpoint: GET /v1/documents/{id}
Document Processing States
| State | Description |
|---|---|
pending_upload | Record created, waiting for encrypted content. |
pending_ocr | Content uploaded, queued for enclave processing. |
processing | Secure enclave is actively processing the document. |
processed | Enclave processing complete — verification seal generated. |
failed | Processing failed — the document must be re-uploaded. |
Processing status and searchability are related but not identical. A document is searchable only after the relevant blind index tokens exist for that scope.
For a deeper look at what happens at each stage, see Document Lifecycle.
Step 7 — Verify Searchability
After processing, generate a search token locally using the same search key and normalization rules used during indexing.
Endpoint: POST /v1/search
Literal matches the token and returns encrypted records. The client decrypts the returned metadata and document key material locally.
See Encrypted Search for the search workflow.
Troubleshooting
- If a reservation expires, create a new reservation and re-encrypt with the new commitment nonce.
- If upload fails after record creation, retry according to the document state returned by the API.
- If the document remains in a processing state, poll with backoff.
- If search returns no results, confirm that the relevant blind index tokens exist for the search scope.
See Error Handling and the API Reference for status-specific errors.
Related Resources
- Zero-Knowledge Model — the trust-boundary foundation upload lives inside.
- Document Lifecycle — follow a document through every stage from upload to deletion.
- Encrypted Search — generate blind index tokens and search encrypted document records.
- Key Hierarchy — the keys that wrap document access at upload time.
- Platform Keys — fetch and cache the platform public key.
Last updated on