
Connexion par empreinte digitale au bureau Linux à l'aide d'un capteur Grow R503 + Arduino + d'un démon de remplacement de fprintd en Rust
Un lecteur d'empreintes digitales USB fait de pièces détachées pour les bureaux Linux. Coût total des pièces
moins de 15 $. Remplacement direct du fprintd amont — PAM, Paramètres KDE,
Paramètres GNOME, fprintd-verify, sudo avec le doigt, déverrouillage d'écran avec le
doigt fonctionnent tous.
À partir de fw=1.0 / r503d 1.0.0 la liaison Arduino↔hôte est authentifiée :
chaque commande et réponse porte un MAC SipHash-2-4 lié à un
secret apparié par TOFU dans l'EEPROM. Les attaques par rejeu et par échange à chaud contre la liaison série USB
sont bloquées. Voir SPEC.md §13 pour la conception complète,
y compris ce que le modèle de menace ne couvre pas.

si seulement j'avais une imprimante 3D…``` ┌──────────┐ UART ┌─────────────┐ USB-CDC ┌──────────────────┐ │ Grow │ 57600 8N1│ Arduino │ /dev/r503 │ r503d daemon │ │ R503 │◀─────────▶│ (firmware) │◀──────────▶│ net.reactivated │ │ sensor │ 3.3V TTL │ │ framed, │ .Fprint on D-Bus│ └──────────┘ └─────────────┘ MAC'd └──────────────────┘ │ ▼ PAM, KDE, GNOME, fprintd-verify, …
## Pourquoi
Les lecteurs d'empreintes digitales USB matériels pour Linux sont rares, chers, et ceux qui existent (Validity, Synaptics, etc.) sont rétro-ingénierés via des pilotes libfprint instables qui cessent de fonctionner avec les mises à jour du firmware des fabricants. Le protocole du Grow R503 est **public**, le côté Arduino est votre propre code, et la couche de compatibilité libfprint n'est que du D-Bus.
Vous vous retrouvez aussi avec un lecteur d'empreintes dont vous pouvez lire le code source, de haut en bas.
## Liste du matériel
| Composant | Notes | Coût approx. |
|------|-------|------|
| Capteur d'empreintes digitales capacitif Grow R503 | Le modèle rond avec l'anneau RGB | ~$10 |
| Arduino Uno R3 / Nano / Mega / toute carte ATmega328 | Tout ce qui exécute SoftwareSerial | $5–$25 |
| 4–6 fils de connexion | Dupont / breadboard | négligeable |
C'est tout. **Ni level shifter, ni diviseur de tension** — voir [`SPEC.md` §3.1](https://github.com/matpb/linux-fingerprint-r503/blob/main/SPEC.md) pour savoir pourquoi (la ligne RX du R503 tolère 5 V en pratique ; la fiche technique ment).
## Câblage```
R503 Arduino (Uno R3 / Nano / etc.)
---- ------------------------------
Red (VCC) 3V3
White (3.3VT) 3V3 (touch-IC supply; shares rail with red)
Black (GND) GND
Yellow (TXD) D2 ── SoftwareSerial RX
Brown (RXD) D3 ── SoftwareSerial TX (direct — no divider!)
Blue (WAKEUP) D4 (optional; not used by firmware yet)
Si votre R503 est livré avec le connecteur JST-SH, coupez un pigtail 6 broches JST-SH vers Dupont pour sortir les fils. Le brun est parfois vert selon le vendeur — vérifiez par rapport au fil qui va dans la broche RXD du connecteur JST, pas la couleur.
Testé sur Fedora 44 KDE ; devrait fonctionner sur toute distribution basée sur systemd avec fprintd, pam_fprintd et une toolchain Rust récente.
Paquets système :
| Distribution | Compilation | Exécution |
|---|---|---|
| Fedora / RHEL | rust cargo arduino-cli tpm2-tss-devel | fprintd pam fprintd-pam tpm2-tss |
| Debian / Ubuntu | rustc cargo arduino-cli libtss2-dev | fprintd libpam-fprintd libtss2-esys-3.0.2-0 |
Les paquets tss-esapi ne sont nécessaires que si vous prévoyez d'utiliser --pair --seal-tpm (SPEC §13.12). Le démon se compile et s'exécute sans TPM sinon — tss-esapi est une dépendance de compilation obligatoire mais une dépendance d'exécution facultative (le chemin de code n'est emprunté que lorsque /var/lib/r503d/key.tpm existe).
Rust 1.95+, arduino-cli dans votre $PATH.
Avez-vous un TPM2 ?```bash ls /dev/tpmrm0 && tpm2_pcrread sha256:7 | head -3
Si les deux réussissent, votre hôte peut utiliser le chemin de la clé scellée. Si `/dev/tpmrm0` est
absent (matériel ancien, TPM désactivé dans le BIOS, ou une VM sans TPM virtuel),
restez avec le flux de clé en texte brut par défaut.
## Compilation et installation
### 1. Flasher le firmware
Ouvrez `firmware/r503fp/r503fp.ino` dans l'IDE Arduino et téléversez. Ou avec
`arduino-cli` :```bash
# Uno R3:
arduino-cli compile --fqbn arduino:avr:uno firmware/r503fp/
arduino-cli upload --fqbn arduino:avr:uno --port /dev/ttyACM0 firmware/r503fp/
# Nano (modern Optiboot, including most Elegoo / WAVGAT clones):
arduino-cli compile --fqbn arduino:avr:nano:cpu=atmega328 firmware/r503fp/
arduino-cli upload --fqbn arduino:avr:nano:cpu=atmega328 --port /dev/ttyUSB0 firmware/r503fp/
# Nano with legacy 57600-baud bootloader (older clones):
# replace `cpu=atmega328` with `cpu=atmega328old`
Le firmware utilise Adafruit_Fingerprint. L'IDE proposera de l'installer
lors de la première compilation.
Si arduino-cli upload échoue avec not in sync: resp=0x7e, votre bootloader
est l'autre variante — remplacez atmega328 ↔ atmega328old et réessayez. Les deux
fonctionnent ; la différence réside uniquement dans le débit en bauds du bootloader.
Nécessite Rust 1.95+.```bash cd pcside/daemon cargo build --release
### 3. Installation```bash
sudo bash pcside/daemon/dist/install.sh
Ce script :
target/release/r503d vers /usr/local/bin/r503d/var/lib/r503d/ (mode 0700 root:root) pour la clé, l'état, et
le registre d'emplacements utilisateur/dev/r503 et verrouille le
nœud de périphérique en root:root 0600 (seul le démon, qui tourne en root, en a besoin ;
cela ferme le chemin par défaut 0660 root:dialout afin qu'aucun autre utilisateur local ne puisse
ouvrir le port — audit de sécurité 2026-05-28 / H1). Conséquence : après
l'installation, toute commande manuelle arduino-cli/serial-monitor à destination de /dev/r503
nécessite sudo./etc/systemd/system/r503d.service)net.reactivated.Fprint/usr/share/polkit-1/actions/net.reactivated.fprint.device.r503d.policy)
utilisée par le contrôle d'identité de l'appelant/etc/dbus-1/system.d/net.reactivated.Fprint.conf) — seuls les membres de root et
wheel peuvent parler au démon ; tous les autres reçoivent
AccessDenied au niveau du courtier, avant que le démon ne voie l'appelfprintd.service amontr503d.serviceC'est idempotent — relancez-le après chaque cargo build --release pour
redéployer le nouveau binaire.