Indian banks send billions of SMS OTPs a year. Each one is a shared secret broadcast in plaintext across a 1970s protocol (SS7) and a 1990s network (GSM). SIM swap costs ₹40,000 on the dark web; SS7 intercept costs $500. Zoza Auth replaces the OTP with a 30-second Curve25519 challenge signed inside the Secure Enclave / Android Keystore. No shared secret — no SIM swap attack surface. Same tap-to-approve UX banks already ship.
Every Zoza product passes through a 5-point rigor gate before any customer-facing scaffolding is built. Auth's analysis lives right here on this page — not in a closed-door deck. If you find a gap, tell us and we'll either fix it or explicitly mark it as "NOT built yet".
| Solution | Shared secret? | Works offline? | Cross-bank portable? | India & EU? | Per-auth cost |
|---|---|---|---|---|---|
| SMS OTP (Twilio / MSG91) | Yes — 6 digits on the wire | Yes (at SMS layer) | No — per-bank | Yes | ₹0.15–0.50 |
| Apple / Google Passkeys | No | Yes | No — platform-locked | Yes (if Apple/Google acct) | $0 |
| Indian bank Face ID (today) | Session token + PIN | Yes after first login | No — per-bank | Yes (RBI cleared) | Included in IMPS |
| Authy / Google Authenticator (TOTP) | Yes — HMAC seed | Yes | No — per-account | Yes | $0 (but user-managed) |
| Zoza Auth | No — asymmetric keys | Yes (challenge is pushed) | Yes — one registered device per user, many banks | Yes (RBI + DPDP scoped) | Target < ₹0.05 |
Attacker social-engineers the telco store, ports the victim's number to a new SIM, intercepts every OTP. Costs ₹40,000–₹2L on the Indian darknet. A ₹1 trillion-rupee bank runs on top of a telco counter clerk.
Twitter CEO Jack Dorsey, 2019 · T-Mobile 76M users 2021 · 10,000+ reported cases/year in India.
✓ Zoza Auth: private key lives in Secure Enclave / Android Keystore. SIM swap gives the attacker nothing — the challenge is pushed to the device registration, not the phone number.
Global SS7 mobile roaming protocol has no authentication. Any carrier can request any subscriber's SMS. Kits sold as "SMS Hunter" for $500–$3000. Cannot be patched — it's the network.
O2 Germany 2017 bank-drain attack · Metro Bank UK 2019.
✓ Zoza Auth: no SMS. Auth flows over HTTPS via the bank's webhook or the user's own device push channel (FCM/APNs). SS7 interception yields nothing.
Android "Accessibility Service" malware reads notifications and forwards OTPs to C2. Families: SharkBot, Cerberus, Brokewell. Installed via fake APKs posing as "TRAI verification" or "Income Tax app".
₹1,750 crore reported to I4C in 2024 — ~50% involved an SMS-read step.
✓ Zoza Auth: the challenge context (e.g. "Transfer ₹50,000 to Unknown Account") is shown in the app UI, signed by the bank's server key. User confirms with biometric inside our app — the malware can read the notification but cannot fake the signed response.
"I'm from PhonePe support, share the OTP to cancel the fraudulent charge." OTP is text that users can read and relay over voice. Social-engineering exploits the shared-secret nature of the OTP itself.
RBI 2024 report: 1.17 lakh digital-payment fraud cases, ₹485 cr lost — majority vishing.
✓ Zoza Auth: the cryptographic proof is a 32-byte DH value. There is nothing short and human-readable for the victim to "read out" over a phone call. The metadata field ("Pay ₹5000 to Flipkart") is what's shown — the attacker cannot alter it.
Attacker runs a real-time proxy: the victim enters their credential on a fake page, the proxy forwards to the real bank, captures the OTP from the phone, and replays within the 30-second window. Evilginx, Muraena, and commercial "phishing-as-a-service" kits automate this.
₹100 crore+ mapped to Evilginx kits targeting Indian banks 2023–2024.
✓ Zoza Auth: the challenge is bound to the bank's specific server public key. A phishing proxy cannot forward the DH proof because the victim's device rejects challenges with a mismatched ServerPub. This is the same binding Passkeys use — we port it to Indian banks.
Telco employees with access to the SMSC can read outbound OTPs. Reported abuse at multiple Indian telcos 2018–2022. The bank has no visibility.
Case-specific; under-reported.
✓ Zoza Auth: no SMS path. Zoza operators cannot read the DH proof either — even with a full database dump, every challenge is one-shot, 30s TTL, and the private key never leaves the device. See the data-policy page.
Physical theft of an unlocked device. Or "five-dollar wrench attack" — victim is coerced into authenticating.
1.3M phone thefts India 2023 (NCRB) — though most thieves aren't targeting bank auth specifically.
Partial. Zoza Auth requires biometric to unlock the private key, and supports remote revocation when the user reports theft. NOT solved today: the "wrench attack" — no authentication system solves coercion. See "What's NOT built" below.
Zoza's own Postgres is breached. What does the attacker get? Every registered device's public key, every challenge nonce, and the app's server private key. With the server private key they can forge future new challenges — but devices reject any challenge whose ServerPub doesn't match the one baked in at registration.
Hypothetical — in the design phase. Root-key rotation playbook documented in OPS.md.
Partial. Today the server private key lives as a single Fly secret. NOT done yet: HSM backing or threshold signing on the server side. Roadmap item — see "What's NOT built".
SecKeyCreateRandomKey with kSecAttrTokenIDSecureEnclave. ETA: 30 dev-days.AndroidKeyStore. Biometric prompt integration included. ETA: 25 dev-days.nonce. Banks should dedupe on challenge_id until this ships. ETA: 3 dev-days.Four surfaces, all verifiable in the browser — no word-taking.
challenge_issued, challenge_approved, challenge_denied, device_revoked is appended to auth_audit. The customer bank sees its own events via GET /v1/apps/{id}/audit. → audit policyproducts/zoza-auth/ in the source-available tree. 29 Go tests — unit + integration + adversarial (replay, wrong-key, expired, revoked, rate-limit).https://auth-api.zoza.world/health. Docs: /developers/auth.html.POST /v1/applications (rate-limited, no auth). Review happens in zoza-admin.fly.dev.auth_audit. Two-sided log.MSG91 + Twilio sell SMS OTP. Apple + Google sell Passkeys. Indian banks build Face-ID-in-the-app. Each works in its lane and stops there. Zoza Auth is designed from day one to do seven things none of those do — the category-defining 7. Not "we match what's out there", but "we raise the bar".
Passkeys are platform-locked (one per vendor). Indian bank Face ID is bank-locked (one per bank — users have 6 different apps). Zoza Auth's design: one device keypair, many banks. Same fingerprint unlocks HDFC login, SBI payment approval, and ICICI UPI PIN — each bank keeps its own server_pub and sees its own challenges, but the user carries one identity. This is the $1B India path the industry has been unable to build because platform vendors won't federate.
SMS OTP is just a 6-digit number — "Read it to me, sir" works. Zoza Auth's challenge includes signed metadata: "Pay ₹5,000 to Flipkart". That metadata is bound to the challenge cryptographically; the attacker cannot change it over a phone call. No other Indian bank OTP system binds what is being approved to the proof itself.
SMS OTP costs banks ₹0.15–0.50 per message + infrastructure. We target < ₹0.05 amortised on the enterprise tier, and ₹0 on Free. Over a billion auths a year at a major bank, this is a ₹30–45 crore direct savings on top of the security improvement.
Our client SDKs use Secure Enclave (iOS) / Android Keystore (Android) by default — not as an opt-in. A malware-infected device cannot exfiltrate the private key because it never exists outside the hardware trust boundary. TOTP apps and bank Face ID use software storage or session tokens. Zoza Auth's crypto lives one layer lower.
MSG91 / Twilio give banks a "delivery report". Zoza Auth gives the bank a cryptographically-scoped audit log: every challenge issued, approved, denied, expired, every device registered / revoked — queryable via GET /v1/apps/{id}/audit. Real dispute-resolution material, not a billing record.
None of MSG91 / Twilio / Apple / Google publish a monthly warrant canary for their OTP / Passkey infrastructure. We do. If RBI / CERT-In ever compels us to backdoor a customer's server key or hand over device public keys silently, the canary stops — and banks building on us have a public signal to migrate.
The Go reference implementation at products/zoza-auth/ is the same code that runs in production. The attack-surface grid on this page names every class of attack we know of — with real incidents and real rupee losses — and maps each to a test in the suite (TestSecurity_WrongDevice, TestSecurity_ReplayChallenge, etc.). Industry standard is "secure by vendor claim". Ours is "secure by reproducible Go test run".
Items 1, 2, 4, 5, 6, 7 are shipped or live today. Item 3 is a commercial milestone (priced at enterprise-close). Next gates queued:
The classical OTP flow is: bank → generate 6-digit secret → send to the user's phone over SMS → user copies it back. Every step is shared-secret. Every step is interceptable. Zoza Auth inverts the model: the user's device owns a keypair, the bank's server owns a keypair, and every challenge is a one-shot Diffie-Hellman computation that only the genuine pair can both solve.
Once enrolled (one-time), every subsequent login or payment confirmation uses the same six-step dance. The six are enforced in products/zoza-auth/auth.go and covered by TestFullAuthFlow_HappyPath in the test suite.
/v1/challenges with a context ("Login to NetBanking") and a 32-byte random nonce.HKDF(DH(device_priv, server_pub), nonce) and POSTs it to /v1/challenges/{id}/respond.HKDF(DH(server_priv, device_pub), nonce) independently, ConstantTimeCompares, and webhooks the bank "approved".
Listed above in the pre-analysis — scroll back up for the full grid. Each has a real-incident
citation, a real-rupee loss figure, and the specific line in auth.go /
auth_test.go that stops it. The three attacks we only partially solve are flagged ⚠
with a roadmap — we don't claim wins we haven't earned.
Auth flows have to work on a 2G Jio connection in Ramanagaram at 11:47pm with a dying battery. Here are the specific failure modes we've walked through and the behaviour we commit to.
POST /v1/challenges again. No silent re-use.DELETE /v1/devices/{id}). New device: re-enrol via the bank app flow. Same as re-registering a Passkey.GetUserDevices returns all active devices; challenge pushes to all of them; first valid response wins, rest are marked as "used". Proven by TestMultiDevice_ThreeDevices.TestSecurity_RevokedDevice.(app_id, user_id, challenge_id, status, timestamp) for 90 days. Served under MLAT + DPDP-compliant warrant. See data policy. Canary monitors compelled-access.A security product that says "trust us" is a security product you shouldn't. Each of these pages is publicly reachable, cryptographically verifiable where it matters, and updated on the cadence committed below.
What we log, who can read it, how long we keep it. Every admin action on your Zoza Auth account leaves an immutable row in auth_audit. Customer banks have full read of their own events via API.
Monthly signed statement — "As of 2026-04-17 Zoza has not received a gag-ordered request to produce user device public keys or compel backdoored signing behaviour." If the canary stops, read the absence.
What we store (metadata for 90 days), what we don't (no plaintext proofs, no passwords, no SMS, no user-chosen secrets), how to request deletion, how we honour DPDP consent-withdrawal.
Open-scope for the crypto path (replay, signature forgery, constant-time bypass). Severity tiers + SLA + safe-harbour binding today; cash payouts coming soon and backfill retroactively once the first paying pilot signs. Submit via security@zoza.world.
challenge_id in the interim.Prefer honest gaps to marketing claims. If you find one we missed, open a bounty report or email us.
Banks, fintechs, exchanges, healthcare portals, and enterprise IAM teams: the Go API is live at https://auth-api.zoza.world. Apply for a key, we'll review inside 24h, and you can be issuing your first real cryptographic challenge by Friday.