SRIFT Security Architecture and Threat Model
By SRIFT maintainers · Published
Reviewed by SRIFT maintainers · last reviewed against the SRIFT 4.3.2 source.
Short answer
SRIFT encrypts file and chat content with keys generated on the participants' devices: DTLS on direct WebRTC connections, per-transfer ECDH P-256 + HKDF-SHA256 + AES-256-GCM for chunks that pass through its relay, sender keys for browser chat, AES-256-GCM with the key in the URL fragment for encrypted quick-share links, and Ed25519/X25519 for AgentNet. The servers keep state in RAM only and store no files.
That protects content from network observers, TURN providers and an honest-but-curious SRIFT server. It does not protect against an actively malicious SRIFT server, because public keys are introduced through it with no verification step in the UI yet, and it does not hide metadata such as file names, sizes and IP addresses.
- Sealed with
- AES-256-GCM (relay, chat, quick-share, AgentNet); DTLS on direct WebRTC
- Key agreement
- ECDH P-256 (sessions), X25519 (AgentNet)
- Server storage
- RAM only: no database, no stored files
- Key verification UI
- Not yet; a safety code exists in code only
Key takeaways
- File and chat content is encrypted under keys made on the participants' devices: DTLS on direct WebRTC, AES-256-GCM on the relay, in chat, in encrypted quick-share links and on AgentNet.
- The servers keep state in RAM only and store no files.
- This protects content from network observers, TURN providers and a server that only observes, not from an actively malicious SRIFT operator: keys are introduced through the server and the interface has no verification step yet.
- Metadata stays visible: file names, sizes, MIME types, IP addresses and timing.
- Mitigations exist today: --room-secret for CLI sessions, encrypted quick-share links decrypted with srift get, and tool approval for agents.
This page documents SRIFT specifically. For the questions to ask of any P2P tool, see is P2P file transfer secure?; for metadata alone, see what a relay can see.
Components and trust boundaries
Everything below is taken from SRIFT's open-source code at version 4.3.2. The system has six parts that matter for security, and each sits on a different side of a trust boundary.
| Component | Role | Holds content keys? |
|---|---|---|
| Browser app | Creates and joins sessions, sends files, chat and audio. Generates its keys with Web Crypto. | Yes, its own |
| Signaling and relay server | Host approval, member lists, WebRTC signaling, forwarding of sealed file chunks and chat frames when no direct path works. | No (except legacy fallbacks, below) |
| TURN providers | Third-party relays for WebRTC packets, reached with short-lived credentials the server mints per request (6 hours by default). | No |
| CLI daemon | Runs on the user's machine at 127.0.0.1:3822; backs the srift CLI and the local MCP server. | Yes, its own |
| Quick-share relay | Turns /d/<token> requests into byte-range requests to the sender's daemon and forwards the reply. Stores nothing. | No, when --encrypt is used |
| AgentNet relay | Presence, signed agent cards, search, and delivery of encrypted envelopes to online agents. | No (except the A2A bridge) |
Keys and algorithms on each channel
| Channel | Keys | Encryption | Readable by |
|---|---|---|---|
| Session file, direct WebRTC | DTLS handshake; certificate fingerprints travel in SDP through the SRIFT server, unsealed | DTLS only: no additional application-level layer | The two endpoints |
| Session file, relay (pgcm1) | Fresh ECDH P-256 pair per transfer on each side; HKDF-SHA256, salt = session code (+ room secret), info = file ID and both public keys | AES-256-GCM per 256 KB chunk, random 12-byte IV, 16-byte tag | The two endpoints |
| Session file, fallback (sgcm1) | PBKDF2-SHA256, 100,000 iterations, over the session code (+ room secret) | AES-256-GCM per chunk | Endpoints, and the server, which knows the session code (unless a room secret is set) |
| Browser chat (mesh) | ECDSA P-256 identity per device; pairwise ECDH P-256 + HKDF-SHA256 for signals and key hand-offs | Per-sender random AES-256-GCM key, rotated when a member leaves; records signed | Current members |
| Chat copy for CLI/agent members (pk1) | Per-session ECDH P-256 pair per device; random message key wrapped per recipient | AES-256-GCM | Members; session-code key (server-derivable) if a member's client is too old |
| Browser audio | DTLS-SRTP, fingerprints inside pair-sealed mesh signals | SRTP; relayed Opus frames sealed with the sender key | Members |
| Quick-share --encrypt (SRE1) | 32 random bytes made by the sender, carried in the #k= fragment | AES-256-GCM, 1 MiB chunks; name, size and MIME in an encrypted metadata block | Anyone with the full link |
| Quick-share --password | HKDF-SHA256(fragment key ‖ PBKDF2-SHA256(password, salt, 100,000)) | As above | Anyone with the link and the password |
| Quick-share, no --encrypt | None beyond TLS | TLS to and from the server | Server and downloader |
| AgentNet message or file | Ed25519 identity; ephemeral X25519 per message; HKDF-SHA256 | AES-256-GCM, outer fields as AAD; inner payload Ed25519-signed | The recipient agent |
| A2A bridge message | Encrypted by the relay on arrival | AES-256-GCM from the relay onward | Relay and recipient |
Relay chunks: binding each chunk to its place
On the relay path, each pgcm1 chunk carries the sender's 65-byte ephemeral public key, a random 12-byte IV, the ciphertext and a 16-byte tag. The additional authenticated data is pgcm1|fileId|chunkIndex|totalChunks, so the relay cannot reorder chunks, move them between files or change the chunk count without the tag failing. The HKDF construction follows RFC 5869, and keys are created as non-extractable Web Crypto keys. The AES-256-GCM explainer covers why the IV must never repeat under one key; a fresh key per transfer keeps the random-IV budget small.
Quick-share: a streaming construction
SRE1 uses a STREAM-style nonce: a 7-byte prefix, a 32-bit chunk counter and a final byte that marks the last chunk. Because “last” is part of the nonce, a truncated download cannot pass as complete, and the 36-byte header is authenticated as AAD. Without a password the fragment key is the content key; with one, both are needed. Browsers do not send the URL fragment in HTTP requests, so the key does not reach the server through the download.
AgentNet: self-certifying addresses
An AgentNet address is srift: plus the first 20 base32 characters of the SHA-256 of the agent's Ed25519 public key. Agent cards carry the X25519 key and are signed by the Ed25519 key, so a client that already knows an address can check that the card belongs to it. Each message uses a new ephemeral X25519 key; the version, ID, recipient and timestamp are authenticated as AAD, and the signature inside covers the recipient and ID, so a relay cannot redirect or replay a message to someone else. File transfers are verified with a SHA-256 of the whole file.
Trust model: where keys come from and who vouches for them
Private keys are generated on each device and never sent anywhere. The weak point is how the other side's public key arrives. In browser and CLI sessions, it arrives through the SRIFT server: the mesh pins the first key it sees for each member (trust on first use), and pk1 and pgcm1 take whatever key the other side advertised over the session socket. A 12-digit safety code derived from both identity keys exists in the mesh code so two people could compare it out of band, but the UI does not show it yet. Until it does, a session relies on the server introducing the right keys.
For direct file transfers, the WebRTC offer and answer, including the DTLS certificate fingerprints, pass through the server unsealed. WebRTC's own security architecture (RFC 8827) notes the same property: without an identity mechanism, the signaling service is trusted not to swap fingerprints.
The CLI offers one mitigation that does not depend on the server: a room secret, mixed into the HKDF salt of pk1 and pgcm1 keys and into the sgcm1 key. A server that substitutes public keys still cannot derive the resulting keys without the secret. It is available only on the command line and does not cover the browser chat mesh.
srift session start --room-secret "<long random secret>"
srift session join ABC1234 --room-secret "<same secret>"Quick-share and AgentNet use different anchors. A quick-share link is a bearer secret: whoever has it has the key, so its security is the security of the channel used to send it. AgentNet anchors trust in the address itself; looking agents up by name or bare handle trusts the relay's search results, while a full address does not.
Threat model
| Adversary | Protected? | Why |
|---|---|---|
| Network eavesdropper (Wi-Fi, ISP, corporate network) | Content: yes | TLS to the server, DTLS between peers, AES-256-GCM sealing inside the relay. Still visible: IP addresses, the srift.app domain, volume and timing. |
| TURN provider | Content: yes | Forwards DTLS ciphertext. Sees IP addresses, volume and timing. |
| Honest-but-curious SRIFT server | Content: yes, when both clients are current | Handles only public keys and ciphertext for pgcm1, pk1 and the mesh. It can read sgcm1 and session-key fallbacks with older clients, quick-share files sent without --encrypt, and A2A bridge text. |
| Actively malicious SRIFT server (or whoever controls it) | No | It could substitute public keys at first contact (mesh, pk1, pgcm1), man-in-the-middle the direct WebRTC path through the unsealed SDP, admit a member of its own (admission runs on the server), or serve altered web app code. A CLI room secret blocks key substitution for relayed files and chat copies. Encrypted quick-share holds if the recipient decrypts with srift get, not with the browser page the server serves. AgentNet keys for an address you already know cannot be swapped. |
| Uninvited person who learns a session code | Yes | Joining needs the host's approval; unanswered requests expire after 5 minutes. |
| Member who leaves or is removed | New messages: yes | Chat sender keys rotate when a member leaves or is kicked. What they already received stays with them. |
| Anyone holding a quick-share URL | No, by design | The key is in the link. --password adds a second factor; --once, --max-downloads and --ttl limit exposure. |
| Compromised endpoint | No | Malware on either device sees plaintext and keys. |
| Metadata or traffic observer | No | No padding or mixing. The server sees file names, sizes, MIME types, IP addresses, members and timing. |
| Someone who seizes the server later | Mostly | No database and no stored files; session state is lost with the process. Logs pseudonymise IPs and session codes and never record file names or usernames. |
The metadata row is covered in detail in what a file transfer relay can see, with a per-item table for the SRIFT server, TURN and the other peer.
What is stored, and for how long
- Server state is RAM only. There is no database, Redis or disk store. Sessions idle for 7 days are dropped; join requests expire after 5 minutes. Chat content is not kept; the server tracks message IDs only.
- No stored files. Relay chunks and quick-share bytes are forwarded as they arrive. A quick-share download may briefly buffer up to 256 out-of-order chunks in memory, and responses are sent with
Cache-Control: no-store. A link lives while the sender's process serves it, unless--ttlor a download limit ends it sooner. - Logs. IP addresses, session codes and user IDs are replaced with HMAC tags under a random key that exists only in the running process; usernames are redacted. File names and chat content are never logged.
- AgentNet relay. Presence, cards, beacons and the search index live in memory while agents are connected. Messages are delivered only to online recipients; queueing for offline ones happens in the sender's own outbox.
- On devices. Mesh keys and chat history are erased when the session ends. Browsers keep relay acknowledgements in IndexedDB so a transfer can resume after a refresh. AgentNet keeps history locally (30 days by default) with an ephemeral mode that keeps it in memory.
Known gaps, and what you can do about them
- No key verification in the UI. An actively malicious server could substitute keys at first contact. For CLI sessions, use
--room-secretshared over another channel. For a single sensitive file, an encrypted quick-share link decrypted withsrift getkeeps the key away from the server. - Direct WebRTC signaling is unsealed. File-transfer SDP and ICE candidates pass through the server in the clear, so it sees peer IP addresses and DTLS fingerprints and could interpose. The direct path has DTLS only, without an extra application-level layer.
- Transfer metadata is visible. File names, sizes and MIME types travel in plaintext offers. Use neutral names, or an encrypted quick-share link, which encrypts the name.
- Legacy fallbacks. With older clients, relay chunks fall back to sgcm1 and chat copies to the session-code key, both derivable by the server; very old clients send relay chunks with TLS only. Keep the CLI current (
srift self-update). - Plain quick-share links are TLS only. Without
--encryptthe server forwards the real name and bytes. The CLI warns about this; add--encryptor--password. - The web app is delivered by the same operator. As with any browser-based encryption, the code that holds the keys is served by srift.app on each visit. The CLI is installed from npm, PyPI or a checksum-verified binary instead.
- No whole-file hash in browser sessions. Integrity comes from the GCM tag on each relay chunk, DTLS on the direct path and a final byte-count confirmation. AgentNet transfers do verify a SHA-256.
- The local MCP server does not confine paths. Its file tools pass any path the agent supplies, so any file the user can read can be shared if the agent is told to. Keep tool-approval prompts on, run agents in a container, and prefer encrypted, single-use links. See MCP server security.
- A2A bridge messages are readable by the relay. Use native AgentNet messaging when the content is sensitive.
- Direct connections reveal IP addresses to the other peer. Use a VPN if that matters.
export SRIFT_LINK_PASSWORD='<shared over another channel>'
srift quick-share ./contract.pdf --once --ttl 1h
# recipient:
srift get "https://srift.app/d/<token>#k=<key>"Setting the password through the environment keeps it out of shell history, implies encryption, and srift get reads the same variable. The encrypted file sharing page shows the browser flow.
Frequently asked questions
Can SRIFT read my files?
Not when both sides run current clients and the server behaves as designed: it forwards ciphertext and never receives private keys. It does see file names, sizes and types, and an actively malicious operator could substitute public keys at first contact, because there is no key verification in the UI yet. Files shared with quick-share without --encrypt pass through the server in plaintext.
Is the direct WebRTC path encrypted with AES-256-GCM?
It is encrypted with WebRTC's mandatory DTLS, which is negotiated between the two browsers. SRIFT does not add a second application-level layer on that path; the AES-256-GCM sealing applies to chunks that go through the relay.
Does the room secret work in the browser?
No. It is a CLI option (srift session start --room-secret and srift session join --room-secret), and it covers relayed file chunks and the chat copy for CLI members, not the browser chat mesh.
References
- RFC 8827: WebRTC Security Architecture (IETF)
- RFC 5764: DTLS Extension to Establish Keys for SRTP (IETF)
- RFC 5869: HMAC-based Extract-and-Expand Key Derivation Function (HKDF) (IETF)
- NIST SP 800-38D: Galois/Counter Mode (GCM) and GMAC (NIST)
- RFC 8018: PKCS #5 Password-Based Cryptography (PBKDF2) (IETF)
- RFC 8032: Edwards-Curve Digital Signature Algorithm (Ed25519) (IETF)
- RFC 7748: Elliptic Curves for Security (X25519) (IETF)
See exactly what SRIFT encrypts
Every key, algorithm and metadata field — including what servers can see and what the design does not stop.
Related resources
- What a File Transfer Relay Can Actually SeeEven with end-to-end encryption, a relay sees metadata: IP addresses, sizes and timing. A concrete inventory, using SRIFT as the worked example.Explainer
- How AES-256-GCM Works, and How Files Use ItAES-256-GCM explained: counter-mode encryption, the authentication tag, why nonces must never repeat, and how to encrypt a large file in chunks safely.Explainer
- Is Peer-to-Peer File Transfer Secure?What a direct connection protects, what it exposes (such as IP addresses), and the questions to ask before trusting any P2P file transfer tool.Explainer
- Encrypted File Sharing, End-to-EndEnd-to-end AES-256-GCM file sharing with keys made on your devices.SRIFT product
