Soty

Security

What Soty actually protects

End-to-end encryption is not a checkbox in the interface: it is a specific envelope, a fixed order of checks and a list of assumptions. Here is what the project does, what an intermediary sees and where the guarantees end.

The app and the relay are open source: there is more to check than this page.

AES-256-GCM

Every message gets its own key, and the authentication tag catches tampering before decryption.

One-off keys

Each message uses a fresh X25519 pair. Two identical texts look like two unrelated byte strings.

Ed25519 signatures

The envelope is signed with the sender long-term key: text, recipient and time cannot be swapped.

Relays hold no plaintext

A node stores encrypted envelopes and metadata only. It cannot decrypt them.

Threat model

Security is always a list of whom and what we protect against. This is the honest boundary.

What it protects against

  • Network eavesdropping

    An ISP, a Wi-Fi operator or a relay owner sees ciphertext and header fields only.

  • Message tampering

    The Ed25519 signature and the envelope id prevent changes to the text, the recipient or the time on the way.

  • Fake history

    chainLink binds messages into a directed chain: inserting or reordering an envelope cannot go unnoticed.

  • Account takeover

    There are no accounts: a password or an email cannot be stolen because neither exists.

  • A relay database leak

    Even a full dump of a node does not reveal conversations — it holds no recipient private keys.

What it does not protect against

  • A compromised device

    Anyone with access to an unlocked phone or to the app files sees the keys and the conversation.

  • Metadata

    A relay and the network see who sent what, when and how much. This is not hidden, only minimised.

  • The recipient

    The other side reads the message legitimately. A screenshot or a forward is outside the encrypted zone.

  • Invite substitution

    If an attacker swaps the keys in an invite, they become the conversation partner. Compare keys over another channel.

  • Denial of service

    A relay or the network can delay or drop an envelope. Delivery stays best-effort.

Anatomy of an envelope

One envelope, one recipient. Inside there is only ciphertext, a signature and the fields needed to verify and deliver it.

envelope.json

id Content address
senderPubKey Who signed
recipientPubKey For whom
timestamp When
ciphertext What
ephemeralPubKey One-off key
signature Signature
chainLink Previous message

id

SHA-256 over the sender, the recipient, the ciphertext, the time and chainLink.

senderPubKey

The sender long-term Ed25519 key. The same key verifies the signature.

recipientPubKey

The recipient long-term X25519 key. No other device can decrypt the envelope.

timestamp

UTC creation time. A timestamp too far in the future is dropped: the tolerance is 5 minutes.

ciphertext

AES-256-GCM: cipher || mac || nonce, base64 encoded. There is no plaintext here.

ephemeralPubKey

The public half of the X25519 pair created for this message only.

signature

Ed25519 over the id, the time, the ciphertext and chainLink. Changing any field breaks it.

chainLink

The id of the previous envelope in this directed chain. Empty for the first message.

An envelope is accepted only after a fixed order of checks: frame size → clock → signature → id → duplicate → decryption. Anything that fails is dropped without logging.

From text to decryption

Five steps, each with its own area of responsibility.

  1. 1

    One-off exchange

    The sender creates an X25519 pair and computes a shared secret with the recipient long-term key.

  2. 2

    Key derivation

    HKDF turns the shared secret into an AES-256-GCM key. No two messages share a key.

  3. 3

    Encryption

    AES-256-GCM with a 12-byte nonce returns the ciphertext and a 16-byte authentication tag.

  4. 4

    Signature

    Ed25519 signs the id, the time, the ciphertext and chainLink with the sender long-term key.

  5. 5

    Verification on receipt

    Clock first, then the signature, the id, duplicates and only then decryption. A failure is never retried.

Limits are part of the model: a frame up to 256 KiB, plaintext up to 4 KiB, future time no more than 5 minutes. This protects against memory exhaustion and floods.

What a relay sees

A relay is an honest but curious intermediary. It must not be able to read conversations, and it cannot.

Sees

  • Who sent to whom — as public keys
  • When an envelope was created and how long it stays
  • The envelope size and the hop count
  • The signature and the id used for verification

Does not see

  • The message text and attachments
  • Private keys and seed phrases
  • Names from the address book
  • The decrypted history after delivery

Public keys are pseudonyms, not names. But frequency and timing still reveal a lot: that is metadata, and it stays visible.

Keys and local data

A Soty identity is two key pairs on the device, not a record on a server.

Ed25519 — who you are

The long-term signing key. Its public half goes into the invite, the private half never leaves the device.

X25519 — how people write to you

The key envelopes are encrypted to. The other side needs the public half; the private half is yours alone.

One device, one identity

History and keys do not sync between devices. A new phone starts with a new identity.

Retention

Conversations live for 30 days by default. You can pick 7, 90, 180 or 365 days, or keep them forever.

App lock

A password of 6 characters or more is stored as PBKDF2-HMAC-SHA256 with 210,000 iterations, plus fingerprint unlock.

Important: seed keys sit in local SQLite in plain form. This is a documented residual risk: with full access to the app files the keys can be extracted. For higher requirements use a dedicated device and app lock.

Boundaries worth knowing

No system protects against everything. These limits are better known before than after.

No independent audit

The code is open, but the project does not claim an external audit. This page is not a substitute for one.

No forward secrecy against key theft

One-off keys protect messages from each other, but the recipient long-term X25519 key decrypts everything addressed to it.

No anonymity

Public keys are stable and a relay sees network addresses. Soty hides the text, not the fact of a conversation.

No backups

Losing the device means losing the keys and the history. There is no key export and no cloud backup.

Check it yourself

Sources, protocol and builds are open. Start with the install, then verify the details in the code.