Cryptographic Stack#
| Layer | Algorithm | Purpose |
|---|---|---|
| Key Exchange | ECDH (P-256) | Agent-server session key establishment |
| Key Derivation | HKDF-SHA256 | Derive session keys from ECDH shared secret |
| Wire Encryption | AES-256-GCM | Encrypt all agent-server communication |
| At-Rest Encryption | AES-256-GCM | Encrypt sensitive database fields |
| Master Key | PBKDF2 | Derive per-engagement master key from passphrase |
| Password Storage | bcrypt | Hash operator passwords |
| Anti-Replay | Monotonic counter | Prevent message replay attacks |
Wire Encryption#
All agent communication is encrypted at the application layer using AES-256-GCM:
- During registration, the agent and server perform ECDH key exchange
- Both derive a session key using HKDF-SHA256
- All subsequent messages are encrypted with the session key
- Each message includes a 12-byte random nonce and GCM authentication tag
- A monotonic counter prevents replay attacks
Wire Format (Dev Agent)#
| |
The counter is included inside the encrypted payload. The server rejects any message with a counter value that is not strictly greater than the last received.
At-Rest Encryption#
Sensitive data in the engagement database is encrypted with the engagement’s master key:
- Credential secrets are encrypted before storage
- Session keys and private keys are encrypted per-session
- Master key is derived from the engagement passphrase using PBKDF2 (600,000 iterations, 16-byte salt)
Encrypted values are stored as nonce || ciphertext || GCM tag in a single blob.
graph LR
Pass[Engagement Passphrase] --> PBKDF2[PBKDF2]
PBKDF2 --> MK[Master Key]
MK --> AES[AES-256-GCM]
AES --> EncData[Encrypted Fields]
The passphrase is never stored — it must be provided to activate an engagement.
Session Key Rotation#
When enabled, the server periodically checks session key age:
- Keys older than
key_rotation_session_ttlare marked for rotation - On the agent’s next check-in, a new key exchange is performed
- The transition is transparent to the agent
Config: key_rotation_enabled, key_rotation_session_ttl
Authentication#
Operator Authentication#
- Passwords are hashed with bcrypt
- Access tokens (3600s TTL) and refresh tokens (86400s TTL) are issued on login
- Refresh tokens are single-use — consumed and replaced on each refresh
- Tokens are stored in-memory and validated on every API request
- Rate limiting: max 5 failed login attempts per 300-second window
- Force-logout invalidates all tokens for an operator
Agent Authentication#
- Agents authenticate via the ECDH key exchange during registration
- Session tokens (16 bytes) identify sessions in subsequent check-ins
- The session key provides mutual authentication — only the holder of the correct key can produce valid encrypted messages
Log Redaction#
When enabled (default), the server filters sensitive values from log output:
- Credentials and secrets
- Callback addresses
- Cryptographic keys and tokens
This prevents accidental exposure of operational data in log files.
P2P Relay Security#
When agents relay traffic for other agents via P2P chaining:
- Traffic is end-to-end encrypted between the originating agent and the teamserver
- Relay agents handle only opaque ciphertext — they cannot decrypt or inspect forwarded messages
- Chains of 3+ hops are supported (agent -> relay -> relay -> teamserver)
- If a relay agent is compromised, the forwarded traffic remains confidential
Module Memory Security#
When the Tanto Loader Spec is implemented, agents MUST:
- Zero sensitive memory on module unload — cryptographic keys, session tokens, and module data are wiped
- Clean unload managed modules without crashing the host agent
- Isolate module memory so a failed module doesn’t corrupt the agent’s state
Kill Dates#
Every agent build includes a mandatory kill date — a hard expiration timestamp set at build time:
- When the kill date is reached, the agent self-destructs regardless of teamserver connectivity
- Self-destruct removes persistence, zeros sensitive memory, and deletes artifacts
- Kill dates are immutable after deployment — they cannot be extended remotely
Clock Drift Tolerance#
The clock_drift_tolerance setting (default: 300 seconds) defines acceptable clock drift between the server and agents for crypto operations and status tracking.