Back to About

Public document

AegisMeetings zero-knowledge encryption architecture whitepaper

This document is public for any reader: architecture, threat model, and assurance boundaries. The design is based on open cryptographic standards and can be reviewed independently — see the body below.

Version 2.3 · Published 2026-07 · Public edition — implementation details omitted

Version 2.3 · Published 2026-07-09 · Public edition (no secrets, no internal addresses, no source-code names, no custom resource names)

🌐 How to read this document

  • This paper has two parts. Overview covers the core design principles and security protections in plain language; Technical Specifications provides in-depth cryptographic architecture for independent verification.
  • Cryptographic names (AES, RSA, XChaCha20, etc.) stay in English.
  • Honest Processing Window: the only moment plaintext is touched—after audio (and any custom vocabulary decrypted for ASR accuracy) reaches a transcription host and before its temporary data is securely wiped. Data lives only in processing memory and short-lived temporary storage; it is never persisted.

Table of contents

Overview

Technical Specifications


Overview

One-sentence guarantee

Not even AegisMeetings can read your meeting audio, transcripts, AI summaries, or custom vocabulary.

This is not a promise—it is a cryptographic design. Your data is locked on your own device before it ever leaves, and the key never leaves you. Even our engineers, administrators, or an attacker who breaks into our servers would only ever get unreadable ciphertext.

The single exception is that AI transcription must briefly "listen" to your audio once. We disclose this openly and use strict isolation to minimize its exposure (see Honest Processing Window).

Who can see your data?

Role Can see Cannot see
Your browser (your own device) All plaintext (it's yours)
Our servers Locked ciphertext, basic account info, vocabulary Blob paths and counts Any plaintext of your audio, transcripts, summaries, or vocabulary
Cloud storage Encrypted files (gibberish to it) Any readable content
Transcription host (AI) The single job's audio and related vocabulary (wiped after) Your past meetings, anyone else's data

The point: even if someone steals our servers, database, and cloud storage all at once, they get only ciphertext they cannot open.

Why even we cannot decrypt it

Three sentences:

  1. The key is in your hands, not ours. When you first create your vault, the encryption key is generated inside your browser on your device and is never sent to our servers.
  2. We only keep a "locked safe." Your data is encrypted before it leaves your device; we store ciphertext — we do not hold your vault private key (the sole key to your transcripts, summaries, and other sealed outputs).
  3. Only your device can unlock it. Decryption happens entirely in your browser, unlocked by your biometrics (Face ID / fingerprint / Windows Hello) or your vault password.

Analogy: you lock your valuables in a safe and then hand it to us, keeping the key yourself. We can store and move the box, but we can never open it.

The one exception: Honest Processing Window

To turn speech into text and produce a summary, the AI must actually "listen" to the audio once—a physical reality no AI transcription service can avoid. We choose to be honest about it and minimize the risk:

  • The "transcription hosts" that run AI are a fully separate system from the public website, with separate duties and permissions.
  • Decrypted audio exists only in memory and is deleted immediately after processing—no playable plaintext file ever touches disk.
  • Custom vocabulary (general / personal / meeting buckets) is also briefly decrypted in the same window in memory as ASR hotwords—never written to disk or persisted.
  • Transcription hosts disable memory swap, reducing the chance of plaintext being written to disk.
  • Outside this brief window, everything you store at rest is unreadable even to us.

Our cloud AI provider (Microsoft Azure OpenAI), per its data-privacy policy, does not use your data to train its models.

New / lost devices

Because the key is only in your hands, we cannot "reset your password" for you. But we provide two safe paths:

  • New phone / new browser: on a device that is already signed in and authorized, open Security Settings → Authorize new device to generate short-lived pairing credentials—a 12-character pairing code, a 6-digit PIN, and a scannable QR code (scan on phone/tablet to open the authorization page with fields pre-filled). On the new device, open Security Settings → Authorize this device from another device, enter the pairing code and PIN, or scan the QR to complete binding. Throughout, the server is only a relay for an encrypted bundle—it never sees your key.
  • All devices lost: when you first create your vault, the system downloads an Aegis Recovery PDF (containing a 24-word mnemonic and your encrypted private key). Store it safely (cloud drive or USB; keep at least two off-site copies). Later, upload it to the recovery page and your private key is restored locally in your browser—the PDF contents are never sent to our servers.

⚠️ This PDF is the master key to your vault—keep it safe and never share it.


Technical Specifications

This part provides algorithm choices, key hierarchy, trust boundaries, and cloud network controls for independent verification. All diagrams are de-identified: no internal addresses, subscription identifiers, custom resource names, or code paths; network components are described by generic Microsoft Azure service names and logical roles.

1. Cryptography (algorithms & key hierarchy)

1-1. Keys never leave your device

The master private key (RSA-4096) is generated by the browser in device memory and is never transmitted to our servers. The symmetric key protecting it is derived via one of two paths:

  • WebAuthn PRF (hardware path, preferred): key-derivation material is bound to the device's secure element / TPM. Even with physical access, an attacker must pass biometrics or PIN; software-only attacks cannot bypass the hardware barrier.
  • Argon2id (password path, downgrade): used where WebAuthn PRF is unavailable. The symmetric key is derived from vault password + server-issued salt + a "device secret" stored only in that browser's IndexedDB, via Argon2id (128 MB memory cost). The password alone, without that browser's device secret, cannot recover the private key—removing the risk that stealing server ciphertext plus the user's password is enough to decrypt anywhere.

Audio key transit during the honest window (explicit to prevent ambiguity): Audio is encrypted with a per-meeting audio key (derived from the per-meeting random master secret via HKDF — see §1-3) in the browser, then uploaded directly to Blob storage via SAS token—audio bytes never transit through the Web VM. Simultaneously, the audio key is wrapped a second time with the transcription host's public key and placed alongside the Blob audio path in the Service Bus job payload (not written to the database). When the transcription host receives the job, it unwraps this package in memory using its own private key, recovers the audio key, downloads and decrypts the Blob audio, and runs speech recognition. The audio key and all audio plaintext are wiped from memory when the job ends; the transcription host retains no audio decryption capability after that point.

The implication: no audio decryption key targeting the transcription host is ever persisted in the database; the job message is consumed and gone. If a user loses their device private key, AegisMeetings is by design unable to decrypt stored audio on their behalf—this is the necessary cost of zero-knowledge, and the fundamental mechanism preventing misuse by the service operator.

1-2. Algorithm choices

Purpose Algorithm Rationale
Master key pair RSA-4096 OAEP Industry standard; native in major browsers
Static key protection AES-256-GCM Hardware-accelerated; NIST standard
Audio upload ciphertext (browser) libsodium secretstream (XChaCha20-Poly1305) Streaming AEAD, large nonce space; fits chunked large audio
Transcript ciphertext XChaCha20-Poly1305 family Same libsodium pipeline as upload
Key derivation (password path) Argon2id 2015 Password Hashing Competition winner; resists GPU/ASIC brute force
Device binding (hardware path) WebAuthn PRF W3C standard; material produced by the device secure element
Message integrity HMAC-SHA256 Ensures internal task messages are not tampered with
Per-meeting subkey separation HKDF-SHA256 Derives audio key and HLS streaming key from each meeting's random master secret with fixed info

1-3. Key hierarchy

User master key pair (RSA-4096)
│  ← generated on device; private key never uploaded
│
└── Per-meeting encrypted key material (RSA-wrapped with your public key, stored in database)
      │
      ├── Upload path: 32-byte per-meeting random master secret (high entropy)
      │     → HKDF-SHA256 (RFC 5869; fixed info to separate uses)
      │        ├── Audio key (32B) … audio secretstream encryption
      │        │     ↑ ALSO wrapped a second time with the transcription host's public key,
      │        │       sent only in the Service Bus job payload (not stored in DB);
      │        │       host unwraps in memory → decrypts audio → audio key wiped on job end;
      │        │       Web VM holds no transcription-host private key and cannot decrypt
      │        └── HLS streaming key (16B) … HLS AES-128 segments (separate from audio key, no cross-protocol reuse)
      │
      └── Transcript key ← produced by the transcription host, then RSA-wrapped into per-meeting encrypted key material

Each meeting uses independent symmetric material: a single meeting's exposure does not affect others. The keys protecting sealed transcript outputs (transcript key in per-meeting encrypted key material) are wrapped with your RSA master public key — only your private key can open them. The audio key is additionally wrapped with the transcription host's public key, transmitted via Service Bus job payload (not persisted to DB), and used for in-memory audio decryption during the honest window; the audio key is wiped when the job ends. These two wrapping paths are independent, target different key holders, and once a job completes, no transcription-host audio decryption capability survives anywhere.

1-4. Form of data at rest

Data Location Form Who can read
Audio (full file or live chunks) Cloud Blob storage Encrypted ciphertext object Devices holding your private key; or the transcription host during the honest processing window (host unwraps audio key with its own private key, decrypts in memory)
Transcript / summary / highlights / action items (sealed bundle) Blob (primary) + database (pointers) Ciphertext in Blob; DB stores only path, length, integrity hash Devices holding your private key
Vocabulary (general / personal / meeting — separate Blobs) Blob (primary) + database (pointers) Audio-key XChaCha20-Poly1305 sealed; DB stores only Blob path and phrase count — no word plaintext, ciphertext, or per-word hashes Devices holding your private key; or the transcription host during the honest processing window (decrypted into ASR hotwords in memory, purged on task completion)
Per-meeting encrypted key material Database Wrapped with your RSA public key Devices holding your private key

What the server (including database and Blob) sees at rest is always ciphertext that cannot be read without the corresponding private key, or non-reversible pointers such as paths, hashes, or counts.

1-5. Custom vocabulary (three Blob types)

To improve ASR accuracy, users may maintain three vocabulary types. All are sealed with the audio key (which is independent from the transcript key); regular servers cannot read vocabulary content at rest, but the transcription host decrypts designated vocabulary into ASR hotwords in memory during the honest processing window (see operation details below):

Type Purpose At rest
General vocabulary Cross-meeting proper nouns One sealed Blob
Personal vocabulary Terms bound to a category One sealed Blob per category
Meeting vocabulary Terms for a single meeting One sealed Blob per meeting
  • Browser: edit phrases → seal with the audio key → direct SAS upload to Blob; the web API stores only path and count.
  • Transcription host: job dispatch carries Blob pointers; during the Honest Processing Window phrases are decrypted in memory, merged as ASR hotwords (capped), then wiped when the job ends.
  • Retired: per-word RSA-encrypted database rows or per-word hashes — the current architecture stores no vocabulary form in the DB.

2. Trust boundaries

Zone Can see Cannot see
Browser (you control) Keys, decrypted plaintext — (your device)
Web server (we operate) Ciphertext, metadata (meeting time, participant accounts) Any plaintext of audio/transcripts/summaries
Cloud storage Encrypted files (gibberish to it) Any readable content
Transcription host (we operate, semi-trusted) Plaintext audio and related vocabulary during the honest window (wiped after) Historical meetings, any web-server credential

Even with full access to the web server, database, and cloud storage simultaneously, all an attacker gets is undecryptable ciphertext.

3. Multi-device & downgrade paths

3-1. Cross-device authorization (out-of-band / pairing code)

To use an existing vault on a new browser or device:

  1. On device A (unlocked and already authorized), open Security Settings → Authorize new device to generate 15-minute pairing credentials: a 12-character hexadecimal pairing code, a 6-digit PIN, and a QR code (for the new device to scan and auto-fill).
  2. On new environment B, open Security Settings → Authorize this device from another device, enter the pairing code and PIN (or scan the QR) to fetch a PIN-encrypted private-key bundle from the server (opaque to the server).
  3. The bundle is deleted from the server once binding succeeds (replay protection).
  4. B unwraps the bundle locally with the PIN and re-binds per its capabilities (WebAuthn PRF, or Argon2 + a freshly generated device secret for that browser).

Throughout, the server is only an "encrypted-bundle relay" and cannot read the in-transit private key; the vault password is never sent to the server.

Pairing strength (distinct from the vault password): the pairing code (12 hex characters) and PIN (6 digits) serve different roles—the code retrieves the bundle from the server; the PIN decrypts the private key locally. Both must be correct to complete authorization. This design does not provide vault-password-grade offline brute-force resistance. In practice, online enumeration is constrained by short validity (15 minutes), deletion after successful binding, and server-side API rate limiting and abuse detection. For long-term offline resistance, rely on the Recovery PDF or the WebAuthn PRF / vault-password paths.

3-2. Binding scope per path

  • WebAuthn PRF users: cross-device behavior depends on the authenticator. Cloud-synced passkeys work across synced environments; strongly bound authenticators (Windows Hello, Touch ID) require pairing (3-1) on a new device, or Recovery PDF restore then re-binding.
  • Argon2 password-path users: within the same browser profile, decryption needs "vault password + that browser's device secret"; on a different browser/profile/device, account credentials plus vault password alone cannot bind—pairing or Recovery PDF is required.
  • Clearing browser site data (which also clears IndexedDB): equivalent to losing the binding on that browser; re-bind via Recovery PDF or a pairing code.

4. Disaster recovery (Recovery PDF)

  • An Aegis Recovery PDF is downloaded automatically when you first create your vault; store it safely with off-site backups.
  • The PDF contains: ① a 24-word mnemonic (BIP-39 compatible, also printed for manual verification) ② a QR code ③ the full encrypted private key (encrypted with mnemonic + Argon2id, embedded in PDF metadata) ④ the vault password (kept for the password path).
  • To recover, upload the PDF to the recovery page; the browser parses and restores the private key locally, and the contents are never sent to the server.

⚠️ Recovery depends on the complete electronic PDF; a printed copy loses the encrypted private-key payload in the metadata and cannot be used for digital recovery. ⚠️ This PDF is the master credential to your vault—never share it.

5. Security assurances & known limits

What we guarantee

  • Server cannot decrypt: even with all servers compromised, an attacker only gets ciphertext.
  • Storage-leak safe: a cloud-storage breach exposes only encrypted files.
  • Minimal historical exposure: a compromised transcription host sees at most the single job in progress, not history.
  • Deploy-time secret injection: runtime secrets are pulled once at deploy time via Managed Identity from Key Vault into a permission-protected local cache; zero external secret lookups at runtime.
  • PHP runtime sandboxing: dangerous system functions disabled, filesystem access restricted; even an RCE struggles to run system commands.
  • Immutable application layer: post-deploy the code directory is root-owned and read-only to PHP—no web shell can be planted.
  • Self-hosted core assets: fonts, styles, and the application JS/CSS are self-hosted build artifacts; a few runtime-required third parties (e.g., libsodium WASM, edge analytics) are explicitly allow-listed in CSP (see §7).
  • Global API rate limiting, stricter on sensitive endpoints.
  • Full-disk VM encryption (Encryption at Host).
  • Minimal network exposure: application VMs have no directly Internet-reachable public interface; the admin channel does not rely on an Internet-open SSH port.
  • Automatic database backups; code is the source of truth for restore via Git + CI/CD.
  • Supply-chain scanning: composer audit + npm audit before each deploy abort on high severity; Dependabot continuously monitors.
  • Pinned dependency versions: production uses exact lock-file versions only.

Known limits (disclosed honestly)

  • ⚠️ Compromised user device: an attacker controlling your browser can read the private key in memory; no client-side encryption system can protect against this.
  • ⚠️ AI processing window: during transcription, plaintext briefly exists in transcription-host memory (see Honest Processing Window).
  • ⚠️ No forward secrecy on a static master key: if your master private key leaks, historical meetings can in theory be decrypted. This is inherent to a static-master-key model; future versions plan per-meeting ephemeral keys.
  • ⚠️ Operational metadata is plaintext: meeting time, duration, participant accounts, processing status, etc. are plaintext for system operation; users may optionally store meeting display titles in client-encrypted form (the server still cannot read them).
  • ⚠️ Limited pairing-code and PIN entropy: see §3-1; designed for short-lived OOB authorization, not vault-password-grade offline resistance.

6. Cloud & network defense

This chapter shows how operations complements cryptographic zero-knowledge, described as "who is public, who is not, who can reach whom"—without revealing internal addresses, subscription identifiers, or custom resource names. The overview diagram below summarizes the same chapter (see subsections for tables and detail).

6-1. Three-layer ingress

An attacker cannot bypass Cloudflare to reach the web VM directly—the web VM has no public interface. Hitting the load balancer from a source outside the Cloudflare allow-list is explicitly denied at the web-subnet NSG.

6-2. Web-subnet NSG inbound (logical)

Priority Rule (logical) Source Dest port Action
High LB health probe Azure Load Balancer 80 Allow
Mid Cloudflare origin allow-list Cloudflare public ranges 80, 443 Allow
Low Deny other Internet Internet 80, 443 Deny
Default In-VNet Same virtual network * Allow

Domains must stay Cloudflare-proxied (orange cloud); switching to DNS-only (grey cloud) makes origin traffic lose the Cloudflare signature and be denied—by design.

6-3. Data plane, identities, and internal paths

  • Key Vault / Blob / database / Azure OpenAI: public endpoints are off or unreachable from workers; web VM and transcription hosts use Private Link + Managed Identity for the data plane; a leaked connection string still cannot reach services from the open Internet.
  • Split identities: web and transcription-host managed identities differ; transcription-only secrets (private key, queue-integrity key) are readable only by the transcription identity—the web app cannot decrypt on its behalf.
  • Internal webhooks: travel over in-VNet HTTPS, never the user-visible public hostname.
  • Service Bus: jobs are published with HMAC-SHA256; transcription hosts verify before processing—mismatches are rejected to the dead-letter queue. Queues are tiered (VIP / priority / default).

6-4. Transcription VMSS bidirectional isolation

The transcription cluster uses a different NSG from the web VM, has no public IP (NSG attached to VMSS NICs), and is designed so the Internet cannot reach it directly and everything not on the egress allow-list is denied:

Direction Class Destination (logical) Purpose
Inbound Ops (optional) Same virtual network Limited in-VNet channels only (e.g. SSH); no Internet sources allowed
Egress Platform Azure metadata & DNS Managed identity, name resolution (including privatelink zones)
Egress Data plane Private Endpoint subnet Blob, Key Vault, Redis, Azure OpenAI (443)
Egress Job queue Service Bus service tag Pull/complete jobs (Standard tier; no Private Link yet)
Egress Observability Azure Monitor service tag Application Insights and similar telemetry
Egress Capacity Azure Resource Manager VMSS scaling
Egress Report-back Web VM subnet (in-VNet) Internal HTTPS webhooks only
Egress Default Everything else DenyAllOutbound

Even under RCE, a transcription host can hardly exfiltrate to an arbitrary public C2 (only the allow-listed Azure destinations above and the internal webhook are reachable). At boot: swap is off, secrets are injected from Key Vault, and ASR models are baked into the image and loaded into memory.

6-5. Relationship to the cryptography chapters (keep distinct)

If… Network layer (this chapter) Cryptography layer (§1–§4)
Intruder gets a DB + Blob snapshot May obtain ciphertext and metadata Cannot read content without the private key
Bypass Cloudflare to hit the LB NSG denies non-CF sources
Transcription host compromised Affects only the single current job Historical ciphertext stays RSA-protected
XSS runs in the browser May read keys in already-unlocked device memory (see §5 limits)

The network layer provides defense in depth and attack-surface minimization; content confidentiality still rests primarily on client-side keys and the zero-knowledge pipeline. Neither substitutes for the other.

7. Transport, CSP & runtime

7-1. Content Security Policy (highlights)

Directive Setting (summary) Notes
script-src 'self' + a few explicit sources Supports libsodium WASM (audio encrypted in browser memory); wasm-unsafe-eval is a known trade-off
connect-src 'self' + Blob storage origin Browsers do not call Azure OpenAI directly; LLM calls originate from transcription-host egress
form-action 'self' + Paddle Checkout domains Payment forms can only post to Paddle (Merchant of Record)
frame-ancestors none Anti-clickjacking
object-src / base-uri none / 'self' Disable legacy plugins; block base-tag injection

Plus X-Content-Type-Options: nosniff, Referrer-Policy, Permissions-Policy, Strict-Transport-Security (HSTS 1 year), upgrade-insecure-requests.

Even if XSS occurs, an attacker still cannot read your vault private key or meeting plaintext from the server—those do not exist there in plaintext.

7-2. Secret management (deploy-time injection)

Runtime secrets are pulled once at deploy time via Managed Identity from Key Vault into a permission-protected local cache (read-only to PHP-FPM); zero Key Vault network calls at runtime. Production does not rely on a plaintext .env.

7-3. Stealing a session yields no keys

Attacker obtains Can do Cannot do
Session token Impersonate a logged-in session Obtain the private key (only in browser memory)
DB ciphertext / wrapped keys Decrypt/unwrap; needs the user's private key

Session + database + cloud storage all together = still no plaintext.

7-4. Abuse controls & payments

  • Rate limiting: global API limits; stricter on vault creation, SAS authorization, pairing.
  • Upload/transcription abuse gates: caps on meeting-creation rate and concurrent unfinished transcriptions; repeated failures past a threshold pause uploads (records hold only risk-control metrics, not meeting content).
  • Meeting processing locks: Redis-coordinated to prevent duplicate dispatch or webhook races.
  • Payments (Paddle): subscriptions, renewals, and refunds are handled by Paddle (Merchant of Record); pages may be unavailable until payment integration is live—the target architecture is unchanged.

7-5. Session lifecycle

Configurable idle logout (1 hour / 8 hours / 1 day / 7 days; default 7 days); on expiry the browser auto-clears the local key cache. Session payloads are server-side encrypted before reaching Redis; cookies enforce secure, httponly, samesite=Lax.

8. Data flow & processing environments

Stage Environment Data form & retention
Key generation & unlock User browser (device memory) Private key and plaintext only on device; not uploaded
Audio upload Browser → Blob (SAS direct) Ciphertext throughout; web VM never touches plaintext
Live recording Browser → Web PubSub → Blob Encrypted chunks; after stop, user device supplies keys for live-finalize / ASR dispatch / play-asset repair; server never supplies keys
Vocabulary edit Browser → Blob (SAS direct) Audio-key sealed; DB holds only path and count
Job dispatch Service Bus Task description + Blob audio path + audio key sealed with transcription-host public key (not stored in DB) + integrity tag; no plaintext
Transcription & AI Transcription VMSS (RAM workspace) Honest window: audio and vocabulary plaintext only in memory and short temp; deleted after
Persist Blob (primary) + database (pointers) Transcript bundle is ciphertext; DB holds only path/hash
Transcript read / edit User browser Download sealed bundle from Blob → decrypt / edit / re-upload locally; server never decrypts bundle content
Progress report Internal webhook → web VM Pointers and integrity fields only
Billing Paddle (external MoR) Separate from meeting ciphertext
Web API Web VM Ciphertext, metadata, locks/counters; no user private keys or plaintext

Rule: at rest is always ciphertext; the only brief plaintext window is on the transcription VMSS during the honest window—memory-first, swap off, wiped when the job ends.

9. Glossary

Term Meaning
Zero-knowledge encryption An architecture where, by design, the provider cannot read user data at rest
End-to-end encryption (E2EE) Only sender and receiver can read. AegisMeetings is not E2EE: AI transcription must briefly process plaintext on a host (honest window)
Honest Processing Window The only plaintext period—after audio enters the transcription environment and before wipe—where data flows only in memory
RSA-4096 / AES-256-GCM Industry-standard asymmetric / symmetric algorithms
XChaCha20-Poly1305 Modern AEAD; audio upload uses libsodium secretstream framing
Argon2id 2015 Password Hashing Competition winner; for secure key derivation from passwords
WebAuthn PRF W3C standard; key material from the device secure element, underivable without physical verification
Device secret A random secret stored only in the browser's IndexedDB, used in the password-path derivation; the server never holds it
HMAC-SHA256 / HKDF-SHA256 Message-integrity verification / key-derivation function
SAS token A time- and scope-limited cloud-storage credential for direct browser upload of audio and vocabulary Blobs; expires automatically
Vocabulary Blob (general / personal / meeting) An audio-key-sealed bucket of custom terms; the DB stores no vocabulary content, only path and count
Sealed bundle Transcript / summary outputs sealed with XChaCha20-Poly1305 in Blob; reading and editing happen locally in the browser
Managed Identity Azure password-less machine identity for secure service-to-service access
Private Endpoint / Private Link Brings cloud resources onto the private network, closing public endpoints
NSG (Network Security Group) Inbound/outbound firewall rules on a subnet or on VM/VMSS network interfaces
Egress filtering Restricts outbound destinations to block exfiltration
Forward secrecy The property that past communications stay protected even if a long-term key leaks

10. Contact

If you find a potential security issue, please contact us privately first, giving us the chance to fix it before public disclosure:

[email protected]

We commit to responding, verifying, and remediating promptly. Until a fix ships, please keep vulnerability details confidential so we can protect every user's data together.