Skip to content
bug-breederPublic

About

No description, website, or topics provided.

Resources

Stars

2 stars

Watchers

1 watching

Forks

Latest commit

 

History

252 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 

Repository files navigation

2FAir

An offline, end-to-end encrypted authenticator for 2FA (TOTP) codes. It runs entirely in the browser as an installable PWA: no account, no server, nothing leaves the device.

A Bambotics project.

Features

  • Unlock with a passkey (Face ID, Touch ID, Windows Hello, security key) via the WebAuthn PRF extension, with an optional 6-digit backup passcode.
  • Encrypted at rest. Accounts are stored in IndexedDB, encrypted with AES-256-GCM.
  • Works offline after the first visit, and can be installed to the home screen or desktop.
  • Add accounts by scanning a QR code with the camera, uploading or pasting a QR image, or typing the secret key. Supports SHA-1/256/512, 6–8 digits and custom periods.
  • Encrypted backups. Export to a password-protected file and import it on another device.
  • Move between apps. Import or export a plain-text file with one otpauth:// link per line (the format many authenticators export), or share a single account as a QR code or link.
  • Auto-lock, search, light/dark theme, English and Vietnamese.

How it works

A random 256-bit vault key encrypts all accounts. That key is never stored in the clear; it is wrapped once per unlock method:

Unlock method Wrapping key
Passkey WebAuthn PRF output → HKDF-SHA256 → AES-256-GCM key
Passcode PBKDF2-SHA256 (600,000 iterations) → AES-256-GCM key

Adding or removing an unlock method only re-wraps the vault key. Backups are encrypted separately with a key derived from the backup password.

Security notes

  • The passkey is the strong factor. A 6-digit passcode protects against casual access, but someone who copies the browser profile can brute-force it offline. The lockout delay only slows guessing through the UI.
  • Codes live only in this browser's storage. Clearing site data deletes them, so export a backup.
  • The otpauth:// text export is not encrypted: anyone with the file can generate your codes. Delete it once it's imported where you need it.
  • Service icons are loaded from the aegis-icons CDN on jsDelivr, which reveals the issuer names (not secrets) of your accounts to the CDN.
  • Passkey unlock needs a browser and authenticator that support PRF (recent Chrome, Edge, Safari 18+, Firefox 135+ with a platform authenticator or a FIDO2 security key). Otherwise, use the passcode.

Development

cd client
npm install --legacy-peer-deps
npm run dev        # http://localhost:5173
npm test           # unit tests (Vitest)
npm run lint
npm run build      # production build + service worker in dist/
npm run preview    # serve dist/ at http://localhost:4173

The service worker is only generated by npm run build, so test offline behaviour with npm run preview. Passkeys need a secure context: localhost or HTTPS.

Stack

React 18, Vite, TypeScript, HeroUI + Tailwind CSS, i18next, otpauth, qr-scanner, idb and vite-plugin-pwa (Workbox).

Layout

client/src/
├── lib/vault/      crypto, passkey (PRF), IndexedDB store, backup, lockout
├── lib/totp.ts     code generation and otpauth:// parsing
├── providers/      VaultProvider: lock state, entries, auto-lock, tab sync
├── pages/          onboarding, unlock, home, settings
└── components/     OTP card, entry/QR modals, passcode input, FAB

Deploying

client/dist is a static site. Host it on any static host over HTTPS (GitHub Pages, Cloudflare Pages, Netlify, Vercel), with unknown paths falling back to index.html.

The earlier full-stack version (Go server + PostgreSQL) is preserved on the backup/fullstack-with-server branch.

License

GPL-3.0

About

No description, website, or topics provided.

Resources

Stars

2 stars

Watchers

1 watching

Forks

Releases

Packages

Used by

Contributors

Languages