Why
Most DIY fingerprint projects I've seen use a ready-made module that does the matching itself and talks to the ESP over a plain, unauthenticated UART. It's relatively easy to get access to the wiring and tell the ESP that "match is OK". A few modules do encrypt that link, but the key sits in the ESP's flash, and the same ESP still opens the door, so owning the ESP still means owning the door.
This project turns that around: the device in front of the door is deliberately dumb.
The idea
- The sensor is a bare FPC1020 capacitive sensor. It has no matching logic, no templates. It only produces a 192×192 image at 508 dpi.
- The ESP detects a finger, captures a frame, and uploads it to the server over Wi-Fi. That's all it does. It never decides anything.
- The server extracts the minutiae, matches them (SourceAFIS), and makes the decision.
- Home Assistant gets the result from the server (not from the device) and owns the access policy.
Threat model
I assume the device is physically reachable: it hangs outside, meaning it can be unplugged, replaced, opened, or have its cable and Wi-Fi intercepted.
What an attacker gets by compromising the device:
- the ability to submit images to the API, and to see the raw frames of whoever touches the sensor
- but not the things that actually make the decision: no templates, no names, no "granted" flag to flip. The server sends the verdict to Home Assistant itself, and the device only gets a vibration/LED hint for local feedback.
With a ready-made module, the attack takes a minute: open the case, connect to the sensor wires, send a fake "match". Here that doesn't work, because there is nothing to impersonate. The attack becomes a multi-step one:
- Get physical access and either tap the SPI bus or reflash the ESP to collect frames of legitimate touches.
- Come back (or connect remotely, if you have the token) and replay one of the collected frames.
This isn't impossible, but it takes time and preparation, and the measures below are meant to make it even harder.
What the design does about it
The server-side parts are planned, not built yet.
- Tamper switch. Opening the case triggers an alert, and Home Assistant stops reacting to the server's events until a manual reset is done. A device_offline alert that lasts longer than the grace period does the same, so unplugging the device doesn’t bypass it.
- Encrypted transport. Frames travel over TLS with a pinned server certificate, so someone sniffing the Wi-Fi sees neither the images nor the device token.
- Duplicate detection (an idea so far). Two real touches never give identical pixels. The server would reject exact copies of earlier frames, and flag frames whose minutiae are suspiciously close to an earlier one. Whether this works as I expect still has to be verified on real data.
- Policy in Home Assistant (optional, may not make it in). A fingerprint is one factor, not the whole decision. Automations could require something the device can’t fake alone, e.g., a phone nearby.
- Rate limiting and alerts. Bursts of no_match, invalid tokens, and unusual activity all raise alerts.
- Revocable device token. It can only submit frames, and the server drops the connection as soon as it’s revoked. The device is meant to sit on an IoT VLAN that reaches only the server.
- Encryption at rest on the server. Both the raw images and the minutiae templates are encrypted in the database, with a key kept outside the data volume. Fingerprints are biometrics: unlike a password, you can’t change them after a leak.
What remains
- Replay of frames the device has already seen. A fully compromised ESP can resend them. Duplicate detection and the policy make this expensive, but not impossible. A real fix needs trusted hardware (a secure element), which version 1 doesn't have.
- Secrets in the flash. The Wi-Fi PSK and the device token can be read by someone who takes the device. Flash encryption and secure boot can lock this down, but they make ESPHome OTA updates harder, so I treat them as optional.
- Fake fingers. A capacitive sensor resists some of them, not all.
- A compromised server. If the server is owned, everything is. It lives inside the trusted network, and the admin UI is never meant to be exposed to the internet.
Hardware
Lesson learned: the sensor needs a bezel. My first board didn’t work because it had none. The chip drives the finger through a metal bezel, and without one, the frames are pure noise. The finger has to touch the bezel and the sensor at the same time.
The second board, with a homemade bezel, worked right away. It looks awful, but the images are clean. I was going to put a raw frame here, but publishing my own fingerprint to the whole internet would make the encryption on the server a bit pointless. Imagine a very clean fingerprint here :)
The version 1 board is built around the FPC1020AM, a flex-cable version that comes with the bezel already built in, so no more hand-made bezels.

Firmware
An ESPHome external component (ESP32, ESP-IDF). A FreeRTOS task polls the sensor's 12-zone finger detection, captures a frame (~43 ms at 8 MHz), and streams it to the server. Everything the component reports (finger present, result, latency) is exposed as ordinary ESPHome entities.
The prototype measured the full path from finger detection to the verdict at about 160 ms.
Server
A Dockerized ASP.NET server with SourceAFIS. The prototype already enrolls and matches fingers. The full version will add:
- a WebSocket device API over TLS with a pinned certificate and per-device tokens;
- an admin UI (enrollment, people, devices, event log);
- events for Home Assistant;
- adaptive templates, so recognition keeps improving as the finger changes with seasons and use.
Status
Works
- Sensor with a homemade bezel on a test board
- Prototype firmware and server: ~160 ms from finger detection to verdict
In progress
- Version 1 board around the FPC1020AM
Next
- Full ESPHome component (WebSocket over TLS, device token, feedback)
- Full server (admin UI, Home Assistant events, encryption at rest, adaptive templates)
- Enclosure (for now, only preliminary shape)

Later
- Possibly a Doorbell v2 with a camera, Ethernet, and several power options (PoE among them)
strange.rand