The encryption

  • Identity: an Ed25519 key pair on the device, without an email address or phone number. Every message is signed with it.
  • Bubble: a random 32-byte root key. HKDF derives the mailbox ID the relay sees (random-looking, unrelated to the name) and the content key for ChaCha20-Poly1305.
  • Message: JSON → sign → encrypt. Mailbox and message ID are bound as associated data, so the server can neither alter messages nor replay them under a new ID.
  • Hearts and comments: separate signed, encrypted messages carrying the post’s ID. They expire with the post and are deleted with it.
  • Profile: name, profile picture (512 × 512, without metadata) and bio are only sent, encrypted, to the Bubbles you are in.
  • Lifetime: 24h posts get an expiresAt. The relay deletes them permanently, and the app hides them on its own as well.
  • Photos: are rotated on the device, scaled down to at most 1600 px and re-saved as JPEG. EXIF and GPS data are removed in the process.
  • On the device: keys live in the platform’s secure storage (Keystore, Keychain, DPAPI). Android cloud backups are disabled.

Invites

An invite is a link like bubble://join#…. The key sits in the fragment after the #, so it never reaches a server. The app shows it as a QR code, generated locally and scanned with the camera.

Alternatively there is a short code like 7KQ2M-9XH4T, valid for 24 hours. From the code, the app derives a mailbox ID and a key with Argon2id. The invite is stored encrypted on the relay under that ID. The relay sees neither the code nor the Bubble.

QR code, link and code contain the Bubble’s key. Only share them with people who should be in it.

Backup and new devices

  1. During setup, the app creates a backup code with 25 characters (125 bits). It’s best to keep it in your password manager.
  2. Argon2id derives a key, a backup ID and a write token from the code.
  3. Your identity and all Bubble keys are backed up, encrypted, on the server. The backup updates itself, for example when you join a Bubble.
  4. On a new device, the code is all you need to restore everything.

The data format leaves room for a passkey as a second option. It isn’t in the app yet.

What the relay knows

knowsdoesn’t know
Mailbox IDs, number and size of messagesNames of Bubbles or people, content, photos
Expiry time of 24h postswho is in which Bubble (there are no accounts)
IP addresses during a request (not logged or stored)the content of backups

Known gaps in the MVP

Bubble is still in development. These points are known and open:

  • No member management: whoever has the invite link is in. Removing someone would require key rotation, which doesn’t exist yet.
  • No rate limiting and no storage quotas on the relay.
  • No local cache: the feed is loaded completely every time you open it.
  • Short invite codes can be guessed: 50 bits, but only valid for 24 h and slowed down by Argon2id. When in doubt, use the QR code or link.
  • Not included: push notifications, story editor, passkey, emoji reactions.