PrivyNote is designed with a Zero-Knowledge Architecture. The security model relies on the fact that the server is never privy to the encryption key or the plaintext content.
- Algorithm: AES-GCM (256-bit).
- Key Generation: 256-bit keys generated via
window.crypto.subtle.generateKey. - Initialization Vector (IV): 96-bit random IV generated for every operation.
- Payload Format:
{ "v": 1, "alg": "AES-GCM", "iv": "base64url", "ct": "base64url" }
The encryption key is appended to the note link as a URL Fragment (e.g., /n/<token>#<key>).
- Browsers do not send fragments to the server.
- The key is processed via
window.location.hashin a Client Component.
- Token Hashing: Tokens are hashed with SHA-256 before storage.
- Single-Use Enforcement: Retrieval and deletion happen in a single database transaction.
- TTL (Time To Live):
expiresAtis checked both at the query level and in a background cleanup job.
The application implements strict security headers via next.config.mjs:
Content-Security-Policy: Restricts scripts and styles.X-Frame-Options: DENY: Prevents clickjacking.Referrer-Policy: no-referrer: Prevents leaking note links via Referer header.Cache-Control: no-store: Prevents browser caching of sensitive responses.
- Implement HMAC/Signing for ciphertext integrity (though GCM already provides authentication).
- Argon2 for token hashing if high-entropy tokens aren't sufficient.
- Redis-based rate limiting for horizontal scaling.