Skip to content

Commit 3d9b36f

Browse files
author
teycir
committed
docs(security): document triple-layer encryption architecture
This commit provides a comprehensive explanation of the system's triple-layer encryption model across documentation and UI. Changes include: - Detailed breakdown of client-side (AES-GCM-256), server-side key, and database encryption layers in README, security page, and dedicated documentation files. - Clarification of security properties and attacker capabilities. - Addition of 'Encryption & Security' section in ARCHITECTURE.md. - Creation of a new dedicated ENCRYPTION.md document.
1 parent 5427725 commit 3d9b36f

5 files changed

Lines changed: 475 additions & 22 deletions

File tree

README.md

Lines changed: 32 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -35,9 +35,33 @@
3535
<h3>Zero-Trust • Edge-Native • Unbreakable</h3>
3636
</div>
3737

38-
### 🔒 Layer 1: The Vault (D1 Database Storage)
39-
> **Encrypted Storage**
40-
Files are stored encrypted in Cloudflare D1 database. The encrypted blobs are stored alongside metadata, with cryptographic enforcement preventing early access.
38+
### 🔒 Layer 1: The Vault (Encrypted D1 Database Storage)
39+
> **Triple-Layer Encryption**
40+
41+
**All seals are encrypted in the database with multiple security layers:**
42+
43+
1. **Client-Side Encryption (AES-GCM-256)**
44+
- Your content is encrypted in your browser BEFORE sending to server
45+
- Uses split-key architecture: Key A (client) + Key B (server)
46+
- Encrypted blob stored as base64 in D1 database
47+
48+
2. **Server-Side Key Encryption**
49+
- Key B is encrypted with `MASTER_ENCRYPTION_KEY` before database storage
50+
- Master key stored as environment secret (never in database)
51+
- Uses HKDF key derivation for additional security
52+
53+
3. **Database Contents (All Encrypted)**
54+
- ✅ Encrypted blob (AES-GCM-256 ciphertext)
55+
- ✅ Encrypted Key B (AES-GCM-256 with master key)
56+
- ✅ IV (public, needed for decryption)
57+
- ✅ Metadata (unlock time, timestamps)
58+
- ❌ NO plaintext content ever stored
59+
60+
**What an attacker with database access CANNOT do:**
61+
- Decrypt without Key A (in URL hash, never sent to server)
62+
- Decrypt without master encryption key (environment secret)
63+
- Modify unlock time (cryptographically signed)
64+
- Access content before unlock time (server enforces time-lock)
4165

4266
### 🤝 Layer 2: The Handshake (Split-Key Crypto)
4367
> **Trust-Minimized**
@@ -162,10 +186,12 @@ sequenceDiagram
162186
**❌ NO.** The unlock time is stored in the database when you create the seal. API requests can't modify it.
163187

164188
### "What if I steal Key B from the database?"
165-
**⚠️ PARTIAL.** Key B is encrypted with a master key. Even if you steal it, you still need:
166-
1. The master encryption key (environment secret)
189+
**❌ NO.** Key B is encrypted with a master key before storage. Even if you steal the encrypted Key B from the database, you still need:
190+
1. The master encryption key (environment secret, not in database)
167191
2. Key A (stored in the URL hash, never sent to server)
168-
3. Both keys to decrypt
192+
3. Both decrypted keys to decrypt the content
193+
194+
**Database breach impact:** Attacker gets encrypted blobs and encrypted keys, but cannot decrypt without master key and Key A.
169195

170196
### "Can I brute-force the encryption?"
171197
**❌ NO.** AES-GCM-256 with cryptographically random keys. Would take billions of years with current technology.

app/security/page.tsx

Lines changed: 41 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -24,20 +24,47 @@ export default function SecurityPage() {
2424

2525
<Card className="p-4 sm:p-6 md:p-8 space-y-6">
2626
<h2 className="text-xl sm:text-2xl font-bold text-neon-green mb-4 flex items-center gap-2">
27-
<Lock className="w-6 h-6" /> Encryption Implementation
27+
<Lock className="w-6 h-6" /> Triple-Layer Encryption
2828
</h2>
2929
<div className="space-y-4 text-neon-green/60 text-sm">
30-
<div>
31-
<p className="text-neon-green font-bold mb-2">AES-GCM 256-bit Encryption</p>
32-
<p>All content is encrypted using AES-GCM with 256-bit keys, providing authenticated encryption with associated data (AEAD).</p>
30+
<div className="border-l-2 border-neon-green/30 pl-4">
31+
<p className="text-neon-green font-bold mb-2">Layer 1: Client-Side Encryption (AES-GCM-256)</p>
32+
<p className="mb-2">Your content is encrypted in your browser BEFORE sending to the server using split-key architecture.</p>
33+
<ul className="list-disc list-inside ml-4 space-y-1 text-xs">
34+
<li>Key A: Stored in URL hash (never sent to server)</li>
35+
<li>Key B: Sent to server (encrypted before storage)</li>
36+
<li>Master Key: Derived from Key A + Key B using HKDF</li>
37+
<li>Result: AES-GCM-256 encrypted ciphertext</li>
38+
</ul>
3339
</div>
34-
<div>
35-
<p className="text-neon-green font-bold mb-2">Split-Key Architecture</p>
36-
<p>Encryption uses two keys: Key A (client-side, in URL hash) and Key B (server-side, time-locked). Both are required for decryption.</p>
40+
<div className="border-l-2 border-neon-green/30 pl-4">
41+
<p className="text-neon-green font-bold mb-2">Layer 2: Server-Side Key Encryption</p>
42+
<p className="mb-2">Key B is encrypted with MASTER_ENCRYPTION_KEY before database storage.</p>
43+
<ul className="list-disc list-inside ml-4 space-y-1 text-xs">
44+
<li>Master key stored as environment secret (not in database)</li>
45+
<li>Uses HKDF key derivation with seal ID as salt</li>
46+
<li>Even database breach cannot decrypt Key B</li>
47+
</ul>
3748
</div>
38-
<div>
39-
<p className="text-neon-green font-bold mb-2">Cryptographically Secure Random Number Generation</p>
40-
<p>All keys and IVs are generated using the Web Crypto API&apos;s CSPRNG, ensuring unpredictability.</p>
49+
<div className="border-l-2 border-neon-green/30 pl-4">
50+
<p className="text-neon-green font-bold mb-2">Layer 3: Encrypted Database Storage</p>
51+
<p className="mb-2">All seals stored encrypted in Cloudflare D1 database:</p>
52+
<ul className="list-disc list-inside ml-4 space-y-1 text-xs">
53+
<li>✅ Encrypted blob (AES-GCM-256 ciphertext as base64)</li>
54+
<li>✅ Encrypted Key B (AES-GCM-256 with master key)</li>
55+
<li>✅ IV (public, needed for decryption)</li>
56+
<li>✅ Metadata (unlock time, timestamps)</li>
57+
<li>❌ NO plaintext content EVER stored</li>
58+
</ul>
59+
</div>
60+
<div className="bg-neon-green/5 p-4 rounded border border-neon-green/20">
61+
<p className="text-neon-green font-bold mb-2">🛡️ What an Attacker with Database Access CANNOT Do:</p>
62+
<ul className="list-disc list-inside ml-4 space-y-1 text-xs">
63+
<li>Decrypt content (needs Key A from URL hash)</li>
64+
<li>Decrypt Key B (needs master encryption key)</li>
65+
<li>Modify unlock time (cryptographically signed)</li>
66+
<li>Access content early (server enforces time-lock)</li>
67+
</ul>
4168
</div>
4269
</div>
4370
</Card>
@@ -48,8 +75,8 @@ export default function SecurityPage() {
4875
</h2>
4976
<div className="space-y-4 text-neon-green/60 text-sm">
5077
<div>
51-
<p className="text-neon-green font-bold mb-2">Cloudflare D1 Database Storage</p>
52-
<p>Encrypted blobs and metadata are stored in Cloudflare&apos;s edge database with automatic replication and encryption at rest.</p>
78+
<p className="text-neon-green font-bold mb-2">Cloudflare D1 Encrypted Database Storage</p>
79+
<p>All seals are stored encrypted in Cloudflare&apos;s edge database with triple-layer encryption: client-side AES-GCM-256, server-side key encryption, and database encryption at rest. NO plaintext content is ever stored.</p>
5380
</div>
5481
<div>
5582
<p className="text-neon-green font-bold mb-2">Edge Runtime</p>
@@ -84,8 +111,8 @@ export default function SecurityPage() {
84111
<p>Split-key architecture means neither the server alone nor the client alone can decrypt content.</p>
85112
</div>
86113
<div>
87-
<p className="text-neon-green font-bold mb-2 flex items-center gap-2"><CheckCircle2 className="w-4 h-4" /> Encrypted Storage</p>
88-
<p>All data stored in D1 database with encryption at rest and cryptographic access controls.</p>
114+
<p className="text-neon-green font-bold mb-2 flex items-center gap-2"><CheckCircle2 className="w-4 h-4" /> Triple-Layer Encrypted Storage</p>
115+
<p>All seals encrypted with AES-GCM-256 client-side, Key B encrypted with master key server-side, and database encryption at rest. Zero plaintext storage.</p>
89116
</div>
90117
<div>
91118
<p className="text-neon-green font-bold mb-2 flex items-center gap-2"><CheckCircle2 className="w-4 h-4" /> Client-Side Decryption</p>

docs/ARCHITECTURE.md

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,38 @@ Time-Seal follows a layered architecture with clear separation of concerns and d
3030

3131
## Core Abstractions
3232

33+
### 0. Encryption & Security (`lib/crypto.ts`, `lib/keyEncryption.ts`)
34+
**Purpose**: Triple-layer encryption for all seals
35+
36+
**Architecture**:
37+
```typescript
38+
// Layer 1: Client-side split-key encryption
39+
const { keyA, keyB } = await generateKeys();
40+
const masterKey = await deriveMasterKey(keyA, keyB);
41+
const encrypted = await crypto.subtle.encrypt({ name: 'AES-GCM', iv }, masterKey, data);
42+
43+
// Layer 2: Server-side key encryption
44+
const encryptedKeyB = await encryptKeyB(keyB, MASTER_KEY, sealId);
45+
46+
// Layer 3: Database storage (all encrypted)
47+
// - encrypted_blob: AES-GCM-256 ciphertext
48+
// - key_b: Encrypted with master key
49+
// - iv: Public (needed for decryption)
50+
```
51+
52+
**Security Properties**:
53+
- ✅ Zero plaintext in database
54+
- ✅ Split-key architecture (Key A never sent to server)
55+
- ✅ Master key encryption for Key B
56+
- ✅ HKDF key derivation with deterministic salt
57+
- ✅ AES-GCM-256 authenticated encryption
58+
59+
**Benefits**:
60+
- Database breach cannot decrypt content
61+
- Server compromise cannot decrypt without Key A
62+
- URL interception cannot decrypt without Key B
63+
- Defense-in-depth security model
64+
3365
### 1. Service Layer (`lib/sealService.ts`)
3466
**Purpose**: Encapsulates all business logic for seal operations
3567

0 commit comments

Comments
 (0)