Skip to content

Encryption

atreoAGENT uses modern cryptographic primitives throughout. No traffic passes through atreoLINK in plaintext.

All client-to-server traffic is encrypted by WireGuard using:

  • ChaCha20-Poly1305 for symmetric encryption.
  • Curve25519 for key exchange.
  • BLAKE2s for hashing.

WireGuard provides perfect forward secrecy through its Noise protocol handshake.

The reverse proxy serves all apps over HTTPS with TLS certificates from Let’s Encrypt:

  • TLS 1.3 minimum (raised from 1.2). Clients connecting to the proxy must support TLS 1.3.
  • Wildcard certificate for *.<apps-hostname> (covering both the default subdomain and any active custom domain).
  • ACME DNS-01 challenge via atreoLINK’s DNS relay. For custom domains, the user’s own zone delegates the challenge via CNAME to acme.<deviceId>.atreo.link so atreoLINK never needs access to the user’s DNS.
  • Automatic renewal (checked daily, renewed within 30 days of expiration).
  • ECDSA P-256 account key.

Notifications use end-to-end encryption so that atreoLINK (the relay) never sees notification content. Each notification is encrypted to the recipient user’s atreoLINK identity public key, not to a per-device key.

Each notification carries three independently encrypted fields:

FieldRequired?Purpose
summaryyesShort title and body excerpt for the lockscreen banner.
htmloptionalFull HTML body, rendered in the inbox.
plaintextoptionalFull plaintext body.

The agent encrypts each field with libsodium’s crypto_box_seal (sealed-box, RFC 7748 X25519 plus XChaCha20-Poly1305 with an ephemeral sender keypair). The recipient’s Ed25519 identity public key is converted to its X25519 Montgomery form before sealing. Each call uses a fresh ephemeral keypair.

ct = sealed_box(recipient_x25519_pubkey, plaintext)

The recipient’s identity private key, held only on their devices and browsers, decrypts. atreoLINK never sees plaintext.

For browser delivery the same sealed-box ciphertext is wrapped in a WebPush layer (RFC 8291) using the browser’s p256dh and auth keys. atreoLINK signs the WebPush request with its VAPID keypair and posts it to the browser’s push service. The Service Worker decrypts the WebPush layer (transparent to JavaScript), then unwraps the inner sealed-box. atreoLINK never sees the inner plaintext at either layer.

During device pairing, the agent sends its Ed25519 public key fingerprint to atreoLINK. This fingerprint is verified during approval.

During WireGuard client provisioning, the agent signs its response over a transcript that covers every field that ends up in the client’s wg-quick config:

transcript = SHA-256(
"atreos-wg-server-v2" || nonce || client_pubkey || device_id ||
server_pubkey || tunnel_ip || endpoint || allowed_ips || persistent_keepalive
)
signature = Ed25519.Sign(agent_identity_private, transcript)

The client verifies this signature against the agent’s identity public key, which it pinned at pair time.

All private keys are stored in the agent’s data directory:

FileContents
keys/ed25519.keyDevice identity private key (base64).
keys/wg_private.keyWireGuard private key (base64).
keys/acme_account.keyACME account private key (PEM).
certs/<suffix>/privkey.pemTLS private key per served suffix (PEM).

Loaded TLS certificates are sanity-checked on startup: the agent parses the leaf and refuses to use a cert whose SAN doesn’t include *.<suffix> for the registered suffix. A swapped-on-disk cert can’t quietly take over a suffix in the registry.

User identity private keys never reach the agent or atreoLINK. They live in:

  • iOS Keychain / Android Keystore on phones.
  • IndexedDB on browsers (per-origin, encrypted at rest by the OS where supported).

The notification system encrypts to the public part of the user’s identity key, which the agent learns from the ACL.

KeyAlgorithmPurpose
Device identity (agent)Ed25519Long-term server identity. Signs provisioning responses. Pinned in mobile after pair.
Owner identity (user)Ed25519User’s account-level signing key. Pinned in agent at pair.
Member identity (user)Ed25519Per-member signing key. Used to accept an invite and to authenticate wg:provision.
WireGuardCurve25519VPN tunnel encryption and peer auth.
Notification contentX25519 sealed-box (libsodium)End-to-end encryption to the recipient’s identity key.
ACME accountECDSA P-256TLS certificate management.

WireGuard is a registered trademark of Jason A. Donenfeld.