
Вход в систему Linux по отпечатку пальца с использованием датчика Grow R503 + Arduino + демона на Rust, заменяющего fprintd
Самодельный USB-сканер отпечатков пальцев для Linux. Общая стоимость компонентов менее $15. Замена для штатного fprintd — PAM, настройки KDE, настройки GNOME, fprintd-verify, sudo с пальцем, разблокировка экрана пальцем — всё работает.
Начиная с fw=1.0 / r503d 1.0.0 провод Arduino↔хост аутентифицирован: каждая команда и ответ содержат MAC SipHash-2-4, привязанный к секрету, установленному по принципу TOFU в EEPROM. Атаки повторного воспроизведения и горячей замены на последовательный USB-канал блокируются. Полное описание, включая то, что не покрывает угрозная модель, см. в SPEC.md §13.

жаль, что у меня нет 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, …
## Зачем
Аппаратные USB-сканеры отпечатков пальцев для Linux — редкость, дороги, а те,
что существуют (Validity, Synaptics и т.д.), работают через обратно разработанные
нестабильные драйверы libfprint, которые ломаются при обновлениях прошивки вендора.
Протокол Grow R503 **открыт**, сторона Arduino — ваш собственный код,
а уровень совместимости с libfprint — просто D-Bus.
В итоге вы получаете сканер отпечатков пальцев, код которого можно прочитать
от корки до корки.
## Список материалов
| Деталь | Примечания | Примерная цена |
|--------|------------|------|
| Ёмкостный датчик отпечатков пальцев Grow R503 | Круглый с RGB-кольцом | ~$10 |
| Плата Arduino Uno R3 / Nano / Mega / любая на ATmega328 | Любая, поддерживающая SoftwareSerial | $5–$25 |
| 4–6 перемычек | Dupont / макетная плата | копейки |
Вот и всё. **Никакого преобразователя уровней, никакого делителя напряжения** — см. [`SPEC.md` §3.1](https://github.com/matpb/linux-fingerprint-r503/blob/main/SPEC.md)
почему (линия RX у R503 на практике терпит 5 В; даташит врёт).
## Подключение```
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)
Если ваш R503 поставляется с разъемом JST-SH, отрежьте 6-контактный переходник JST-SH-to-Dupont, чтобы разделить провода. Коричневый иногда бывает зеленым в зависимости от продавца — проверяйте по проводу, который идет в контакт RXD разъема JST, а не по цвету.
Протестировано на Fedora 44 KDE; должно работать на любом дистрибутиве на основе systemd с fprintd, pam_fprintd и актуальной цепочкой инструментов Rust.
Системные пакеты:
| Дистрибутив | Сборка | Среда выполнения |
|---|---|---|
| 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 |
Пакеты tss-esapi нужны только в том случае, если вы планируете использовать --pair --seal-tpm (SPEC §13.12). В остальных случаях демон собирается и запускается без TPM — tss-esapi является жесткой зависимостью сборки, но мягкой зависимостью времени выполнения (код запускается только когда существует /var/lib/r503d/key.tpm).
Rust 1.95+, arduino-cli в вашем $PATH.
У вас есть TPM2?```bash ls /dev/tpmrm0 && tpm2_pcrread sha256:7 | head -3
Если обе операции успешны, ваш хост может использовать путь с запечатанным ключом. Если `/dev/tpmrm0` отсутствует (старое оборудование, TPM отключен в BIOS или виртуальная машина без виртуального TPM), придерживайтесь стандартного потока с открытым ключом.
## Сборка и установка
### 1. Прошейте прошивку
Откройте `firmware/r503fp/r503fp.ino` в Arduino IDE и загрузите. Или с помощью `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`
Прошивка использует Adafruit_Fingerprint. IDE предложит установить её
при первой компиляции.
Если arduino-cli upload завершается ошибкой not in sync: resp=0x7e, ваш загрузчик
— другой вариант — замените atmega328 ↔ atmega328old и повторите попытку. Оба
работают; разница лишь в скорости загрузчика.
Требуется Rust 1.95+.```bash cd pcside/daemon cargo build --release
### 3. Установка```bash
sudo bash pcside/daemon/dist/install.sh
That script:
target/release/r503d в /usr/local/bin/r503d/var/lib/r503d/ (режим 0700 root:root) для ключа, состояния и реестра пользовательских слотов/dev/r503 и блокирует узел устройства с правами root:root 0600 (только демону, работающему от root, он нужен; это закрывает путь по умолчанию 0660 root:dialout, так что ни один другой локальный пользователь не сможет открыть порт — аудит безопасности 2026-05-28 / H1). Следствие: после установки любая ручная команда arduino-cli/serial-monitor для /dev/r503 требует sudo./etc/systemd/system/r503d.service)net.reactivated.Fprint/usr/share/polkit-1/actions/net.reactivated.fprint.device.r503d.policy), используемое шлюзом идентификации вызывающего/etc/dbus-1/system.d/net.reactivated.Fprint.conf) — только члены групп root и wheel могут общаться с демоном; все остальные получают AccessDenied от брокера, прежде чем демон увидит вызовfprintd.servicer503d.serviceОн идемпотентен — повторно запускайте его после каждого cargo build --release, чтобы развернуть новый бинарник.