SeraVault Security Whitepaper

Technical Architecture & Post-Quantum Cryptographic Implementation

Version: 1.0 Date: November 2025 Status: Production

1. Abstract

SeraVault is a zero-knowledge, end-to-end encrypted file storage and messaging platform designed to resist attacks from both classical and quantum computers. The system employs ML-KEM-768 (NIST FIPS 203), a lattice-based key encapsulation mechanism standardized by NIST for post-quantum cryptography, combined with AES-256-GCM for symmetric encryption.

This whitepaper provides a comprehensive technical description of SeraVault's cryptographic architecture, security model, and implementation. We detail our zero-knowledge design, key management protocols, and post-quantum cryptographic primitives.

Note: This is a living document. As cryptographic standards evolve and security research progresses, we will update our implementation and this documentation accordingly. The current version reflects the production system as of November 2025.

2. Threat Model

2.1 Adversary Capabilities

SeraVault is designed to protect against the following adversaries:

2.1.1 Server Compromise

We assume the server infrastructure can be fully compromised. An attacker gaining complete access to our servers should not be able to decrypt user files or messages. This is achieved through client-side encryption where encryption keys never reach the server in plaintext form.

2.1.2 Network Adversary

We assume an adversary can intercept, modify, or inject network traffic between clients and servers. TLS provides transport-level security, but our application-layer encryption ensures that even TLS compromise does not expose plaintext data.

2.1.3 Quantum Adversary

We anticipate future adversaries with access to cryptographically-relevant quantum computers (CRQC). Traditional public-key cryptosystems like RSA and elliptic curve cryptography are vulnerable to Shor's algorithm. SeraVault uses ML-KEM-768, which is based on the hardness of lattice problems believed to be resistant to quantum attacks.

2.1.4 State-Level Adversary

We design against state-level actors with significant computational resources, the ability to compel service providers, and "Harvest Now, Decrypt Later" capabilities where encrypted data is stored for future decryption when quantum computers become available.

2.2 Trust Assumptions

2.3 Out of Scope

The following threats are explicitly out of scope:

2.4 Browser Extensions

Browser extensions deserve their own entry rather than a line in the out-of-scope list, because they are the most realistic client-side threat most users face. An extension granted access to this application's origin (or to all sites, a permission users grant routinely) can inject scripts into the page itself. From there it can capture your passphrase as you type it, read decrypted content as it is displayed, and intercept data before encryption or after decryption.

No web application can defend against this. Content Security Policy does not bind extensions, and no code a page ships can detect or resist a script injected at the same privilege level. This is a property of the browser platform shared by every browser-delivered encryption product, not a SeraVault limitation — and any product claiming otherwise should be treated with suspicion. Hardware-backed credentials limit the damage in one narrow way: an extension cannot extract secrets from a security key or passkey authenticator. It can, however, read whatever those secrets decrypt once the page displays it.

Mitigation: a dedicated, extension-free browser profile. Browser extensions are installed per profile. Creating a separate browser profile with no extensions — and using it exclusively for SeraVault — removes the entire class of threat while keeping every unlock method available: security keys, synced passkeys, and phone-via-QR all work normally, because the profile is still a full browser. Installing SeraVault as an app from that profile gives it its own window and icon. This matters most at account creation, when your keys are generated. Auditing the extensions in an everyday profile is weaker but better than nothing; treat any extension with access to all sites as able to read anything you decrypt.

Managed deployments can enforce this at the browser level. Chromium-based browsers under enterprise management support the ExtensionSettings policy with runtime_blocked_hosts: an administrator can declare that no extension may run on or inject into app.seravault.com, enforced by the browser itself regardless of what users have installed — extensions keep working on every other site. The policy is deployed through Group Policy, Intune, or the Google Admin console (for example, "runtime_blocked_hosts": ["*://app.seravault.com"] applied to the wildcard extension ID *), and Firefox and Edge offer equivalent policy controls. For organizations, this converts the extension threat from a user-education problem into an enforced configuration.

Device-level malware (keyloggers, screen capture, OS compromise) remains out of scope for both environments: no application can protect data on a machine the attacker already controls.

3. System Architecture

3.1 Zero-Knowledge Design

SeraVault implements a true zero-knowledge architecture where the server has no access to:

All encryption and decryption operations occur client-side in the user's browser or application. The server stores only encrypted data and acts as a dumb storage and synchronization layer.

3.2 Component Overview

3.2.1 Client Application

3.2.2 Cloud Backend

3.3 Data Flow

File Upload Flow

  1. User selects file in browser
  2. Client generates random 256-bit symmetric key (File Key)
  3. Client encrypts file content with AES-256-GCM using File Key
  4. Client encrypts file metadata (name, size, type) with user's Shared Secret
  5. Client encapsulates File Key for user's public key using ML-KEM-768
  6. Client uploads encrypted blob to cloud storage
  7. Client writes encrypted metadata and encapsulated key to backend database

File Download Flow

  1. Client retrieves encrypted metadata from backend database
  2. Client decrypts metadata using user's Shared Secret
  3. Client decapsulates File Key using ML-KEM-768 with user's private key
  4. Client downloads encrypted blob from cloud storage
  5. Client decrypts file content with AES-256-GCM using File Key
  6. Client presents plaintext file to user

4. Cryptographic Primitives

4.1 ML-KEM-768 (NIST FIPS 203)

Module-Lattice-Based Key-Encapsulation Mechanism is our primary post-quantum cryptographic primitive, standardized by NIST in August 2024 as FIPS 203.

Parameters

Parameter Value
Security Level NIST Level 3 (equivalent to AES-192)
Public Key Size 1,184 bytes
Private Key Size 2,400 bytes
Ciphertext Size 1,088 bytes
Shared Secret Size 32 bytes

Why ML-KEM-768?

4.2 AES-256-GCM

Advanced Encryption Standard with 256-bit keys in Galois/Counter Mode provides authenticated encryption for file contents.

Properties

4.3 ChaCha20-Poly1305

ChaCha20-Poly1305 is a high-speed authenticated encryption algorithm used to protect sensitive key material (like your private key) at rest.

4.4 Argon2id

Argon2id for deriving encryption keys from user passphrases. Winner of the Password Hashing Competition (2015).

Why Argon2id: Argon2id is memory-hard, making GPU and ASIC attacks expensive. It combines data-independent (Argon2i) and data-dependent (Argon2d) approaches for side-channel resistance and maximum protection against parallel cracking attempts.

5. File Encryption Protocol

5.1 Key Generation

When a user first creates their account and generates their encryption keys:

// Generate ML-KEM-768 keypair (publicKey, privateKey) = ML-KEM-768.KeyGen() // Derive encryption key from passphrase salt = CSPRNG(32 bytes) encryptionKey = Argon2id(passphrase, salt, t=3, m=64MiB, p=4, 32 bytes) // Encrypt private key with passphrase-derived key nonce = CSPRNG(12 bytes) encryptedPrivateKey = ChaCha20-Poly1305.Encrypt(encryptionKey, nonce, privateKey) // Store encrypted private key in backend database // Public key stored in backend database (plaintext, it's public)

5.2 File Encryption

For each file uploaded:

// 1. Generate random file encryption key fileKey = CSPRNG(32 bytes) // 2. Encrypt file content nonce = CSPRNG(12 bytes) encryptedContent = AES-256-GCM.Encrypt(fileKey, nonce, fileContent) // Result includes 16-byte authentication tag // 3. Encapsulate file key for owner (ciphertext, sharedSecret) = ML-KEM-768.Encapsulate(ownerPublicKey) // Shared secret is used to encrypt the file key keyNonce = CSPRNG(12 bytes) encryptedFileKey = AES-256-GCM.Encrypt(sharedSecret, keyNonce, fileKey) // 4. Encrypt metadata metadata = {name, size, type, uploadDate} metadataNonce = CSPRNG(12 bytes) encryptedMetadata = AES-256-GCM.Encrypt(userSharedSecret, metadataNonce, metadata)

5.3 File Decryption

// 1. Decrypt private key using passphrase encryptionKey = Argon2id(passphrase, salt, t=3, m=64MiB, p=4, 32 bytes) privateKey = ChaCha20-Poly1305.Decrypt(encryptionKey, nonce, encryptedPrivateKey) // 2. Decapsulate to recover shared secret sharedSecret = ML-KEM-768.Decapsulate(privateKey, ciphertext) // 3. Decrypt file key fileKey = AES-256-GCM.Decrypt(sharedSecret, keyNonce, encryptedFileKey) // 4. Decrypt file content fileContent = AES-256-GCM.Decrypt(fileKey, nonce, encryptedContent) // 5. Decrypt metadata metadata = AES-256-GCM.Decrypt(userSharedSecret, metadataNonce, encryptedMetadata)

5.4 Metadata Encryption

Unlike many encrypted storage systems, SeraVault encrypts file metadata including:

This prevents the server from building a profile of user activity patterns based on file names or types.

Metadata Visibility: While content and names are encrypted, the server still knows:
  • Encrypted blob sizes (approximate file sizes)
  • Upload/modification timestamps
  • Number of files per user
  • Sharing relationships (user A shared something with user B)
This is inherent to any cloud storage system and cannot be fully eliminated without using techniques like ORAM (Oblivious RAM), which would severely impact performance.

6. Key Management

6.1 User Key Hierarchy

Each user has multiple keys serving different purposes:

Key Type Purpose Storage
ML-KEM-768 Public Key File key encapsulation (others encrypt for you) Backend database (plaintext)
ML-KEM-768 Private Key File key decapsulation Backend database (encrypted once with AES-256-GCM under the DEK)
Data Encryption Key (DEK) Encrypts the private key Never stored in the clear; one wrapped copy per unlock method in the backend database
Shared Secret Metadata encryption Derived from ML-KEM-768 key pair
Passphrase-Derived Key Encrypts the DEK Derived on-demand, never stored
WebAuthn PRF Output Encrypts the DEK Released by the authenticator after user verification; never stored

6.2 Key Storage Locations

Important: SeraVault supports multiple authentication methods simultaneously. Users can enable passphrase authentication, hardware key authentication, and biometric authentication at the same time.

These methods are layered using envelope encryption. The ML-KEM-768 private key is encrypted exactly once, with AES-256-GCM, under a randomly generated 256-bit Data Encryption Key (DEK). Each enabled authentication method then encrypts only the DEK — a 32-byte secret — rather than its own full copy of the private key:

DEK = random 256 bits

private key --AES-256-GCM under DEK--------------> encryptedPrivateKeyV4   (one copy)

DEK --ChaCha20-Poly1305 under Argon2id(passphrase)--> wrappedDeks.passphrase
DEK --AES-256-GCM under WebAuthn PRF(credential A)--> wrappedDeks[credential A]
DEK --AES-256-GCM under WebAuthn PRF(credential B)--> wrappedDeks[credential B]

This yields two properties that per-method key copies cannot provide. First, adding an authentication method costs 32 bytes of wrapped key material instead of another full copy of the private key. Second, revocation can be made cryptographically meaningful: when a credential is removed, the DEK is rotated — a new DEK is generated, the private key is re-sealed under it, and fresh wraps are issued for the remaining methods. Every previously-issued wrap then opens nothing, including copies retained outside the live database.

Rotation requires the surviving methods to be re-wrappable. A PRF wrap can only be rebuilt while its authenticator is physically present to produce the PRF output. Rotation therefore runs when the user confirms removal with their passphrase and the surviving set can be reconstructed. If other hardware credentials remain that cannot be re-wrapped at that moment, SeraVault deletes the revoked wrap but does not rotate — re-sealing would lock those authenticators out of the vault. In that case the revoked credential is removed from the live record but a retained copy of its wrap would still open the old ciphertext, so users are told the vault was not fully re-secured.

Envelope encryption protects the private key only. File content is encrypted with per-file AES-256-GCM keys that are encapsulated to the ML-KEM-768 public key; the private key merely decapsulates them. Files, folders, and existing shares are never re-encrypted when unlock methods change.

6.2.1 Passphrase Authentication

The primary authentication method where the private key is encrypted with a passphrase-derived key and stored in the backend database:

6.2.2 Hardware Key Authentication

Users can enable hardware key authentication in addition to or instead of passphrase authentication. Private keys are protected by a hardware security key (YubiKey, Titan Key) using FIDO2/WebAuthn:

Because the wrapped DEK is stored server-side rather than in browser storage, hardware key unlock works on any device the authenticator is presented to, and clearing browser data does not destroy access.

Hardware Key Trade-off: If using hardware keys without passphrase authentication, losing the hardware key means losing access to your encrypted data unless you have a backup key or exported key file. The wrapped DEK cannot be decrypted without the physical hardware key present to release its PRF output.
Superseded design: Earlier versions wrapped the private key with a key derived via Argon2id from the credential ID and user ID, storing the result in browser IndexedDB. Because both inputs are public values, such a blob was decryptable offline without the authenticator ever being present. That format is no longer created. Any remaining blob is migrated to the PRF-protected scheme above on first use and then deleted from IndexedDB.

6.2.3 Biometric Authentication

Users can enable biometric authentication (fingerprint, Face ID) for convenient access on mobile devices:

Because the wrapped DEK is stored server-side, biometric unlock survives browser storage being cleared, and a passkey that syncs between a user's devices can unlock the vault on each of them.

6.2.4 Key File Backup

Users can export their private key encrypted with a separate passphrase:

6.3 Key Rotation

SeraVault supports key rotation to maintain forward secrecy:

Key Rotation Process

  1. User generates new ML-KEM-768 keypair
  2. For each file owned by user:
    • Decrypt file key using old private key
    • Re-encapsulate file key using new public key
    • Update backend database with new encapsulated key
  3. For each shared file:
    • Notify sharing partners of key change
    • Re-encapsulate shared keys with new public key
  4. Old private key securely erased
  5. New public key published
Performance Consideration: Key rotation for users with thousands of files can be time-consuming. The operation is performed incrementally in the background.

7. Secure File Sharing

7.1 Sharing Model

SeraVault implements per-recipient key encapsulation for file sharing:

// File owner shares file with recipient // 1. Owner retrieves recipient's public key from backend database recipientPublicKey = Backend.getPublicKey(recipientUserId) // 2. Owner decrypts file key for themselves ownerSharedSecret = ML-KEM-768.Decapsulate(ownerPrivateKey, ownerCiphertext) fileKey = AES-256-GCM.Decrypt(ownerSharedSecret, keyNonce, encryptedFileKey) // 3. Owner encapsulates file key for recipient (recipientCiphertext, recipientSharedSecret) = ML-KEM-768.Encapsulate(recipientPublicKey) recipientKeyNonce = CSPRNG(12 bytes) recipientEncryptedFileKey = AES-256-GCM.Encrypt(recipientSharedSecret, recipientKeyNonce, fileKey) // 4. Store recipient's encapsulated key in backend database Backend.grantAccess(fileId, recipientUserId, recipientCiphertext, recipientEncryptedFileKey)

7.2 Sharing Properties

7.3 Permission Model

Permission Description
Owner Full control: read, modify, delete, share, revoke
View Can decrypt and view file, cannot modify or share

Currently, SeraVault implements a simple owner/view permission model. Shared users can view files but cannot modify them or share with others.

7.4 Group Sharing

For sharing with multiple users, the owner can create a "group share":

Storage Cost: Each shared file requires storing one encapsulated key per recipient (~1 KB). For large-scale sharing, this is negligible compared to the file content itself. Only the file owner's storage quota is consumed, regardless of how many people it's shared with.

8. Authentication Methods

8.1 Multi-Factor Authentication

SeraVault separates account authentication from encryption key access:

8.2 Passphrase-Based Authentication

The default authentication method:

8.3 Biometric Authentication

Uses WebAuthn with platform authenticators:

8.4 Hardware Key Authentication (YubiKey)

Uses FIDO2/CTAP2 for hardware-backed authentication:

8.5 Passkey (Platform Authenticator)

Modern passwordless authentication using WebAuthn:

9. Encrypted Messaging

9.1 Chat Architecture

SeraVault includes end-to-end encrypted messaging using the same cryptographic primitives as file encryption:

9.2 Conversation Key Exchange

// Creating a conversation // 1. Initiator generates random conversation key conversationKey = CSPRNG(32 bytes) // 2. For each participant (including initiator): (ciphertext_i, sharedSecret_i) = ML-KEM-768.Encapsulate(participant_i_PublicKey) nonce_i = CSPRNG(12 bytes) encryptedConversationKey_i = AES-256-GCM.Encrypt(sharedSecret_i, nonce_i, conversationKey) // 3. Store encrypted conversation keys in backend database // Each participant can decrypt using their private key

9.3 Message Encryption

// Sending a message // 1. Sender decrypts conversation key sharedSecret = ML-KEM-768.Decapsulate(senderPrivateKey, senderCiphertext) conversationKey = AES-256-GCM.Decrypt(sharedSecret, nonce, encryptedConversationKey) // 2. Encrypt message messageNonce = CSPRNG(12 bytes) encryptedMessage = AES-256-GCM.Encrypt(conversationKey, messageNonce, messageContent) // 3. Upload to backend database Backend.addMessage(conversationId, encryptedMessage, messageNonce, timestamp)

9.4 Chat Properties

Metadata Visibility: The server knows:
  • Who is in which conversations
  • Message timestamps
  • Approximate message lengths
This is similar to Signal's server-side metadata visibility.

9.5 Future Improvements

Potential enhancements for future versions:

10. Implementation Details

10.1 Technology Stack

Component Technology
Frontend React + TypeScript
Crypto Library Web Crypto API + ml-kem (WebAssembly)
Backend Cloud Database, Object Storage, Authentication Service, Serverless Functions
Authentication WebAuthn, FIDO2, OAuth 2.0

10.2 ML-KEM-768 Implementation

We use the ml-kem JavaScript library, which provides:

10.3 Random Number Generation

All cryptographic randomness uses crypto.getRandomValues():

function generateRandomBytes(length: number): Uint8Array { const array = new Uint8Array(length); crypto.getRandomValues(array); return array; }

10.4 Secure Memory Handling

JavaScript does not provide explicit memory control, but we follow best practices:

function secureWipe(array: Uint8Array): void { array.fill(0); }

10.5 Error Handling

Cryptographic errors are handled carefully to prevent information leakage:

11. Security Analysis

11.1 Threat Analysis

11.1.1 Server Compromise

Threat: Attacker gains full access to cloud infrastructure.

Impact: Low. Attacker obtains encrypted files, encrypted private keys, public keys, encrypted metadata.

Mitigation: Without user passphrases or hardware keys, attacker cannot decrypt. Zero-knowledge architecture limits damage to encrypted data collection.

11.1.2 Passive Network Eavesdropping

Threat: Attacker intercepts network traffic.

Impact: Low. TLS protects transport, but even TLS compromise exposes only encrypted data.

Mitigation: Application-layer encryption ensures plaintext never transmitted. Metadata encrypted.

11.1.3 Quantum Computer Attack

Threat: Future quantum computer attempts to break encryption.

Impact: Low for ML-KEM-768 protected data. Symmetric encryption (AES-256) security reduced but still strong.

Mitigation: ML-KEM-768 based on lattice problems resistant to known quantum algorithms. AES-256 provides 128-bit security against quantum attacks (Grover's algorithm), sufficient for most use cases.

11.1.4 Weak Passphrase

Threat: User chooses weak passphrase, attacker performs offline brute-force.

Impact: High if successful. Attacker decrypts private key and gains access to all files.

Mitigation:

11.1.5 Phishing

Threat: User tricked into entering passphrase on malicious site.

Impact: High. Attacker obtains passphrase and can decrypt private key.

Mitigation:

11.2 Cryptographic Strength

Primitive Classical Security Quantum Security
ML-KEM-768 192 bits 192 bits (NIST Level 3)
AES-256-GCM 256 bits 128 bits (Grover)
Argon2id (64 MiB) Depends on passphrase Depends on passphrase

11.3 Known Limitations

  1. Metadata Leakage: File sizes, timestamps, sharing relationships visible to server
  2. Forward Secrecy: Chat does not implement perfect forward secrecy (no ratcheting)
  3. Passphrase Strength: System security limited by user-chosen passphrase strength
  4. Browser Security: Relies on browser sandboxing and Web Crypto API implementation
  5. No Deniability: Encrypted messages provide authentication but not deniability
  6. Traffic Analysis: Activity patterns (uploads, downloads, logins) observable by server

11.4 Audit and Verification

SeraVault allows independent security audits:

12. References

  1. NIST FIPS 203: Module-Lattice-Based Key-Encapsulation Mechanism Standard. https://csrc.nist.gov/pubs/fips/203/final
  2. NIST Post-Quantum Cryptography: Selected Algorithms 2024. https://csrc.nist.gov/projects/post-quantum-cryptography
  3. AES-GCM: Recommendation for Block Cipher Modes of Operation: Galois/Counter Mode (GCM) and GMAC. NIST SP 800-38D.
  4. WebAuthn: Web Authentication: An API for accessing Public Key Credentials Level 2. W3C Recommendation.
  5. Argon2: Argon2: the memory-hard function for password hashing. Winner of Password Hashing Competition (2015). PHC Winner
  6. Web Crypto API: W3C Recommendation. https://www.w3.org/TR/WebCryptoAPI/
  7. Grover's Algorithm: A fast quantum mechanical algorithm for database search. L.K. Grover, 1996.
  8. Shor's Algorithm: Polynomial-Time Algorithms for Prime Factorization and Discrete Logarithms on a Quantum Computer. P.W. Shor, 1997.
  9. Learning With Errors: On lattices, learning with errors, random linear codes, and cryptography. O. Regev, 2005.