Skip to content
KitploitKITPLOIT
StrumentiBlog
Invia
StrumentiBlog
Invia

Strumenti di Hacking, PenTest e Cybersecurity per il tuo Arsenale di Sicurezza!

Kitploit è una directory di strumenti di hacking, cybersecurity e pentesting. Scopri gli ultimi aggiornamenti dei progetti per trovare vulnerabilità, analizzare sistemi, automatizzare i test e rafforzare la tua sicurezza.

··Feed·Contatto·Privacy·© 2026 Kitploit

Directory degli strumenti

Categorie

Vedi tutte le categorie
Loading categories
linux-fingerprint-r503 — Login con impronta digitale sul desktop Linux usando un sensore Grow R503 + Arduino + un daemon Rust sostitutivo di fprintd | Kitploit
Strumenti/GitHubGitHub/matpb/linux-fingerprint-r503
Sicurezza Sistemi EmbeddedCrittografiaPenetration TestingSicurezza HardwareAutenticazioneRed Teaming
GitHubmatpb/linux-fingerprint-r503

linux-fingerprint-r503

Login con impronta digitale sul desktop Linux usando un sensore Grow R503 + Arduino + un daemon Rust sostitutivo di fprintd

Vedi Repository
44232 mesi faRevisionato da Kitploit

Più Popolari

Vedi tutti →

Scopri gli strumenti più utilizzati dalla nostra community.

Esplora tutti gli strumenti

Sfoglia la nostra collezione di strumenti

Vedi tutti gli strumenti →
Condividi

linux-fingerprint-r503 — accesso tramite impronta digitale per Linux con un Grow R503 + Arduino

CI r503d firmware Rust 2024 Platform: Linux License: MIT

Un lettore di impronte digitali USB per desktop Linux, assemblato da componenti singoli. Costo totale dei componenti inferiore a 15 $. Sostituto diretto del progetto upstream fprintd — funzionano PAM, KDE Settings, GNOME Settings, fprintd-verify, sudo con il dito e sblocco dello schermo con il dito.

A partire da fw=1.0 / r503d 1.0.0 il collegamento Arduino↔host è autenticato: ogni comando e ogni risposta trasporta un MAC SipHash-2-4 basato su un segreto accoppiato tramite TOFU e memorizzato in EEPROM. Gli attacchi di replay e di scambio a caldo contro il collegamento seriale USB sono bloccati. Vedi SPEC.md §13 per la progettazione completa, incluso ciò che il modello di minaccia non copre.

Sensore R503 montato in un contenitore in legno tagliato a mano, anello blu acceso

vorrei tanto avere una stampante 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, …

root@kitploit:~
## Perché

I lettori di impronte digitali USB hardware per Linux sono scarsi, costosi, e
quelli che esistono (Validity, Synaptics, ecc.) sono reverse-engineered tramite
driver libfprint instabili che si rompono con gli aggiornamenti del firmware del fornitore. Il
protocollo del Grow R503 è **pubblico**, il lato Arduino è codice tuo,
e il livello di compatibilità libfprint è solo D-Bus.

Ti ritrovi anche con un lettore di impronte digitali di cui puoi leggere il sorgente, dall'inizio
alla fine.

## Distinta dei materiali

| Parte | Note | Costo approssimativo |
|------|-------|------|
| Sensore capacitivo di impronte digitali Grow R503 | Quello rotondo con l'anello RGB | ~$10 |
| Arduino Uno R3 / Nano / Mega / qualsiasi scheda ATmega328 | Qualsiasi cosa che esegua SoftwareSerial | $5–$25 |
| 4–6 fili jumper | Dupont / breadboard | trascurabile |

Questo è tutto. **Niente level shifter, niente partitore di tensione** — vedi [`SPEC.md` §3.1](https://github.com/matpb/linux-fingerprint-r503/blob/main/SPEC.md)
per il motivo (la linea RX dell'R503 è tollerante ai 5V nella pratica; il datasheet mente).

## Cablaggio```
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)

Se la tua R503 viene fornita con il connettore JST-SH, taglia un pigtail a 6 pin JST-SH-to-Dupont per separare i fili. Il marrone a volte è verde a seconda del venditore — verifica in base al filo che entra nel pin RXD del connettore JST, non al colore.

Prerequisiti

Testato su Fedora 44 KDE; dovrebbe funzionare su qualsiasi distro basata su systemd con fprintd, pam_fprintd e una toolchain Rust recente.

Pacchetti di sistema:

DistroCompilazioneRuntime
Fedora / RHELrust cargo arduino-cli tpm2-tss-develfprintd pam fprintd-pam tpm2-tss
Debian / Ubunturustc cargo arduino-cli libtss2-devfprintd libpam-fprintd libtss2-esys-3.0.2-0

I pacchetti tss-esapi sono necessari solo se prevedi di usare --pair --seal-tpm (SPEC §13.12). Altrimenti il demone compila e funziona senza TPM — tss-esapi è una dipendenza di compilazione obbligatoria ma di runtime facoltativa (il percorso del codice viene seguito solo quando /var/lib/r503d/key.tpm esiste).

Rust 1.95+, arduino-cli nel tuo $PATH.

Hai un TPM2?```bash ls /dev/tpmrm0 && tpm2_pcrread sha256:7 | head -3

root@kitploit:~
Se entrambi riescono, il tuo host può utilizzare il percorso della chiave sigillata. Se `/dev/tpmrm0` è
assente (hardware più vecchio, TPM disabilitato nel BIOS o una VM senza TPM virtuale),
attieniti al flusso predefinito con chiave in chiaro.

## Compilazione e installazione

### 1. Flash del firmware

Apri `firmware/r503fp/r503fp.ino` nell'IDE Arduino e caricalo. Oppure con
`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`

The firmware uses Adafruit_Fingerprint. The IDE will offer to install it on first compile.

If arduino-cli upload fails with not in sync: resp=0x7e, your bootloader is the other variant — swap atmega328 ↔ atmega328old and retry. Both work; the difference is just bootloader baud rate.

2. Build the daemon

Requires Rust 1.95+.


Traduzione in italiano:

Il firmware utilizza Adafruit_Fingerprint. L'IDE offrirà di installarlo alla prima compilazione.

Se arduino-cli upload fallisce con not in sync: resp=0x7e, il tuo bootloader è l'altra variante — scambia atmega328 ↔ atmega328old e riprova. Entrambi funzionano; la differenza è solo il baud rate del bootloader.

2. Build del daemon

Richiede Rust 1.95+.```bash cd pcside/daemon cargo build --release

root@kitploit:~
### 3. Installazione```bash
sudo bash pcside/daemon/dist/install.sh

Questo script:

  • installa target/release/r503d in /usr/local/bin/r503d
  • crea /var/lib/r503d/ (permessi 0700 root:root) per la chiave, lo stato e il registro degli slot utente
  • scrive la regola udev che espone l'Arduino come /dev/r503 e fissa il nodo del dispositivo a root:root 0600 (solo il daemon, in esecuzione come root, ne ha bisogno; questo chiude il percorso predefinito 0660 root:dialout così nessun altro utente locale può aprire la porta — audit di sicurezza 2026-05-28 / H1). Conseguenza: dopo l'installazione, qualsiasi comando manuale arduino-cli/serial-monitor su /dev/r503 richiede sudo.
  • installa l'unità systemd (/etc/systemd/system/r503d.service)
  • sostituisce la voce di avvio automatico D-Bus per net.reactivated.Fprint
  • installa l'azione polkit (/usr/share/polkit-1/actions/net.reactivated.fprint.device.r503d.policy) usata dal gate dell'identità del chiamante

È idempotente — rieseguilo dopo ogni cargo build --release per ridistribuire il nuovo binario.

4. Abbina il Nano al daemon

Un Nano appena flashato non è associato — il daemon gli parlerebbe, ma il firmware rifiuterebbe ogni comando strutturato in frame. Scegli uno dei due flussi sotto; entrambi terminano con un Nano associato e un daemon funzionante. Il flusso sigillato con TPM è consigliato se il tuo host ha un TPM2 (vedi Prerequisiti per la verifica rapida).

Il file opt-in (/etc/r503d/allow-pair) usato in entrambi i flussi serve a sconfiggere un attaccante che si precipita alla tua scrivania con il proprio Nano — l'associazione senza root è impossibile. r503d --pair elimina il marcatore prima di inviare la chiave al Nano: se l'host va in crash tra il commit lato Nano e la persistenza lato host, la porta è già chiusa, quindi il tentativo di associazione successivo richiede che un amministratore esegua di nuovo touch sul marcatore. Un'uscita anticipata prima dell'invio (niente marcatore, o "già associato") lascia il marcatore intatto per un nuovo tentativo.

4a. Associazione con chiave in chiaro (predefinita)

Usa questo se non hai un dispositivo TPM2, o se non ti serve la resistenza ad attacchi offline su disco.```bash sudo systemctl stop r503d sudo mkdir -p /etc/r503d sudo touch /etc/r503d/allow-pair # opt-in (see SPEC §13.5) sudo r503d --pair # 128-bit key → /var/lib/r503d/key sudo systemctl start r503d

root@kitploit:~
* Genera una tabella Markdown con i campi dello strumento, supporta più righe e ha una logica per decidere colonne e righe.
	+ $ drupwn users:list http://example.com --markdown
	+ $ drupwn nodes:list http://example.com --markdown
	+ $ drupwn modules:list http://example.com --markdown
* Genera un formato JSON con i campi dello strumento, questa opzione sopprime automaticamente la verbosità.
	+ $ drupwn config:dump http://example.com --json
	+ $ drupwn taxonomy:list http://example.com --json
* Genera un formato XML con i campi dello strumento, questa opzione sopprime automaticamente la verbosità.
	+ $ drupwn config:dump http://example.com --xml
	+ $ drupwn users:list http://example.com --xml
* Salva l'intero output su un file, utile per grandi output che possono essere ulteriormente elaborati.
	+ $ drupwn config:dump http://example.com > output.txt
	+ $ drupwn modules:list http://example.com > output.txt```bash
sudo r503d --status
# port:             /dev/r503
# firmware:         fw=1.1 fmt=2
# firmware paired:  true
# firmware counter: 42
# host key.tpm:     (absent)
# host key:         /var/lib/r503d/key
# host key.bak:     /var/lib/r503d/key.bak
# tpm device:       (absent)
# allow-pair:       (absent)

4b. Associazione sigillata con TPM (consigliata su host TPM2, SPEC §13.12)

Stesso flusso, più --seal-tpm. La chiave generata viene sigillata su PCR7 (policy Secure Boot + chiavi) e scritta in /var/lib/r503d/key.tpm invece del file key in chiaro. Gli attaccanti con accesso offline al disco (dd di una partizione non montata, scambio dell'SSD in un host ostile) ottengono solo testo cifrato.```bash sudo systemctl stop r503d sudo mkdir -p /etc/r503d sudo touch /etc/r503d/allow-pair sudo r503d --pair --seal-tpm # seals new key to current PCR7 sudo systemctl start r503d

root@kitploit:~
Il contenuto del chunk 19 non è stato fornito nell'input. Nessuna traduzione possibile.```bash
sudo r503d --status
# port:             /dev/r503
# firmware:         fw=1.1 fmt=2
# firmware paired:  true
# firmware counter: 12
# host key.tpm:     /var/lib/r503d/key.tpm
# host key:         (missing)
# host key.bak:     (missing)
# tpm device:       /dev/tpmrm0
# allow-pair:       (absent)

Gli aggiornamenti del kernel, gli aggiornamenti initrd, gli aggiornamenti del firmware UEFI tramite fwupd e gli aggiornamenti di grub2 non modificano PCR7 e non richiedono una nuova sigillatura. PCR7 cambia solo in caso di modifiche alle policy di Secure Boot, iscrizioni MOK o spostamento del disco su un host diverso — a quel punto il daemon rifiuta di avviarsi con TPM_RC_POLICY_FAIL e dist/reseal-tpm.sh recupera in ~90 secondi. Vedi Recupero: PCR7 modificata.

5. Iscrizione e verifica```bash

Enroll a finger (use KDE Settings → Users → Fingerprint Auth for a GUI):

fprintd-enroll mat

Verify:

fprintd-verify mat

sudo with finger:

sudo whoami

root@kitploit:~
Sia KDE Settings (Plasma 6) che i dialoghi delle impronte digitali dell'account utente di GNOME Control Center guidano `r503d` esattamente come guidano l'upstream `fprintd`.

### Riassociazione / rotazione delle chiavi

Se vuoi una chiave nuova (chiave compromessa, sostituzione hardware pianificata, paranoia):```bash
sudo systemctl stop r503d
sudo r503d --unpair                        # framed; wipes Nano EEPROM + host key
sudo touch /etc/r503d/allow-pair
sudo r503d --pair                          # plaintext-key rotation
#  - or -
sudo r503d --pair --seal-tpm               # TPM-sealed rotation
sudo systemctl start r503d

Abbina il tuo percorso di associazione originale. Se hai usato originariamente --seal-tpm, ruota con --seal-tpm — altrimenti la rotazione ti declassa silenziosamente a una chiave in chiaro su disco.

Recupero: PCR7 cambiato, è necessario risigillare

Se hai usato --pair --seal-tpm e in seguito hai cambiato qualcosa che PCR7 misura (Secure Boot disattivato/attivato, nuovo MOK registrato, disco spostato su un'altra macchina), il daemon rifiuterà di avviarsi con un messaggio di journal relativo a TPM_RC_POLICY_FAIL. Il recupero richiede un solo comando:```bash sudo bash pcside/daemon/dist/reseal-tpm.sh

root@kitploit:~
Lo script ferma `r503d`, riprogramma `firmware/r503fp_wipe/` per cancellare la EEPROM del Nano, riprogramma il firmware principale, crea `/etc/r503d/allow-pair`, esegue `r503d --reseal-tpm` per generare una nuova chiave sigillata al PCR7 *attuale* e riavvia il demone. Tempo reale: ~90 secondi. Le impronte registrate vengono preservate: i template risiedono nella flash del sensore R503, non nel Nano.

Lo script richiede `arduino-cli` disponibile. Se è installato in `$HOME/.local/bin` dell'utente, viene rilevato automaticamente tramite `$SUDO_USER`; altrimenti imposta `ARDUINO_CLI=/full/path/to/arduino-cli` prima di eseguirlo.

### Recupero: `state.json` mancante (desincronizzazione del contatore)

Se la chiave host è intatta ma `/var/lib/r503d/state.json` è sparito o è stato ripristinato da un backup vecchio (o cancellato accidentalmente), il contatore del demone resta indietro rispetto al `last_seen` del Nano e ogni comando incorniciato viene respinto con `ERR replay`. `r503d --status` lo segnala; la soluzione è un solo comando:```bash
sudo systemctl stop r503d
sudo r503d --resync                         # reads Nano last_seen, sets host counter to last_seen+1
sudo systemctl start r503d

No re-pair, no reflash: la chiave non si sposta mai. La query status su cui si basa --resync non è autenticata, ma può solo spostare il contatore dell'host in avanti per allinearlo a ciò che il Nano ha già impegnato, quindi non può mai rendere un vecchio frame riproducibile (nel peggiore dei casi un MITM mendace forza un altro ERR replay, cosa che potrebbe già fare corrompendo i frame). Vedi SPEC.md §13.11.

Recupero: persa completamente la chiave host

L'--unpair autenticato ha bisogno della chiave per autorizzare. Se tutte le copie su disco sono sparite (crash del disco, rm accidentale, sia key che key.bak eliminate, o blob key.tpm perso), hai bisogno della via di fuga reflash-to-wipe — la stessa procedura che dist/reseal-tpm.sh automatizza per il caso di PCR7 cambiato sopra:```bash sudo systemctl stop r503d

/dev/r503 is root:root 0600 since install (audit H1), so the uploads need root.

sudo arduino-cli upload --fqbn arduino:avr:nano:cpu=atmega328 --port /dev/r503 firmware/r503fp_wipe/

Wait ~1s for the wipe to complete (LED starts blinking — that's the wipe sketch).

sudo arduino-cli upload --fqbn arduino:avr:nano:cpu=atmega328 --port /dev/r503 firmware/r503fp/ sudo touch /etc/r503d/allow-pair sudo r503d --pair sudo systemctl start r503d

root@kitploit:~
Se `sudo arduino-cli` segnala un errore di comando non trovato (arduino-cli si trova nella tua
`~/.local/bin`, non nel `PATH` di root), eseguilo come
`sudo env "PATH=$PATH" arduino-cli …` oppure fornisci il percorso assoluto.

Non è una backdoor che un attaccante può usare: la ri-associazione richiede i privilegi di root sul
host (il file opt-in e la CLI `--pair` richiedono entrambi root), quindi un
Nano reflashato non può essere portato in uno stato di fiducia senza che tu sia già
root.

### Disinstallazione```bash
sudo bash pcside/daemon/dist/uninstall.sh

Ripristina tutto, rimuove il mascheramento di fprintd, lascia /var/lib/r503d/ (chiave, stato, utenti) al suo posto nel caso si voglia reinstallare in seguito. Elimina manualmente quella directory se vuoi un vero stato pulito.

Come funziona

L'Arduino esegue un piccolo firmware a protocollo ASCII (firmware/r503fp/) che parla il protocollo binario nativo R30x ("Sync Word") dell'R503 sul lato UART e scambia comandi di testo orientati a riga con l'host tramite USB-CDC: ping, info, enroll N, verify, delete N, clear, led off. Protocollo v1 completo in SPEC.md §5.

Dalla versione fw=1.0 (Milestone E del lavoro sul canale autenticato v2), ogni comando e risposta è incapsulato in un frame C <counter> <body> M <mac> / R <counter> <seq> <body> M <mac>, autenticato con MAC SipHash-2-4 su una chiave a 128 bit abbinata tramite TOFU. La Nano mantiene un contatore monotono con livellamento dell'usura in EEPROM; il demone mantiene un contatore corrispondente in /var/lib/r503d/state.json. I tentativi di replay (lato firmware incoming <= last_seen) vengono rifiutati come ERR replay; i frame manomessi ricevono ERR mac_invalid. Specifica completa, modello di minaccia e limitazioni note in SPEC.md §13.

Il demone Rust (r503d) parla D-Bus su net.reactivated.Fprint — bit per bit la stessa interfaccia esposta dall'upstream fprintd — quindi ogni client fprintd funziona senza modifiche. Un sidecar JSON in /var/lib/r503d/users.json mappa (utente, dito) agli indici di slot nella flash interna dell'R503.

Layout:``` firmware/r503fp/ Arduino firmware (v2 framed ASCII protocol) firmware/r503fp_wipe/ Emergency one-shot EEPROM wipe (lost-key recovery) firmware/* Diagnostic / development sketches (ping, loopback, ...) pcside/daemon/ Rust daemon (the fprintd replacement) pcside/daemon/src/{crypto,framing,keystore,state,pairing}.rs v2 wire protocol implementation pcside/daemon/src/auth.rs caller-identity gating for D-Bus methods pcside/daemon/dist/ udev rule, systemd unit, polkit + bus policy, install scripts docs/ Decision logs + troubleshooting SPEC.md Full architecture + protocol spec (§13 = v2 auth)

root@kitploit:~
## Modello di sicurezza — riepilogo rapido

L'autenticazione a livello di wire mira a una minaccia specifica —
**"evil maid con cinque minuti e una Nano di scorta"** più un processo
locale ostile su `/dev/r503` — non a stati-nazione o attaccanti hardware
con laboratori. Distribuzione desktop per singolo utente con una lista
documentata di elementi fuori scope. Il modello di minaccia completo è in
[`SPEC.md` §13.1](https://github.com/matpb/linux-fingerprint-r503/blob/main/SPEC.md); le prove di implementazione e revisione sono
in
[`docs/REVIEW-2026-05-28.md`](https://github.com/matpb/linux-fingerprint-r503/blob/main/docs/REVIEW-2026-05-28.md). Un audit
separato di escalation dei privilegi avversariale (2026-05-28) e la
relativa passata di validazione/rimediazione per ogni affermazione sono
in
[`docs/SECURITY-AUDIT-2026-05-28.html`](https://github.com/matpb/linux-fingerprint-r503/blob/main/docs/SECURITY-AUDIT-2026-05-28.html)
e
[`docs/SECURITY-AUDIT-2026-05-28-VALIDATION.html`](https://github.com/matpb/linux-fingerprint-r503/blob/main/docs/SECURITY-AUDIT-2026-05-28-VALIDATION.html).

**Difeso:**
- Hot-swap della Nano con un'unità ostile (nessuna chiave → tutti i frame falliscono il MAC).
- Processo locale che inietta finte risposte di match su `/dev/r503`. Due livelli:
  il nodo del dispositivo è `root:root 0600` (regola udev) e il demone lo tiene
  con `TIOCEXCL`, quindi un processo non-root non può aprirlo — e anche se
  potesse, non ha la chiave, quindi il frame fallisce la verifica MAC.
- Replay di frame `OK match=...` registrati in una sessione futura.
- Manomissione bit-flip di qualsiasi campo del frame (confronto MAC a tempo costante).
- Brick per esaurimento contatore: un peer (o un MITM one-shot durante `--resync`)
  che porta il contatore monotono a `u64::MAX` e blocca permanentemente il
  canale viene bloccato da un tetto del contatore riservato, applicato su entrambe
  le estremità (`fw=1.1+`; audit SPEC §13.4 / 2026-05-28 DoS-2).
- Denial-of-service locale del sensore da parte dell'utente: un singolo gate dello
  slot di acquisizione limita il lavoro di enroll/verify in corso e i percorsi di
  eliminazione sono vincolati da un'azione, quindi un flood di `Start`/`Stop` (o
  di eliminazioni concorrenti) non può bloccare l'autenticazione.
- Impianto / cancellazione / enumerazione di impronte cross-user da parte di un
  utente locale non-root (es. `mallory` che chiama `Claim "root"` e poi registra
  il proprio dito) — l'identità del chiamante viene controllata su ogni metodo
  D-Bus che accetta `username`, e la policy del bus di sistema nega i chiamanti
  non-`wheel` a livello di broker.
- **Attacchi offline al disco contro la chiave host** *se abbinati a `--seal-tpm`*:
  la chiave su disco è sigillata TPM2 rispetto a PCR7, quindi `dd` di una
  partizione smontata o lo spostamento di un SSD in un host ostile produce solo
  ciphertext. Viene dissigillata solo sulla stessa macchina con la stessa policy
  Secure Boot. Vedi [SPEC §13.12](https://github.com/matpb/linux-fingerprint-r503/blob/main/SPEC.md).

**Non difeso:**
- Compromissione della root dell'host (la chiave è in `/var/lib/r503d/key`, `0600 root:root`).
  La root su un host in esecuzione può dissigillare anche la variante sigillata TPM —
  la sigillatura attenua gli attacchi *offline*, non quelli online.
- Attacco fisico alla Nano (lettura EEPROM ~30 sec con ISP; decap del chip; ecc.).
- Attacco di reflash del firmware (il bootloader Arduino non ha firma — ma la
  ri-associazione richiede la root sull'host, quindi una Nano riflashata non può
  essere resa affidabile senza compromettere comunque l'host).
- Compromissione lato R503 (il protocollo R30x non ha alcuna autenticazione;
  fuori dal nostro scope).
- **Postura crittografica.** MAC SipHash-2-4, chiave condivisa a 128 bit, output
  MAC a 64 bit, input MAC separati per dominio. Due implementazioni indipendenti
  (C++ scritto a mano sull'AVR con autotest KAT all'avvio; Rust scritto a mano
  sull'host, convalidato in modo incrociato bit per bit contro la crate
  `siphasher` di terze parti su 1024 vettori casuali in CI). Il confronto MAC
  sull'host usa `subtle::ConstantTimeEq`. I parser wire vengono sottoposti a
  property-fuzzing a ogni esecuzione CI (~135 000 input). `cargo audit` pulito.
  La chiave SipHash è avvolta in `zeroize::Zeroizing<...>` così da essere
  cancellata al drop (come i buffer di input MAC per-frame). Un target libFuzzer
  di `cargo fuzz` è incluso in `pcside/daemon/fuzz/` per esecuzioni con corpus
  lungo su nightly. Nessun audit umano di terze parti a pagamento — sarebbe
  comunque prezioso, PR benvenute.

Modello di minaccia completo con motivazioni: [`SPEC.md` §13.1](https://github.com/matpb/linux-fingerprint-r503/blob/main/SPEC.md).

## Limitazioni

- **Il multi-utente funziona, ma solo per i membri di `wheel`.** L'identità del
  chiamante viene verificata su ogni metodo D-Bus che accetta un `username`
  (`Claim`, `EnrollStart`, `VerifyStart`, `ListEnrolledFingers`,
  `DeleteEnrolledFingers`); le richieste verso se stessi e `uid 0` (PAM) riescono
  silenziosamente, mentre una richiesta cross-user da un chiamante non-root viene
  negata con `net.reactivated.Fprint.Error.PermissionDenied`. La policy del bus
  di sistema limita ulteriormente quali account possono persino avviare una
  conversazione: solo `root` e i membri di `wheel` raggiungono il demone, tutti
  gli altri ricevono `org.freedesktop.DBus.Error.AccessDenied` a livello di
  broker. Serve un enroll cross-user? Diventa root:
  `sudo fprintd-enroll target-user`. Serve allentare il gate cross-user per un
  chiosco / laboratorio multi-utente? Inserisci una regola JS in
  `/etc/polkit-1/rules.d/` che ha come target
  [`net.reactivated.fprint.device.setusername`](https://gitlab.freedesktop.org/libfprint/fprintd/-/blob/master/src/net.reactivated.fprint.device.policy.in)
  — il nome dell'azione rispecchia alla lettera l'upstream fprintd.
- **Un solo lettore.** Il demone espone un singolo oggetto Device su D-Bus.
  Le configurazioni multi-lettore richiedono un'estensione del Manager.
- **Nessun emit di `PropertiesChanged`** per le proprietà hint
  `finger-present` / `finger-needed`. Ogni client fprintd comune (PAM, KDE
  Settings, GNOME) si basa sui segnali `EnrollStatus` / `VerifyStatus` (che
  vengono emessi), non su quegli hint interrogati — ma un client rigoroso che
  fa `Get + PropertiesChanged` vedrà valori obsoleti.
- **Una sola Nano = punto unico di guasto.** Se la Nano muore, il login con
  impronta sparisce finché non riflashate una di scorta e la ri-associate.
  Tenete attivo un metodo di autenticazione con password come backup.
- **La perdita di State.json si recupera con un comando.** Se `state.json` viene
  perso mentre il firmware ha ancora un `last_seen` alto, il demone incontra
  `ERR replay` al primo invio. Eseguite `sudo r503d --resync` per leggere il
  contatore della Nano e riallineare l'host — nessuna ri-associazione necessaria.
  Vedi [`SPEC.md` §13.11](https://github.com/matpb/linux-fingerprint-r503/blob/main/SPEC.md).

## Risoluzione dei problemi```bash
# Daemon logs:
sudo journalctl -u r503d.service -f

# Confirm the sensor enumerates correctly:
ls -l /dev/r503
busctl --system call net.reactivated.Fprint /net/reactivated/Fprint/Device/0 \
    net.reactivated.Fprint.Device ListEnrolledFingers s ""

# Confirm fprintd is masked and r503d owns the bus name:
systemctl is-enabled fprintd  # should print "masked"
busctl --system list | grep -i fprint

Se il daemon non si avvia o il sensore non risponde mai, la soluzione più comune è il cablaggio — vedi SPEC.md §3, in particolare la nota "no voltage divider" nel §3.1. C'è un runbook più dettagliato in docs/TROUBLESHOOTING.md.

Licenza

MIT — vedi LICENSE.

Crediti

  • Adafruit_Fingerprint — implementazione del protocollo R30x lato Arduino.
  • zbus, serialport-rs, tokio — lo stack Rust D-Bus / serial / async.
  • Il progetto fprintd — per aver progettato un'interfaccia D-Bus pulita che questo daemon potesse implementare senza mai leggere il codice sorgente di libfprint.
Scarica lo strumento
  • installa la policy restrittiva del bus di sistema (/etc/dbus-1/system.d/net.reactivated.Fprint.conf) — solo root e i membri di wheel possono parlare col daemon; tutti gli altri ricevono AccessDenied dal broker, prima che il daemon veda la chiamata
  • arresta e maschera il servizio upstream fprintd.service
  • avvia r503d.service