Veto · Private messenger

Private messaging without a phone number

Veto is an end-to-end encrypted messenger: local identity, keys on the device and relays that only see ciphertext. We built the site, the web app and a native Flutter app for Android and iOS, all on one Rust core.

Two Android phones, each with its own identity, chatting through two local relays: request accepted, messages, a reaction and a quoted reply. Invented contacts.
In short

Veto is an end-to-end encrypted messenger that doesn't ask for a phone number: identity and keys are created on the device, and messages travel through several relays that only see ciphertext. We built its trilingual site, the /app PWA and, in October 2026, a native Flutter app that runs the same Rust cryptographic core as the web. On the phone, the app adds contacts by link or QR code, runs groups and polls, and locks behind a local passcode.

Client
Veto · Private messenger
Sector
Privacy and messaging
Year
2026
Deliverables
  • Native Flutter app (Android, iOS)
  • Rust core over FFI
  • PWA at /app
  • Trilingual marketing site
  • E2E multi-relay architecture
0phone numbers required
ML-KEM-768+ X25519 hybrid handshake
4,366lines in the Rust crypto core
50mobile app tests
The context

Nobody in the middle reads the messages

The brief for Veto was strict. Scanners, relays and operators should never see plaintext, and nobody should need a phone number or an SMS to join. The security claims also had to be honest: a privacy product that overstates its protection breaks the trust it asks for. The project needed a real product and a clear statement of where it stands.

Design and build

A native app on the same Rust core

In October 2026 we replaced the Capacitor shells with a native Flutter app for Android and iOS. Rewriting the protocol in Dart would have forked the cryptography and split Veto into two networks that can't talk to each other. So the app calls the same Rust core as the web app, through a small C interface (veto-ffi). Secrets stay behind native handles; Dart only receives public keys, ciphertext and the plaintext it asks for. Golden test vectors generated from the TypeScript code run in both test suites, and CI fails if web and native drift apart.

The native app uses the same relays as the web app, so a phone user and a browser user add each other with the same invite link or QR code. A message counts as delivered once at least two relays have stored it. On the phone, every SQLite row is sealed under the vault key, and that key is wrapped again with a device key kept in the Android Keystore or the iOS Keychain: copying the app's files doesn't allow offline passcode guessing. The app locks after five minutes in the background and hides chats in the app switcher.

The repository has 217 commits since May 2026. The app is 53 Dart files and 16,369 lines, with 50 test cases, on top of a 4,366-line Rust crypto crate. An end-to-end script runs the real APK on an emulator against the real web app.

First run of the native app: welcome, name, local passcode and the empty chat list. No phone number asked.
  1. 01

    Flutter app, Rust core

    One Flutter codebase for Android and iOS calls the same Rust cryptography as the web app through veto-ffi, so there is a single protocol to maintain.

  2. 02

    Hybrid handshake

    Protocol v2 combines X25519 and ML-KEM-768 in the handshake, then runs a Double Ratchet with periodic ML-KEM re-keys. The post-quantum part protects message confidentiality.

  3. 03

    Safety numbers

    Each contact has a 60-digit safety number in 12 groups of 5. You compare it in person or on a call, mark the contact as verified, and Veto warns you if the keys change.

  4. 04

    Phone, laptop and web

    The web app runs in any laptop browser and meets native users on the same relays. The native app doesn't link devices yet, so each device has its own identity.

Outcomes

One messenger on phone, laptop and web

Veto now runs as a native app on Android and iPhone and as a web app on laptops and desktops, with the same relays and the same invite links. Groups, polls, stickers, reactions, replies, locked chats and a dark theme work in the native app, and Veto Echo, a demo contact that runs on the phone itself, lets a new user try it alone.

  • Native Flutter app over the same Rust core as the web app
  • Same relays and invite links for phone and browser users
  • 50 mobile tests and golden vectors shared with the web code
Frequently asked questions

The questions we hear often

Is the Veto app safe?

Veto encrypts each message on your device before it leaves, with a hybrid X25519 + ML-KEM-768 handshake and a Double Ratchet, and the relays only carry sealed envelopes they can't read. The app's own "Honest status" note sets the limit: post-quantum protection covers message confidentiality, while identity checks are classical, so compare safety numbers with the people you talk to.

Do I need a phone number to use Veto?

No. Veto asks for no phone number, no e-mail and no account. Your identity and keys are created on your device, and you add people by sharing an invite link or showing a QR code.

Can I use Veto on a laptop?

Yes, through the web app in a browser, which you can install as a PWA. It runs the same Rust cryptographic core as the phone app and uses the same relays, so laptop and phone users can add each other. The native app doesn't link devices yet, so the laptop gets its own identity.

Is there a Veto app for my phone?

Yes: a native app for Android and iPhone, built from one Flutter codebase. It creates your identity on the phone and asks for no phone number to get started.

Talk to Slash

Let's put it in production

Tell us your challenge. We reply within 24 business hours with an honest first read: if we can help, we'll say how; if not, we'll say who can.

I reply personally. No endless forms, no canned replies.

Message Esteban