Account Recovery
Restore your account using a recovery key when you've lost your password in a zero-knowledge system.
Recovery in Literal works differently from most platforms. Because Literal is a zero-knowledge system, the server never has access to your password or your encryption keys. This means Literal cannot reset your password or recover your data on your behalf — but it also means your data is protected even if the server is compromised.
This guide explains how account recovery works, what you need to set up in advance, and how to walk through the recovery process step by step.
Overview
On traditional platforms, if you forget your password, the service can simply send you a reset link. That works because the service stores (or can access) your data independently of your password.
Literal is different. Your password is used to derive a personal master key on your device — this key protects all of your documents, private keys, and search indexes. The server never sees your password or your master key. If you lose your password, the server has no way to decrypt your data or generate a new key for you.
That's where the recovery key comes in. It's a separate secret, generated during account setup, that can unlock a backup of your master key. Think of it as a spare key to your house — it only works if you made a copy before locking yourself out.
For a deeper look at how keys are organized in Literal, see Key Hierarchy. For background on the zero-knowledge model itself, see Zero-Knowledge Model.
Prerequisites
Before you can recover your account, you need to have completed the recovery key setup while you still had access. There is no way to generate a recovery key after you've lost your password.
Generating Your Recovery Key
During account registration (or at any time while logged in), Literal generates a recovery key for you. This key is:
- Created on your device, not by the server
- Used to encrypt a backup of your personal master key
- Stored in your account in encrypted form (encrypted with your master key, so the server can't read it)
When recovery key setup completes, two things are saved:
- Your recovery key, encrypted with your master key — so you can export it later while logged in
- A master key backup, encrypted with your recovery key — so the recovery flow can restore your master key if you lose your password
Both must be present for recovery to work. If either is missing, recovery is not available for that account.
Storing Your Recovery Key Safely
Your recovery key is your only backup. If you lose both your password and your recovery key, your data is permanently inaccessible. Literal cannot help you recover it — that's the security guarantee of zero-knowledge.
Best practices for storing your recovery key:
- Write it down on paper and store it somewhere physically secure (e.g. a safe or lockbox)
- Save it in a separate password manager — not the same one that stores your Literal password
- Do not store it alongside your password — if someone gains access to both, they can access your account
- Keep multiple copies in different physical locations if the data is critical to you
What Can And Cannot Be Recovered
What Is Recovered
When you complete the recovery process, the following are fully restored:
- All your documents — every document you own is re-protected with your new password. Document contents are not lost.
- Your encryption keys — your private keys are re-encrypted under your new credentials.
- Your search indexes — encrypted search tokens are preserved, so you can continue searching your documents.
- Your organization memberships — if you belong to any organizations (entities), your membership records remain intact.
What Is Not Recovered
- Your old password — it is permanently replaced. There is no way to retrieve it.
- Active sessions — all existing sessions are invalidated during recovery for security. You'll need to log in again on every device.
- Shared access tokens — any access tokens associated with your old credentials are rotated. Shared documents will be re-linked automatically, but collaborators may briefly see interrupted access during the transition.
Recovery Process
If you've lost access to your password but have your recovery key, follow these steps.
Step 1 — Start The Recovery Flow
Navigate to the login page and select the "Forgot password?" or "Recover account" option. You'll be asked for your email address and recovery key.
Your device derives a recovery blind index from email + recovery key (Argon2id), then sends only the blind index to the server. The system retrieves your encrypted master key backup. This backup can only be decrypted with your recovery key — the server cannot read it, and never sees your plaintext email.
API Call: GET /auth/recovery
Fetch the encrypted UMK backup for your account:
curl "https://api.kyndex.co/v1/auth/recovery?id=<64-hex-char-recovery-blind-index>"Response (200 OK):
{
"umk_backup": "dW1rYmFja3VwZW5jcnlwdGVkd2l0aHJlY292ZXJ5a2V5...",
"key_version": 1,
"user_id": "550e8400-e29b-41d4-a716-446655440000"
}| Field | Type | Description |
|---|---|---|
umk_backup | base64 string | The user master key encrypted with the recovery key. Your client decrypts this with your recovery key to restore the old UMK in memory. |
key_version | integer | Key version for AAD reconstruction |
user_id | UUID | User UUID for AAD reconstruction during recovery decrypt |
Error Responses:
404 Not Found— Recovery not available for this account (no recovery key backup stored)429 Too Many Requests— Rate limit exceeded500 Internal Server Error— Server error
Step 2 — Enter Your Recovery Key
Paste or type your recovery key when prompted. Your device uses this key to decrypt the master key backup, restoring your personal master key in memory.
At this point, your client has temporary access to your old master key — enough to decrypt your documents and private keys.
No API call is made. Your recovery key is used locally to decrypt the umk_backup from Step 1.
The recovery key never leaves your device.
Step 3 — Set A New Password
Choose a new password. Your client derives a new personal master key from this password on your device. The new master key replaces the old one as the root of your key hierarchy.
No API call is made. Your device performs OPAQUE key exchange locally to derive the new master key from your password, and computes the new registration record that will be sent in Step 5.
Step 4 — Re-Protect Your Data
With both the old master key (from recovery) and the new master key (from your new password) available, your client automatically:
- Re-encrypts your private keys (encryption and signing) under the new master key
- Re-wraps every document key so each document is now protected by the new master key
- Optionally re-encrypts your recovery key under the new master key (so you can export it again later)
- Creates a new master key backup encrypted with the recovery key (so recovery remains available in the future)
This step happens entirely on your device. The server receives only the re-encrypted outputs — it never sees any plaintext keys.
No API call is made. All cryptographic operations (re-encryption, key wrapping, token generation) happen locally on your device. The outputs are prepared for Step 5.
Step 5 — Finalize And Log In
Once the re-encryption is complete, the client submits the updated credentials and re-wrapped keys to the server. The system:
- Stores your new authentication credentials
- Updates all document key records with the re-wrapped versions
- Invalidates all previous sessions (for security)
- Issues a new session so you can start using Literal immediately
API Call: POST /auth/recovery
Submit the re-encrypted credentials and re-wrapped document keys:
curl -X POST "https://api.kyndex.co/v1/auth/recovery?id=<recovery-blind-index>" \
-H 'Content-Type: application/json' \
-d '{
"login_bidx": 42,
"email_encrypted": "cmVlbmNyeXB0ZWRlbWFpbHdpdGhuZXdVTUs=...",
"registration_record": "base64encodedOpaqueRecord...",
"encryption_salt": "bmV3c2FsdDMyYnl0ZXNiYXNlNjRlbmNvZGVk...",
"mlkem_private_encrypted": "cmVlbmNyeXB0ZWRNTEtFTXByaXZhdGVrZXk=...",
"signing_private_encrypted": "cmVlbmNyeXB0ZWRTaWduaW5nUHJpdmF0ZUtleQ==...",
"recovery_key_encrypted": "cmVlbmNyeXB0ZWRyZWNvdmVyeWtleQ==...",
"umk_backup": "bmV3dW1rYmFja3VwZW5jcnlwdGVk...",
"new_recovery_bidx": "a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f0a1b2",
"rewrapped_deks": [
{
"document_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"wrapped_dek_umk": "cmV3cmFwcGVkREVLd2l0aG5ld1VNSw==..."
}
],
"old_revocation_token": "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=...",
"revocation_token": "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=..."
}'Request Fields:
| Field | Type | Required | Description |
|---|---|---|---|
login_bidx | integer | Yes | New login bucket index (integer 0-8191) derived via OPRF from email and new password |
email_encrypted | base64 string | Yes | Email re-encrypted with new UMK |
registration_record | base64 string | Yes | OPAQUE registration record (the verifier, not a password hash) from your new password |
encryption_salt | base64 string | Yes | New salt for UMK derivation (32 bytes decoded) |
mlkem_private_encrypted | base64 string | Yes | ML-KEM private key re-encrypted with new UMK |
signing_private_encrypted | base64 string | Yes | Hybrid signing private key re-encrypted with new UMK (minimum 28 bytes decoded) |
recovery_key_encrypted | base64 string | No | Recovery key re-encrypted with new UMK (optional, but recommended to preserve recovery capability) |
umk_backup | base64 string | No | New UMK backup encrypted with recovery key (optional, but recommended for future recovery) |
new_recovery_bidx | string | Yes | New recovery blind index derived from new recovery key. Replaces the old one to prevent reuse. |
rewrapped_deks | array | Yes | Array of document keys re-wrapped with new UMK (can be empty if no documents) |
rewrapped_deks[].document_id | UUID | Yes | Document ID |
rewrapped_deks[].wrapped_dek_umk | base64 string | Yes | Document encryption key re-wrapped with new UMK |
old_revocation_token | base64 string | No | Revocation token from the old session (32 bytes decoded). If provided, all old sessions are invalidated. |
revocation_token | base64 string | Yes | New revocation token derived from new UMK (32 bytes decoded). Used to create the new session. |
Response (200 OK):
{
"message": "Account recovery completed successfully",
"access_token": "YWNjZXNzdG9rZW4zMmJ5dGVzYmFzZTY0ZW5jb2RlZA==...",
"refresh_token": "cmVmcmVzaHRva2VuMzJieXRlc2Jhc2U2NA==...",
"access_expires_at": "2026-03-10T12:30:45Z",
"documents_updated": 5,
"key_version": 2
}| Field | Type | Description |
|---|---|---|
message | string | Confirmation message |
access_token | base64 string | Short-lived access token for a locked recovery session (no crypto tokens yet). Must be unlocked via Step 5b before full access. |
refresh_token | base64 string | Long-lived refresh token used to unlock the session in Step 5b. Absent when the server sets it as an HttpOnly cookie instead. |
access_expires_at | ISO 8601 timestamp | When the access token expires |
documents_updated | integer | Number of document keys that were re-wrapped and stored |
key_version | integer | New key version after recovery. Use this as x_key_version in encrypted requests with the new master key. |
Error Responses:
400 Bad Request— Invalid request body (missing fields, malformed base64, invalid registration record)404 Not Found— Account not found or recovery not available429 Too Many Requests— Rate limit exceeded500 Internal Server Error— Server error
Locked Session: The access token returned is a locked recovery session — it has no
owner_token or user_member_token embedded yet. Your client cannot make authenticated requests
that require these tokens (document access, search queries, etc.) until you complete Step 5b.
Step 5b — Unlock Your Session (Token Rotation)
The access token from Step 5 is locked — it cannot access your documents yet because it lacks the cryptographic tokens (owner_token, user_member_token, and search tokens) derived from your new master key. This step recomputes those tokens and upgrades your session to unlocked.
API Call: POST /auth/recovery/tokens
Submit the new cryptographic tokens derived from your new UMK:
curl -X POST https://api.kyndex.co/v1/auth/recovery/tokens \
-H 'Authorization: Bearer <locked_access_token>' \
-H 'Content-Type: application/json' \
-d '{
"refresh_token": "cmVmcmVzaHRva2VuMzJieXRlc2Jhc2U2NA==...",
"owner_token": "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=...",
"user_member_token": "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=...",
"owner_tokens": [
{
"old_token": "oldOwnerToken32BytesBase64...",
"new_token": "newOwnerToken32BytesBase64..."
}
],
"grantor_tokens": [
{
"old_token": "oldGrantorToken32BytesBase64...",
"new_token": "newGrantorToken32BytesBase64..."
}
],
"doc_tokens": [
{
"old_token": "oldDocToken32BytesBase64...",
"new_token": "newDocToken32BytesBase64..."
}
]
}'Request Fields:
| Field | Type | Required | Description |
|---|---|---|---|
refresh_token | base64 string | No | Refresh token from Step 5 response. Omit when using HttpOnly cookie transport — the server reads it from the cookie automatically. |
owner_token | base64 string | Yes | HMAC(new ConsumerBIK, "owner:" || user_id) derived from new UMK. Will be embedded in the unlocked access token. |
user_member_token | base64 string | Yes | HMAC(new ConsumerBIK, "my-memberships:" || user_id) derived from new UMK. Will be embedded in the unlocked access token. |
owner_tokens | array | No | Batch rotation of owner tokens for fast searches. Each entry has old_token (from old UMK) and new_token (from new UMK). |
grantor_tokens | array | No | Batch rotation of grantor tokens for grants you've issued. Each entry has old_token and new_token. |
doc_tokens | array | No | Batch rotation of per-document tokens. Each entry has old_token and new_token. |
Response (200 OK):
{
"access_token": "YWNjZXNzdG9rZW4zMmJ5dGVzYmFzZTY0ZW5jb2RlZA==...",
"access_expires_at": "2026-03-10T12:30:45Z",
"rotated": {
"owner_tokens": 1,
"grantor_tokens": 0,
"doc_tokens": 5,
"user_member_tokens": 0
},
"tokens_rotated_at": "2026-03-10T11:45:30Z"
}| Field | Type | Description |
|---|---|---|
access_token | base64 string | New unlocked access token with crypto tokens embedded. Use this for all authenticated requests. |
access_expires_at | ISO 8601 timestamp | When the new access token expires |
rotated.owner_tokens | integer | Number of owner tokens rotated (typically 1 if you have a personal search index) |
rotated.grantor_tokens | integer | Number of grantor tokens rotated (grants you've issued) |
rotated.doc_tokens | integer | Number of document tokens rotated |
rotated.user_member_tokens | integer | Always 0 (entity membership tokens are rotated separately via a different mechanism) |
tokens_rotated_at | ISO 8601 timestamp | When the rotation completed |
Error Responses:
400 Bad Request— Invalid refresh token or malformed tokens401 Unauthorized— Invalid or expired locked access token429 Too Many Requests— Rate limit exceeded500 Internal Server Error— Server error
Session Unlocked: After this step completes, your new access token is fully unlocked with all crypto tokens embedded. You can now make authenticated requests (search, access documents, manage grants, etc.) with complete access to your account. Your old sessions have been invalidated.
Error Handling
"Recovery Not Available For This Account"
This error means the account does not have a recovery key backup stored. This can happen if:
- Recovery key setup was never completed during or after registration
- The recovery key backup was removed or corrupted
Unfortunately, without a recovery key backup, there is no way to recover the account. This is an inherent property of zero-knowledge systems — the server cannot decrypt your data on your behalf.
Lost Recovery Key
If you've lost your recovery key but still know your password, you can:
- Log in normally with your password
- Generate a new recovery key from your account settings
- Store the new recovery key safely (see best practices above)
If you've lost both your password and your recovery key, the account and its data are permanently inaccessible.
Related Resources
- Zero-Knowledge Model — why Literal can't see your data
- Key Hierarchy — how your keys are organized and protected
- Getting Started — initial account setup, including recovery key generation