Skip to content
KitploitKITPLOIT
HerramientasBlog
Enviar
HerramientasBlog
Enviar

¡Herramientas de Hacking, PenTest y Ciberseguridad para tu Arsenal de Seguridad!

Kitploit es un directorio de herramientas de hacking, ciberseguridad y pentesting. Descubre las últimas actualizaciones de proyectos para encontrar vulnerabilidades, analizar sistemas, automatizar pruebas y fortalecer tu seguridad.

··Feeds·Contacto·Privacidad·© 2026 Kitploit

Directorio de Herramientas

Categorías

Ver todas las categorías
Loading categories
linux-fingerprint-r503 — Inicio de sesión por huella dactilar en el escritorio de Linux mediante un sensor Grow R503 + Arduino + un daemon de reemplazo de fprintd en Rust | Kitploit
Herramientas/GitHubGitHub/matpb/linux-fingerprint-r503
Seguridad de Sistemas EmbebidosCriptografíaPruebas de PenetraciónSeguridad de HardwareAutenticaciónRed Teaming
GitHubmatpb/linux-fingerprint-r503

linux-fingerprint-r503

Inicio de sesión por huella dactilar en el escritorio de Linux mediante un sensor Grow R503 + Arduino + un daemon de reemplazo de fprintd en Rust

Ver Repositorio
442hace 1 mesRevisado por Kitploit

Más Populares

Ver todos →

Descubre las herramientas más usadas por nuestra comunidad.

Explora todas las herramientas

Explora nuestra colección de herramientas

Ver todas las herramientas →
Compartir

linux-fingerprint-r503 — inicio de sesión con huella digital para Linux usando un Grow R503 + Arduino

CI r503d firmware Rust 2024 Platform: Linux License: MIT

Un lector USB de huellas dactilares para escritorios Linux construido a partir de componentes. Coste total de las piezas inferior a 15 $. Sustituto directo del fprintd oficial: PAM, Ajustes de KDE, Ajustes de GNOME, fprintd-verify, sudo con el dedo y desbloqueo de pantalla con el dedo, todo funciona.

A partir de fw=1.0 / r503d 1.0.0 el cable Arduino↔host está autenticado: cada comando y respuesta lleva un MAC SipHash-2-4 con clave asociada a un secreto emparejado por TOFU en la EEPROM. Los ataques de reproducción y de intercambio en caliente contra el enlace serie USB quedan bloqueados. Consulta SPEC.md §13 para ver el diseño completo, incluido lo que el modelo de amenazas no cubre.

Sensor R503 montado en una carcasa de madera cortada a mano, con un anillo azul brillante

ojalá tuviera una impresora 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:~
## Por qué

Los lectores de huellas dactilares USB para Linux son escasos, caros y los
que existen (Validity, Synaptics, etc.) se basan en controladores libfprint
inestables creados mediante ingeniería inversa que se rompen con las
actualizaciones de firmware del proveedor. El protocolo del Grow R503 es **público**,
el lado de Arduino es tu propio código, y la capa de compatibilidad libfprint es solo D-Bus.

También terminas con un lector de huellas dactilares cuyo código fuente puedes leer de arriba
a abajo.

## Lista de materiales

| Pieza | Notas | Coste aprox. |
|------|-------|------|
| Sensor de huellas dactilares capacitivo Grow R503 | El redondo con el anillo RGB | ~$10 |
| Placa Arduino Uno R3 / Nano / Mega / cualquier placa ATmega328 | Cualquier placa que ejecute SoftwareSerial | $5–$25 |
| 4–6 cables puente | Dupont / placa de pruebas | trivial |

Eso es todo. **Sin cambiador de nivel, sin divisor de voltaje** — consulta [`SPEC.md` §3.1](https://github.com/matpb/linux-fingerprint-r503/blob/HEAD/SPEC.md)
para saber por qué (la línea RX del R503 tolera 5V en la práctica; la ficha técnica miente).

## Conexiones```
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 tu R503 viene con el conector JST-SH, corta un pigtail de 6 pines JST-SH a Dupont para sacar los cables. El marrón a veces es verde dependiendo del vendedor — verifica contra el cable que va al pin RXD del conector JST, no por el color.

Requisitos previos

Probado en Fedora 44 KDE; debería funcionar en cualquier distro basada en systemd con fprintd, pam_fprintd y una toolchain reciente de Rust.

Paquetes del sistema:

DistribuciónCompilaciónEjecución
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

Los paquetes tss-esapi solo son necesarios si planeas usar --pair --seal-tpm (SPEC §13.12). El daemon se compila y funciona sin un TPM de lo contrario — tss-esapi es una dependencia de compilación obligatoria pero una dependencia de ejecución opcional (la ruta de código solo se ejecuta cuando existe /var/lib/r503d/key.tpm).

Rust 1.95+, arduino-cli en tu $PATH.

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

root@kitploit:~
Si ambos tienen éxito, tu host puede usar la ruta de clave sellada. Si falta
`/dev/tpmrm0` (hardware antiguo, TPM deshabilitado en la BIOS o una VM sin TPM
virtual), quédate con el flujo de clave en texto plano predeterminado.

## Compilar e instalar

### 1. Grabar el firmware

Abre `firmware/r503fp/r503fp.ino` en el Arduino IDE y súbelo. O 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`

El firmware utiliza Adafruit_Fingerprint. El IDE ofrecerá instalarla en la primera compilación.

Si arduino-cli upload falla con not in sync: resp=0x7e, tu bootloader es la otra variante — intercambia atmega328 ↔ atmega328old y reintenta. Ambos funcionan; la diferencia es solo la velocidad de baudios del bootloader.

2. Compilar el daemon

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

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

Ese script:

  • instala target/release/r503d en /usr/local/bin/r503d
  • crea /var/lib/r503d/ (modo 0700 root:root) para la clave, el estado y el registro de ranuras de usuario
  • escribe la regla de udev que expone el Arduino como /dev/r503 y bloquea el nodo de dispositivo a root:root 0600 (solo el daemon, que se ejecuta como root, lo necesita; esto cierra la ruta predeterminada 0660 root:dialout para que ningún otro usuario local pueda abrir el puerto — auditoría de seguridad 2026-05-28 / H1). Consecuencia: después de la instalación, cualquier comando manual de arduino-cli/serial-monitor contra /dev/r503 requiere sudo.
  • instala la unidad de systemd (/etc/systemd/system/r503d.service)
  • sobrescribe la entrada de autolanzamiento de D-Bus para net.reactivated.Fprint
  • instala la acción de polkit (/usr/share/polkit-1/actions/net.reactivated.fprint.device.r503d.policy) utilizada por la compuerta de identidad del llamante

Es idempotente — vuelve a ejecutarlo después de cada cargo build --release para reimplementar el nuevo binario.

4. Vincular el Nano con el daemon

Un Nano recién flasheado no está vinculado — el daemon intentaría hablar con él, pero el firmware rechazaría cada comando enmarcado. Elige uno de los dos flujos siguientes; ambos terminan con un Nano vinculado y un daemon funcional. El flujo sellado con TPM se recomienda si tu equipo tiene un TPM2 (consulta Requisitos previos para la comprobación rápida).

El archivo de adhesión voluntaria (/etc/r503d/allow-pair) utilizado en ambos flujos existe para frustrar a un atacante que corra a tu escritorio con su propio Nano — el emparejamiento sin root es imposible. r503d --pair elimina el marcador antes de enviar la clave al Nano: si el equipo se bloquea entre la confirmación del lado del Nano y la persistencia del lado del host, la compuerta ya está cerrada, por lo que el siguiente intento de emparejamiento requiere que un administrador vuelva a hacer touch al marcador. Una salida previa al envío (sin marcador, o «ya vinculado») deja el marcador intacto para reintentar.

4a. Emparejamiento con clave en texto plano (predeterminado)

Utiliza esto si no tienes un dispositivo TPM2, o si no necesitas resistencia a ataques de disco fuera de línea.```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:~
I don't see any input text to translate. The chunk content appears to be missing from your message. Please provide the actual text for chunk 15/37 and I'll translate it from English to Spanish according to the rules.```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. Emparejamiento sellado con TPM (recomendado en hosts con TPM2, SPEC §13.12)

Mismo flujo, más --seal-tpm. La clave generada se sella a PCR7 (política de Secure Boot + claves) y se escribe en /var/lib/r503d/key.tpm en lugar del archivo key en texto plano. Los atacantes con acceso sin conexión al disco (un dd de una partición desmontada, cambio de SSD a un host hostil) solo obtienen texto cifrado.```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:~
No se recibió ningún texto de entrada en este chunk.```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)

Las actualizaciones del kernel, de initrd, de firmware UEFI de fwupd y de grub2 no cambian PCR7 y no requieren un nuevo sellado. PCR7 solo cambia con ediciones de la política de Secure Boot, inscripciones de MOK o al mover el disco a otro host — en ese punto, el daemon se niega a iniciar con TPM_RC_POLICY_FAIL y dist/reseal-tpm.sh se recupera en ~90 segundos. Consulte Recuperación: PCR7 cambiado.

5. Inscribir y verificar```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:~
Tanto la Configuración de KDE (Plasma 6) como los diálogos de huellas dactilares de cuentas de usuario del Centro de Control de GNOME controlan `r503d` exactamente igual que controlan el `fprintd` estándar.

### Re-emparejamiento / rotación de claves

Si quieres una clave nueva (clave comprometida, cambio de hardware planificado, 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

Haz que coincida tu ruta de emparejamiento original. Si originalmente usaste --seal-tpm, rota con --seal-tpm — de lo contrario, la rotación te degrada silenciosamente a una clave en texto plano en disco.

Recuperación: PCR7 cambió, es necesario volver a sellar

Si usaste --pair --seal-tpm y luego cambiaste algo que PCR7 mide (Secure Boot activado/desactivado, nuevo MOK inscrito, disco movido a otra máquina), el demonio se negará a iniciar con un mensaje de journal sobre TPM_RC_POLICY_FAIL. La recuperación es un solo comando:```bash sudo bash pcside/daemon/dist/reseal-tpm.sh

root@kitploit:~
The script stops `r503d`, reflashes `firmware/r503fp_wipe/` to wipe the
Nano EEPROM, reflashes the main firmware, creates `/etc/r503d/allow-pair`,
runs `r503d --reseal-tpm` to generate a fresh key sealed to the *current*
PCR7, and starts the daemon back up. Tiempo total: ~90 segundos. Las huellas
inscritas se conservan: las plantillas viven en la flash del sensor R503, no
en el Nano.

El script necesita `arduino-cli` disponible. Si está instalado en
`$HOME/.local/bin` de tu usuario, se detecta automáticamente mediante
`$SUDO_USER`; de lo contrario, establece `ARDUINO_CLI=/full/path/to/arduino-cli`
antes de ejecutarlo.

### Recuperación: `state.json` perdido (desincronización del contador)

Si la clave del host está intacta pero `/var/lib/r503d/state.json` falta o se
revirtió (restauraste una copia de seguridad antigua, rm accidental), el
contador del daemon queda por detrás del `last_seen` del Nano y cada comando
enmarcado rebota con `ERR replay`. `r503d --status` lo señala; la solución es
un 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 hay que reemparejar ni reflashear — la clave nunca se mueve. La consulta status de la que depende --resync no está autenticada, pero solo puede mover el contador del host hacia adelante para que coincida con lo que el Nano ya ha confirmado, por lo que nunca puede hacer que un frame antiguo sea repetible (en el peor caso, un MITM mentiroso provoca otro ERR replay, algo que ya podía hacer alterando frames). Ver SPEC.md §13.11.

Recuperación: pérdida total de la clave del host

El comando autenticado --unpair necesita la clave para autorizarse. Si todas las copias en disco han desaparecido (fallo de disco, rm accidental, tanto key como key.bak eliminados, o el blob de key.tpm perdido), necesitas la vía de escape reflash-to-wipe — el mismo procedimiento que dist/reseal-tpm.sh automatiza para el caso de PCR7 modificado anteriormente:```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:~
If `sudo arduino-cli` reports command-not-found (arduino-cli lives in your
`~/.local/bin`, not on root's `PATH`), run it as
`sudo env "PATH=$PATH" arduino-cli …` or give the absolute path.

Esto no es una puerta trasera que un atacante pueda usar: volver a emparejar requiere ser root en el host (el archivo de opt-in y la CLI `--pair` ambos requieren root), por lo que un Nano reflasheado no puede pasar a ser de confianza sin que ya seas root.

### Desinstalación```bash
sudo bash pcside/daemon/dist/uninstall.sh

Deshace todo, desenmascara fprintd, deja /var/lib/r503d/ (clave, estado, usuarios) en su lugar por si quieres reinstalar más adelante. Borra ese directorio manualmente si quieres una verdadera limpieza.

Cómo funciona

El Arduino ejecuta un pequeño firmware de protocolo ASCII (firmware/r503fp/) que se comunica mediante el protocolo binario nativo R30x ("Sync Word") del R503 en su lado UART e intercambia comandos de texto orientados a líneas con el host a través de USB-CDC: ping, info, enroll N, verify, delete N, clear, led off. Protocolo v1 completo en SPEC.md §5.

Desde fw=1.0 (hito E del trabajo del canal autenticado v2), cada comando y respuesta se envuelve en una trama C <counter> <body> M <mac> / R <counter> <seq> <body> M <mac> protegida con MAC mediante SipHash-2-4 sobre una clave de 128 bits emparejada por TOFU. El Nano mantiene un contador monotónico con nivelación de desgaste en la EEPROM; el daemon mantiene un contador correspondiente en /var/lib/r503d/state.json. Los intentos de replay (del lado del firmware incoming <= last_seen) se rechazan como ERR replay; las tramas alteradas reciben ERR mac_invalid. Especificación completa, modelo de amenazas y limitaciones conocidas en SPEC.md §13.

El daemon de Rust (r503d) se comunica por D-Bus en net.reactivated.Fprint — bit a bit la misma interfaz que expone el fprintd upstream — por lo que cualquier cliente fprintd funciona sin modificaciones. Un archivo sidecar JSON en /var/lib/r503d/users.json asigna (usuario, dedo) a índices de ranura en la memoria flash interna del R503.

Estructura:``` 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:~
## Modelo de seguridad — resumen rápido

La autenticación a nivel de cable se dirige a una amenaza específica —
**"doncella malvada con cinco minutos y un Nano de repuesto"** más un proceso
local hostil en `/dev/r503` — no a estados-nación ni a atacantes de hardware
con laboratorios. Implementación de escritorio de un solo usuario con una
lista documentada de elementos fuera de alcance. El modelo de amenazas completo
se encuentra en [`SPEC.md` §13.1](https://github.com/matpb/linux-fingerprint-r503/blob/HEAD/SPEC.md); la evidencia de implementación y
revisión se encuentra en
[`docs/REVIEW-2026-05-28.md`](https://github.com/matpb/linux-fingerprint-r503/blob/HEAD/docs/REVIEW-2026-05-28.md). Una auditoría
adversarial separada de escalada de privilegios (2026-05-28) y su pasada de
validación/remediación por afirmación están en
[`docs/SECURITY-AUDIT-2026-05-28.html`](https://github.com/matpb/linux-fingerprint-r503/blob/HEAD/docs/SECURITY-AUDIT-2026-05-28.html)
y
[`docs/SECURITY-AUDIT-2026-05-28-VALIDATION.html`](https://github.com/matpb/linux-fingerprint-r503/blob/HEAD/docs/SECURITY-AUDIT-2026-05-28-VALIDATION.html).

**Defendido:**
- Intercambio en caliente del Nano por una unidad hostil (sin clave → todas
  las tramas fallan el MAC).
- Proceso local que inyecta respuestas de coincidencia falsas en `/dev/r503`.
  Dos capas: el nodo de dispositivo es `root:root 0600` (regla de udev) y el
  demonio lo mantiene con `TIOCEXCL`, por lo que un proceso no root no puede
  abrirlo — e incluso si pudiera, no tiene clave, por lo que la trama falla la
  verificación MAC.
- Replay de tramas `OK match=...` grabadas en una sesión futura.
- Manipulación por volteo de bits de cualquier campo de la trama (comparación
  MAC de tiempo constante).
- Bloqueo (brick) por agotamiento del contador: un peer (o un MITM de una
  sola vez durante `--resync`) que lleve el contador monotónico a `u64::MAX` y
  atasque permanentemente el canal es bloqueado por un techo de contador
  reservado aplicado en ambos extremos (`fw=1.1+`; SPEC §13.4 / auditoría de
  2026-05-28 DoS-2).
- Denegación de servicio del sensor por parte de un usuario local: una única
  compuerta de ranura de captura limita el trabajo de enroll/verificación en
  curso y las rutas de borrado están controladas por acción, por lo que una
  inundación de `Start`/`Stop` (o de borrados concurrentes) no puede atascar la
  autenticación.
- Plantado / borrado / enumeración de huellas entre usuarios por parte de un
  usuario local no root (p. ej., `mallory` llamando a `Claim "root"` y luego
  inscribiendo su propio dedo) — la identidad del llamante se comprueba en cada
  método D-Bus que toma `username`, y la política del bus del sistema deniega
  a los llamantes que no son de `wheel` en la capa de broker.
- **Ataques fuera de línea al disco contra la clave del host** *cuando se
  combina con `--seal-tpm`*: la clave en disco está sellada con TPM2 a PCR7,
  por lo que un `dd` de una partición desmontada o el traslado de un SSD a un
  host hostil produce solo texto cifrado. Solo se desenvuelve en la misma
  máquina bajo la misma política de Secure Boot. Ver [SPEC §13.12](https://github.com/matpb/linux-fingerprint-r503/blob/HEAD/SPEC.md).

**No defendido:**
- Compromiso de root del host (la clave está en `/var/lib/r503d/key`,
  `0600 root:root`). El root en un host en ejecución también puede desellar la
  variante sellada por TPM — el sellado atenúa los ataques *fuera de línea*,
  no los en línea.
- Ataque físico al Nano (lectura de EEPROM ~30 s con ISP; decapado de chip;
  etc.).
- Ataque de reflash de firmware (el bootloader de Arduino no tiene firma —
  pero el re-parejado requiere root en el host, por lo que un Nano reflasheado
  no puede ser aceptado como confiable sin comprometer el host de todos modos).
- Compromiso del lado R503 (el protocolo R30x no tiene autenticación en
  absoluto; fuera de nuestro alcance).
- **Postura criptográfica.** MAC SipHash-2-4, clave compartida de 128 bits,
  salida MAC de 64 bits, entradas MAC separadas por dominio. Dos
  implementaciones independientes (C++ artesanal en el AVR con autoprueba KAT
  en el arranque; Rust artesanal en el host, validado cruzadamente bit a bit
  contra el crate de terceros `siphasher` en 1024 vectores aleatorios en CI).
  La comparación MAC del host usa `subtle::ConstantTimeEq`. Los parsers de
  línea se someten a fuzzing de propiedades en cada ejecución de CI
  (~135 000 entradas). `cargo audit` limpio. Clave SipHash envuelta en
  `zeroize::Zeroizing<...>` para que se borre al hacer drop (al igual que los
  búferes de entrada MAC por trama). Un objetivo libFuzzer de `cargo fuzz` se
  incluye en `pcside/daemon/fuzz/` para ejecuciones de corpus largo en
  nightly. Sin auditoría humana externa de pago — eso seguiría siendo valioso,
  PRs bienvenidos.

Modelo de amenazas completo con justificación: [`SPEC.md` §13.1](https://github.com/matpb/linux-fingerprint-r503/blob/HEAD/SPEC.md).

## Limitaciones

- **El modo multiusuario funciona, pero solo para miembros de `wheel`.**
  La identidad del llamante se comprueba en cada método D-Bus que toma un
  `username` (`Claim`, `EnrollStart`, `VerifyStart`, `ListEnrolledFingers`,
  `DeleteEnrolledFingers`); las autosolicitudes y `uid 0` (PAM) tienen éxito
  silenciosamente, el acceso entre usuarios desde un llamante no root se
  deniega con `net.reactivated.Fprint.Error.PermissionDenied`. La política del
  bus del sistema restringe aún más qué cuentas pueden siquiera iniciar una
  conversación: solo `root` y los miembros de `wheel` llegan al demonio, todos
  los demás reciben `org.freedesktop.DBus.Error.AccessDenied` en la capa de
  broker. ¿Necesitas realizar enroll entre usuarios? Hazte root:
  `sudo fprintd-enroll target-user`. ¿Necesitas relajar la restricción de
  cruce de usuarios para un kiosco / laboratorio multiusuario? Coloca una
  regla JS en `/etc/polkit-1/rules.d/` dirigida a
  [`net.reactivated.fprint.device.setusername`](https://gitlab.freedesktop.org/libfprint/fprintd/-/blob/master/src/net.reactivated.fprint.device.policy.in)
  — el nombre de la acción replica exactamente el de fprintd upstream.
- **Un solo lector.** El demonio expone un único objeto Device en D-Bus.
  Las configuraciones con varios lectores necesitan una extensión del Manager.
- **Sin emisión de `PropertiesChanged`** para las propiedades de sugerencia
  `finger-present` / `finger-needed`. Todos los clientes fprintd comunes (PAM,
  KDE Settings, GNOME) se basan en las señales `EnrollStatus` / `VerifyStatus`
  (que sí se emiten), no en esas sugerencias por sondeo — pero un cliente
  estricto que haga `Get + PropertiesChanged` verá valores obsoletos.
- **Un solo Nano = un solo punto de fallo.** Si el Nano muere, el inicio de
  sesión por huella desaparece hasta que reflashes un repuesto y lo vuelves a
  emparejar. Mantén un método de autenticación por contraseña habilitado como
  respaldo.
- **La pérdida de State.json se recupera con un solo comando.** Si
  `state.json` se pierde mientras el firmware aún tiene un `last_seen` alto,
  el demonio se topa con `ERR replay` en el primer envío. Ejecuta
  `sudo r503d --resync` para leer el contador del Nano y realinear el host —
  sin necesidad de volver a emparejar. Ver [`SPEC.md` §13.11](https://github.com/matpb/linux-fingerprint-r503/blob/HEAD/SPEC.md).

## Solución de problemas```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

Si el demonio no arranca o el sensor nunca responde, la solución más común es el cableado: consulte SPEC.md §3, en particular la nota "sin divisor de voltaje" en §3.1. Hay un manual más detallado en docs/TROUBLESHOOTING.md.

Licencia

MIT — consulte LICENSE.

Créditos

  • Adafruit_Fingerprint — implementación del protocolo R30x del lado de Arduino.
  • zbus, serialport-rs, tokio — la pila Rust de D-Bus / serial / async.
  • El proyecto fprintd — por diseñar una interfaz D-Bus limpia que este demonio pudiera implementar sin tener que leer nunca el código fuente de libfprint.
Descargar herramienta
  • instala la política restrictiva del bus del sistema (/etc/dbus-1/system.d/net.reactivated.Fprint.conf) — solo los miembros de root y wheel pueden hablar con el daemon; todos los demás reciben AccessDenied en el broker, antes de que el daemon vea la llamada
  • detiene y enmascara el fprintd.service aguas arriba
  • inicia r503d.service