Skip to content
KitploitKITPLOIT
FerramentasBlog
Enviar
FerramentasBlog
Enviar

Ferramentas de Hacking, PenTest e Cibersegurança para o seu Arsenal de Segurança!

Kitploit é um diretório de ferramentas de hacking, cibersegurança e pentesting. Descubra as últimas atualizações de projetos para encontrar vulnerabilidades, analisar sistemas, automatizar testes e fortalecer sua segurança.

··Feeds·Contato·Privacidade·© 2026 Kitploit

Diretório de Ferramentas

Categorias

Ver todas as categorias
Loading categories
linux-fingerprint-r503 — Login por impressão digital no desktop Linux usando um sensor Grow R503 + Arduino + um daemon substituto do fprintd escrito em Rust | Kitploit
Ferramentas/GitHubGitHub/matpb/linux-fingerprint-r503
Segurança de Sistemas EmbarcadosCriptografiaTestes de PenetraçãoSegurança de HardwareAutenticaçãoRed Teaming
GitHubmatpb/linux-fingerprint-r503

linux-fingerprint-r503

Login por impressão digital no desktop Linux usando um sensor Grow R503 + Arduino + um daemon substituto do fprintd escrito em Rust

Ver Repositório
442há 1 mêsRevisado pelo Kitploit

Mais Populares

Ver todos →

Descubra as ferramentas mais usadas pela nossa comunidade.

Explore todas as ferramentas

Navegue pela nossa coleção de ferramentas

Ver todas as ferramentas →
Compartilhar

linux-fingerprint-r503 — login por impressão digital no Linux usando um Grow R503 + Arduino

CI r503d firmware Rust 2024 Platform: Linux License: MIT

Um leitor de impressão digital USB montado a partir de peças para desktops Linux. Custo total das peças inferior a US$ 15. Substituição direta do fprintd upstream — PAM, KDE Settings, GNOME Settings, fprintd-verify, sudo com o dedo, desbloqueio de tela com o dedo — tudo funciona.

A partir de fw=1.0 / r503d 1.0.0 o link Arduino↔host é autenticado: cada comando e resposta carrega um MAC SipHash-2-4 vinculado a um segredo pareado via TOFU na EEPROM. Ataques de replay e de troca a quente contra o link serial USB são bloqueados. Consulte SPEC.md §13 para o design completo, incluindo o que o modelo de ameaças não cobre.

Sensor R503 montado em um invólucro de madeira cortado à mão, anel azul brilhando

quem me dera ter uma impressora 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:~
## Motivação

Leitores de impressão digital USB para Linux são escassos, caros e os
que existem (Validity, Synaptics, etc.) dependem de drivers libfprint
instáveis, criados por engenharia reversa, que quebram com atualizações
de firmware do fornecedor. O protocolo do Grow R503 é **público**, o lado
do Arduino é código seu, e a camada de compatibilidade libfprint é apenas
D-Bus.

Você também acaba com um leitor de impressão digital cujo código-fonte
você pode ler de cima a baixo.

## Lista de materiais

| Peça | Notas | Custo aproximado |
|------|-------|------|
| Sensor de impressão digital capacitivo Grow R503 | O redondo com o anel RGB | ~$10 |
| Placa Arduino Uno R3 / Nano / Mega / qualquer placa ATmega328 | Qualquer placa que rode SoftwareSerial | $5–$25 |
| 4–6 fios jumper | Dupont / protoboard | trivial |

## Ligação```
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 o seu R503 vier com o conector JST-SH, corte um pigtail JST-SH para Dupont de 6 pinos para separar os fios. O fio marrom às vezes é verde, dependendo do vendedor — verifique em relação ao fio que vai para o pino RXD do conector JST, não pela cor.

Pré-requisitos

Testado no Fedora 44 KDE; deve funcionar em qualquer distro baseada em systemd com fprintd, pam_fprintd e uma toolchain Rust recente.

Pacotes do sistema:

DistroCompilaçãoTempo de execução
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

Os pacotes tss-esapi só são necessários se você planeja usar --pair --seal-tpm (SPEC §13.12). O daemon compila e executa sem um TPM caso contrário — tss-esapi é uma dependência de compilação obrigatória, mas uma dependência de execução opcional (o caminho de código só é percorrido quando /var/lib/r503d/key.tpm existe).

Rust 1.95+, arduino-cli no seu $PATH.

Você tem um TPM2?```bash ls /dev/tpmrm0 && tpm2_pcrread sha256:7 | head -3

root@kitploit:~
Se ambos forem bem-sucedidos, seu host poderá usar o caminho de chave selada. Se `/dev/tpmrm0` estiver ausente (hardware mais antigo, TPM desabilitado na BIOS ou uma VM sem TPM virtual), continue com o fluxo padrão de chave em texto puro.

## Compilação e instalação

### 1. Grave o firmware

Abra `firmware/r503fp/r503fp.ino` na IDE do Arduino e carregue. Ou com `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`

O firmware usa Adafruit_Fingerprint. A IDE se oferecerá para instalá-lo na primeira compilação.

Se arduino-cli upload falhar com not in sync: resp=0x7e, o seu bootloader é a outra variante — troque atmega328 ↔ atmega328old e tente novamente. Ambos funcionam; a diferença é apenas a taxa de transmissão do bootloader.

2. Compile o daemon

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

root@kitploit:~
### 3. Instalação```bash
sudo bash pcside/daemon/dist/install.sh

Esse script:

  • instala target/release/r503d em /usr/local/bin/r503d
  • cria /var/lib/r503d/ (modo 0700 root:root) para a chave, o estado e o registro de slots de usuário
  • grava a regra udev que expõe o Arduino como /dev/r503 e bloqueia o nó de dispositivo para root:root 0600 (somente o daemon, executando como root, precisa disso; isso fecha o caminho padrão 0660 root:dialout para que nenhum outro usuário local possa abrir a porta — auditoria de segurança 2026-05-28 / H1). Consequência: após a instalação, qualquer comando manual de arduino-cli/serial-monitor contra /dev/r503 exige sudo.
  • instala a unit do systemd (/etc/systemd/system/r503d.service)
  • substitui a entrada de autolaunch do D-Bus para net.reactivated.Fprint
  • instala a ação do polkit (/usr/share/polkit-1/actions/net.reactivated.fprint.device.r503d.policy) usada pela barreira de identidade do chamador

É idempotente — execute-o novamente após cada cargo build --release para reimplementar o novo binário.

4. Emparelhe o Nano com o daemon

Um Nano recém-gravado não está emparelhado — o daemon falaria com ele, mas o firmware rejeitaria cada comando enquadrado. Escolha um dos dois fluxos abaixo; ambos terminam com um Nano emparelhado e um daemon em funcionamento. O fluxo com selo TPM é recomendado se o seu host tiver um TPM2 (consulte os Pré-requisitos para a verificação rápida).

O arquivo opt-in (/etc/r503d/allow-pair) usado em ambos os fluxos existe para derrotar um atacante que corre até a sua mesa com o próprio Nano — o emparelhamento sem root é impossível. r503d --pair exclui o marcador antes de enviar a chave para o Nano: se o host travar entre a confirmação no lado do Nano e a persistência no lado do host, a barreira já está fechada, então a próxima tentativa de emparelhamento exige que um administrador execute touch no marcador novamente. Uma saída antes do envio (sem marcador, ou "já emparelhado") deixa o marcador intacto para nova tentativa.

4a. Emparelhamento com chave em texto puro (padrão)

Use isto se você não tiver um dispositivo TPM2, ou se não precisar de resistência a ataques a disco offline.```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:~
...```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. Emparelhamento selado por TPM (recomendado em hosts TPM2, SPEC §13.12)

Mesmo fluxo, mais --seal-tpm. A chave gerada é selada para PCR7 (política de Secure Boot + chaves) e gravada em /var/lib/r503d/key.tpm em vez do arquivo key em texto puro. Atacantes com disco offline (dd de uma partição desmontada, troca de SSD para um host hostil) obtêm apenas 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:~
The input chunk appears to be empty — no content was provided after "INPUT:". Please supply the chunk text to translate.```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)

Atualizações de kernel, atualizações de initrd, atualizações de firmware UEFI via fwupd e atualizações do grub2 não alteram o PCR7 e não exigem reseal. O PCR7 só muda em edições da política do Secure Boot, inscrições de MOK ou ao mover o disco para outro host — ponto em que o daemon se recusa a iniciar com TPM_RC_POLICY_FAIL e dist/reseal-tpm.sh recupera em ~90 segundos. Veja Recuperação: PCR7 alterado.

5. Inscrever e 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 as Configurações do KDE (Plasma 6) quanto os diálogos de impressão digital de conta de usuário do GNOME Control Center controlam `r503d` exatamente como controlam o `fprintd` upstream.

### Reemparelhamento / rotação de chave

Se você quiser uma chave nova (chave comprometida, troca de hardware planejada, 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

Corresponda ao seu caminho de emparelhamento original. Se você usou originalmente --seal-tpm, faça a rotação com --seal-tpm — caso contrário, a rotação o rebaixa silenciosamente para uma chave em texto simples no disco.

Recuperação: PCR7 alterado, é necessário resselar

Se você usou --pair --seal-tpm e depois alterou algo que o PCR7 mede (Secure Boot desligado/ligado, novo MOK registrado, disco movido para outra máquina), o daemon se recusará a iniciar com uma mensagem no journal sobre TPM_RC_POLICY_FAIL. A recuperação é um único comando:```bash sudo bash pcside/daemon/dist/reseal-tpm.sh

root@kitploit:~
O script para o `r503d`, regrava `firmware/r503fp_wipe/` para limpar a EEPROM do Nano, regrava o firmware principal, cria `/etc/r503d/allow-pair`, executa `r503d --reseal-tpm` para gerar uma nova chave selada ao PCR7 *atual* e reinicia o daemon. Tempo real: ~90 segundos. As impressões digitais cadastradas são preservadas — os templates ficam na flash do sensor R503, não no Nano.

O script precisa do `arduino-cli` disponível. Se estiver instalado em `$HOME/.local/bin` do seu usuário, ele é detectado automaticamente via `$SUDO_USER`; caso contrário, defina `ARDUINO_CLI=/full/path/to/arduino-cli` antes de executar.

### Recuperação: `state.json` perdido (dessincronização do contador)

Se a chave do host estiver intacta, mas `/var/lib/r503d/state.json` tiver sumido ou sido revertido (restaurado de um backup antigo, `rm` acidental), o contador do daemon fica atrás do `last_seen` do Nano e todo comando enquadrado é rejeitado com `ERR replay`. O `r503d --status` sinaliza isso; a correção é um único comando:```bash
sudo systemctl stop r503d
sudo r503d --resync                         # reads Nano last_seen, sets host counter to last_seen+1
sudo systemctl start r503d

Sem re-pareamento, sem reflash — a chave nunca se move. A consulta status da qual --resync depende não é autenticada, mas ela só pode mover o contador do host para frente para corresponder ao que o Nano já confirmou, portanto nunca pode tornar um quadro antigo reproduzível (no pior caso, um MITM mentiroso força outro ERR replay, o que ele já poderia fazer ao corromper quadros). Veja SPEC.md §13.11.

Recuperação: perdeu a chave do host completamente

O --unpair autenticado precisa da chave para autorizar. Se todas as cópias em disco sumiram (falha de disco, rm acidental, tanto key quanto key.bak deletados, ou o blob key.tpm perdido), você precisa da válvula de escape reflash-to-wipe — mesmo procedimento que dist/reseal-tpm.sh automatiza para o caso de PCR7 alterado acima:```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` relatar command-not-found (o arduino-cli fica no seu
`~/.local/bin`, não no `PATH` do root), execute-o como
`sudo env "PATH=$PATH" arduino-cli …` ou forneça o caminho absoluto.

Isto não é uma backdoor que um invasor possa usar: o re-pareamento requer root no
host (o arquivo opt-in e a CLI `--pair` ambos precisam de root), então um
Nano reflashado não pode ser aceito como confiável sem que você já seja
root.

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

Reverte tudo, desmascara fprintd, deixa /var/lib/r503d/ (chave, estado, usuários) no lugar caso queira reinstalar mais tarde. Apague esse diretório manualmente se quiser um estado realmente limpo.

Como funciona

O Arduino executa um pequeno firmware de protocolo ASCII (firmware/r503fp/) que fala o protocolo binário nativo R30x ("Sync Word") do R503 no lado UART e troca comandos de texto orientados por linha com o host via USB-CDC: ping, info, enroll N, verify, delete N, clear, led off. Protocolo v1 completo em SPEC.md §5.

Desde fw=1.0 (Marco E do trabalho de canal autenticado v2), todo comando e resposta é envolvido em um quadro C <counter> <body> M <mac> / R <counter> <seq> <body> M <mac> com MAC via SipHash-2-4 sobre uma chave de 128 bits pareada por TOFU. O Nano mantém um contador monotônico com nivelamento de desgaste na EEPROM; o daemon mantém um contador correspondente em /var/lib/r503d/state.json. Tentativas de replay (no lado do firmware, incoming <= last_seen) são rejeitadas como ERR replay; quadros adulterados resultam em ERR mac_invalid. Especificação completa, modelo de ameaça e limitações conhecidas em SPEC.md §13.

O daemon Rust (r503d) fala D-Bus em net.reactivated.Fprint — exatamente a mesma interface que o fprintd upstream expõe — então todo cliente fprintd funciona sem modificações. Um sidecar JSON em /var/lib/r503d/users.json mapeia (usuário, dedo) para índices de slot na flash interna do 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:~
## Modelo de segurança — resumo rápido

A autenticação em nível de protocolo visa uma ameaça específica —
**"empregada maliciosa com cinco minutos e um Nano sobressalente"** mais um processo local
hostil em `/dev/r503` — não estados-nação ou atacantes de hardware com
laboratórios. Implantação desktop de usuário único com uma lista documentada de itens fora de escopo.
O modelo de ameaça completo vive em [`SPEC.md` §13.1](https://github.com/matpb/linux-fingerprint-r503/blob/HEAD/SPEC.md); as
evidências de implementação e revisão vivem em
[`docs/REVIEW-2026-05-28.md`](https://github.com/matpb/linux-fingerprint-r503/blob/HEAD/docs/REVIEW-2026-05-28.md). Uma auditoria
adversarial separada de escalonamento de privilégios (2026-05-28) e sua
passagem de validação/remediação por alegação estão em
[`docs/SECURITY-AUDIT-2026-05-28.html`](https://github.com/matpb/linux-fingerprint-r503/blob/HEAD/docs/SECURITY-AUDIT-2026-05-28.html)
e
[`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:**
- Troca a quente do Nano por uma unidade hostil (sem chave → todos os quadros falham no MAC).
- Processo local injetando respostas falsas de correspondência em `/dev/r503`. Duas camadas:
  o nó de dispositivo é `root:root 0600` (regra udev) e o daemon o mantém
  com `TIOCEXCL`, então um processo não-root não pode abri-lo — e mesmo se
  pudesse, não tem chave, então o quadro falha na verificação MAC.
- Repetição (replay) de quadros `OK match=...` gravados em uma sessão futura.
- Adulteração por bit-flip de qualquer campo do quadro (comparação MAC em tempo constante).
- Travamento por esgotamento de contador: um par (ou um MITM de uso único durante `--resync`)
  conduzindo o contador monotônico a `u64::MAX` e travando permanentemente o
  canal é bloqueado por um teto de contador reservado aplicado em ambas as extremidades
  (`fw=1.1+`; auditoria SPEC §13.4 / 2026-05-28 DoS-2).
- Negação de serviço por usuário local contra o sensor: uma comporta de slot de captura única
  limita o trabalho de enroll/verify em andamento e os caminhos de exclusão são controlados por ação,
  então uma enxurrada de `Start`/`Stop` (ou exclusões concorrentes) não pode travar a autenticação.
- Inserção / remoção / enumeração de impressões digitais entre usuários por um usuário local
  não-root (ex.: `mallory` chamando `Claim "root"` e então cadastrando o próprio
  dedo) — a identidade do chamador é verificada em todo método D-Bus que recebe `username`,
  e a política do barramento do sistema nega chamadores não-`wheel` na
  camada do broker.
- **Ataques offline ao disco contra a chave do host** *quando combinado com `--seal-tpm`*:
  a chave em disco é selada por TPM2 para PCR7, então um `dd` de uma partição
  desmontada ou a troca de SSD para um host hostil produz apenas texto cifrado.
  Só é desembrulhada na mesma máquina sob a mesma política Secure Boot.
  Veja [SPEC §13.12](https://github.com/matpb/linux-fingerprint-r503/blob/HEAD/SPEC.md).

**Não defendido:**
- Comprometimento de root no host (a chave está em `/var/lib/r503d/key`, `0600 root:root`).
  O root em um host em execução também pode deselar a variante selada por TPM — a selagem
  atenua ataques *offline*, não os online.
- Ataque físico ao Nano (leitura da EEPROM ~30 s com ISP; decapagem do chip; etc.).
- Ataque de regravação de firmware (o bootloader do Arduino não tem assinatura — mas
  o re-pareamento exige root no host, então um Nano regravado não pode ser
  estabelecido como confiável sem comprometimento do host de qualquer forma).
- Comprometimento do lado do R503 (o protocolo R30x não tem autenticação alguma; fora do nosso escopo).
- **Postura criptográfica.** MACs SipHash-2-4, chave compartilhada de 128 bits, saída MAC
  de 64 bits, entradas MAC separadas por domínio. Duas implementações independentes
  (C++ implementado manualmente no AVR com autoteste KAT na inicialização; Rust
  implementado manualmente no host, validado bit a bit contra o crate `siphasher`
  de terceiros em 1024 vetores aleatórios no CI). A comparação MAC no host usa
  `subtle::ConstantTimeEq`. Os parsers de protocolo são submetidos a fuzzing de propriedades em toda execução de CI
  (~135 000 entradas). `cargo audit` limpo. A chave SipHash é envolvida em
  `zeroize::Zeroizing<...>` para que seja apagada no drop (assim como os buffers
  de entrada MAC por quadro). Um alvo libFuzzer de `cargo fuzz`
  é fornecido em `pcside/daemon/fuzz/` para execuções com corpus longo no
  nightly. Nenhuma auditoria humana paga de terceiros — isso ainda seria
  valioso, PRs são bem-vindos.

Modelo de ameaça completo com justificativa: [`SPEC.md` §13.1](https://github.com/matpb/linux-fingerprint-r503/blob/HEAD/SPEC.md).

## Limitações

- **Multiusuário funciona, mas apenas para membros de `wheel`.** A identidade do chamador é
  verificada em todos os métodos D-Bus que recebem um `username` (`Claim`,
  `EnrollStart`, `VerifyStart`, `ListEnrolledFingers`,
  `DeleteEnrolledFingers`); solicitações para si mesmo e `uid 0` (PAM) têm sucesso
  silencioso, enquanto a solicitação entre usuários a partir de um chamador não-root é negada com
  `net.reactivated.Fprint.Error.PermissionDenied`. A política do barramento do sistema
  restringe ainda mais quais contas podem sequer iniciar uma conversa: apenas
  `root` e membros de `wheel` alcançam o daemon; todos os demais recebem
  `org.freedesktop.DBus.Error.AccessDenied` na camada do broker.
  Precisa de enroll entre usuários? Torne-se root: `sudo fprintd-enroll target-user`.
  Precisa afrouxar a portaria entre usuários para um quiosque / laboratório multiusuário? Coloque
  uma regra JS em `/etc/polkit-1/rules.d/` direcionada a
  [`net.reactivated.fprint.device.setusername`](https://gitlab.freedesktop.org/libfprint/fprintd/-/blob/master/src/net.reactivated.fprint.device.policy.in)
  — o nome da ação espelha o fprintd upstream literalmente.
- **Um leitor.** O daemon expõe um único objeto Device no D-Bus.
  Configurações com vários leitores precisam de uma extensão do Manager.
- **Nenhuma emissão de `PropertiesChanged`** para as propriedades de dica
  `finger-present` / `finger-needed`. Todos os clientes fprintd comuns (PAM, KDE Settings, GNOME)
  usam os sinais `EnrollStatus` / `VerifyStatus` (que são emitidos),
  e não essas dicas pesquisadas — mas um cliente estrito que faça
  `Get + PropertiesChanged` verá valores obsoletos.
- **Um único Nano = ponto único de falha.** Se o Nano morrer, o login por impressão
  digital desaparece até você regravar um sobressalente e parear novamente. Mantenha um método
  de autenticação por senha habilitado como reserva.
- **A perda de `state.json` é recuperável com um único comando.** Se `state.json` for perdido
  enquanto o firmware ainda tem um `last_seen` alto, o daemon recebe `ERR replay`
  no primeiro envio. Execute `sudo r503d --resync` para ler o contador do Nano e
  realinhar o host — nenhum re-pareamento é necessário. Veja [`SPEC.md` §13.11](https://github.com/matpb/linux-fingerprint-r503/blob/HEAD/SPEC.md).

## Solução 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

Se o daemon não iniciar ou o sensor nunca responder, a correção mais comum é a fiação — veja SPEC.md §3, particularmente a nota "sem divisor de tensão" na §3.1. Há um runbook mais detalhado em docs/TROUBLESHOOTING.md.

Licença

MIT — veja LICENSE.

Créditos

  • Adafruit_Fingerprint — implementação do protocolo R30x no lado Arduino.
  • zbus, serialport-rs, tokio — a pilha Rust de D-Bus / serial / async.
  • O projeto fprintd — por projetar uma interface D-Bus limpa que este daemon pudesse implementar sem nunca ler o código-fonte do libfprint.
Baixar ferramenta
  • instala a política restritiva do barramento do sistema (/etc/dbus-1/system.d/net.reactivated.Fprint.conf) — somente membros de root e wheel podem falar com o daemon; todos os outros recebem AccessDenied no broker, antes de o daemon ver a chamada
  • interrompe e mascara o fprintd.service upstream
  • inicia o r503d.service