Security

A trust model that is explained can be audited; one that is hidden cannot. This is what SecureChat does, and also what it doesn’t.

In short

How a message is encrypted (envelope v1)

We use libsodium, an audited and widely used cryptographic library. These are the building blocks of envelope v1 (sc1):

Cryptographic primitives of envelope v1
ComponentConstruction
Identity (your device and the business)X25519 key pair
Conversation key32 random bytes generated by your phone when you redeem the invitation. If we generated it, we would know it.
Distributing that keyIt is sealed separately (crypto_box_seal) for your public key and for the business’s. We only store the two sealed envelopes.
Encryption of each messageXChaCha20-Poly1305 with a random 24-byte nonce
Associated dataEach message is bound to its conversation, its sender, its identifier and the key version. A server cannot move it to another conversation, duplicate it under another identifier or pass off one of your messages as one from the business.
PaddingUp to multiples of 256 bytes, to hide the exact length
Business key signatureEd25519, with the platform key
Key rotation signatureEd25519, with the business’s own signing key (see below)
FingerprintsBLAKE2b-256 with domain separation

Encrypted attachments

Photos and documents are encrypted on the device that sends them (your phone or the business’s server), just like text:

What it protects

What it doesn’t protect

Platform key and business verification

Before a business can send invitations, we check that it legally exists, that it controls its domain (DNS record) and the WhatsApp number it invites from. We then sign its public key with our Ed25519 platform key. The app verifies that signature and shows the Verified business badge.

Platform public key (Ed25519, base64url):

qxh_sOak_wQVqZifJjDcoy-TeWIF3NADjqsjta0GPlw

What gets signed is exactly SecureChat|v1|company-key|<companyId>|<keyVersion>|<public key>. This concentrates the risk on us: if someone stole the platform key, they could impersonate a brand. That is why the link check also exists.

The business generates its own key pair on its infrastructure with our SDK (npx @securechat/sdk keygen) and only uploads the public key to us. The portal does not offer to generate it in the browser: if the private key went through our servers, the promise would no longer be verifiable.

Unverified businesses and Test mode

So that a business can test its integration while we review it, it can create test invitations. Its key is not signed as verified, so anyone could sign up as “Bank X” and use them to impersonate a brand. That is why:

Encryption is the same as in a regular conversation. What changes is the identity guarantee: in a test conversation we have not checked who the business is.

The fingerprint in the invitation link

When the business creates the invitation with the SDK, it adds a #s=…&fp=… fragment to the link. Browsers don’t send the fragment to the server, so we never see it, but the link travels over WhatsApp, a channel we don’t control. When you redeem it:

  1. The app checks that the business key we provide matches the fp fingerprint in the link.
  2. The app binds its own key to the secret s with a MAC, and the business verifies it.

If we swapped either key, one of the two ends would detect it. Limits: it only covers redeeming by link, not a typed short code, and invitations created manually in the portal don’t include that secret.

Key rotation signed by the business

Besides its encryption key, the business uses the SDK to generate an Ed25519 signing key that also stays on its infrastructure; it only uploads the public key to us. The app pins it at first contact, together with the encryption key. When the business rotates its encryption key, it signs the change with that signing key: SecureChat|v1|company-key-rotation|<companyId>|<previous version>|<previous key>|<new version>|<new key>. We check the signature before accepting the new key, and the app checks it again.

Why it matters: with only our platform signature, a legitimate rotation and an impersonation by us would look the same. With the business’s signature, impersonating a business you have already pinned requires its signing key, which never goes through us. The platform signature remains mandatory in both cases. For now the signing key does not rotate: changing it is treated as an unsigned rotation.

No forward secrecy in v1

Each conversation uses a stable key. If your private key or the business’s were ever leaked, together with the stored encrypted messages, the earlier messages of that conversation could also be decrypted. Protocols like Signal renew keys with every message to prevent this; we deliberately left it out of the first version of the protocol and it is on our roadmap.

Metadata

Even though we don’t see the content, we do see who talks to which business, when and how often, the approximate size of each message (rounded to 256 bytes), the size and date of each attachment, IP addresses and device details. That is enough to infer quite a lot, which is why we declare it in the privacy policy.

Your history is tied to your device: if you lose it, you get each conversation back with a new invitation from the business, which seals the key again for your new device.

Report a vulnerability

Email us at soporte@securechat-app.com with the subject “Security”. We ask you to allow us a reasonable time to fix it before disclosing it.