HOW IT WORKS

Everything, broken down

No part of Owli is secret or unexplainable. Here's exactly what happens from the moment you create an identity to the moment a message reaches someone else — in plain language, with the real technical detail underneath for anyone who wants it.

OPEN STANDARDS - NOTHING HERE IS PROPRIETARY

NIP-01 Base protocol
NIP-17 Private DMs
NIP-19 Key encoding
NIP-40 Expiration
NIP-44 Encryption
NIP-57 Zaps
NIP-59 Gift wrap
Double Ratchet Forward secrecy
BIP-39 Recovery phrase
secp256k1 Key curve
PBKDF2-SHA256 Password KDF
AES-256-GCM Storage at rest
WebAuthn / PRF Passkey unlock
LUD-16 / LUD-18 Lightning address

UNDER THE HOOD

What actually happens, step by step

Two flows cover almost everything: creating your account, and sending a message. Everything else on this page builds on these two.

🔑

Creating your account

✉️

Sending a message

1

Your device generates a keypair

A secp256k1 keypair is created locally, on-device. Nothing is sent anywhere yet - there's no account to register.

1

You hit send

Your device checks whether a Double Ratchet session already exists with this contact.

2

You get a 24-word recovery phrase

The private key is encoded directly as a BIP-39 mnemonic - the same 32 bytes, just written as words. It's the one and only real backup.

2

The message is encrypted with a one-time key

If a ratchet session exists, every message gets its own throwaway key (forward secrecy). If not, it falls back automatically to standard NIP-17 encryption - no visible difference to you.

3

You choose how this device unlocks it

A device password (PBKDF2-SHA256, 600,000 rounds, AES-256-GCM), a passkey (Face ID/Touch ID via WebAuthn), or skip entirely - nothing saved, phrase needed every time.

3

It's sealed, then gift-wrapped

One layer of encryption hides the content; a second, outer layer (NIP-59) hides who sent it too - the wrapper that relays actually see reveals only the recipient.

4

Everything local gets encrypted at rest

Contacts and messages are encrypted with a separate storage key before they ever touch the browser's on-disk database - a stolen device without your password reveals nothing.

4

It's published to independent relays

Plain WebSocket servers hold the encrypted blob briefly, and can be asked to prune it later (NIP-40). They can't read it and can't tell who sent it.

5

You're in

Your public key is your address. Share it (as npub) so people can add you - your private key never left the device.

5

Their device unwraps and decrypts it

The plaintext only ever exists on your device and theirs - never on a relay, never on a server in between.

Private. Decentralized. End-to-end encrypted.

No accounts. No central server. No company in the loop.

You own your identity
Your data stays on your device
Relays can't read or identify you
Only the recipient can decrypt

THE FULL PICTURE

Every piece, explained in full

🔑

Creating your identity

When you create an account, your device generates a random pair of keys: one you keep secret, one you share. Together with a 24-word recovery phrase, this pair is your identity. There's no username, no password, and no company keeping a list of accounts anywhere — just this key, on your device. Those 24 words are the only way back in if you ever lose this device, so writing them down somewhere safe is the single most important step.

Technical detail

On Create, the app generates a secp256k1 keypair on-device using cryptographically secure randomness — the same curve every Nostr key uses. The 32-byte private key is encoded directly as entropy into a 24-word BIP-39 mnemonic (the same standard Bitcoin wallets use for seed phrases). The public key becomes your Nostr pubkey; the private key never leaves the device unencrypted. The same bytes can equally be written as standard npub1…/nsec1… (NIP-19 bech32) — Owli can show either, they're the exact same key.

✉️

Sending a message

Your device locks each message with a key that only the recipient can open, before it ever leaves your phone or computer. It then passes through a small network of independent relay servers, which briefly hold it and hand it over once the recipient is online. Those relays never see what you wrote — only that some encrypted data passed through, addressed to a specific person. You can also set messages to carry an expiry, asking relays to prune them after a chosen time so encrypted packets don't sit around indefinitely.

Technical detail

Messages use the Nostr protocol's NIP-17 private direct messages: the plaintext is wrapped in an unsigned "rumor," sealed with a key derived via ECDH between sender and recipient (NIP-44 encryption, signed with the sender's real key), then wrapped again with a one-time throwaway key so even that signature doesn't reveal who sent it (NIP-59 gift wrap). Only this outermost layer is what relays ever see or store. Relays are a plain list of independent WebSocket servers — nothing operated or logged by Owli. Messages can optionally carry a NIP-40 expiration tag, a plain unix timestamp in the gift wrap's tags, asking a compliant relay to delete the event once it's passed — a relay-side request, not a guarantee, and it has no effect on the copy already decrypted and stored on your own device.

🔁

Forward secrecy — the Double Ratchet

Once your device and a contact's have exchanged a couple of messages, Owli quietly upgrades that conversation to a stronger form of encryption called a Double Ratchet — the same core technique used by Signal. Instead of one key protecting the whole conversation, every message gets its own key that's thrown away right after use. If someone ever stole today's key, none of your past messages could be unlocked with it. This happens automatically; if the other person's device hasn't upgraded yet, your messages keep working over the standard method until it can.

Technical detail

Layered underneath NIP-17, following a NIP-104-shaped Double Ratchet transport: once a contact has published an invite event, a session is established with per-message symmetric-ratchet keys derived via HKDF, giving forward secrecy and post-compromise security beyond a single long-term key. Falls back transparently to plain NIP-17 if the other side hasn't published an invite yet.

🛡️

What protects it in transit

The lock on your message is the same style of encryption used by other trusted secure messengers. Even someone intercepting traffic between relays, or running a relay themselves, would only ever see scrambled bytes — never your message.

Technical detail

NIP-44 v2: a per-message key derived via ECDH over secp256k1 and HKDF, then ChaCha20 for encryption and HMAC-SHA256 for authentication, so tampered ciphertext fails to decrypt rather than silently returning garbage. The connection itself is plain WebSocket unless you're using Tor Browser, in which case it's also wrapped in Tor's own onion-routing encryption.

👥

Group chats

Groups work the same way as one-to-one chats underneath: every member is connected to every other member through the same private, upgraded channel used elsewhere in the app. There's no group server or shared room key sitting on a relay somewhere. When someone's added, removed, or a group detail changes, that update is sent privately to every current member individually.

Technical detail

NIP-104-shaped sender-keys group messaging, built directly on the same pairwise Double Ratchet sessions above — not NIP-EE/MLS, which is a different, separate proposal some other Nostr clients use instead. Roster and metadata changes are fanned out as a metadata rumor, sent individually to every remaining member over their existing pairwise session.

Zaps

A zap is a real Bitcoin payment sent over the Lightning Network — not a token or points system. Tapping the zap button on a contact with a Lightning address fetches a real invoice from their wallet provider and hands it to your own wallet app to pay. Owli never touches the money; it only helps the two wallets find each other. Because zaps are a public Nostr feature, a receipt confirming payment is published openly, same as on any other Nostr app.

Technical detail

NIP-57 zaps: a signed zap request (kind 9734, profile-level) is sent to the recipient's LNURL-pay callback, which returns a bolt11 invoice handed to the user's own wallet via a lightning: deep link. If the provider supports it, a public zap receipt (kind 9735) is published once paid. Owli never holds funds or a wallet credential.

🤝

Trade proposals

The trade feature lets two people agree the terms of a Bitcoin trade — what's being exchanged, the amount, where to send payment — entirely inside their private encrypted conversation, with accept/decline buttons and a status you both see. Owli never verifies or holds any of the money; it only carries the negotiation privately. Marking a trade paid or received is just each side honestly reporting what happened on their end.

Technical detail

A dedicated rumor kind, routed through the same pairwise ratchet session as regular messages — never a public event. Deliberately doesn't reuse zap receipts: those are public by design, which would leak the existence of a private trade. Status is self-reported by each side independently; Owli performs no verification of settlement.

🫥

The Sten tool

Sten hides a message inside an ordinary-looking emoji. To anyone else, it's just an emoji; only someone who pastes it back into this same tool can reveal the hidden text. It's camouflage, not real security — the technique is public and well-known, so a message specifically checked for hiding can be found. A screenshot destroys the hidden part entirely.

Technical detail

Encodes UTF-8 text as bytes, then appends one Unicode variation-selector codepoint per byte after a visible base emoji. No cryptographic protection — purely a visibility/steganography technique. Some platforms strip unrecognized Unicode ranges in transit, which also destroys it.

🗑️

Wiping data and recovering your account

Wiping deletes your key, contacts, and messages from this device permanently. Nothing is kept anywhere unless you set up a backup yourself first. To get back in afterward, your 24-word recovery phrase re-creates the exact same identity, so people can still reach you at the same address — but contacts and message history don't come back automatically that way unless you'd turned on relay backup or saved an export file beforehand.

Technical detail

Wipe clears local storage entirely, including the IndexedDB stores holding contacts and message history. Recovery re-derives the identical secp256k1 keypair from the BIP-39 phrase (deterministic), so the public key is unchanged. Contacts/messages return only via an optional relay-published encrypted snapshot (gift-wrapped to your own pubkey) or a manually exported backup file.

See who this actually helps

From everyday conversations to journalists, activists, and anyone whose safety depends on privacy holding up.

Who it's for →