Security Model
Security isn't an afterthought — it's the foundation everything is built on. Here's exactly how LastSignal protects your most sensitive messages.
Zero-Knowledge Architecture
"Zero-knowledge" means the server stores your data but cannot understand it. Even if the database was completely exposed, your messages would remain private.
What the Server Stores
- Email addresses
- Encrypted message blobs (unreadable)
- Recipient public keys
- Message labels (optional metadata)
- Timestamps and check-in status
What the Server Cannot Access
- Your message contents
- Recipient passphrases
- Recipient private keys
- Decryption keys
- Any way to read your messages
Encryption Flow
Three key processes work together to keep your messages secure. All cryptographic operations happen in your browser — the server never sees plaintext or private keys.
1. Recipient Key Setup
When a recipient accepts your invitation, they create a passphrase. This passphrase generates a unique encryption key pair that only they can recreate.
┌────────────────────────────────────────────────────────────┐
│ RECIPIENT KEY SETUP │
│ How recipients create their encryption keys │
├────────────────────────────────────────────────────────────┤
│ │
│ ┌─────────────┐ │
│ │ Passphrase │ (chosen by recipient, never sent) │
│ └──────┬──────┘ │
│ │ │
│ ▼ │
│ ┌─────────────┐ ┌──────────────┐ │
│ │ Argon2id │◄────│ Random Salt │ (from server) │
│ │ 256 MB │ │ (16 bytes) │ │
│ └──────┬──────┘ └──────────────┘ │
│ │ │
│ ▼ │
│ ┌─────────────┐ │
│ │ Seed │ (32 bytes, deterministic) │
│ └──────┬──────┘ │
│ │ │
│ ▼ │
│ ┌─────────────┐ │
│ │ X25519 │ │
│ │ Keypair │ │
│ └──────┬──────┘ │
│ │ │
│ ┌─────┴─────┐ │
│ ▼ ▼ │
│ ┌────────┐ ┌─────────┐ │
│ │ Public │ │ Private │ │
│ │ Key │ │ Key │ │
│ └───┬────┘ └────┬────┘ │
│ │ │ │
│ ▼ ▼ │
│ Stored Discarded │
│ on server immediately │
│ │
└────────────────────────────────────────────────────────────┘ Key insight: The private key is generated from the passphrase, used once, and immediately discarded. It can be regenerated anytime using the same passphrase and salt.
2. Message Encryption
When you write a message, it's encrypted in your browser using a random key. That key is then encrypted separately for each recipient using their public key.
┌────────────────────────────────────────────────────────────┐
│ MESSAGE ENCRYPTION │
│ How your messages are protected │
├────────────────────────────────────────────────────────────┤
│ │
│ ┌─────────────┐ │
│ │ Plaintext │ (your message, in browser only) │
│ │ Message │ │
│ └──────┬──────┘ │
│ │ │
│ ▼ │
│ ┌─────────────────────┐ ┌──────────────┐ │
│ │ XChaCha20-Poly1305 │◄────│ Random Key │ │
│ │ (AEAD) │ │ (32 bytes) │───────┐ │
│ └──────────┬──────────┘ └──────────────┘ │ │
│ │ │ │
│ ▼ │ │
│ ┌─────────────────────┐ │ │
│ │ Ciphertext │ │ │
│ │ (encrypted blob) │ │ │
│ └──────────┬──────────┘ │ │
│ │ │ │
│ │ For each recipient: │ │
│ │ ┌──────────────────┐ │ │
│ │ │ crypto_box_seal │◄─────────┘ │
│ │ │ (sealed box) │ │
│ │ └────────┬─────────┘ │
│ │ │ │
│ │ ▼ │
│ │ ┌──────────────────┐ │
│ │ │ Wrapped Key │ │
│ │ │ (per recipient) │ │
│ │ └────────┬─────────┘ │
│ │ │ │
│ ▼ ▼ │
│ ┌─────────────────────────────────────────┐ │
│ │ Sent to Server │ │
│ │ • Ciphertext (encrypted message) │ │
│ │ • Wrapped keys (one per recipient) │ │
│ │ • Nonce (random, for decryption) │ │
│ └─────────────────────────────────────────┘ │
│ │
└────────────────────────────────────────────────────────────┘ Key insight: The message is encrypted once with a symmetric key. Only the small key (not the whole message) is encrypted per-recipient, making the system efficient even with many recipients.
3. Message Decryption
When a recipient receives a message, they enter their passphrase to regenerate their key pair and decrypt the message — all in their browser.
┌────────────────────────────────────────────────────────────┐
│ MESSAGE DECRYPTION │
│ How recipients read your messages │
├────────────────────────────────────────────────────────────┤
│ │
│ ┌─────────────┐ ┌─────────────┐ │
│ │ Passphrase │ │ Salt │ (from server) │
│ └──────┬──────┘ └──────┬──────┘ │
│ │ │ │
│ └─────────┬─────────┘ │
│ ▼ │
│ ┌─────────────┐ │
│ │ Argon2id │ (same params as setup) │
│ └──────┬──────┘ │
│ │ │
│ ▼ │
│ ┌─────────────┐ │
│ │ Keypair │ (regenerated identically) │
│ └──────┬──────┘ │
│ │ │
│ ┌────────────────┼────────────────┐ │
│ │ ▼ │ │
│ │ ┌─────────────────────────┐ │ │
│ │ │ crypto_box_seal_open │◄───┼─── Wrapped Key │
│ │ └───────────┬─────────────┘ │ (from server) │
│ │ │ │ │
│ │ ▼ │ │
│ │ ┌─────────────────────────┐ │ │
│ │ │ Message Key │ │ │
│ │ └───────────┬─────────────┘ │ │
│ │ │ │ │
│ │ ▼ │ │
│ │ ┌─────────────────────────┐ │ │
│ │ │ XChaCha20-Poly1305 │◄───┼─── Ciphertext │
│ │ │ Decrypt │ │ (from server) │
│ │ └───────────┬─────────────┘ │ │
│ │ │ │ │
│ │ ▼ │ │
│ │ ┌─────────────────────────┐ │ All in browser │
│ │ │ Plaintext │ │ Never sent back │
│ │ │ Message │ │ │
│ │ └─────────────────────────┘ │ │
│ └─────────────────────────────────┘ │
│ │
└────────────────────────────────────────────────────────────┘ Key insight: The decrypted message is displayed in the browser and never sent back to the server. The server has no way to know what the message says.
Cryptographic Algorithms
| Purpose | Algorithm | Parameters | Library |
|---|---|---|---|
| Key Derivation | Argon2id | 256 MB memory, 3 iterations | libsodium |
| Message Encryption | XChaCha20-Poly1305 | 256-bit key, 192-bit nonce | libsodium |
| Key Wrapping | X25519 + crypto_box_seal | Curve25519 | libsodium |
| Token Hashing | SHA-256 | Standard | Ruby OpenSSL |
Why These Choices?
Argon2id
Winner of the Password Hashing Competition. Memory-hard design resists GPU and ASIC attacks, making brute-force extremely expensive.
XChaCha20-Poly1305
Modern AEAD cipher. Extended nonce eliminates collision risks. Faster than AES on devices without hardware acceleration.
X25519
Industry-standard elliptic curve. Used by Signal, WhatsApp, and TLS 1.3. Fast, secure, and well-audited.
libsodium
Widely audited cryptographic library with misuse-resistant API. No configuration needed — secure by default.
Threat Model
LastSignal is designed to protect against the most likely attack scenarios. Here's what happens in each case:
🖥️ Server Compromise
Scenario: The server is controlled by a malicious operator, an attacker gains full database access, or a government demands user data. Whether the threat is internal, external, or legal, the guarantees are identical.
They get:
- • Encrypted message blobs
- • Recipient public keys
- • Email addresses and metadata
- • Argon2id salts
They can't get:
- • Message contents
- • Passphrases or private keys
- • Any way to decrypt messages
Protection: Zero-knowledge architecture means even with full server access, messages remain private. This is a mathematical guarantee, not a policy choice.
🔗 Transport Security
Scenario: An attacker intercepts traffic between you and the server, or performs a man-in-the-middle attack.
- • TLS/HTTPS enforced in production with HSTS
- • All cryptographic operations happen client-side before transmission
- • Even intercepted traffic contains only encrypted blobs
Residual risk: Compromised Certificate Authorities could enable MITM attacks. The real vulnerability isn't the network—it's the code being served (see Code Integrity below).
🌐 Code Integrity
Scenario: The JavaScript served to your browser is compromised—either at the server, via a CDN, or through a supply chain attack on dependencies like libsodium.
- • Malicious code could capture passphrases as users type them
- • Could exfiltrate decrypted messages before display
- • libsodium is loaded via importmap with a pinned version, but a compromised CDN could still serve malicious code
- • Dependencies are minimal (only libsodium for cryptography)
Important: This is the main trust boundary for any browser-based E2EE system. It's not a bug—it's a structural limitation of web apps that deliver cryptographic code dynamically.
Mitigation: Self-host your own instance with all dependencies. Audit the code. Verify hashes before deploying. Use browser extensions to monitor script integrity.
💻 Client-Side Compromise
Scenario: A user's device, browser, or browser extensions are compromised—applies to both senders and recipients.
- • Malicious browser extensions can capture passphrases and exfiltrate data
- • Keyloggers or screen capture malware can record everything typed or displayed
- • Physical device access allows reading saved passphrases or browser cache
- • For recipients: a compromised device after message delivery means the attacker can decrypt messages if they also have the passphrase
Important: LastSignal protects messages in transit and at rest on the server, but cannot protect against endpoint compromise. Once a message is decrypted in the browser, its confidentiality depends on the user's environment.
Mitigation: Use trusted devices with full-disk encryption. Minimize browser extensions. Use a dedicated browser profile. Lock devices when not in use. Never save passphrases on shared computers.
🔑 Credential Attacks
Scenario: An attacker targets authentication credentials—either by brute-forcing recipient passphrases or compromising a sender's email account.
Passphrase brute force:
- • Argon2id requires 256 MB memory per attempt, making GPU attacks expensive
- • Rate limiting on all endpoints prevents online attacks
- • No server feedback on wrong passphrase (fails silently)
- • Offline attacks require both ciphertext and salt from database
Compromised sender email:
They can:
- • Intercept magic login links
- • Access the sender's account
- • Trigger or cancel message delivery
They can't:
- • Read encrypted messages
- • Obtain recipient passphrases
Critical: Weak passphrases are vulnerable to offline attacks if the database is compromised. See the Passphrase Security section below for details.
Mitigation: Use a secure email provider with 2FA. Generate strong, random passphrases for recipients. Consider using a password manager.
Critical: Passphrase Security
Why This Matters
LastSignal uses a server-generated KDF salt stored alongside recipient public keys. This is a deliberate architectural trade-off that enables deterministic key regeneration from passphrases—recipients can decrypt messages by entering the same passphrase they used during setup, without storing any secrets.
However, this means that if an attacker gains access to the database—whether through server compromise, data breach, malicious operator, insider threat, or legal request—they obtain the salt and can attempt offline brute-force attacks against recipient passphrases without any rate limiting or detection.
This doesn't make E2EE useless—it means passphrase strength becomes the only defense against a database compromise.
Offline Attack Time Estimates
These estimates assume ~1 guess/second per GPU with Argon2id (256 MB, 3 iterations) and an attacker running 1,000 GPUs. This is an order-of-magnitude guide; real hardware varies.
| Passphrase Type | Example | Entropy | Time to Crack | Security |
|---|---|---|---|---|
| 8 lowercase letters | abcdefgh | ~38 bits | ~3 years | UNSAFE |
| 8 mixed (upper+lower+digit) | Abc12345 | ~48 bits | ~3,500 years | MARGINAL |
| 12 mixed case + numbers | Abc123Xyz789 | ~72 bits | ~50 billion years | SECURE |
| 16 random characters | kX9#mP2$vL5@nQ8! | ~105 bits | ~300 quintillion years | SECURE |
| 20 random characters | aB3$kL9@mN2#pQ5%xR8! | ~131 bits | ~40 octillion years | SECURE |
| 4 random words (diceware) | correct horse battery staple | ~51 bits | ~45,000 years | MARGINAL |
| 6 random words (diceware) | correct horse battery staple piano lamp | ~77 bits | ~3 trillion years | SECURE |
Note: Entropy assumes the passphrase is randomly generated from the stated character set or word list. Human-chosen passwords typically have much lower entropy.
Recommended Passphrases
- • 16+ random characters (mixed case, numbers, symbols)
- • 6+ random words from a diceware list
- • Generated by a password manager
- • Unique to LastSignal (not reused elsewhere)
Avoid These
- • Dictionary words or common phrases
- • Personal information (names, dates, addresses)
- • Keyboard patterns (qwerty, 123456)
- • Passwords reused from other services
- • Anything shorter than 16 characters
The Bottom Line
LastSignal's E2EE architecture provides strong protection against an honest-but-curious server—one that operates correctly but might be tempted to read your data. The server genuinely cannot decrypt your messages because it never has the private keys.
However, against a compromised, malicious, or coerced server, your passphrase becomes the only defense. This is an inherent limitation of any browser-based E2EE system that uses deterministic keys derived from passphrases.
If you're protecting high-value secrets: use a strong passphrase (16+ random characters or 6+ diceware words), store it in a secure password manager, and consider self-hosting on infrastructure you control.
Known Limitations
Honest security communication matters. Here's what LastSignal doesn't protect:
Server-Generated KDF Salt
The server generates and stores the salt used for recipient key derivation. This is necessary for deterministic key regeneration but creates a specific vulnerability.
- • If the database is compromised (breach, malicious operator, legal request), attacker gets the salt
- • With the salt, they can attempt offline brute-force attacks against passphrases
- • No rate limiting applies to offline attacks
- • Weak passphrases can be cracked in days; strong ones remain secure
This is the main reason strong passphrases are critical. See the Passphrase Security section for timing estimates and recommendations.
Liveness Detection Ambiguity
The system cannot reliably distinguish between death, incapacity, or temporary loss of access.
- • You're alive but can't respond (coma, travel, spam filter, device loss)
- • You're deceased but someone else responds on your behalf
- • Email delivery failures could trigger false positives
This isn't a bug—it's a fundamental limitation of any email-based liveness detection. Configure check-in intervals carefully, and consider the consequences of both premature and delayed delivery.
Mitigations: Use a Trusted Contact who can confirm you're alive but unreachable, buying extra time before delivery. You can also set a per-recipient delivery delay (up to a year) so messages aren't accessible immediately after delivery triggers.
Metadata Exposure
The server knows who sends messages to whom, and when. This is necessary for the service to function.
- • Sender and recipient email addresses
- • Timestamps of message creation and delivery
- • Check-in patterns and frequency
- • Number of messages and recipients per sender
An adversary with server access could analyze communication patterns even without reading message contents. If metadata privacy is critical, consider using anonymous email addresses.
Message Labels
Labels are stored in plaintext on the server. They help you organize messages but are visible to anyone with database access.
- • Don't use labels like "Bitcoin wallet seed" or "Affair with..."
- • Use generic labels: "For Alice", "Important", "Family"
- • The message content itself remains encrypted regardless of the label
No Forward Secrecy
Unlike Signal or WhatsApp, LastSignal doesn't use ephemeral keys that change with each message.
- • If a passphrase is compromised, all past and future messages to that recipient are exposed
- • There's no way to rotate keys for messages already stored on the server
- • A compromised passphrase affects all messages encrypted with that recipient's key
This is a deliberate trade-off: forward secrecy requires ongoing key exchange, which isn't possible for a dead man's switch where recipients may not interact with the system until delivery.
No Passphrase Recovery
If a recipient forgets their passphrase, their messages are permanently inaccessible.
- • The server never stores passphrases—only the public key derived from them
- • There is no "forgot password" flow, no recovery email, no backup codes
- • Even the sender cannot recover messages for a recipient who lost their passphrase
This is by design—recovery mechanisms would require storing something that could decrypt messages, breaking zero-knowledge guarantees. Recipients should store their passphrase securely (e.g., in a password manager or written in a safe place).
Optionally, they may add a passphrase hint to help them remember it when needed. This hint must be used with caution: it should not reveal the passphrase or make it guessable, as doing so could weaken overall security.
Verify It Yourself
The code is publicly available, auditable, and self-hostable. Read the code, audit the crypto, or deploy your own instance. Don't take anyone's word for it — verify.
LastSignal is provided as-is, without warranties or guarantees. We do not host or operate your instance, and bugs may exist. You are solely responsible for how you configure, run, and use it. See the full disclaimer.