Zero-Knowledge by Design
Tijori is built from the ground up with security as the primary concern. Your secrets are encrypted in your browser and never leave your device in plaintext.
Overview
Tijori employs a zero-knowledge architecture where the server never sees plaintext secrets. All encryption and decryption happens client-side in the browser using the Web Crypto API. Even if our database were compromised, your secrets would remain encrypted and unusable without your passcodes.
Encryption Stack
256-bit key, 96-bit IV, 128-bit authentication tag.
Provides both confidentiality and integrity. If any bit of the ciphertext is tampered with, decryption will fail.
100,000 iterations with SHA-256 and a 128-bit salt.
Derives a cryptographic key from your 6-digit passcode. High iteration count makes brute-force attacks computationally expensive.
Salted hashing for passcode verification.
We store a hash of your passcode for verification, but never the passcode itself. This allows us to confirm correctness without knowing the value.
Key Hierarchy
Master Key (memorized)
│
├── Hash (SHA-256 + salt) → Stored in DB for verification
│
└── Derive via PBKDF2 → Master CryptoKey
│
└── Encrypts Project Passcodes (for recovery)
Project Passcode (6-digit)
│
├── Hash (SHA-256 + salt) → Stored in DB for verification
│
└── Derive via PBKDF2 → Project CryptoKey
│
└── Encrypts all Environment VariablesThreat Model
Protected Against
- Eavesdropping (encryption at rest + in transit)
- Server compromise (zero-knowledge design)
- XSS attacks (CSP + React's escaping)
- Clickjacking (X-Frame-Options: DENY)
- CSRF (Convex's token-based auth)
- IDOR (ownership verification on all resources)
- SQL Injection (N/A - document database)
- Unauthorized access (RBAC on all mutations)
Out of Scope
- ⚠️Client-side keyloggers (user's machine compromised)
- ⚠️Shoulder surfing (physical access)
- ⚠️Weak passcodes (6-digit provides ~1M combinations)
- ⚠️Forgotten master key (no recovery possible by design)
Security Headers
In production, Tijori serves responses with the following security headers:
| Header | Value | Purpose |
|---|---|---|
| Content-Security-Policy | Strict allowlist | Prevent XSS |
| X-Content-Type-Options | nosniff | Prevent MIME sniffing |
| X-Frame-Options | DENY | Prevent clickjacking |
| Referrer-Policy | strict-origin-when-cross-origin | Control referrer leakage |
| Permissions-Policy | camera=(), microphone=(), geolocation=() | Disable unused browser APIs |