Раздел: Security & Network
Идентификатор:passwords· Экран:ui/vault/(7 файлов)
Снимок: 2026-10-11
1. Зачем и что это
Экран — единственное место, где эти данные существуют: в чатах агента, в логах и в мостах паролей нет. Отдельный аккаунт (webai) и записи SSH-серверов хранятся по-своему — см. инструменты «Аккаунты WebAI» и «Удалённые агенты».
2. Как попасть
Хаб инструментов → секция Security & Network → карточка «Хранилище паролей» (hub_passwords_title, подпись «Зашифрованные логины, пароли и генератор», тайл — «Пароли»).
| Откуда ещё | Путь |
|---|---|
| Мост | app_navigate с screen: "passwords" |
Маршрут: Screen.kt:126 ("passwords" -> Screen.PasswordVault) → MainRouter.kt:452 (PasswordVaultScreen). При выходе с экрана ViewModel блокируется (vm.lock() при onBack).
3. Экран: элементы и действия
| Элемент | Что делает | Где в коде |
|---|---|---|
| Фаза SETUP | Создание хранилища мастер-паролем | createVault |
| Фаза LOCKED | Ввод пароля + биометрия | unlock, unlockWithBiometric |
| Фаза UNLOCKED | Список записей, поиск, формы | — |
| Поле поиска | «Search vault» | PasswordVaultScreen:438 |
| Карточка записи | Название, логин, копирование полей | copySensitiveToClipboard |
| Кнопка «Export encrypted backup» | Выгрузка зашифрованного бэкапа | exportBackup |
| Кнопка «Import encrypted backup» | Загрузка бэкапа | importBackup |
| Кнопка «Change master password» | Смена мастер-пароля | changeMasterPassword |
| Переключатель биометрии | Включить/выключить вход по биометрии | enableBiometric, disableBiometric |
| Кнопка «Lock now» | Немедленная блокировка | lock |
| Генератор паролей | Настройки длины и наборов символов | PasswordVaultGenerator |
SecureVaultWindow | Запрет скриншотов окна | PasswordVaultSecurity |
4. Возможности подробно
Три фазы
VaultPhase = SETUP / LOCKED / UNLOCKED. Начальная фаза выбирается по repository.hasVault: если хранилища ещё нет — сразу SETUP, иначе LOCKED.
Криптография
Схема — конверт с обёрнутым DEK (VaultEnvelope, VaultCrypto):
| Параметр | Значение |
|---|---|
| KDF | PBKDF2-HMAC-SHA256 |
| Итераций | 600 000 (VAULT_KDF_ITERATIONS) |
| Шифр | AES/GCM/NoPadding |
| Размер ключа | 256 бит (32 байта) |
| Nonce | 12 байт, генерируется SecureRandom |
| Тег GCM | 128 бит |
| AAD | "y83-vault-envelope-v1" |
Мастер-пароль даёт KEK, которым обёрнут DEK; DEK шифрует данные. В конверте хранятся salt, wrappedDek и опционально biometricWrappedDek — отдельная обёртка DEK биометрией, чтобы вход по отпечатку не требовал мастер-пароль.
При выводе ключа массив символов и PBEKeySpec очищаются (clearPassword, chars.fill('\u0000')).
Автоблокировка
Через AUTO_LOCK_MS = 5 60 1000 (5 минут) бездействия хранилище блокируется само (scheduleAutoLock). Любая активность (touch) перезапускает таймер. При уходе с экрана и в onCleared() ViewModel тоже блокирует и закрывает репозиторий.
Защита от утечек на экране
SecureVaultWindowставитFLAG_SECUREна окно, пока открыт хранилище, и снимает флаг при выходе (сохраняя прежнее состояние окна) — скриншоты и запись экрана запрещены.copySensitiveToClipboardпомечает буфер как чувствительный (EXTRA_IS_SENSITIVEна Android 13+) и очищает его через 30 секунд (SENSITIVE_CLIPBOARD_CLEAR_MS), если за это время его не переписали.
Генератор паролей
PasswordGeneratorOptions: длина (12…64, дефолт 20) и наборы символов — заглавные, строчные, цифры, спецсимволы. Криптостойкость — SecureRandom. Требование длины 12…64 проверяется require, так что слишком короткий пароль генератор не выдаст.
Бэкапы
exportBackup(uri, password) и importBackup(uri, password) работают через VaultBackup — бэкап зашифрован собственным паролем и восстанавливается в любое хранилище. Импорт возвращает сводку VaultImportSummary(added, updated, kept).
5. Данные: БД, файлы, настройки
| Что | Где лежит | Как меняется | Кто читает |
|---|---|---|---|
| Записи | Room vault.db, таблица vault_items | saveItem, deleteItem | Только разблокированный репозиторий |
| Конверт ключей | filesDir/vault/envelope.json | VaultEnvelopeStore | VaultRepository |
| Запись | VaultItemEntity(id, title, username, password, url, notes, createdAt, updatedAt) | — | — |
Записи сортируются по title без учёта регистра, при равенстве — по дате обновления (ORDER BY title COLLATE NOCASE ASC, updatedAt DESC).
Серверной части нет: хранилище полностью локальное, backend о нём не знает.
6. Backend: REST/роуты
Неприменимо: хранилище работает только на устройстве, ни один REST-роут не задействован.
7. Мост и MCP
| Что | Как | Примечание |
|---|---|---|
| Открыть экран | app_navigate с screen: "passwords" | BridgeScreenCatalog |
Пароли намеренно недоступны агенту: ни через мост, ни через MCP. Это осознанное ограничение — иначе секреты попали бы в контекст модели.
8. Настройки, конфиг, квоты и лимиты
| Параметр | Значение | Где задаётся |
|---|---|---|
| Итераций KDF | 600 000 | VAULT_KDF_ITERATIONS |
| Nonce | 12 байт | NONCE_BYTES |
| Ключ | 32 байта (256 бит) | KEY_BYTES |
| AAD | y83-vault-envelope-v1 | envelopeAad |
| Автоблокировка | 5 минут | AUTO_LOCK_MS |
| Очистка буфера | 30 секунд | SENSITIVE_CLIPBOARD_CLEAR_MS |
| Длина пароля | 12…64, дефолт 20 | PasswordGeneratorOptions |
9. Ловушки и ограничения
- Восстановить мастер-пароль нельзя. Шифрование AES-GCM без сервера и без escape-механизма: потерянный пароль = потерянные данные. Экспорт бэкапа — единственный путь переноса.
- Биометрия оборачивает DEK отдельно. Если включить биометрию, отпечаток открывает тот же DEK; отключение биометрии убирает
biometricWrappedDek. - Автоблокировка — 5 минут. Долгий ввод может прерваться; это защита, а не баг.
- Буфер очищается через 30 секунд. Если нужно вставить пароль в другое приложение, делайте это сразу — иначе буфер будет пуст.
- FLAG_SECURE блокирует скриншоты и запись экрана на время открытого хранилища. Это может мешать, если вы хотите показать экран кому-то — так и задумано.
- Хранилище локальное. Синхронизации между устройствами нет, только ручной экспорт/импорт бэкапа.
- Журнал изменений отсутствует — удалённая запись восстанавливается только из бэкапа.
- Пустые наборы символов в генераторе могут дать пустой или слишком слабый пароль: минимум один набор должен быть включён (проверка
requireкасается только длины).
10. Источники правды
app/src/main/java/com/y83/ws/ui/vault/PasswordVaultScreen.kt— экран, фазы, кнопки.app/src/main/java/com/y83/ws/ui/vault/PasswordVaultViewModel.kt— состояние, автоблокировка, действия.app/src/main/java/com/y83/ws/ui/vault/PasswordVaultSecurity.kt—FLAG_SECURE, чувствительный буфер.app/src/main/java/com/y83/ws/ui/vault/PasswordVaultGenerator.kt— UI генератора.app/src/main/java/com/y83/ws/ui/vault/PasswordVaultFormScreen.kt,PasswordVaultDialogs.kt— формы и диалоги.app/src/main/java/com/y83/ws/data/vault/VaultCrypto.kt— KDF, AES-GCM, конверт.app/src/main/java/com/y83/ws/data/vault/VaultRepository.kt,VaultEnvelopeStore.kt,VaultDatabase.kt— хранение.app/src/main/java/com/y83/ws/data/vault/VaultBackup.kt,VaultBiometric.kt,PasswordGenerator.kt— бэкап, биометрия, генератор.