PaperPhonePlus
A WeChat-style, end-to-end encrypted instant messaging application.
Rewritten with React 19 + TypeScript + Vite frontend and Rust (Axum) backend
for maximum performance and type safety.
Security — v2.4.7
- Hybrid X25519 + ML-KEM-768 + XSalsa20-Poly1305 — message headers identify the actual
PQ v2, downgraded X25519 ↓, or group SK vN protocol
- Fail-closed encrypted sending — encryption, key-distribution, and secure-storage failures stop the send instead of falling back to plaintext
- Zero-knowledge encryption scope — encrypted conversation bodies are stored as ciphertext; the server still processes essential account, contact/group, routing, and push metadata
- Protected local secrets — the Web client uses AES-GCM-wrapped IndexedDB; Android, iOS, Windows, and macOS clients use operating-system secure storage for identity private keys and Sender Keys
- Extra text-appearance insurance above E2EE — the body is first encrypted with the shared extra password and rendered in one of eight appearances, then protected again by the existing private-chat E2EE or group Sender Key encryption; the password is never uploaded or synchronized
Features
- 📹 Video & Voice Calls — LiveKit SFU for both 1:1 calls and meetings (up to 100 participants, host mute-all and lecture mode)
- 🎙️ Voice Changer — real-time voice effects for voice messages, 1:1 calls & group calls with 3 modes (0.8x deep / 1.0x normal / 1.2x high-pitched), powered by Web Audio API
- 🎭 Text Appearance & Extra Encryption — configure one extra password under Profile > Message privacy for every chat on the device; choose Buddhist text, random Chinese, I Ching symbols, Hangul, Egyptian hieroglyphs, Cuneiform, Core Values text, or letters and numbers; supports immediate lock and 5/15/30/60-minute background auto-lock. Both private-chat participants, or every group member, need the same password. If passwords differ, E2EE and delivery still work, but recipients see only styled ciphertext. This extra insurance does not replace, bypass, or downgrade E2EE
- ⏱️ Safe Voice Recording — 120-second automatic limit, wake lock while recording, and reliable microphone cleanup on page exit
- 📱 Session Persistence — 30-minute access tokens with 90-day device refresh sessions; VPN/IP/network changes reconnect without asking for a password
- 📨 Reliable Message Sync — bidirectional heartbeat, persistent outbox, idempotent message IDs, and server-sequence cursor catch-up
- 📴 Offline Access — account-isolated contacts, groups, chats, Moments, Timeline, and media cache; offline sends retry automatically
- 🔎 Unicode Friend Search — IME-safe, NFC-normalized Chinese username and nickname search
- 👥 Group Chat — up to 2000 members, switchable "Encrypted" / "Unencrypted" modes (owner-only toggle, switching clears chat history). Encrypted mode uses Signal-style Sender Key protocol (XSalsa20-Poly1305 + ECDH key distribution) — only members can decrypt; bots disabled in encrypted mode. DND mode, member management
- 🌐 Moments — social feed with text + up to 9 photos or 1 video (≤ 10 min), likes, comments, tag-based visibility
- 👤 User Profile — contact profile page with Moments feed, bidirectional privacy controls (hide their / hide mine)
- 📰 Timeline — Xiaohongshu-style public feed with masonry layout, up to 50 images/videos + 2000-char text, anonymous posting, likes & comments
- ⏱️ Auto-Delete Messages — 5 tiers: never / 1 day / 3 days / 1 week / 1 month
- 🔔 Push Notifications — Web Push (VAPID) + FCM + OneSignal + ntfy + APNS five-channel (iOS native + Chinese Android without Google Services supported)
- 🌐 Multi-language — Chinese, English, Japanese, Korean, French, German, Russian, Spanish
- 📱 iOS PWA — "Add to Home Screen" via Safari, no enterprise cert needed
- 💬 Rich messaging: text, images, video, document files (PDF/DOCX/XLSX etc. with type icons), voice, 200+ emoji (8 categories), Telegram sticker packs, delivery receipts, typing indicators
- 🗂️ Cloudflare R2 file storage (images, voice & video)
- 🏷️ Friend Tags — tag-based contact filtering & Moments visibility control
- 🎭 Telegram Sticker Packs — dynamic sticker packs with configurable pack list (13 built-in defaults), unlimited quantity
- 🔑 Two-Factor Auth (2FA) — Google Authenticator TOTP, 8 recovery codes
- 📷 QR Code Scan & Share — scan QR to add friends or join groups; group QR codes with configurable expiry (1 week / 1 month / 3 months)
- 👫 Friend System — friend requests require approval with up to 512-char message; custom nicknames; multi-tag grouping
- 📤 File Upload — up to 500MB per file, Cloudflare R2 or local storage, with progress animation
- 🌐 Proxy Settings — SOCKS5 / HTTP / HTTPS proxy support, configurable on login and settings pages (address, port, username, password)
- 🛡️ Content Moderation — User reporting (6 reason categories) + user blocking (instantly hides posts/messages) + Terms of Use (EULA)
- 🔧 Admin Panel — Embedded web dashboard (
/admin, path customizable via ADMIN_PATH), password-protected, review reports, delete content, ban users — 8 languages
After Deployment
- Open the domain assigned to the client service.
- Register an account — cryptographic keys are generated locally on your device.
- (Optional) Configure Cloudflare R2 for image/voice/video uploads — set
R2_* variables on the server service.
- (Optional) Enable push notifications — set
VAPID_* variables for Web Push, FCM_* for native Android (Capacitor), APNS_* for native iOS.
- (Optional) Enable Telegram sticker packs — set
TELEGRAM_BOT_TOKEN and optionally STICKER_PACKS.
- (Optional) Access the admin panel at
/admin (or custom ADMIN_PATH) to moderate user reports. Set ADMIN_PASSWORD for production security.
- After an upgrade, inspect the server logs and confirm it becomes healthy before updating clients. Test a VPN/network switch and an offline send to verify automatic recovery and exactly-once storage.
- For v2.4.6, test an encrypted send with key delivery unavailable and confirm it fails without transmitting plaintext; verify the protocol badge matches the actual envelope.
- Lock extra message encryption, select unlock, and confirm the dialog asks for the unlock password rather than asking users to set a password; spot-check all required UI languages.
- Enable the optional history password, select each text appearance, background the app past the selected timeout, and confirm only presentation ciphertext is visible until the correct password is entered. Then try to disable it and confirm the correct extra password must be re-entered even while unlocked.
MySQL is started with utf8mb4 and utf8mb4_unicode_ci. On startup, the server automatically migrates and verifies the message sequence, idempotency, refresh-session, and searchable-character-set fields. For upgrades, redeploy the server first and wait for it to become healthy before updating clients. Back up MySQL before production upgrades.
LiveKit calls on Zeabur
This template deploys a LiveKit service with WebSocket/API (7880) and ICE/TCP
fallback (7881). Zeabur currently does not expose UDP service ports, so calls
can connect over TCP but may have higher latency or reduced quality on weak networks.
The template keeps the LiveKit configuration ready for UDP 7882; expose it when
Zeabur adds UDP support. For production-quality 100-person meetings today, use
LiveKit Cloud or deploy LiveKit on a VM with UDP 7882 and set LIVEKIT_URL on server.
Tip: Zeabur + Vercel Hybrid
You can delete the deployed client service on Zeabur and use Vercel to host the frontend instead.
This gives you Vercel’s global CDN for the frontend while Zeabur handles server/MySQL/Redis.
Just set VITE_API_URL in Vercel to the public domain of this server service.
Docker Hub Images
facilisvelox/paperphone-plus-client:latest
facilisvelox/paperphone-plus-server:latest