← Patterns / SP-039

Client-Side Encryption and Data Privacy

Client-Side Encryption inverts the traditional trust model for web applications. Instead of trusting the server to protect data at rest -- and accepting the risk that a breach, rogue insider, or lawful compulsion exposes everything -- the client encrypts data before it leaves the browser. The server stores ciphertext it cannot read. The user holds the only key. The core architecture is straightforward. On first use, the client generates a symmetric encryption key using the Web Crypto API (AES-256-GCM is the standard choice: authenticated encryption providing both confidentiality and integrity). The key is exported as a JWK (JSON Web Key) and stored in the browser's localStorage. All sensitive data is encrypted with this key before any network request. The server receives, stores, and returns opaque ciphertext. The client decrypts on retrieval. The encrypted payload follows a versioned format -- for example `enc:v1:{base64-iv}:{base64-ciphertext}` -- enabling the server to detect encrypted vs. legacy plaintext data without being able to read either. Each encryption operation generates a fresh 96-bit IV (Initialisation Vector) from the browser's cryptographic random number generator, ensuring that identical plaintext produces different ciphertext every time. The critical architectural decision is what to encrypt and what to leave in plaintext. Not all data should be encrypted. Data needed for server-side operations -- aggregate statistics, search indexes, access control decisions, billing metrics -- must remain readable by the server. The pattern establishes a clean separation: private data (individual scores, notes, personal assessments) is encrypted; aggregate data (anonymous benchmark contributions, usage counts) is transmitted as plaintext in separate API calls under explicit user consent. This dual-path architecture gives users genuine privacy without sacrificing the application's ability to provide value from aggregated data. Key management is the hardest problem. The user's encryption key exists only in their browser's localStorage. Clearing browser data, switching devices, or losing the device means losing the key -- and with it, access to all encrypted data. This is a feature, not a bug: it means the service operator genuinely cannot recover user data, which is the entire point. But it demands that the application provides key export (download the JWK as a file) and key import (restore from backup file) prominently in the UI. Users must understand that key loss equals data loss, and the application must make backup easy and obvious. For applications requiring multi-device access, the pattern extends to key wrapping: the user's data key is encrypted (wrapped) with a key derived from their passphrase using PBKDF2 or Argon2, and the wrapped key is stored on the server. The user enters their passphrase on each device to unwrap the data key. This adds a shared secret (the passphrase) but keeps the data key itself off the server in plaintext. GDPR Article 25 mandates 'data protection by design and by default'. Client-side encryption is the strongest possible implementation of this principle: the data controller literally cannot access the personal data, making most breach notification scenarios moot for the encrypted content. However, organisations must still document what metadata they can observe (IP addresses, timestamps, payload sizes, access patterns) and apply minimisation principles to that metadata too.
Release: 26.02 Authors: Spinoza, Vitruvius Updated: 2026-02-07
Assess
ATT&CK This pattern addresses 455 techniques across 13 tactics View on ATT&CK Matrix →
DATA PRIVACY GOVERNANCE SC-12 SC-13 SC-28 | PT-04 SA-08 | SI-07 AC-04 PM-25 CLIENT TIER · BROWSER TRUST BOUNDARY Web Crypto API crypto.subtle.generateKey() crypto.subtle.encrypt() crypto.subtle.decrypt() SC-13 Key Store localStorage (osa_crypto_key) AES-256-GCM · JWK format Generated once, never transmitted SC-12 SC-07 Encryption Engine { scores, notes } AES-256-GCM + fresh 96-bit IV enc:v1:{base64-iv}:{base64-ciphertext} Authenticated encryption: confidentiality + integrity + authenticity in one operation SC-13 SC-23 SI-07 Key never leaves this boundary XSS is the primary threat vector (CSP + SRI essential) SERVER TIER · ZERO-KNOWLEDGE STORAGE API Layer PUT: accepts encrypted_scores GET: returns ciphertext as-is No parsing, no validation of content AC-03 SC-08 D1 Database scores: enc:v1:Rk9P...xQ== Cannot decrypt · Opaque blob overall_score: 3.2 (plaintext) SC-28 AU-02 Breach Impact: Neutralised Database compromise yields only ciphertext · No key on server · No plaintext to steal Rogue insiders, lawful compulsion, cloud provider access: all see only encrypted blobs AC-04 IR-04 The server is treated as an untrusted relay by design enc:v1:... TLS 1.3 KEY LIFECYCLE · BACKUP & RECOVERY Generate AES-256-GCM key First use, automatic Export Backup Download JWK file osa-encryption-key.json Import / Restore Upload JWK, validates kty:oct + alg:A256GCM SC-12 CP-09 AT-02 Key loss = data loss (by design). Backup is the user's responsibility. AGGREGATE PATH · PLAINTEXT WITH CONSENT User Chooses to Share Numeric scores only (1-5 per area) No notes · No identity · No org name Explicit consent required (PT-04) Anonymous Benchmark Pool Industry & vertical averages Aggregated, anonymised "How do we compare?" for CISOs PT-04 PT-03 PM-25 AC-21 VS Two paths enforced SP-039: Client-Side Encryption and Data Privacy 28 NIST 800-53 Rev 5 controls · AES-256-GCM · Web Crypto API · Authors: Spinoza, Vitruvius · Draft · 2026-02-07 Encrypted data flow Key lifecycle Plaintext aggregate path Trust boundary XX-00 NIST control (click to view) Threat neutralised Aligned with: W3C Web Crypto API · NIST SP 800-38D (GCM) · GDPR Article 25 · Signal Protocol (trust model) · OSA Implementation Guide opensecurityarchitecture.org

Click any control badge to view its details. Download SVG

Key Control Areas

  • Cryptographic Key Lifecycle (SC-12, SC-12(1), SC-13, SC-17): The entire security of client-side encryption rests on the key lifecycle. SC-12 governs key generation: keys must be generated using the Web Crypto API's `generateKey()` with approved algorithms (AES-256-GCM) and the browser's cryptographically secure random number generator -- never from Math.random() or user-derived values without proper key derivation. Key storage in localStorage is acceptable for single-device scenarios but must be documented as a risk: any JavaScript running in the same origin can read localStorage, making XSS the primary threat vector. SC-12(1) addresses key availability: the application must provide key export (JWK download) and key import (JWK upload with validation) to prevent data loss when browsers are cleared or devices are replaced. The export format must include algorithm metadata (`kty: oct`, `alg: A256GCM`) enabling validation on import. SC-13 mandates approved cryptographic algorithms: AES-256-GCM provides authenticated encryption (confidentiality + integrity + authenticity) in a single operation, which is critical because unauthenticated encryption (AES-CBC without HMAC) allows ciphertext manipulation. The 96-bit IV must be generated fresh for every encryption operation using `crypto.getRandomValues()`. SC-17 applies when key wrapping is used for multi-device access: the wrapped key stored server-side should use a key derived from the user's passphrase via an approved KDF (PBKDF2 with >=600,000 iterations or Argon2id), and the wrapping scheme should use AES-KW or AES-GCM.
  • Data Flow Separation and Access Enforcement (AC-03, AC-04, AC-21, SC-08, SC-28): The dual-path architecture requires rigorous enforcement of which data flows are encrypted and which are plaintext. AC-03 enforces access rules at the API layer: endpoints that accept encrypted data must store the ciphertext verbatim without parsing; endpoints that accept aggregate plaintext must validate that no personally identifiable information is included. AC-04 controls information flow between the two paths: the client is the enforcement boundary, and the application must never allow encrypted private data to flow into the plaintext aggregate path (or vice versa) without explicit user action. AC-21 governs information sharing decisions: when users choose to contribute data to an aggregate pool (e.g., anonymous benchmarks), the application must clearly explain what is shared, obtain explicit consent, and transmit only the minimum required data in plaintext -- never the encrypted payload. SC-08 protects both paths in transit with TLS, though for the encrypted path, TLS is defence-in-depth since the payload is already encrypted. SC-28 addresses protection at rest: the server stores ciphertext that it cannot decrypt, which is the strongest form of rest protection. However, the server must still protect the ciphertext from deletion, corruption, and unauthorised modification -- integrity even without confidentiality access. Database backups inherit the same protection: they contain ciphertext that is useless without the client-side key.
  • Privacy Engineering and Data Minimisation (PT-02, PT-03, PT-04, PM-25, SA-08): Client-side encryption is a privacy engineering pattern that must be situated within the organisation's broader privacy programme. PT-02 establishes the authority to process PII: with client-side encryption, the server processes encrypted PII that it cannot read, but it still processes metadata (timestamps, IP addresses, payload sizes, access frequency) that may constitute personal data under GDPR. PT-03 defines processing purposes: encrypted assessment data is processed solely for user self-service; plaintext benchmark data is processed for anonymous aggregation. These purposes must be documented and enforced. PT-04 governs consent: users must provide informed consent before any plaintext data leaves the client, with clear explanation of what the server can and cannot see. The privacy notice must distinguish between encrypted data (server stores but cannot read) and metadata (server can observe). PM-25 mandates PII minimisation: the aggregate data path must strip all identifying information before transmission -- only numeric scores, never names, notes, or organisational identifiers. SA-08 applies privacy by design principles: client-side encryption should be the default for all sensitive data (not opt-in), the key should be generated transparently, and the encryption should be invisible to the user experience while being documented for transparency.
  • Legacy Migration and Version Management (CM-03, CM-06, SA-10, SI-07): Introducing client-side encryption to an existing application with plaintext data requires careful migration. CM-03 governs change control: the migration from plaintext to encrypted storage is a high-impact change that must preserve backward compatibility. The versioned ciphertext format (`enc:v1:` prefix) enables the application to distinguish encrypted from legacy plaintext data and handle both correctly -- old data works as before and gets encrypted on next save. CM-06 defines configuration for the encryption scheme: algorithm (AES-256-GCM), IV length (96 bits), key size (256 bits), encoding (base64), and format version. These must be consistent across all clients and documented for interoperability. SA-10 requires configuration management of the client-side cryptographic code: the encryption/decryption module must be versioned, tested, and reviewed with the same rigour as server-side security code, despite running in the browser. SI-07 verifies the integrity of the cryptographic code delivered to the browser: if an attacker can modify the JavaScript (via compromised CDN, XSS, or supply chain attack), they can exfiltrate keys or bypass encryption entirely. Subresource Integrity (SRI) hashes, Content Security Policy (CSP), and minimising third-party script dependencies are essential mitigations.
  • Audit, Compliance, and Incident Response (AU-02, AU-03, AU-06, IR-04, IR-06): Client-side encryption creates a unique audit and compliance posture. AU-02 defines auditable events: key generation (timestamp, algorithm, browser fingerprint), encryption operations (count, not content), key export events, key import events, decryption failures (potential indicator of key mismatch or data corruption), and plaintext data sharing events (benchmark contributions). Note that the server cannot log the content of encrypted data by design. AU-03 specifies record content: audit records must include the operation type, timestamp, data version (enc:v1), payload size, and user identifier -- but never the plaintext content or the encryption key. AU-06 analyses encryption-specific anomalies: repeated decryption failures may indicate key corruption or a tampered ciphertext; a sudden switch from encrypted to plaintext payloads may indicate a bypassed client; unusually large payloads may indicate data exfiltration attempts. IR-04 addresses incident response: a server breach is significantly less impactful because the attacker obtains only ciphertext, but the incident response plan must still address metadata exposure, potential ciphertext manipulation, and the possibility that the attacker modified the JavaScript to capture future keys. IR-06 requires disclosure: even though encrypted data is unreadable, regulators may still require breach notification for the metadata exposure, depending on jurisdiction.
  • Browser Security and Client Integrity (SC-07, SI-07, SC-23, AT-02): The browser is the trust boundary, and its integrity determines the encryption's effectiveness. SC-07 defines the boundary: the application's origin (scheme + host + port) is the security perimeter within which the encryption key is accessible. Any JavaScript executing within this origin -- including injected scripts from XSS, compromised dependencies, or browser extensions -- can access localStorage and therefore the encryption key. SI-07 protects the integrity of the cryptographic code: Content Security Policy headers must restrict script sources to the application's own origin and trusted CDNs with SRI hashes; inline scripts must be eliminated or nonced; eval() must be forbidden. Third-party analytics, advertising, and chat widgets are particularly dangerous because they execute arbitrary code within the application's origin. SC-23 ensures session authenticity: the encryption key is scoped to the browser session via localStorage, and the application must never transmit the key to the server (not in headers, not in request bodies, not in error reports). AT-02 covers user awareness: users must understand that their encryption key is stored locally, that clearing browser data deletes it, that export is their responsibility, and that the service cannot recover their data. This is a fundamental shift from the 'forgot password' mental model and must be communicated clearly and repeatedly.

When to Use

This pattern is indicated for any application that handles sensitive user data where the service operator should not -- or does not need to -- read the data. Specific indicators include: applications storing personal health information (patient journals, symptom trackers), financial data (personal budgets, portfolio analysis), security assessments (maturity scores, vulnerability data), personal notes and diaries, survey responses containing opinions or whistleblower reports, legal case notes, and any application where a data breach should not expose user content. It is particularly valuable for small teams and startups that cannot afford dedicated security operations: by making the data unreadable on the server, you eliminate the most damaging breach scenario even if your server security is imperfect. The pattern is also indicated when regulatory compliance (GDPR Article 25, HIPAA, DORA) requires demonstrable data protection by design, and when users or their organisations (CISOs, DPOs) require assurance that the service cannot access their data.

When NOT to Use

Applications requiring server-side search, sorting, or filtering of encrypted data cannot use this pattern without additional cryptographic techniques (searchable encryption, order-preserving encryption) that significantly increase complexity and may weaken the security model. Real-time collaborative applications where multiple users need simultaneous access to the same encrypted data require a shared key distribution mechanism (e.g., group key management, key escrow via a trusted server component) that partially undermines the 'server cannot read data' guarantee. Applications where the service must perform computations on user data (recommendation engines, ML model training on user content, server-generated reports) need the data in plaintext on the server and should use traditional server-side encryption at rest instead. Applications targeting users who cannot manage a key file (elderly users, children, users with cognitive disabilities) may find the key loss risk unacceptable -- though passphrase-based key wrapping can mitigate this. If the threat model includes a compromised browser or malicious browser extensions, client-side encryption provides no protection because the attacker has access to the key and plaintext before encryption.

Typical Challenges

The dominant challenge is key management UX. Users accustomed to 'forgot password' flows do not expect that losing their browser data means permanent data loss. The application must make key backup prominent, explain it clearly, and accept that some users will still lose their keys. Multi-device access is the second challenge: without key wrapping via a passphrase (which adds complexity and a shared secret), users must manually export and import their key file on each device. This is acceptable for low-frequency-of-change applications (assessments, configurations) but impractical for real-time collaborative tools. Server-side operations on encrypted data are impossible: you cannot search, sort, filter, or compute aggregates on ciphertext without additional cryptographic techniques (searchable encryption, homomorphic encryption) that add significant complexity and performance overhead. The current pattern uses the clean separation approach instead: anything the server needs to compute on is kept in plaintext (with user consent) or computed client-side. XSS remains the critical vulnerability: because the encryption key is in localStorage accessible to any script in the origin, a single XSS vulnerability defeats the entire encryption scheme. This makes CSP, SRI, and minimal third-party dependencies essential -- not optional. Performance is generally not a concern: AES-256-GCM via Web Crypto API processes megabytes per second even on mobile devices; the encryption/decryption overhead is invisible compared to network latency.

Threat Resistance

Client-Side Encryption provides strong protection against the most common and damaging data breach scenarios. Server-side data breach is neutralised for encrypted content: attackers who compromise the database, backups, or server infrastructure obtain only ciphertext that is computationally infeasible to decrypt without the user's key (SC-12, SC-13, SC-28). Rogue insider access is eliminated: database administrators, support engineers, and system operators cannot read encrypted user data even with full database access (AC-03, AC-04). Lawful interception and compelled disclosure is limited: the service operator genuinely cannot produce plaintext in response to a subpoena or government request for encrypted data -- they can only produce the ciphertext (note: this may create legal complications in some jurisdictions). Man-in-the-middle attacks on the encrypted payload are defeated: even if TLS were compromised, the AES-GCM authenticated ciphertext cannot be read or tampered with without the key (SC-08, SC-13). Cloud provider access is prevented: the hosting provider (Cloudflare, AWS, Azure) stores only ciphertext and cannot access user content (SC-28). The primary residual risks are: XSS attacks that exfiltrate the key from localStorage (mitigated by CSP and SRI per SI-07); compromised JavaScript delivery that replaces the encryption code (mitigated by SRI and supply chain security per SA-10); and metadata exposure (timestamps, payload sizes, access patterns) that may reveal information about the user even without decrypting the content (mitigated by minimisation per PM-25).

Assumptions

The target application runs in modern browsers that support the Web Crypto API (all major browsers since 2015: Chrome 37+, Firefox 34+, Safari 11+, Edge 12+). The data being encrypted is structured (JSON, form data) and can be serialised to a string before encryption. The server can store and return opaque string values without parsing them. Users have a single primary device or are willing to manually transfer their encryption key to additional devices. The application does not require server-side search or computation on encrypted data (if it does, techniques like homomorphic encryption or secure enclaves are needed -- see Contra-indications). The application's origin is protected by HTTPS and a strong Content Security Policy.

Developing Areas

  • Key management UX for non-technical users remains the fundamental barrier to client-side encryption adoption. Despite decades of research into usable security, no approach has reconciled the tension between user convenience and cryptographic key responsibility. Key wrapping via passphrases introduces shared secret risk; platform-managed key sync (iCloud Keychain model) shifts trust to the platform vendor; and manual key export requires user discipline that studies consistently show fewer than 20% of users maintain.
  • Regulatory acceptance of client-side encryption varies dramatically across jurisdictions and is becoming more contentious. The tension between lawful access requirements (government demand to access encrypted data) and privacy engineering (building systems where the operator cannot access data) is unresolved. The EU, UK, and Australia have each proposed or enacted legislation that could mandate backdoor access, while GDPR Article 25 simultaneously encourages encryption as data protection by design. Organisations deploying CSE must monitor this evolving legal landscape and prepare for scenarios where their architecture conflicts with future legislation.
  • Key recovery mechanisms that preserve security guarantees while preventing permanent data loss are an active research area with no production-ready solutions. Social recovery (Shamir secret sharing among trusted contacts), threshold key management, and hardware-backed escrow each solve part of the problem but introduce new trust assumptions. The cryptocurrency wallet recovery ecosystem has explored these approaches extensively, but translating that experience to enterprise data encryption contexts -- where regulatory compliance and audit requirements add constraints -- remains an open challenge.
  • Web Crypto API maturity has reached a stable baseline for symmetric encryption (AES-GCM) but gaps remain for advanced use cases. Key agreement protocols, post-quantum algorithms, and streaming encryption are either unsupported or inconsistently implemented across browsers. The lack of a standard secure storage mechanism (beyond localStorage, which is vulnerable to XSS) means that IndexedDB, service workers, and the upcoming File System Access API are being pressed into service as key stores without established security guarantees.
  • Client-side encryption for collaborative applications -- where multiple users need concurrent access to shared encrypted data -- is a developing frontier. End-to-end encrypted collaboration (as in Matrix/Element, Tresorit, or Proton Drive) requires group key management, key rotation on membership changes, and conflict resolution for concurrent edits, all without server-side access to plaintext. Current approaches work for messaging and file storage but have not scaled to real-time collaborative editing with acceptable latency and complexity.
AC: 3AT: 1AU: 3CM: 2CP: 1IA: 1IR: 2PM: 1PT: 3SA: 2SC: 6SI: 1SR: 1
AC-03 Access Enforcement
AC-04 Information Flow Enforcement
AC-21 Information Sharing
AT-02 Literacy Training and Awareness
AU-02 Event Logging
AU-03 Content of Audit Records
AU-06 Audit Record Review, Analysis, and Reporting
CM-03 Configuration Change Control
CM-06 Configuration Settings
CP-09 System Backup
IA-05 Authenticator Management
IR-04 Incident Handling
IR-06 Incident Reporting
PM-25 Minimization of Personally Identifiable Information Used in Testing, Training, and Research
PT-02 Authority to Process Personally Identifiable Information
PT-03 Personally Identifiable Information Processing Purposes
PT-04 Consent
SA-08 Security and Privacy Engineering Principles
SA-10 Developer Configuration Management
SC-07 Boundary Protection
SC-08 Transmission Confidentiality and Integrity
SC-12 Cryptographic Key Establishment and Management
SC-13 Cryptographic Protection
SC-17 Public Key Infrastructure Certificates
SC-23 Session Authenticity
SC-28 Protection of Information at Rest
SI-07 Software, Firmware, and Information Integrity
SR-03 Supply Chain Controls and Processes