# End-to-End Encryption (E2EE)

Tempest is **end-to-end encrypted**. Your SSH keys, passwords, snippets, and connection metadata are encrypted on your device with a key derived from your vault password — a key that **never leaves your device** — before anything reaches our sync servers. We literally cannot decrypt your data, even if compelled to. This is the same security architecture as 1Password, Bitwarden, Signal, and ProtonMail.

This page goes into the cryptographic detail. For the high-level pitch, see [How Tempest Protects Your Privacy](/account-and-privacy/how-tempest-protect-your-privacy.md).

## Threat model

E2EE is a defense against specific attackers. Tempest's E2EE defends against:

| Attacker                                 | Defended? | How                                                                      |
| ---------------------------------------- | --------- | ------------------------------------------------------------------------ |
| Tempest server breach                    | ✅         | Server only stores ciphertext; no keys to leak                           |
| Tempest employees                        | ✅         | Same — we never see plaintext                                            |
| Network MITM (TLS terminator, ISP, etc.) | ✅         | Records are already ciphertext before TLS                                |
| Government request for "the user's data" | ✅         | We can hand over only what we have — encrypted blobs                     |
| Malware on your device                   | ❌         | Once your vault is unlocked locally, malware with that scope can read it |
| You forgetting your vault password       | ❌         | Recovery would require us to hold a key — defeating E2EE                 |

The last two are inherent to any zero-knowledge system. Tempest can't recover a forgotten vault password — see [Reset Your Tempest Password](/account-and-privacy/resetting-password.md).

## Key derivation: vault password → encryption key

When you set a vault password, Tempest derives a 256-bit symmetric key:

```
key = BLAKE2b(vault_password, salt, output_length=32, person="tempest-vault-v1")
```

* **BLAKE2b** is a fast, modern cryptographic hash — RFC 7693, used in WireGuard, Argon2's reference, and many others.
* The salt is generated per vault and stored locally (it's also synced as part of the encrypted profile so a new device can re-derive the same key).
* The `person` field domain-separates this hash from any other use — a defense-in-depth measure so the same password used elsewhere can't accidentally produce the same key.

The resulting key never leaves your device. It's held in process memory while Tempest is unlocked and zeroed when you sign out.

## Per-record encryption: xsalsa20poly1305

Each document in your vault (a host, a snippet, a keychain entry, etc.) is encrypted independently:

```
ciphertext = secretbox.encrypt(plaintext, nonce, key)
```

Where `secretbox` is a standard **authenticated symmetric encryption** primitive:

* **xsalsa20** stream cipher — confidentiality
* **Poly1305** MAC — authenticity / tamper detection
* **24-byte random nonce** per record — no nonce reuse risk

Per-record encryption (rather than encrypting the whole vault as one blob) means:

* Sync replicates only the documents that changed — not gigabytes per edit
* A damaged record doesn't corrupt the rest
* Conflict resolution can happen at the per-document level without ever decrypting

## Sync transport: TLS over ciphertext

Encrypted records are then transported over **TLS 1.3** between your device and Tempest's sync servers. TLS gives us:

* Forward secrecy on the wire
* Server identity verification (so you can't be MITMed onto a fake Tempest)
* Defense-in-depth — even if the E2EE were ever broken, an attacker would also need to break TLS to passively observe

The double encryption is intentional: TLS protects the *protocol*, E2EE protects the *contents*.

## Conflict-free sync without decryption

Tempest sync uses a **multi-master replication protocol** designed for offline-first apps. The server treats each E2EE document as an opaque blob with:

* A document ID
* A revision counter
* The encrypted body

When two devices edit the same document offline and then sync, the server records both revisions and lets the client decide how to merge — *without the server ever seeing the contents*. This is unusual for a sync system and is a key reason Tempest can offer real-time multi-device sync without compromising E2EE.

## What the server *does* see

A small amount of operational metadata is necessarily plaintext:

| Visible to server                             | Why                                                   |
| --------------------------------------------- | ----------------------------------------------------- |
| Sync account email                            | We need to know which account the document belongs to |
| Document IDs and revision counters            | The sync engine matches revisions across devices      |
| Approximate document sizes                    | Quota enforcement                                     |
| Device public keys (for Tempest Push routing) | We need to deliver notifications to specific devices  |
| Last-sync timestamps                          | Diagnostics and "is this device still active?"        |

We never see hostnames, usernames, passwords, key contents, snippet text, or any other connection detail.

## What the server cannot see

* Anything inside any encrypted document (hosts, keys, certs, snippets, keychain entries, sftp bookmarks…)
* Your vault password
* The derived encryption key
* Plaintext of `Tempest Push` notification payloads (these are E2EE'd to your other devices' public keys before submission)

## Comparison to other security models

| Model                                                        | Server can read your data?    | Recovery if password lost? |
| ------------------------------------------------------------ | ----------------------------- | -------------------------- |
| **No encryption** (typical SaaS)                             | Yes                           | Yes — admin reset          |
| **Server-side encryption at rest** (most cloud DBs)          | Yes (key managed by provider) | Yes                        |
| **Encryption in transit only** (HTTPS but plaintext at rest) | Yes                           | Yes                        |
| **End-to-end encryption** (Tempest, 1Password, Bitwarden)    | **No**                        | **No**                     |

The trade-off is explicit: lose the password, lose the data — in exchange for the strongest possible privacy guarantee.

## Tempest Push notifications and E2EE

When [Tempest Push](/productivity/tempest-push-notifications.md) sends a notification from one of your devices to another, the payload is encrypted to the receiving device's public key *before* hitting our notification relay. APNs / FCM see only:

* A target device token
* A small ciphertext (decrypted on-device into the actual notification text)

We never see the snippet that ran, the host that failed, or the user-readable notification message.

## Limitations and roadmap

* **Local malware**: any process running as you with disk + memory access can read your vault while it's unlocked. Use OS-level disk encryption (FileVault, BitLocker, LUKS) and don't run untrusted code as your user.
* **Quantum threat for stored ciphertext**: xsalsa20 is symmetric and not currently considered broken by Shor's algorithm. The vault's protection against future quantum attacks is acceptable.
* **Open source**: the crypto implementation will be open-sourced for independent audit — see [How Tempest Protects Your Privacy](/account-and-privacy/how-tempest-protect-your-privacy.md).

## See also

* [How Tempest Protects Your Privacy](/account-and-privacy/how-tempest-protect-your-privacy.md) — the high-level overview
* [Reset Your Tempest Password](/account-and-privacy/resetting-password.md) — what happens when you forget
* [Post-Quantum SSH Algorithms](/authentication/post-quantum-ssh-algorithms.md) — the *transport* protocol's PQ story


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.gotempest.app/account-and-privacy/end-to-end-encryption.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
