Files
twofauth-rs/README.ru.md
T
wt cf25e28c28
Rust verification / test (push) Successful in 4m10s
initial commit
2026-10-28 15:59:54 +07:00

13 KiB
Raw Blame History

2FAuth на Rust — 0.3.0

Целевая версия: 2FAuth 8.0.3, коммит 3516c776a1fcbd83d234efc007e3a49807d6ed91.

Это развиваемая реализация совместимости, пока не подтверждённая как полная замена PHP. Рабочий сервер пользователя не изменялся. Все сравнения выполняются на отдельных синтетических базах, включая копию БД, созданной настоящими Laravel-миграциями.

Что реализовано

  • HOTP, TOTP и Steam; SHA-1/256/512 и MD5; атомарный HOTP-счётчик; URI и экспорт.
  • Шифрование Laravel AES-CBC, APP_KEY, предыдущие ключи; транзакционное включение/выключение шифрования данных и иконок.
  • Аккаунты, группы, порядок и назначения отдельно для каждого пользователя; общие аккаунты, всеобщие ссылки доступа, передача владельца с подтверждением пароля; запрет выдачи секретов получателям.
  • Регистрация, вход, CSRF, профиль, смена/восстановление пароля, ограничения регистрации, последний администратор, управление пользователями.
  • Passport 13: настоящие RSA JWT, создание/отзыв PAT, существующие PHP bearer-токены и зашифрованные браузерные laravel_token. Действующая PHP-cookie может быть преобразована в Rust-сессию при загрузке интерфейса.
  • OAuth: authorization code с PKCE, client credentials, Device Code Flow, ротация refresh-токенов и запрет повторного обмена; формат шифрования Defuse PHP совместим с эталоном.
  • Перенос Laravel-сессий из файлов и SQLite: JSON/PHP-сериализация, SESSION_ENCRYPT, проверка cookie/CSRF, remember-me и отзыв при выходе.
  • WebAuthn: регистрация, вход, список/переименование/удаление устройств, восстановление; импорт существующих зашифрованных PEM-ключей Laragear P-256/RSA/Ed25519. Проверки используют подписанные данные аутентификатора.
  • GitHub/OpenID SSO, PKCE, одноразовый state, проверка OIDC JWT при настройке issuer; reverse-proxy-вход только от доверенного сетевого адреса.
  • Импорт 2FAuth, Aegis, 2FAS, Bitwarden, текстовых URI и Google Authenticator; вложенные иконки; QR; официальные и локальные наборы иконок.
  • Настройки, предпочтения, журналы входа/OTP, уведомления, SMTP/STARTTLS/TLS/sendmail/log; исходный собранный Vue-интерфейс и размещение в подкаталоге.

Подробные доказательства и ограничения: compatibility/CURRENT.md, compatibility/VERIFICATION.md. Старые разделы аудита в compatibility/README.md относятся к исходной версии 0.1.0.

Готовый бинарный файл

В архиве есть bin/twofauth-rs для Linux x86_64 GNU. Он проверен в этой среде; для запуска нужны glibc 2.39 или новее и libgcc_s. Контрольная сумма приведена в bin/BUILD.txt. Если система старее или имеет другую архитектуру, соберите проект из исходников либо через Docker.

Запускайте бинарный файл из каталога rust-server; соседний каталог public определяется автоматически. Для новой установки сначала задайте и сохраните APP_KEY, затем используйте команды ниже, заменив ./target/release/twofauth-rs на ./bin/twofauth-rs. Для имеющейся установки ключи должны остаться прежними.

Сборка и отдельная тестовая установка

Нужны современный stable Rust, C-компилятор, make и Perl: OpenSSL собирается из исходников для WebAuthn. Сборка Docker в этой среде не запускалась.

cargo build --locked --release
mkdir -p data
./target/release/twofauth-rs init
RUST_COOKIE_SECURE=false ./target/release/twofauth-rs serve

Откройте http://127.0.0.1:8080. На пустой БД доступна регистрация; первый пользователь становится администратором. Отключать Secure-cookie следует только для локального HTTP. Для HTTPS оставьте значение по умолчанию.

Можно создать отдельного тестового пользователя через файл пароля:

./target/release/twofauth-rs create-user --name Test --email test@example.invalid --password-file /path/password.txt

init отказывается создавать схему поверх существующих пользователей. create-user создаёт обычного пользователя. Файл пароля должен быть доступен только владельцу; для этой CLI-команды требуется 12–72 байта.

Проверка копии существующей SQLite

Сначала сделайте согласованную копию БД и каталога storage средствами SQLite/вашего резервного копирования. Не копируйте только основной файл SQLite при незавершённом WAL.

Настройте окружение на копию:

export DB_CONNECTION=sqlite
export DB_DATABASE=/absolute/path/to/copied/database.sqlite
export APP_URL=https://test.example.invalid
export STORAGE_PATH=/absolute/path/to/copied/storage
export PASSPORT_KEY_PATH=/absolute/path/to/copied/storage
# APP_KEY и APP_PREVIOUS_KEYS должны сохранять исходные значения.
./target/release/twofauth-rs prepare-sqlite
./target/release/twofauth-rs serve

prepare-sqlite проверяет используемые поля таблиц и добавляет только служебные таблицы Rust. Он не выполняет Laravel-миграции и не меняет историю миграций. Если эти служебные таблицы отсутствуют при запуске, serve также проверит схему и создаст их. Исходная БД должна уже быть обновлена до целевого PHP-коммита. Поддержка PostgreSQL/MySQL/SQL Server в этой реализации ещё отсутствует.

Сохраняйте исходные ключи Passport oauth-private.key/oauth-public.key, APP_KEY, предыдущие ключи и содержимое хранилища. Не генерируйте новые ключи вместо существующих. Для encrypted WebAuthn-ключей APP_KEY нужен даже при выключенном шифровании OTP.

Конфигурация

DATABASE_URL=sqlite:///absolute/file.sqlite имеет приоритет над DB_DATABASE. По умолчанию используется sqlite://data/2fauth.sqlite. Адрес прослушивания: LISTEN_ADDR, по умолчанию 127.0.0.1:8080.

Применяются исходные APP_URL, APP_NAME, APP_KEY, APP_PREVIOUS_KEYS, настройки SMTP MAIL_*, параметры GITHUB_*, OPENID_*, WEBAUTHN_*, AUTH_GUARD/AUTHENTICATION_GUARD, AUTH_PROXY_HEADER_FOR_*, TRUSTED_PROXIES, предпочтения USERPREF_DEFAULT__*/USERPREF_LOCKED__*.

Дополнительно:

Параметр Назначение
STORAGE_PATH Каталог Laravel storage; по умолчанию storage
PASSPORT_KEY_PATH Каталог ключей Passport; по умолчанию storage
RUST_PUBLIC_DIR Каталог собранного интерфейса; по умолчанию public рядом с исходниками
RUST_COOKIE_SECURE false только для локального HTTP; по умолчанию Secure
APP_SUBDIRECTORY Например /tools/2fa; APP_URL должен содержать тот же путь
SESSION_DRIVER, SESSION_TABLE, SESSION_COOKIE, SESSION_ENCRYPT Чтение исходных Laravel-сессий: file или database; сохраняйте исходные параметры и STORAGE_PATH
PASSPORT_JSON_API_ROUTES true включает исправленные маршруты управления OAuth-клиентами и токенами; по умолчанию выключено, как в закреплённом PHP-эталоне
RUST_OAUTH_CONSENT_ENABLED true включает исправленный экран согласия OAuth; это явное расширение относительно дефектного маршрута эталона
OPENID_ISSUER Включает discovery и проверку подписанного ID token; без него сохранён upstream-flow с явными URL
OPENID_DISCOVERY_URL, OPENID_JWKS_URL Необязательные переопределения OIDC endpoints

В Docker каталог /data должен быть доступен UID 10001. В образе STORAGE_PATH и PASSPORT_KEY_PATH указывают на /data/storage. Команды и проверки для разработчиков приведены в английском README.

Что ещё препятствует полной замене

Другие СУБД; остальные Laravel session-хранилища (Redis, cookie и другие); все варианты конфигурации и переводы ошибок; полное сравнение всех маршрутов и middleware; браузерная проверка всех экранов и реальных SSO/WebAuthn-провайдеров. Некоторые диагностические ответы сознательно описывают Rust, а не PHP. QR-код может иметь другое SVG-представление при том же URI. Отдельные ограничения удалённых иконок и почтовых драйверов описаны в compatibility/CURRENT.md.

Прохождение ограниченного набора тестов не означает полной совместимости. Боевой PHP-сервер пока не следует выключать на основании этого архива.

Особенности закреплённого OAuth-эталона

В исходном PHP-файле AppServiceProvider флаг регистрации JSON-маршрутов Passport устанавливается после загрузки пакета. Поэтому /oauth/clients и /oauth/tokens по умолчанию возвращают SPA для GET и 405 для изменений. Стандартный GET /oauth/authorize также неработоспособен: отсутствует реализация AuthorizationViewResponse. По умолчанию сохранено наблюдаемое поведение. Два явных параметра выше включают рабочее управление и согласие для authorization code; экран подтверждения Device Flow в этой версии сохраняет исходную ошибку привязки представления. Эти расширения не считаются точным воспроизведением дефектов эталона.