RFC XXXX crypt.fyi Protocol January 2025
crypt.fyi System Specification
Status of This Memo
This document specifies the crypt.fyi protocol for secure, ephemeral secret sharing. It describes the architecture, security model, and implementation requirements for a zero-knowledge secret sharing platform using post-quantum cryptography.
Copyright Notice
Copyright (c) 2025 crypt.fyi contributors. All rights reserved.
Abstract
This document defines the crypt.fyi protocol, a system for secure, ephemeral sharing of sensitive information using post-quantum cryptography. The protocol implements a zero-knowledge architecture where encrypted secrets are stored temporarily on a server that cannot decrypt the content. The system supports features including burn-after-reading, time-based expiration, IP restrictions, read count limits, and webhook notifications.
- 1. Introduction
- 2. Protocol Overview
- 3. Cryptographic Specifications
- 4. Message Formats
- 5. API Endpoints
- 6. Security Considerations
- 7. Implementation Requirements
- 8. Error Handling
- 9. IANA Considerations
- 10. References
crypt.fyi is a zero-knowledge, end-to-end encrypted secret sharing platform that enables users to securely share sensitive information using ML-KEM post-quantum encryption. The system is designed with a "zero-knowledge" architecture, meaning the server never has access to unencrypted data or encryption keys.
This document outlines the system architecture, security measures, and interaction patterns between client and server components of the crypt.fyi system.
crypt.fyi follows a client-server architecture with the following main components:
o Web Client (Browser-based interface) o Web Server (Static file server) o API Server o Data Store (Redis for ephemeral storage)
[Web Client] <--> [Web Server] // Serves static files only
[Web Client] <--> [API Server] <--> [Redis Data Store]
^
|
[Client-side Encryption/Decryption]
The protocol implements a zero-knowledge proof system where the server can verify that a client possesses the correct decryption key without ever seeing the key itself:
- Client generates a random encryption key during secret creation
- Client optionally combines key with user-provided password
- Client computes SHA-512 hash of (key + password)
- Server stores encrypted content alongside the hash
- During retrieval, client proves knowledge by providing the same hash
- Server releases encrypted content only upon hash verification
- Client performs decryption locally using the original key/password
The decryption key MUST be passed in the URL fragment (after the # symbol) to prevent transmission to the server:
Example URL structure:
https://crypt.fyi/v/{vaultId}#{base64-encoded-key}
URL fragments are processed entirely client-side by the browser and are never sent to the server in HTTP requests. This ensures that:
- Web server logs never contain decryption keys
- Network intermediaries cannot observe keys
- Server-side code cannot accidentally log or process keys
- The zero-knowledge architecture is maintained
The system deliberately separates the web server (serving static files) from the API server for enhanced security:
- MUST serve only static files (HTML, CSS, JS)
- MUST be configured to strip URL query parameters and fragments from request logging
- MUST be configured with strict Content Security Policy (CSP)
- SHOULD run on a separate server/hosting platform from API server
- MUST handle only encrypted data operations
- MUST NOT receive or process URLs containing decryption keys
- MUST only receive hashed keys for verification (SHA-512)
- MUST operate independently from web server
This separation ensures that even if the web server logs are compromised, the decryption keys remain secure as they are never transmitted to any server component.
The system supports multiple encryption algorithms identified by algorithm identifiers:
"aes-256-gcm": AES-256 in Galois/Counter Mode"ml-kem-768": ML-KEM-768 post-quantum algorithm (legacy)"ml-kem-768-2": ML-KEM-768 with ChaCha20-Poly1305 (current)
Implementations using ML-KEM-768-2 MUST use:
- ML-KEM-768 for key encapsulation
- SHA3-512 for key derivation from password and salt
- ChaCha20-Poly1305 for symmetric encryption
- 32-byte random salt
- 12-byte random initialization vector
Key derivation process for ML-KEM-768-2:
- Generate 32-byte random salt
- Derive key using SHA3-512(password || salt)
- Generate ML-KEM-768 keypair using derived key
- Perform key encapsulation to get shared secret
- Use shared secret with ChaCha20-Poly1305
Implementations MUST use:
- SHA-512 for key verification hash (key + optional password)
- SHA3-512 for key derivation in ML-KEM-768-2
Implementations MAY use optional compression:
"zlib:pako": zlib compression via pako library"none": no compression (default)
{
"c": "<base64-encoded-encrypted-content>",
"h": "<sha512-hash-of-key-and-password>",
"m": {
"compression": {
"algorithm": "zlib:pako" | "none"
},
"encryption": {
"algorithm": "aes-256-gcm" | "ml-kem-768" | "ml-kem-768-2"
}
},
"b": <boolean-burn-after-reading>,
"dt": "<delete-token>",
"ttl": <time-to-live-milliseconds>,
"cd": <created-date-timestamp>,
"ips": "<encrypted-ip-cidr-allowlist>",
"rc": <read-count-limit>,
"fc": <failed-attempts-limit>,
"wh": {
"u": "<encrypted-webhook-url>",
"n": "<webhook-name>",
"r": <notify-on-read>,
"fpk": <notify-on-failed-key>,
"fip": <notify-on-failed-ip>,
"b": <notify-on-burn>
}
}Complete API specification available at: https://api.crypt.fyi/docs
POST /vaultCreates a new vault entry with encrypted content.
GET /vault/{vaultId}?h={hash}Retrieves vault content using vault ID and key hash.
HEAD /vault/{vaultId}Checks if a vault entry exists without retrieving content.
DELETE /vault/{vaultId}Deletes vault entry using delete token.
The system implements true zero-knowledge security where the server can verify client authorization without learning any sensitive information:
- Server MUST only receive and store encrypted data
- Server MUST NOT be able to decrypt content under any circumstances
- No user accounts or authentication MUST be required
- Server MUST NOT log sensitive data or encryption keys
- Decryption keys MUST NOT be transmitted to server due to URL fragment usage
- Client MUST prove key possession through cryptographic hash verification
- Hash MUST NOT be reversible to obtain the original key or password
- Even with full API server compromise, encrypted data MUST remain secure
- Data MUST have automatic expiration (TTL: 1 second to 7 days)
- Burn after reading MUST use atomic Redis operations
- Read count limits MUST NOT exceed 10 reads
- Failed attempt limits MUST be between 1-10 attempts before burning
- Implementation MUST NOT use persistent storage - ephemeral Redis storage only
- Data MUST be securely deleted upon expiration or burning
- IP address restrictions MAY use CIDR notation
- Implementations MUST NOT allow more than 3 IP restrictions per vault entry
- Key authentication MUST use SHA-512 hash verification
- All API endpoints MUST use HTTPS
- CORS protection MUST be implemented with configurable origins
- Rate limiting MUST be enforced (default: 10 requests per minute per IP)
- Request size limits MUST be enforced (default: 100KB)
- Strict Content Security Policy (CSP) MUST be implemented:
eval()andunsafe-inlineMUST NOT be allowed- Source origins MUST be restricted
- Frame ancestors MUST be disabled
- MIME type checking MUST be strict
- Security headers MUST be implemented (HSTS, XSS protection, etc.)
- Webhook URLs MUST be encrypted in storage
- Retry attempts MUST be configurable with a maximum of 5
- Request timeout protection MUST be implemented (3 seconds default)
- Implementations MAY send event notifications for:
- Successful reads
- Failed authentication attempts
- IP access violations
- Secret burning
- Implementations MUST use ephemeral storage (Redis recommended)
- TTL per entry MUST be configurable (1 second to 7 days)
- Automatic expiration and cleanup MUST be implemented
- Atomic operations MUST be used for critical functions:
- Burn-after-reading implementation
- Read count decrementation
- Failed attempt tracking
- Implementations MUST support concurrent access
- Data consistency MUST be maintained using atomic transactions
- Atomic operations SHOULD use Lua scripts to prevent race conditions
- Concurrent read/delete operations MUST be handled properly
- Read and write operations SHOULD be optimized for speed
- Concurrent requests MUST be handled efficiently
- Storage deployment SHOULD be scalable
- Connection pooling SHOULD be used for optimal performance
Key configuration parameters:
REDIS_URL: Redis connection stringENCRYPTION_KEY: Server-side encryption key for metadataRATE_LIMIT_MAX: Maximum requests per time windowBODY_LIMIT_BYTES: Maximum request body sizeCORS_ORIGIN: Allowed CORS originsWEBHOOK_*: Webhook configuration parameters
- Vault entry TTL SHOULD default to 1 hour (MUST be configurable: 1s to 7 days)
- Body limit SHOULD default to 100KB
- Rate limit SHOULD default to 10 requests per minute per IP
- IP restrictions MUST NOT exceed 3 per vault
- Read count MUST NOT exceed 10
- Vault ID length SHOULD be 20 characters
- Delete token length SHOULD be 20 characters
200: Success201: Vault entry created successfully400: Invalid key/password hash or malformed request404: Vault entry not found or already burned429: Rate limit exceeded500: Internal server error
Error responses include appropriate error messages in the response body following standard HTTP error response patterns.
This document does not require any IANA actions. The protocol uses standard HTTP methods and does not define new URI schemes, media types, or other values requiring IANA registration.
-
[RFC2119] Bradner, S., "Key words for use in RFCs to Indicate Requirement Levels", BCP 14, RFC 2119, March 1997.
-
[RFC8446] Rescorla, E., "The Transport Layer Security (TLS) Protocol Version 1.3", RFC 8446, August 2018.
-
[ML-KEM] National Institute of Standards and Technology, "Module-Lattice-based Key-Encapsulation Mechanism Standard", FIPS 203, August 2024.
-
[ChaCha20] Nir, Y. and A. Langley, "ChaCha20 and Poly1305 for IETF Protocols", RFC 8439, June 2018.
crypt.fyi contributors
- Email: hi@crypt.fyi
- URI: https://crypt.fyi