Security

End-to-end encryption you can verify — because trust shouldn't require blind faith.

Zero-knowledge server

The Contastic server is intentionally blind to your private data.

🚫

No plaintext private data

Private contact fields are encrypted on your device with the recipient's RSA public key before upload. The server stores only the resulting ciphertext.

🔑

Private keys stay local

Your RSA private key is generated locally and never transmitted in plaintext. An encrypted backup is optionally stored on the server — but only you can decrypt it.

👁️

What the server CAN see

Email address, public RSA key, public contact fields (FN, EMAIL, etc. marked public), subscription relationships, and encrypted blobs. Nothing else.

Cryptographic design

Standard algorithms, no proprietary crypto.

Key generation: RSA-OAEP 2048-bit

On registration, a 2048-bit RSA key pair is generated locally using the Web Crypto API (browser) or Android's KeyPairGenerator. Public exponent: 65537.

Data encryption: RSA-OAEP/SHA-256

Each private data value is independently encrypted with the recipient's RSA public key. MGF1 uses SHA-256 for both Android and Web Crypto interoperability.

Key backup: PBKDF2+AES-GCM

Private key backups are encrypted with AES-256-GCM. The AES key is derived from your password using PBKDF2 (100,000 iterations, SHA-256, 16-byte salt).

Password hashing: argon2 (bcrypt fallback)

Passwords are hashed with argon2id server-side. Legacy bcrypt hashes are transparently upgraded to argon2 on next login.

Server hardening

Defense-in-depth for the backend API.

🛡️

Rate limiting

Login (5/min), register (3/hr), search (30/min), and subscription endpoints are rate-limited in production to prevent brute-force and abuse.

🚧

Scanner ban middleware

Any IP that probes non-API paths (e.g. /.env, /wp-admin) is automatically banned for 24 hours after two probes.

🌐

Strict CORS

Only explicitly allowlisted origins are permitted. No wildcard CORS policy.

📏

Request body limits

Default 1 MB limit; 10 MB override for key backup uploads. Prevents memory exhaustion attacks.

⏱️

Constant-time auth checks

Login performs a dummy hash comparison for non-existent users to prevent timing-based account enumeration.

🔐

Non-root container

The Docker container runs as a dedicated non-root appuser to limit the blast radius of any exploit.

Open source

You don't have to take our word for it.

All three components — server, web client, and Android app — are open source on GitHub. Audit the code, run your own instance, and contribute improvements.

View on GitHub