Your bank OTPs on every device, even with no signal.

Your bank texts each OTP to one phone, and only when it has signal. Some banks email the same code. pux takes it from that email and pushes it to your computer and every phone you add, over Wi-Fi or any other internet connection.

Early release: not in any app store yet, so for now you build the apps from source.

An example: abroad on hotel Wi-Fi, with your SIM off

Text message

No service. The SMS hasn't arrived.

pux, over Wi-Fi, on your phone and laptop

OTP from HSBC

482913

Every device, any connection

A texted OTP reaches one phone, the one with your SIM in it, and only while that phone has a mobile network. pux sends the code to every phone and computer you add, over whatever internet connection they have.

On your computer and every phone

  • On your desktop. The code appears on your Mac or Linux computer, where you're logging in. No reaching for your phone to copy six digits across.
  • On more than one phone. Add a second phone, or the phone of someone you share an account with. Each one gets every code.
  • Away from your bank SIM. The SIM your bank texts can stay in a spare phone at home while the codes reach the devices you carry.

When the SMS doesn't come

  • Travelling. Your home SIM is off, roaming is expensive, or you're on a local SIM. Hotel or cafĂ© Wi-Fi is enough.
  • Weak signal. Basements, lifts, big office buildings and patchy rural coverage. If there's Wi-Fi, the code gets through.

How it works

Your bank already emails the code. pux carries it from your mailbox to your devices over the internet, and seals it for every hop after the pux server.

  1. Your bank

    Emails you an OTP, as it does today.

    Readable
  2. Your mailbox

    A forwarding rule you set up sends those emails to your pux inbox address.

    Readable
  3. pux server

    Reads the email in memory, finds the code, checks DKIM and seals the result to your public key. The email is then discarded.

    Briefly readable, in memory
  4. Delivery

    Firebase Cloud Messaging carries the sealed envelope to phones. Desktops fetch it from the server over a WebSocket.

    Sealed
  5. Your device

    Opens the envelope with the private key that was generated on it, and shows the code.

    Readable by you

Setting it up

  1. Install the app and tap Create new relay. Your keys are generated on the phone.
  2. Copy the inbox address it shows and forward your bank's OTP emails there. If Gmail asks you to confirm forwarding, the confirmation code arrives in the app too.
  3. Allow notifications. To add a desktop, export the enrollment from your phone.

Supported banks

These banks are shown by name when the email's DKIM signature verifies.

  • HSBC
  • RBL Bank
  • American Express

Other senders aren't blocked. If pux can find a code in the email, it is delivered under the sender's domain, and marked unverified when no DKIM signature aligns. Bank missing? Adding one is a small change. pux isn't affiliated with or endorsed by any of these banks.

Platforms

Platform Delivery Status
Android Push through Firebase Create a relay or scan a QR code
iOS Push through Firebase and APNs Built, but push hasn't been tested on a real device yet
macOS and Linux WebSocket, with polling as a fallback Import an enrollment from your phone
Windows None Not supported for now

Careful with your codes

An OTP is the last step between someone and your bank account, so pux handles it with care. Here is what it guarantees, and where those guarantees stop. The security policy has the full version, and all of this can be checked in the source.

What pux does

  • Keys stay on your device. The keypair is generated on your phone and the server only gets the public key. The private key leaves the phone only if you export an enrollment to add another device.
  • Codes are sealed before they're stored or sent. Each payload is encrypted with a libsodium sealed box. The server has no key that can open one afterwards.
  • Mail isn't stored. Plaintext exists only in memory while a message is parsed. Email without a code is dropped.
  • No accounts. No name, email or password. A random record ID is the only credential.
  • Sender names have to be earned. A bank's name is shown only when a valid DKIM signature aligns with the From domain. Without one, the message is marked unverified.

Where it stops

  • You trust the server for a moment. It has to read the email to find the code. Code running on it could see that plaintext, which is why the source is open and you can run your own.
  • Your mail provider still sees your mail. So does anything else on the path before pux. pux protects the code after that point.
  • DKIM doesn't stop replays. A genuinely signed bank email can be sent on to another inbox address and still verify.
  • The record ID is a credential. It's sent only in a request header, so a reverse proxy that logs paths doesn't capture it. On its own, it lets someone use the relay's API, including deleting the relay, but not read its OTPs.
  • Your enrollment is the keys. Anyone holding the QR code or JSON export has the record ID and private key, and can read that relay's OTPs.
  • Your device has to be safe. pux can't protect codes on a rooted, jailbroken or compromised device.

What the server stores, and for how long

Data Form Kept for
Email contents In memory only, while parsing Never written to disk or the database
Push jobs Sealed envelope, in the database Deleted about 10 minutes after the job finishes
Desktop deliveries Sealed envelope, in the database. Only if the relay has a desktop Until the desktop confirms it, up to about 15 minutes
Relay Record ID, inbox token, public key, last activity Until you delete it, or 30 days after it loses its last device
Device Push token, platform, last seen, last token check Phones: until you remove it, the push service reports it's no longer valid, or 2 years with no app open and no code delivered. Desktops: until you remove it, or 90 days without registering

Questions

Do I need mobile signal?

No. Each device needs an internet connection, over Wi-Fi or mobile data. Your bank still sends its usual SMS, and pux delivers the emailed copy alongside it, so whichever reaches you first works.

Which OTPs can pux deliver?

Only ones your bank also sends by email. If a bank sends a code by SMS alone, pux never sees it. To check, look in your inbox after your next login or payment.

How do I add my computer or another phone?

Export the enrollment from the phone that created the relay. Another phone scans it as a QR code, and a Mac or Linux computer imports it as JSON. Anyone holding the enrollment can read that relay's OTPs, so only add devices you trust.

Can you read my OTPs?

Not once they're sealed, and nothing readable is kept. But the server does have to read each email in memory to find the code, so for that moment the plaintext is on a machine you don't control. The code that does this is public. If that moment is too much trust, run your own server.

Does anything get stored at all?

Yes, but no mail and no readable codes. Sealed envelopes sit in the database for a few minutes while they're delivered, and the server keeps the relay and device details listed in the table above.

Does a verified bank name prove the email is genuine?

It proves the bank's domain signed that email. It doesn't prove the email was meant for you, because a signed message can be replayed to another inbox address. Check that a code matches something you just did.

What if someone learns my inbox address?

Addresses are unguessable but not secret. Anyone who has yours can send mail to it, and any code it contains reaches you under that sender's domain. Delivery is limited to 20 codes per relay every 10 minutes and extra mail is dropped, so a flood could delay real codes. You can delete the relay and create a new one.

Can a code get lost?

Yes. Push services can delay messages, undelivered pushes expire after 5 minutes, and rate limits can drop mail. Android can pause an app that hasn't been used for a few months, which stops its pushes until you open it; turn off Pause app activity if unused in the app's Android settings. Mail to a relay with no registered devices is refused, so the sender gets a bounce. Keep your bank's usual way of getting a code available.

How do I delete my data?

In the app, Delete relay everywhere removes the relay, its devices and any pending deliveries from the server. Remove this device removes one device. You can also email privacy@vidur.xyz with your inbox address, but never send your record ID, enrollment JSON or private key. A device is removed after 2 years with no app open and no code delivered, and a relay is deleted automatically 30 days after it loses its last device.

Where do I get the app?

It isn't in any app store yet, and there's no published release. For now, the apps are built from source.

Run your own

The hosted instance is pux.vidur.xyz, and you don't have to use it. The whole service is free software under the AGPL-3.0.

Self-hosting guide

  • The server and PostgreSQL run with Docker Compose.
  • You need a domain, a TLS-terminating reverse proxy and a host that can receive mail on port 25.
  • Desktop apps work against your server with nothing else.
  • Push to phones needs your own Firebase project and your own app build.