Last updated February 2026
Secria Team
Secria is an end-to-end encrypted email service designed to resist both classical and quantum cryptanalytic attacks. The protocol employs a hybrid key encapsulation mechanism combining ML-KEM-1024 (FIPS 203) with X25519 Elliptic Curve Diffie-Hellman, ensuring that compromise of either primitive alone does not break message confidentiality. Messages are protected by a two-stage encryption architecture: per-recipient key encapsulation wraps a shared symmetric key, which in turn encrypts the message payload via AES-256. Password-derived keys are computed entirely client-side using Argon2id, and the server never receives plaintext passwords, private keys, or decrypted message content. This paper describes the cryptographic protocol, key management lifecycle, threat model, and security architecture of the Secria platform.
Email remains the most widely used form of digital communication, yet the underlying protocols — SMTP, IMAP, and POP3 — were designed in an era when network eavesdropping was not a primary concern. While TLS has addressed transport-layer security, the fundamental problem remains: email content is readable by any server in the delivery chain. Providers, governments, and attackers who compromise infrastructure can access message contents at rest.
Existing end-to-end encrypted email solutions have made significant progress in addressing this gap. However, the emergence of cryptographically relevant quantum computers (CRQCs) poses a new threat. Shor's algorithm can efficiently solve the integer factorization and discrete logarithm problems underlying RSA, DSA, and elliptic curve cryptography. The "harvest now, decrypt later" attack model — where adversaries record encrypted traffic today for future quantum decryption — makes post-quantum migration urgent even before CRQCs are operational.
Secria addresses this threat by implementing a hybrid post-quantum key exchange that combines the NIST-standardized ML-KEM-1024 lattice-based key encapsulation mechanism with X25519 elliptic curve Diffie-Hellman. This hybrid approach provides security against both classical and quantum adversaries: an attacker must break both primitives to recover message contents.
| Adversary | Capabilities | Secria's Defense |
|---|---|---|
| Network eavesdropper | Passive interception of all network traffic | TLS transport encryption + E2E encryption of message payloads |
| Compromised server | Full read/write access to server storage and databases | Server stores only encrypted private keys (wrapped with client-derived vault key) and encrypted message bodies. No plaintext content is available. |
| Quantum adversary | Access to a cryptographically relevant quantum computer | ML-KEM-1024 key encapsulation resists quantum attacks. Hybrid construction ensures classical X25519 provides defense if the lattice scheme is broken by classical means. |
| Harvest-now-decrypt-later | Records all ciphertext today for future quantum decryption | Hybrid ML-KEM-1024 + X25519 with per-message randomness ensures recorded ciphertext cannot be decrypted even with future quantum capabilities |
| Malicious recipient | A Secria user who attempts to forge or alter messages | Per-recipient key encapsulation prevents cross-recipient key recovery. AES-GCM authentication on key wrapping detects tampering. |
| Function | Primitive | Standard | Library |
|---|---|---|---|
| Post-quantum key encapsulation | ML-KEM-1024 | FIPS 203 | mlkem |
| Classical key exchange | X25519 | RFC 7748 | @noble/curves |
| Key derivation | HKDF-SHA-256 | RFC 5869 | @noble/hashes |
| Password hashing | Argon2id | RFC 9106 | argon2-browser |
| Symmetric encryption (key wrapping) | AES-256-GCM | NIST SP 800-38D | Web Crypto API |
| Symmetric encryption (message body) | AES-256-GCM | NIST SP 800-38D | Web Crypto API |
| Hashing | SHA-256 | FIPS 180-4 | @noble/hashes |
| Random number generation | crypto.getRandomValues | Web Crypto API | Browser engine |
All cryptographic libraries used (@noble/curves, @noble/hashes, mlkem) are open-source, independently audited, and free of native dependencies, ensuring consistent behavior across all platforms.
ML-KEM (Module-Lattice-Based Key-Encapsulation Mechanism), formerly known as CRYSTALS-Kyber, was standardized by NIST in FIPS 203 (August 2024). Secria uses the ML-KEM-1024 parameter set, which provides NIST Security Level 5 — equivalent to AES-256 against quantum adversaries.
X25519 (RFC 7748) is an elliptic curve Diffie-Hellman function on Curve25519, providing ~128 bits of classical security. In Secria, X25519 serves as the classical component of the hybrid key exchange, ensuring security against non-quantum adversaries even if ML-KEM is found to have weaknesses.
The hybrid approach concatenates the ML-KEM shared secret with the X25519 shared secret before key derivation:
IKM = mlkem_shared_secret || x25519_shared_secret
This construction ensures that the derived key is at least as strong as the stronger of the two components. An adversary must break both ML-KEM-1024 and X25519 to recover the input keying material. This follows the conservative approach recommended by NIST and adopted by standards such as TLS 1.3 hybrid key exchange.
Upon registration, each Secria user generates the following key material entirely client-side:
| Key | Type | Size | Purpose |
|---|---|---|---|
| ML-KEM-1024 keypair | Asymmetric | 1,568 B / 3,168 B | Post-quantum key encapsulation |
| X25519 keypair | Asymmetric | 32 B / 32 B | Classical Diffie-Hellman key exchange |
| Sent key | Symmetric | 32 B | Self-encryption of sent mail and drafts |
| Key ID | Identifier | Variable | SHA-256 fingerprint of concatenated public keys |
The vault key is a 256-bit AES-GCM key derived from the user's password via Argon2id:
salt_vault = SHA-256("vault" || email)
vault_key = Argon2id(password, salt_vault, t=3, m=65536 KiB, p=1, tag_len=32)
The vault key is never transmitted to the server and exists only in client memory during an active session. It is used exclusively for encrypting/decrypting private key material.
All private key material is encrypted before leaving the client:
nonce = random(12 bytes) ciphertext || tag = AES-256-GCM(vault_key, nonce, private_key_bytes) stored = base64(nonce || ciphertext || tag)
The server stores only encrypted private key blobs alongside plaintext public keys. Without the vault key (derived from the user's password), the private keys are computationally infeasible to recover.
Secria's message encryption uses a two-stage architecture that separates per-recipient key exchange from message-level symmetric encryption.
STAGE 1 (per-recipient)
For each Secria recipient R:
(ct_kem, ss_kem) ← ML-KEM-1024.Encap(R.pk_kem)
ss_dh ← X25519(sender.sk_dh, R.pk_dh)
salt ← random(32 bytes)
K_first ← HKDF-SHA256(ss_kem || ss_dh, salt, "message-key", 32)
wrapped_key_R ← AES-256-GCM(K_first, K_second)
For sender (self-copy):
salt_self ← random(32 bytes)
K_self ← HKDF-SHA256(sent_key, salt_self, "message-key", 32)
wrapped_key_self ← AES-256-GCM(K_self, K_second)
STAGE 2 (per-message)
K_second ← random(32 bytes)
IV ← random(12 bytes)
ciphertext ← AES-256-GCM(K_second, IV, plaintext)
output ← 0x02 || IV || ciphertext || tag
A fresh 256-bit symmetric key (the second-stage key) is generated for each message. The entire message body — a fully-formed MIME document containing both text/plain and text/html representations — is encrypted with this key using AES-256-GCM. The 0x02 version byte enables forward-compatible algorithm negotiation. The second-stage key is used once and then discarded.
For each Secria recipient, the sender performs a hybrid key exchange to derive a first-stage key that wraps the second-stage key:
MlKem1024.encap(recipient.pk) produces a ciphertext and 32-byte shared secretX25519(sender.sk, recipient.pk) produces a 32-byte DH shared secret| Property | Mechanism |
|---|---|
| Quantum resistance | ML-KEM-1024 (NIST Level 5) component in hybrid KEM |
| Classical resistance | X25519 component in hybrid KEM |
| Per-message key isolation | Fresh second-stage key and fresh HKDF salt per message |
| Recipient isolation | Each recipient receives an independently encapsulated copy of the key |
| Ciphertext integrity | AES-GCM authentication tags on both key wrapping and message encryption |
| No key reuse | All symmetric keys are ephemeral; all salts and nonces are randomly generated per operation |
1. Parse envelope: extract mlkem_ciphertext, dh_public_key, salt, second_stage_key_encrypted for the current user 2. Post-quantum decapsulation: ss_kem ← MlKem1024.decap(ct_kem, my_mlkem_private_key) 3. Classical DH: ss_dh ← X25519(my_dh_private_key, sender_dh_public_key) 4. Derive first-stage key: K_first ← HKDF-SHA256(ss_kem || ss_dh, salt, "message-key", 32) 5. Unwrap second-stage key: K_second ← AES-256-GCM-Decrypt(K_first, second_stage_key_encrypted) 6. Decrypt message body: plaintext ← AES-256-GCM-Decrypt(K_second, message_ciphertext) 7. Parse MIME: Extract text/plain, text/html, inline images, and attachments
For messages the user sent, the client uses the self-encryption path:
1. K_self ← HKDF-SHA256(sent_key, salt, "message-key", 32) 2. K_second ← AES-256-GCM-Decrypt(K_self, second_stage_key_encrypted) 3. plaintext ← AES-256-GCM-Decrypt(K_second, message_ciphertext)
The client implements a fallback mechanism: if the primary decryption path fails (e.g., due to key rotation), it attempts the alternate path, ensuring robustness during key transitions.
Secria implements a split-derivation scheme that produces two cryptographically independent values from the user's password:
salt = SHA-256(email) hash = Argon2id(password, salt, t=3, m=65536, p=1)
salt = SHA-256("vault" || email)
key = Argon2id(password, salt,
t=3, m=65536, p=1, len=32)
Key independence: Because the two derivations use different salts, the login hash and vault key are cryptographically independent. Compromising the login hash — even with full knowledge of the Argon2 parameters — does not reveal the vault key.
Secria supports TOTP-based (RFC 6238) two-factor authentication. After password authentication, the server challenges for a time-based one-time code. TOTP activation requires providing the first valid code, and disabling requires a valid code, preventing unauthorized changes to MFA settings.
Secria implements an account recovery mechanism based on a 12-word mnemonic phrase, following the BIP39 specification. 128 bits of entropy are generated, checksummed with SHA-256, and encoded as 12 words from the standard BIP39 English wordlist.
recovery_key = HKDF-SHA256( IKM = entropy, // 16 bytes from mnemonic salt = "secria-recovery", // static info = "recovery-key", // static len = 32 // 256 bits )
All three private keys (X25519, ML-KEM-1024, sent key) are encrypted with the recovery key using AES-256-GCM and stored on the server. The recovery key is derived from a completely separate path from the vault key, so the two are cryptographically unrelated.
The user provides their 12-word mnemonic and a new password. The client decodes the mnemonic, derives the recovery key, decrypts the private keys, validates all key lengths, re-encrypts with a new vault key derived from the new password, and re-encrypts with the same recovery key so the phrase remains valid. Users can regenerate their recovery phrase at any time, immediately invalidating the old one.
Attachments are encrypted with the same second-stage key as the message body, ensuring they share the message's full security properties including post-quantum protection:
Upload: AES-256-GCM(K_second, IV, file_bytes) → encrypted blob Download: AES-256-GCM-Decrypt(K_second, blob) → file_bytes
Inline images referenced by cid: URIs in HTML email bodies are automatically fetched, decrypted, and converted to data: URIs for rendering. This ensures inline images are never loaded from external servers.
default-src 'self'; script-src 'self' 'wasm-unsafe-eval'; style-src 'self' 'unsafe-inline'; img-src 'self' data: blob: https://app.secria.me:8000; connect-src 'self' https://app.secria.me:8000; object-src 'none'; base-uri 'self';
Received HTML emails are rendered inside a sandboxed iframe with multiple layers of protection:
style, form, input, object, embed), all on* event handlers blocked, and URI protocol whitelist (https, http, mailto, tel, cid only)sandbox="allow-popups allow-popups-to-escape-sandbox allow-same-origin"script-src 'none'; object-src 'none'Images with dimensions of 1x1 pixels or smaller, or images hidden via CSS, are automatically detected, stripped, and counted. Users are informed of the number of tracking pixels detected in each email.
All external image URLs in rendered emails are rewritten to route through Secria's server-side proxy, preventing external servers from learning the recipient's IP address, browser fingerprint, or the timing of email opens.
Secria includes zero analytics, telemetry, or tracking libraries. No user behavior data is collected or transmitted to third parties.
Face ID, Touch ID, and fingerprint authentication. Credentials stored in platform-native secure storage with 30-day expiry.
Opaque overlay prevents app switcher screenshots. In-memory email data is cleared on background.
Payloads contain only generic alerts. No sender, subject, or message content is transmitted in push notifications.
All incoming deep links are validated against alphanumeric regex before navigation, preventing injection attacks.
| Platform | Storage Backend | Protection |
|---|---|---|
| iOS | iOS Keychain | Hardware-backed encryption, biometric-gated access |
| Android | EncryptedSharedPreferences | AES-256-GCM with Android Keystore master key |
| Web | localStorage + application encryption | Origin-isolated, CSP-protected |
Secria is designed to work seamlessly with the existing email ecosystem. When a Secria user sends email to a non-Secria address, the system provides a graceful bridge to standard SMTP. The message is encrypted normally on the client, then securely transmitted to the server over TLS for SMTP delivery with opportunistic TLS (STARTTLS). The sender's own copy remains fully end-to-end encrypted. The client clearly indicates which recipients are Secria users (fully E2E encrypted) and which are external, providing full transparency.
Incoming emails from external senders are immediately encrypted at rest by the server using the recipient's public keys before being stored, following the same two-stage encryption protocol. The server generates the ML-KEM ciphertext and X25519 DH shared secret, encrypts the message, and discards the plaintext. Even externally-received emails are stored with post-quantum encryption.
Secria constructs standard RFC 2045/2046 MIME messages with multipart/alternative (text/plain + text/html) and multipart/mixed for attachments. Filenames are sanitized and binary payloads are Base64-encoded.
Secria is the first email service to ship production post-quantum end-to-end encryption to users across web, iOS, and Android. By combining ML-KEM-1024 with X25519 in a hybrid construction, Secria provides defense against both current and anticipated quantum threats — protecting users today against harvest-now-decrypt-later attacks that threaten every other email provider still relying solely on classical cryptography.
The two-stage encryption architecture cleanly separates per-recipient key management from message-level encryption, enabling efficient multi-recipient messaging while maintaining per-recipient key isolation. The zero-knowledge password protocol ensures that even a fully compromised server cannot decrypt messages or recover user passwords. Every layer of the stack — from Argon2id password hashing to DOMPurify email sanitization to automatic pixel tracker stripping — reflects a security-first design philosophy.
Where other encrypted email providers are still planning their post-quantum migration, Secria has already shipped it. Where competitors rely on legacy OpenPGP or proprietary constructions, Secria uses NIST-standardized primitives from independently audited libraries. Where other services collect telemetry and analytics, Secria collects nothing.
Email is the backbone of digital communication. It deserves cryptography built for the future, not the past. Secria delivers exactly that.
This document describes the Secria protocol as implemented in version 1.0 (February 2026).
For security inquiries, contact: security@secria.me