Offline hardware password manager with 6-layer encryption β ESP32-S3 firmware + Electron desktop app + Chrome extension.
Your vault never leaves the device. No cloud. No accounts. No trust required.
SecureVault is a hardware password manager built on the ESP32-S3 (EdgeHax S3-PRO, N16R8). It stores your passwords in an encrypted vault on the device itself, behind a PIN lock with brute-force backoff. You can type passwords into any device over USB-C HID or Bluetooth LE HID β no software, no drivers, no browser extensions required on the host. For bulk management, AP Mode spins up an end-to-end encrypted WiFi hotspot + webapp, and the Electron desktop companion connects over USB-CDC serial with ECDH P-256 + AES-256-GCM.
flowchart LR
V["Your vault<br/>lives on the device"] --> P["Pick an entry,<br/>tap a field"]
P --> Q{"Connected<br/>how?"}
Q -->|USB-C HID| U["Types into your<br/>PC as a keyboard"]
Q -->|Bluetooth LE| W["Types into your phone<br/>or laptop, wirelessly"]
Q -->|AP Mode WiFi| A["Manage vault from<br/>phone browser (E2EE)"]
Q -->|USB-CDC serial| D["Electron desktop<br/>dashboard (E2EE)"]
To the host computer it just looks like someone typing β no app, no browser extension, no account needed for basic use.
| SecureVault | Cloud manager | Browser autofill | |
|---|---|---|---|
| Where secrets live | π on the device | βοΈ company server | π» browser profile |
| Needs an account | β | β | β |
| Needs host software for basic typing | β | β | β |
| Works on any device, no install | β (USB/BLE) | β | β |
| Usable fully offline | β | β | β |
| End-to-end encrypted management | β (ECDH+AES-GCM) | β (server decrypts) | β |
| Open hardware + firmware | β | β | β |
| Feature | What it does | |
|---|---|---|
| β¨οΈ | Dual-transport typing | Types passwords as real keystrokes over USB-C HID and Bluetooth LE HID simultaneously. |
| π | 6-Layer Security Stack | ECDH P-256 handshake β HKDF-SHA256 key derivation β AES-256-GCM encryption β per-message nonce β method tunneling β traffic obfuscation. |
| π’ | PIN lock + brute-force backoff | 4-digit unlock with escalating lockout (30s β 60s β 2m β 5m) persisted across reboots. |
| πΆ | AP Mode (WiFi hotspot) | Spin up a captive-portal web app with end-to-end encryption. Join WiFi, enter a 6-digit code, manage vault from any phone browser. |
| π₯οΈ | Dashboard Mode (USB-CDC) | Electron desktop companion connects over serial with full ECDH+AES-GCM session. Push/pull entries, view dashboard. |
| π§© | Chrome Extension | Browser extension syncs .svlt encrypted vault file with the Electron app for autofill, breach checking, and save prompts. |
| ποΈ | Encrypted vault on SD + Flash | AES-256-GCM encrypted vault.db on SD card with atomic writes + backup rotation. LittleFS partition for session data. |
| π | Search & favorites | Live filtering with on-screen keyboard, plus favorites view. |
| π‘οΈ | Duress mode | Separate decoy vault unlocked by a secondary PIN β real vault stays hidden. |
| π | Auto-lock, sleep, factory reset | Idle auto-lock, hold-to-lock, PIN-gated factory wipe. |
| π¨ | Custom TFT UI | Hand-drawn UI on 320Γ240 ILI9341 TFT β color avatars, glow effects, pill toggles. |
| π | RTC + diagnostics | DS3231 RTC for timestamps, MPU6050 IMU, AT24C32 EEPROM, full diagnostic logging. |
| π | Secure key zeroing | All ECDH private keys, session keys, and PIN buffers wiped with secureZero() on lock/timeout/mode-exit. |
flowchart LR
L["Lock"] --> P["PIN"]
P --> H["Home / Vault List"]
H --> D["Detail<br/>tap a field β it types"]
H --> A["Add new entry"]
H --> S["Settings"]
S --> M["Mode Menu"]
M --> BLE["BLE Mode"]
M --> AP["AP Mode<br/>WiFi hotspot"]
M --> DB["Dashboard Mode<br/>USB-CDC serial"]
Every management session (AP Mode, Dashboard Mode) is protected by six independent layers:
flowchart TB
L1["Layer 1: ECDH P-256 Key Exchange<br/>Device + client agree on a shared secret"] --> L2
L2["Layer 2: HKDF-SHA256 Key Derivation<br/>Session key = HKDF(ecdh_secret + SHA-256(code))"] --> L3
L3["Layer 3: AES-256-GCM Encryption<br/>Every message encrypted + authenticated"] --> L4
L4["Layer 4: Per-Message Nonces<br/>Sequential counter prevents replay"] --> L5
L5["Layer 5: Method Tunneling<br/>Request types wrapped in obfuscated envelopes"] --> L6
L6["Layer 6: Traffic Obfuscation<br/>Padding + chaff traffic hides real patterns"]
Key lifecycle: all private keys and session keys are zeroed with secureZero() (volatile memset, not optimized away) on lock, timeout, mode-exit, or power-off.
| Part | Detail |
|---|---|
| Board | EdgeHax ESP32-S3 S3-PRO (N16R8) |
| MCU | ESP32-S3, dual-core, 8 MB octal PSRAM, 16 MB flash |
| Display | ILI9341, 320 Γ 240, SPI TFT + XPT2046 touch |
| RTC | DS3231 (IΒ²C) β timestamps on vault entries |
| IMU | MPU6050 (IΒ²C) β motion-based auto-lock detection |
| EEPROM | AT24C32 (IΒ²C) β persistent lockout counters |
| SD Card | microSD on dedicated HSPI bus β encrypted vault storage |
| LED | RGB status LED |
| USB | USB-C, native ESP32-S3 (USB-OTG / TinyUSB) |
| Tool | Version | Where |
|---|---|---|
| PlatformIO | latest | platformio.org |
| ESP32-S3 core | Espressif v5.x | Via PlatformIO |
# Install PlatformIO
pip install platformio
# From the firmware directory:
cd firmware
pio run -t upload
# Monitor serial output (115200 baud):
pio device monitorFirst-time flash (if the partition table changed):
pio run -t erase && pio run -t uploadcd electron
npm install
npm startThe Electron app connects over USB-CDC serial. Make sure Dashboard Mode is active on the ESP32 (TFT shows a 6-digit code), then enter the code in the app.
- Open
chrome://extensions/ - Enable Developer mode
- Click Load unpacked β select the
extension/folder - The SecureVault icon appears in your toolbar
Visit the self-flasher page β connect your ESP32-S3 via USB, click the button, and the firmware installs directly from the browser using ESP Web Tools. See flasher/ for the hosted page.
SecureVault/
βββ firmware/ ESP32-S3 firmware (PlatformIO + ESP-IDF)
β βββ src/ C++ source files
β β βββ main.cpp Main: setup/loop, UI controller, HID dispatch
β β βββ ui_screens.cpp All screen drawing + touch handlers (~150KB)
β β βββ vault_manager.cpp Encrypted vault CRUD on SD + flash
β β βββ web_vault_server.cpp AP Mode HTTPS server + E2EE webapp
β β βββ ap_mode_manager.cpp WiFi AP lifecycle (start/stop/teardown)
β β βββ secure_session.cpp ECDH P-256 + HKDF + AES-256-GCM session
β β βββ serial_protocol.cpp Dashboard Mode USB-CDC serial protocol
β β βββ ble_keyboard_manager.cpp BLE HID keyboard + pairing gate
β β βββ ... Crypto, display, RTC, diagnostics, etc.
β βββ include/ Headers
β β βββ ui_screens.h UiController + Screen enum
β β βββ portal_html.h Captive-portal SPA (embedded HTML)
β β βββ vault_types.h VaultEntry, SessionData structs
β β βββ ... All module headers
β βββ components/ ESP-IDF components (esp_littlefs, esp_tinyusb, tinyusb)
β βββ docs/ AP_MODE.md, GPIO_MAP.md
β βββ platformio.ini Build configuration
β βββ sdkconfig.defaults ESP-IDF sdkconfig overrides
β βββ partitions.csv Flash partition table
β βββ CMakeLists.txt ESP-IDF CMake
β
βββ electron/ Desktop companion app (Electron)
β βββ main.js Main process: serial channel, vault ops, IPC
β βββ preload.js Context bridge to renderer
β βββ secureChannel.js ECDH + AES-256-GCM over USB-CDC serial
β βββ vaultCrypto.js Vault encryption/decryption (PBKDF2 + AES-GCM)
β βββ vaultFileCrypto.js .svlt v2 file format for extension sync
β βββ breachCheck.js HaveIBeenPwned API integration
β βββ wordlist.js Diceware wordlist for passphrase generation
β βββ renderer/ UI (index.html + renderer.js + style.css)
β βββ package.json Electron + serialport dependencies
β
βββ extension/ Chrome extension (Manifest V3)
β βββ manifest.json MV3 manifest with permissions
β βββ background.js Service worker: vault sync, autofill engine
β βββ content.js Content script: form detection
β βββ window.js Vault UI (popup window)
β βββ window.html Vault HTML
β βββ window.css Vault styles
β βββ inline-overlay.js In-page overlay for credential capture
β βββ save-prompt.js New-credential save prompt
β βββ urlMatcher.js URL matching for autofill
β βββ vaultFileCrypto.js .svlt file read/write (shared with Electron)
β βββ breachCheck.js Breach checking (shared with Electron)
β βββ icons/ Unlocked icons (16/48/128px)
β βββ icons_locked/ Locked icons (16/48/128px)
β
βββ docs/ Project documentation
β βββ AP_MODE.md AP Mode architecture, threat model, troubleshooting
β βββ GPIO_MAP.md ESP32-S3 GPIO pin assignments
β βββ ARCHITECTURE.md Full architecture deep dive
β
βββ scripts/ Utility scripts
β βββ disable_component_manager.py ESP-IDF component manager disable
β
βββ flasher/ Web-based firmware installer
β βββ index.html ESP Web Tools installer page
β βββ manifest.json Firmware manifest for ESP Web Tools
β βββ firmware/ Pre-built binary files for web flasher
β
βββ .github/workflows/ CI
β βββ build.yml PlatformIO build on push/PR
β
βββ .gitignore Ignore patterns
βββ LICENSE MIT license
βββ CONTRIBUTING.md Contribution guidelines
βββ SETUP.md New-machine setup guide
βββ README.md This file
- Power on β enter PIN β vault list.
- Tap the mode badge (top-right) β DASHBOARD.
- TFT shows a 6-digit code (e.g.
482917). - Launch the Electron app β click Connect to ESP32 Device.
- Enter the 6-digit code β ECDH handshake completes (~100ms).
- All reads/writes are AES-256-GCM encrypted frames over USB-CDC serial.
- Exit: tap mode badge β BLE MODE, or click Lock in the Electron app.
- Power on β enter PIN β vault list.
- Tap mode badge β AP MODE.
- TFT shows SSID, WPA2 password, and 6-digit code.
- On your phone: join the WiFi β open
http://192.168.4.1/(captive portal auto-opens). - Enter the 6-digit code β ECDH handshake β vault loads in the browser.
- All traffic is end-to-end encrypted (same 6-layer stack).
- Exit: tap BACK, or idle timeout (5 min), or auto-lock.
Every AP session regenerates the WPA2 password + 6-digit code + ECDH keypair. Exiting AP mode tears down WiFi, DNS, mDNS, the web server, and zeros all session credentials with
secureZero().
- Load the extension (Developer mode β Load unpacked β
extension/folder). - Set a master password β this encrypts the local
.svltvault file. - The Electron app and extension share the
.svltfile for two-way sync:- Extension β Electron: new logins captured on the web get pushed to the ESP32.
- Electron β Extension: entries synced from the ESP32 appear in the browser autofill.
- Inline overlay detects login forms and offers to save credentials.
- Breach check queries HaveIBeenPwned (k-anonymity API) for password exposure.
What it does today:
- Vault is offline, PIN-gated, and encrypted at rest (AES-256-GCM on SD card).
- Brute-force PIN backoff persists across reboots (stored in AT24C32 EEPROM).
- AP Mode and Dashboard Mode require ECDH P-256 handshake before any vault data flows.
- All session keys zeroed with
secureZero()on lock/timeout/exit. - Duress mode: secondary PIN unlocks a decoy vault, real vault stays hidden.
- Browser extension vault file uses PBKDF2-SHA512@600k iterations + AES-256-GCM + HMAC-SHA256.
What it does not do yet (PRs welcome):
- ESP32 Flash Encryption + Secure Boot v2 (one-way fuses, release mode).
- FIDO2 / WebAuthn passkey (ECC P-256).
- TOTP / 2FA code generator (HMAC-SHA1) β code exists but is not yet wired into the UI.
Treat this as a strong DIY / learning project with real crypto, not a certified security product. See the roadmap.
The firmware is a PlatformIO project using the arduino + espidf dual framework. The main loop runs at ~60Hz: poll touch, render screen, service background managers (BLE, WiFi AP, auto-lock, secure session). No RTOS scheduling in user code.
loop() @ ~60 Hz
βββ pollTouch() β tap/drag/swipe/long-press β onTapScreen()
βββ per-screen animation ticks
βββ BLE keyboard manager (advertise, pairing gate)
βββ WiFi captive-portal service (AP Mode)
βββ USB-CDC serial secure session (Dashboard Mode)
βββ auto-lock / LED / physical button
βββ secure key lifecycle (zero on exit)
The Electron desktop app connects to the ESP32 over USB-CDC serial (no HTTP, no network stack). The secure channel (secureChannel.js) performs ECDH P-256 handshake, then all communication is AES-256-GCM encrypted frames. The app also reads/writes an encrypted .svlt file that the browser extension consumes, enabling two-way vault sync.
Manifest V3 extension with a service worker background, content scripts for form detection, and a popup vault UI. Shares vaultFileCrypto.js and breachCheck.js with the Electron app for format compatibility.
For the full deep dive, see docs/ARCHITECTURE.md.
- Touch UI, encrypted vault, USB + BLE HID, AP Mode, Dashboard Mode
- 6-Layer Security Stack (ECDH + HKDF + AES-GCM + nonces + tunneling + obfuscation)
- Chrome extension + Electron desktop companion +
.svltfile sync - Duress mode (decoy vault)
- ESP32 Flash Encryption + Secure Boot v2 (one-way fuses)
- FIDO2 / WebAuthn passkey (ECC P-256)
- TOTP / 2FA code generator (HMAC-SHA1)
- Custom PCB + 3D-printed enclosure
Contributions, bug reports, and hardware ports are welcome β see CONTRIBUTING.md.
MIT Β© Purujith Kadekar.
- EdgeHax β ESP32-S3 S3-PRO hardware platform
- Espressif β ESP32-S3 MCU + ESP-IDF framework
- PlatformIO β build system
- NimBLE-Arduino β lightweight BLE stack
- mbedtls β ECDH + HKDF + AES-GCM crypto
- Electron β desktop app framework
- HaveIBeenPwned β breach check API
If this project helped you, drop a β β it genuinely helps.