Inspiration

Physical security hasn't kept up with digital security. Most smart locks rely on a single factor: a code, a fingerprint, or a phone app. But in cybersecurity, we know that single-factor authentication is the weakest link. Banks don't let you log in with just a password, so why should your door be any different?

We set out to bring true multi-factor authentication to physical access control, something you know, something you have, and something you have on you, all working together in a system where compromising one factor isn't enough to get in.


What it does

Safe Safe is a three-factor authentication smart lock that requires all of the following to unlock:

  1. PIN Code (something you know) — entered on a physical keypad, verified against a bcrypt-hashed password stored server-side
  2. RFID Badge (something you have) — tap a registered card on the reader; the UID is checked against an authorized list
  3. Dashboard Unlock (a second device you possess + are logged into) — press the unlock button on a web dashboard from your authenticated phone

All three factors must pass before the lock opens. The OLED display shows real-time progress ("1/3 factors", "2/3 factors") and a status bar indicating WiFi, server connection, and which factors have been verified.

The web dashboard allows users to:

  • Register and manage multiple lock devices
  • Change PINs remotely (the lock prompts you to type a new one on the keypad)
  • Register new RFID cards by sending a scan command to the lock
  • View a real-time access log of every unlock attempt (successful or denied)
  • Send the dashboard unlock signal as the third authentication factor

Everything communicates in real time; press a button on the dashboard, and the lock responds instantly.


How we built it

Hardware:

  • ESP32 microcontroller (WiFi-enabled, runs the lock firmware)
  • RFID-RC522 module for card scanning
  • 4x4 matrix keypad for PIN entry
  • SSD1306 OLED display (128x64) for status and prompts
  • DF9GMS servo motor for the physical lock mechanism

Firmware (C++/Arduino):

  • Written for ESP32 using Arduino framework
  • Handles keypad input with PIN masking on the OLED
  • Reads RFID card UIDs via SPI
  • Communicates with the server over WebSocket (Socket.IO) for real-time bidirectional messaging
  • Implements a state machine for idle, PIN entry, PIN change, RFID scanning, and unlocked states
  • Auto-locks after a configurable timeout

Backend (Node.js):

  • Express server handling REST API routes for authentication and device management
  • SQLite database storing users, devices, hashed PINs (bcrypt), RFID tags, and access logs
  • JWT-based authentication for the web dashboard
  • Socket.IO server acting as a real-time relay between the dashboard and ESP32
  • All PINs are hashed with bcrypt on the server; the ESP32 sends PINs to the server for verification rather than storing them locally

Architecture:

The server is the central hub. The ESP32 connects via WebSocket on boot and authenticates with a unique device token. The browser connects separately. When the user triggers an action on the dashboard, the server relays the command to the ESP32 and vice versa. Neither the lock nor the browser talks to the other directly; everything routes through the server, which handles authentication, credential storage, and logging.


Challenges we ran into

  • BLE MAC randomization killed our original plan. We initially designed the third factor as Bluetooth proximity detection; if your phone is nearby, the factor passes. But modern phones (especially iOS) randomize BLE MAC addresses, making reliable identification impossible without a complex pairing protocol. We pivoted to the dashboard unlock button, which is actually a stronger security model: it proves you possess a second authenticated device, not just that some phone is nearby.
  • Socket.IO protocol version mismatch.
  • SPI bus conflicts.
  • Servo jitter.

Accomplishments that we're proud of

  • True multi-factor auth on a physical lock.
  • Server-side PIN verification with bcrypt.
  • Real-time bidirectional communication with milliseconds response time.
  • Complete access logging. Every attempt, successful or denied, every method, every timestamp, is stored and viewable on the dashboard in real time.
  • Built in one day. Full-stack system with hardware, firmware, backend, and frontend, all wired together and working.

What we learned

  • Socket.IO protocol versioning matters a lot when mixing embedded and web clients
  • BLE is surprisingly unreliable for phone identification due to MAC randomization
  • Splitting hardware and software workstreams in parallel is essential for hackathon speed
  • SQLite is perfect for hackathon prototyping

What's next for Safe Safe

  • BLE challenge-response — replace MAC matching with a proper handshake where the phone signs a server-generated nonce
  • Biometric factor — add a fingerprint sensor as a fourth authentication factor
  • Offline mode — cache hashed credentials on the ESP32 so the lock works without WiFi
  • End-to-end encryption — TLS on WebSocket and encrypted credential storage on the ESP32
  • Multi-user access — role-based permissions so admins can grant/revoke access for others
  • Cloud deployment — move from local server to cloud hosting for remote access anywhere
Share this project:

Updates