Introduction
This proposal defines a new URI scheme, e2e:, to standardize the sharing of end-to-end encrypted files via links. The scheme enables users to share encrypted files without requiring custom client-side logic or out-of-band key exchange, leveraging existing web standards like the Web Crypto API.
Motivation:
- Users need a simple, standardized way to share encrypted files without exposing keys to servers hosting the files.
- No existing URI scheme supports encrypted file links natively.
- The scheme should work with current web technologies (e.g., Web Crypto,
fetch).
URI Scheme
Syntax
The e2e: URI scheme is structured as:
<key>: URL-safe base64-encoded encryption key (e.g., AES-GCM).
<iv>: URL-safe base64-encoded initialization vector (IV).
<url>: URL of the encrypted file (e.g., https://example.com/file.enc).
Example:
e2e:SGVsbG8gV29ybGQh:SGVsbG8gV29ybGQh:https://example.com/files/123.enc
Workflow
-
Encryption:
- Users encrypt files client-side using the Web Crypto API (e.g., AES-GCM).
- The key and IV are encoded as URL-safe base64 and embedded in the
e2e: link.
-
Sharing:
- The
e2e: link is shared via email, messaging, or other channels.
-
Decryption:
- Recipients browser parses the
e2e: link to extract the key, IV, and file URL, downloads the encrypted file and decrypts it using the Web Crypto API and then uses it as a normal file.
Use Cases
Alice Shares a File with Bob
- Alice encrypts
file.txt with a random key/IV using Web Crypto.
- Alice constructs an
e2e: link:
e2e:<key>:<iv>:https://example.com/files/123.enc
- Alice shares the link with Bob (e.g., via email).
- Bob’s browser/web app:
- Parses the
e2e: link.
- Downloads
https://example.com/files/123.enc.
- Decrypts the file using the embedded key/IV.
- Uses the file as a normal File Blob
Browser Integration (Optional)
- Browsers could natively support
e2e: links by:
- Detecting the scheme and prompting the user to decrypt the file.
- Falling back to external apps if no native support exists.
Security Considerations
- Servers only store encrypted files and cannot decrypt them without the key.
- Keys are embedded in the URI and must be shared securely (e.g., via encrypted messaging).
- The URI itself may leak metadata (e.g., file location). Users should avoid sharing
e2e: links publicly.
- AES-GCM (or another authenticated encryption algorithm) is recommended.
- IV must be unique per file and included in the URI.
- 256-bit keys for AES-GCM.
Backward Compatibility
- Browsers without
e2e: support will treat it as an unrecognized scheme (e.g., prompt to open an external app).
- Web apps can polyfill support by parsing
e2e: links manually.
Example Implementation
Constructing an e2e: Link (JavaScript)
// Encrypt a file
const key = await crypto.subtle.generateKey({ name: "AES-GCM", length: 256 }, true, ["encrypt"]);
const iv = crypto.getRandomValues(new Uint8Array(12));
const encrypted = await crypto.subtle.encrypt({ name: "AES-GCM", iv }, key, fileData);
// Encode key/IV for URI
const keyBase64 = btoa(String.fromCharCode(...new Uint8Array(await crypto.subtle.exportKey("raw", key))))
.replace(/=/g, "").replace(/\+/g, "-").replace(/\//g, "_");
const ivBase64 = btoa(String.fromCharCode(...iv))
.replace(/=/g, "").replace(/\+/g, "-").replace(/\//g, "_");
// Construct e2e: link
const e2eLink = `e2e:${keyBase64}:${ivBase64}:${fileUrl}`;
Decrypting an e2e: Link
// Parse e2e: link
const [_, keyB64, ivB64, url] = e2eLink.match(/^e2e:([^:]+):([^:]+):(.+)$/);
// Decode key/IV
const keyBuffer = Uint8Array.from(atob(keyB64.replace(/-/g, "+").replace(/_/g, "/")), c => c.charCodeAt(0));
const ivBuffer = Uint8Array.from(atob(ivB64.replace(/-/g, "+").replace(/_/g, "/")), c => c.charCodeAt(0));
const key = await crypto.subtle.importKey("raw", keyBuffer, { name: "AES-GCM" }, false, ["decrypt"]);
// Download and decrypt
const response = await fetch(url);
const encryptedData = new Uint8Array(await response.arrayBuffer());
const decrypted = await crypto.subtle.decrypt({ name: "AES-GCM", iv: ivBuffer }, key, encryptedData);
Open Questions
- Key/IV Encoding: Is base64url the best choice, or should we use another format?
- Algorithm Agility: How to support multiple algorithms (e.g., ChaCha20) in the URI?
Looking forward to your thoughts!
Introduction
This proposal defines a new URI scheme,
e2e:, to standardize the sharing of end-to-end encrypted files via links. The scheme enables users to share encrypted files without requiring custom client-side logic or out-of-band key exchange, leveraging existing web standards like the Web Crypto API.Motivation:
fetch).URI Scheme
Syntax
The
e2e:URI scheme is structured as:<key>: URL-safe base64-encoded encryption key (e.g., AES-GCM).<iv>: URL-safe base64-encoded initialization vector (IV).<url>: URL of the encrypted file (e.g.,https://example.com/file.enc).Example:
Workflow
Encryption:
e2e:link.Sharing:
e2e:link is shared via email, messaging, or other channels.Decryption:
e2e:link to extract the key, IV, and file URL, downloads the encrypted file and decrypts it using the Web Crypto API and then uses it as a normal file.Use Cases
Alice Shares a File with Bob
file.txtwith a random key/IV using Web Crypto.e2e:link:e2e:link.https://example.com/files/123.enc.Browser Integration (Optional)
e2e:links by:Security Considerations
e2e:links publicly.Backward Compatibility
e2e:support will treat it as an unrecognized scheme (e.g., prompt to open an external app).e2e:links manually.Example Implementation
Constructing an
e2e:Link (JavaScript)Decrypting an
e2e:LinkOpen Questions
Looking forward to your thoughts!