Browser Encryption: How It Really Works
By Simon Themiot - freelance cybersecurity consultant. Published May 19, 2026.
Summary
- The Web Crypto API is a native interface in modern browsers that allows encrypting data directly client-side, without any extension or plugin.
- When E2E is enabled in PrivCloud, the file is encrypted with AES-256-GCM in independently authenticated 1 MB records. Transport chunks are sized separately for the network and object storage.
- The server then receives neither plaintext content nor its key. It still retains metadata required for the service and delivers the client code, which remains part of the trust model.
Table of contents
1. The Web Crypto API in 2 minutes
The Web Crypto API (accessible via window.crypto.subtle) is a W3C standard natively implemented in Chrome, Firefox, Safari and Edge since 2017. It exposes low-level cryptographic primitives directly in the browser:
- Key generation:
generateKey()creates AES, RSA, and EC keys through the browser's native cryptographic implementation. - Encryption/decryption:
encrypt()/decrypt()with AES-GCM, AES-CBC, RSA-OAEP. - Key derivation:
deriveKey()with PBKDF2, HKDF to transform a password into a cryptographic key. - Hashing:
digest()with SHA-256, SHA-384, SHA-512. - Cryptographic randomness:
getRandomValues()to generate unpredictable IVs, nonces and salts.
The primitives run in the browser's native cryptographic implementation. A key created with extractable: false cannot be exported as raw bytes, although authorised JavaScript can still ask the browser to use it. For link sharing, PrivCloud intentionally creates an exportable key so it can be encoded in the URL fragment: security therefore also depends on the integrity of the served JavaScript and the client device.
2. The complete workflow: from clear file to encrypted file
Here are the exact steps that occur when you upload a file to an E2E service like PrivCloud:
- Master key generation: The browser calls
crypto.subtle.generateKey()to create a random AES-256 key. This key is generated locally and exported only to build the sharing fragment. - File reading: A
Web Workerreads the file withBlob.slice(). Transport chunks range from 6 to 35 MB without an account and up to 50 MB for authenticated profiles, based on measured bandwidth. The browser only bounds its memory/CPU use; the server then allocates a fair network window recalculated from available resources. - Record encryption: Within each transport chunk, the worker encrypts 1 MB records with
crypto.subtle.encrypt(). A unique 12-byte IV is generated for every record viagetRandomValues(). - Integrated authentication: AES-GCM produces a 128-bit authentication tag for each block. Any modification (even a single bit) will be detected during decryption. No separate HMAC needed.
- Encrypted chunk upload: Chunks containing encrypted records (data + IV + tag) are sent over HTTPS. A lightweight request preinitializes the multipart session so data parts can start together. The backend forwards them to storage without being able to decrypt them.
- Link construction: The master key is encoded in Base64url and placed in the URL fragment (
#). This fragment is never transmitted to the server by the browser (RFC 3986 specification).
3. Where does the key go? The URL fragment
This is the key point (no pun intended) of the E2E architecture in the browser. The sharing URL has this structure:
https://share.privcloud.fr/s/abc123#key=clé-de-déchiffrement-en-base64url
The part after the # is the "fragment identifier". According to RFC 3986 and the behavior of all browsers, this part:
- Is never sent to the server in the HTTP request
- Does not appear in server logs
- Is not transmitted in the Referer header to third-party sites
- Is processed exclusively by JavaScript client-side
Concretely: when the recipient opens the link, their browser makes a GET request to /s/abc123 (without the fragment). The server returns the HTML page + encrypted file. The page's JavaScript reads the fragment, decodes the key, and decrypts the file locally. At no point does the server have access to the key.
The optional PrivCloud password is an additional access-control barrier: the server verifies it against an Argon2 hash before issuing a download token. It does not encrypt the E2E key, which remains in the fragment. It therefore helps when only the link leaks, but does not replace E2E encryption or a separate delivery channel.
4. Limits and guarantees
Browser-side encryption is not magic. Here is what it guarantees and what it does not:
What is guaranteed
- Server-side storage alone cannot reveal content without the E2E key
- An attacker intercepting HTTPS traffic only sees already-encrypted data
- Integrity is verified: any alteration is detected (GCM tag)
- Source code is auditable (open source on GitHub)
What is not guaranteed
- If your machine is compromised (keylogger, malware), the attacker can capture the key in memory
- If the service provider modifies the JavaScript to exfiltrate the key (hence the importance of open source and audits)
- If you share the full link (with fragment) on an unsecured channel, the unintended recipient can decrypt
- Metadata (file name, size, upload date) may remain visible server-side depending on implementation
5. FAQ
Is browser encryption as secure as a native application?
In terms of cryptographic primitives, yes: the Web Crypto API uses the same algorithms (AES-256-GCM) as native applications. The difference is the trust model: with a native app, you trust the installed binary. With the web, you trust the JavaScript served on each visit. This is why open source and build reproducibility are essential.
What file size can be encrypted in the browser?
Chunked processing and the Web Worker avoid loading the whole file into RAM. PrivCloud is designed for transfers of several hundred GB, up to the configured Team-plan limits. Real-world feasibility still depends on the browser, disk space for streamed writes, network stability, and plan limits, so it should not be described as unlimited.
Why not use RSA to encrypt everything?
RSA is suitable for small amounts of data, not for directly encrypting a large file. A hybrid scheme protects a symmetric key with an asymmetric mechanism, then encrypts the content with AES. For Team shares, {appName} wraps file keys for members with X25519 and can add ML-KEM-768; link shares carry their key in the URL fragment.
Does private browsing mode change anything?
For the encryption itself, no. The Web Crypto API works the same way in private browsing. The advantage of private browsing is that the URL fragment (containing the key) will not be saved in local history when the tab is closed.
Related articles
Test browser encryption in action
PrivCloud implements this workflow with client-side AES-256-GCM, a URL-fragment key for link shares, 1 MB E2E records, and adaptive transport. The optional password adds server-side access control that is separate from encryption. Open source and hosted in France.
This article is provided for educational purposes. Implementation details may vary between versions. Consult the source code on GitHub for exact specifics. Last updated: July 14, 2026.