Безпека

Як побудовано сховище, і що можна знайти в разі пролому.

Останнє оновлення 21 вересня 2026 р. · AssuredAuth, CircleRoll LLC

Це публічний опис того, як AssuredAuth захищає двофакторні секрети, паролі та картки, які ви в ньому зберігаєте. Він написаний таким чином, щоб читач, який піклується про безпеку, міг перевірити кожне твердження щодо програми та опублікованих векторів тестування (доступних будь-якому рецензенту за запитом на hello@assuredauth.com). Він говорить правду і нічого більше: тут немає нічого, що претендує на те, щоб бути неуразливим, і нічого не обіцяно у відсотках.

Коротко кажучи: сховище знаходиться в одному місці – у вашому телефоні. Кожне значення в ньому зашифровано ключем, який зберігає апаратне забезпечення безпеки телефону та не може експортувати. Ми не використовуємо сервер сховища, не зберігаємо жодної копії та не зберігаємо жодного ключа. Файл резервної копії залишає телефон лише після того, як його зашифровано за допомогою парольної фрази, яка ніде не зберігається.

Повідомити про проблему: hello@assuredauth.com. Див. розділ «Повідомлення про слабкість» в кінці.

1. Що шифрується, за допомогою чого

ДаніНа телефоніКлюч
Двофакторні секрети (TOTP/HOTP/насіння Steam) На телефоніЗв'язка ключів (iOS) / магазин, що підтримується сховищем ключів Android КлючАпаратно-прив'язаний ключ платформи; рядок бази даних містить лише посилання (secretRef), а не початкове значення (seed).
Паролі (значення пароля, примітки) На телефоніЗапечатаний рядок: AES-256-GCM, випадковий 96-бітний nonce на значення КлючВипадковий 256-бітний ключ даних, сам по собі обгорнутий апаратним ключем у §2
Картки (номер, термін дії, ім'я на картці, CVC) На телефоніТа сама печатка, що й для паролів; CVC необов'язковий і зберігається лише після введення. КлючТой самий ключ даних
Метадані (назви служб, імена користувачів, значки, порядок сортування) На телефоніБаза даних програми (SwiftData / Room) КлючЗахищено шифруванням файлів операційної системи; вважається несекретним
Файл резервної копії (.authbackup) На телефоніКуди б ви його не поклали: Файли, iCloud Drive, додаток Google Диск, папка даних, спільний доступ КлючКлюч, отриманий з вашої парольної фрази (§3). Apple та Google отримують запечатаний файл і нічого більше.
Застосунок для Watch / Wear На телефоніВласний брелок годинника / EncryptedSharedPreferences КлючКлючі платформи годинника; передаються через канал сполученого пристрою платформи
Трафік розширення для комп’ютера (одноразові коди за запитом) На телефоніНе зберігається; передається у вигляді конвертів із наскрізним шифруванням КлючПара ключів X25519 на пару, закритий ключ у зв'язці ключів / сховищі ключів; реле бачить лише зашифрований текст.

Діагностика не має методу, який би приймав секретний код. Жодна аналітична подія не містить поля сховища. Жодне значення зі сховища ніколи не записується до журналу в жодній збірці.

2. Де знаходяться ключі на кожній платформі

iOS. Ключ даних обгорнутий ключем, згенерованим всередині Захищеного Анклаву (kSecAttrTokenIDSecureEnclave) з контролем доступу .privateKeyUsage + .userPresence, доступність …ThisDeviceOnly, у спільній групі доступу Keychain програми, щоб розширення AutoFill могло використовувати той самий ключ. Закритий ключ не може бути зчитаний з Анклаву програмою, резервною копією або налагоджувачем; Анклав погоджується використовувати його лише після присутності користувача (Face ID, Touch ID або пароль пристрою). ThisDeviceOnly означає, що резервна копія телефону в iCloud або iTunes не містить ключа; відновлений телефон починається з порожнього сховища та запитує ваш файл резервної копії та пароль. Телефон без пароля не може захистити ключ .userPresence (Анклав відмовляється його створювати), і симулятор за своєю природою обирає той самий шлях (його запит на присутність – це сповіщення, на яке жоден тест не може відповісти): там ключ даних – це звичайний елемент брелока, доступний лише для пристрою, – все ще поза резервною копією, все ще нечитабельний, поки телефон заблоковано, але без другого запиту – і екран безпеки показує саме це та пропонує встановити пароль.

Android. Ключ даних обгорнутий ключем AndroidKeyStore AES-256, згенерованим у StrongBox, якщо пристрій має такий ключ (інакше TEE), з setUserAuthenticationRequired(true) та 30-секундним терміном дії автентифікації після біометричних або облікових даних пристрою, setUnlockedDeviceRequired(true) та setInvalidatedByBiometricEnrollment(true), що залишаються увімкненими. Останній прапорець є чесним, а не навантажувальним: Android застосовує його лише до ключів, які вимагають біометричних даних при кожному використанні, тому на цьому 30-секундному ключі з дозволеними обліковими даними пристрою це нічого не змінює — те, що незнайомця не втручає палець, так це те, що для реєстрації потрібен PIN-код, а зняття блокування екрана робить ключ недійсним назавжди. Ключі сховища ключів не можна експортувати та вони виключаються з хмарної резервної копії Android. Домен, який додаток називає у власних представленнях (webDomain), вважається прийнятим лише з відомого браузера; з будь-якого іншого пакета він також повинен бути тим, який система перевірила для цього пакета (Digital Asset Links), оскільки будь-який додаток може претендувати на будь-який домен.

Що це означає для викраденого файлу бази даних. Файл SQLite та запечатані рядки є зашифрованим текстом. Ключ, який їх відкриває, знаходиться в апаратному забезпеченні безпеки на телефоні, з якого було отримано файл, і його не можна скопіювати разом із файлом. Немає чого вгадувати офлайн: ключ даних випадковий, а не походить від чогось, що вибрала людина.

3. Файл резервної копії

Резервні копії – це єдине, що залишає телефон, тому вони є єдиним місцем, де в принципі можлива офлайн-атака. Така конструкція робить таку атаку дорогою та дає їй якомога менше можливостей для роботи:

Файл має формат JSON і його можна читати в будь-якому текстовому редакторі; непрозорим є лише зашифрований текст. Той, хто знайде файл через п'ять років, коли додаток буде видалено, зможе побачити, як саме його було запечатано, і відкрити його за допомогою OpenSSL або будь-якої бібліотеки Argon2.

Формат v1 (постачається у версії 1.0, залишається читабельним)

{
  "format": "authbackup",
  "version": 1,
  "kdf": "PBKDF2-HMAC-SHA256",
  "rounds": 600000,
  "salt": "<base64, 16 bytes>",
  "cipher": "AES-256-GCM",
  "nonce": "<base64, 12 bytes>",
  "ciphertext": "<base64>",
  "tag": "<base64, 16 bytes>"
}
КрокБайти
keyPBKDF2-HMAC-SHA256(passphrase as UTF-8, salt, 600000 rounds, 32 bytes)
aadUTF-8("authbackup:1:600000:") ‖ salt (необроблені байти солі, не base64)
ciphertext, tagAES-256-GCM(key, nonce, plaintext, aad); тег 16 байт, зберігається окремо
plaintextUTF-8 JSON, відсортовані ключі: {"accounts":[…],"exportedAt":"…Z","passwords":[…],"version":1}

Примітка щодо сумісності: Android 1.0 написав варіант v1 — kdf у нижньому регістрі, без ключа тегу (16-байтовий тег, доданий до зашифрованого тексту), без додаткових даних. Обидві платформи продовжують зчитувати ці файли (коли тег відсутній: розділити останні 16 байтів, відкрити з порожнім AAD; порівняти kdf без урахування регістру) і обидві тепер записують лише вищевказаний макет.

Формат v2 (поточний; стандартний для нових резервних копій)

{
  "format": "authbackup",
  "version": 2,
  "kdf": "Argon2id",
  "memoryKiB": 65536,
  "passes": 3,
  "lanes": 1,
  "salt": "<base64, 16 bytes>",
  "cipher": "AES-256-GCM",
  "nonce": "<base64, 12 bytes>",
  "ciphertext": "<base64>",
  "tag": "<base64, 16 bytes>"
}
КрокБайти
keyArgon2id(version 0x13, passphrase as UTF-8, salt, m = 65536 KiB, t = 3, p = 1, tagLength 32, no secret, no associated data)
aadUTF-8("authbackup:2:argon2id:65536:3:1:") ‖ salt
ciphertext, tagAES-256-GCM(key, nonce, plaintext, aad); тег 16 байт, зберігається окремо
plaintextUTF-8 JSON, відсортовані ключі: {"accounts":[…],"cards":[…],"exportedAt":"…Z","passwords":[…],"version":2}

Argon2id — це еталонна реалізація на C (phc-winner-argon2, CC0), що постачається на обох платформах. 64 МіБ та 3 проходи займають близько секунди на сучасному телефоні, і кожна здогадка коштує стільки ж пам'яті та часу на будь-якому обладнанні — властивість, якої бракує PBKDF2 проти графічних процесорів, і причина існування версії 2. Зчитувач ігнорує ключі, які йому невідомі, тому зчитувач версії 1 з корпусом версії 2 просто ніколи не бачить картки.

Доказ

Три файли тестових векторів (резервна копія v1, резервна копія v2 та Argon2id) генеруються третьою реалізацією, незалежно від обох програм (OpenSSL Node для PBKDF2 та AES-GCM, Argon2id WebAssembly, перевірений під час генерації на відповідність опублікованим відповідям еталонної реалізації). Кожен містить пароль, сіль, nonce, відкритий текст, похідний ключ, AAD, очікуваний шифротекст та тег, а також повний файл. Модульні тести на iOS та Android зчитують одні й ті ж файли та стверджують одні й ті ж байти — тому резервна копія, запечатана на одній платформі, доведена, а не передбачається, що відкривається на іншій, і збіг усіх трьох не є двома копіями однієї й тієї ж помилки. Супутній інструмент відкриває файл, який телефон фактично записав з тією ж третьою реалізацією, і перевіряє заголовок на відповідність вищезазначеним правилам (точно ключі формату, тому не може бути підказки чи назви; 16-байтова саль, 12-байтовий nonce, 16-байтовий тег зберігаються окремо; версія 2 рівно 64 MiB / 3 / 1; неправильна парольна фраза відхилена); автоматизований запуск iOS записує його на симуляторі та відкриває таким чином, а також шукає в контейнері програм симулятора, контейнері групи програм та базі даних зв'язки ключів для кожного встановленого пароля та номера картки у форматі UTF-8 та UTF-16 (0 збігів).

4. Модель загрози

СитуаціяЩо вони маютьЩо вони отримують
Втрачений або вкрадений телефон, заблокований Що вони маютьПристрій, файл бази даних, запечатані рядки Що вони отримуютьЗашифрований текст. Ключ обгортання знаходиться в Secure Enclave / StrongBox і розблоковується лише після блокування пристрою плюс новий біометричний код або пароль. Дистанційне стирання телефону (Find My / Find My Device) знищує матеріал ключа разом з ним.
Вкрадений файл резервної копії Що вони маютьФайл .authbackup з хмарного облікового запису, електронної пошти, ноутбука Що вони отримуютьТіло AES-256-GCM під ключем, отриманим з парольної фрази довжиною щонайменше 12 символів, з солтю для кожного файлу та Argon2id з розміром 64 МіБ × 3 проходи (версія 2) або PBKDF2 з частотою 600 000 раундів (версія 1). Без підказки, без імені користувача, без списку облікових записів у відкритому вигляді. Кожна здогадка коштує повного виведення; немає скороченого шляху. Надійна парольна фраза — це весь захист, і додаток вказує це на аркуші.
Викрадений пристрій з розблокованим екраном Що вони маютьТелефон у вашій руці, розблокований Що вони отримуютьСписок кодів. Сховище (паролі, картки) знаходиться за блокуванням програми та повторно блокується за таймером автоматичного блокування (негайно / 1 хв / 5 хв); розшифроване значення існує в пам’яті лише тоді, коли воно відображається на екрані. Автозаповнення та експорт у звичайному тексті запитують нові біометричні дані, навіть коли програма відкрита. Увімкніть блокування програми за допомогою опції «Негайно», якщо вас це турбує.
Шкідливий додаток на тому ж телефоні Що вони маютьПісочниця іншої програми, буфер обміну, спеціальні можливості або хитрощі накладання Що вони отримуютьВін не може читати наші файли (пісочниця платформи) або використовувати наш ключ (ключ пов’язаний з нашою ідентифікатором підпису та присутністю користувача). Копії видаляються з буфера обміну через 30 секунд; на Android копія позначається як конфіденційна та виключається з історії буфера обміну. ​​Для екранів сховища встановлено FLAG_SECURE на Android (без скріншотів, без запису екрана, порожнє вікно перемикача); iOS очищує мініатюру перемикача. Автозаповнення на Android здійснюється лише для програм, які система перевірила на відповідність збереженому домену (посилання на цифрові активи), тому схожій програмі не пропонується ваш пароль.
Фішингова сторінка Що вони маютьСайт, схожий на той, який ви зберегли Що вони отримуютьНічого не заповнюється. Зіставлення здійснюється за зареєстрованим доменом (список публічних суфіксів, об'єднаний та оновлюється разом із додатком): login.example.com та example.com збігаються, example.com.evil.net та examp1e.com – ні. Вбудований браузер збігається так само та заповнює лише фрейм, який запитував, повторно перевіряючи його походження на момент заповнення; хост без власного зареєстрованого домену — IP-адреса, порожнє ім'я в локальній мережі — збігається точно і нічого гіршого. Автозаповнення iOS додає перевірку пов'язаних доменів від Apple. Пароль, який потрібно вставити вручну у схожий файл, все ще є ризиком; додаток не може його видалити, лише уникає допомоги.
Наші власні сервери Що вони мають— Що вони отримуютьНемає сервера сховища. AssuredAuth не має облікових записів, входу та копії вашого сховища, тому на нашому боці немає нічого вашого, що можна було б вкрасти та зламати. На стороні сервера працюють дві речі, жодна з яких не стосується сховища: поштова скринька ретрансляції для розширення для робочого столу, яка зберігає конверти з наскрізним шифруванням (одноразові коди, що видаляються після зчитування; ретрансляція ніколи не має ключа), та вихідні сервери додаткового приватного з’єднання, які передають трафік і не зберігають журнали доступу.
Повістка до суду або урядовий запит Що вони маютьЮридичний процес, адресований нам Що вони отримуютьНічого передавати: у нас немає ні сховища, ні ключа, ні пароля, ні резервної копії. Нас можуть змусити це сказати; нас не можуть змусити створити те, чого не існує.

5. Буфер обміну, скріншоти та пам'ять

6. Автозаповнення: що заповнюється, а що ні

ДеПароліКартки
iOS: Safari та програми (розширення AutoFill) ПароліТак, після нового Face ID / Touch ID / пароля в розширенні (LAContext), і лише для реєстрованого домену, для якого було збережено запис, з перевіркою пов’язаних доменів Apple на наявність програм КарткиНі. Автозаповнення картки в Safari — це лише функція Apple; на екрані картки написано «Заповнюється в браузері AssuredAuth та з копіюванням» і більше нічого не обіцяє.
Android: програми та Chrome (AutofillService) ПароліТак, автентифікація для кожного набору даних: система показує BiometricPrompt перед заповненням; пакет програми збігається лише тоді, коли Digital Asset Links пов’язує його зі збереженим доменом. КарткиТак, підказки creditCardNumber, creditCardExpiration* та creditCardSecurityCode, той самий біометричний шлюз
Браузер AssuredAuth (обидві платформи) ПароліТак, за допомогою зареєстрованого домену — хоста, який не має власних точних збігів — у фрейм, що запитував, біометричний перед заповненням КарткиТак, шляхом виявлення поля, біометричні дані перед заповненням
Кнопки копіювання ПароліЗа блокуванням програми, 30-секундний буфер обміну КарткиНомер, термін дії, CVC (ті ж правила)

Ніщо не заповнюється на схожому хості. Ніщо не заповнюється без біометричних даних.

7. Чого ніколи не буває

Немає сервера сховища. Немає аналітики, яка містить поле сховища. Немає експорту звичайного тексту без аркуша підтвердження та нових біометричних даних. Немає завантаженого на екран сховища стороннього SDK. Немає знімка екрана сховища. Немає підказки до парольної фрази. Немає реєстрації значень у жодній збірці.

8. Від чого ми не можемо захиститися

Парольна фраза, достатньо слабка для вгадування. Телефон, операційна система якого скомпрометована в кореневому режимі (пристрій з джейлбрейком або рутуванням може брехати додатку про все вищезазначене). Людина, за якою спостерігають під час введення тексту. Шкідливе програмне забезпечення на робочому столі, куди ви вставляєте код. Ми кажемо це, щоб список вище був прочитаний таким, яким він є: речі, які дизайн може видалити, видалено.

9. Статус перевірки

Цей дизайн пройшов модульне тестування на основі опублікованих відомих відповідей на обох платформах та на основі власних кросплатформних векторів. Зовнішня перевірка знаходиться у списку власника, перш ніж сховище буде опубліковано в списку магазину; доки це не станеться, про це буде зазначено в цьому документі.

10. Де все відбувається

Ніщо зі сховища не залишає телефон, але кілька речей навколо нього працюють на комп’ютерах інших людей. Ось список і те, що містить кожен із них; самі потоки даних описані в політиці конфіденційності за адресою https://assuredauth.com/privacy.

Кожен містить те, що зазначено в його рядку, і нічого зі сховища. Список змінюється разом із продуктом, і цей розділ змінюється разом із ним.

Повідомлення про слабкість

Якщо ви вважаєте, що знайшли слабке місце в будь-чому з описаного тут, напишіть на адресу hello@assuredauth.com з темою «Безпека». Будь ласка, вкажіть платформу, версію програми та кроки; достатньо підтвердження, яке використовує ваші власні дані, і ми просимо вас не тестувати на даних інших людей. Ми не пропонуємо ключ PGP; якщо звіт не повинен надсилатися звичайною електронною поштою, повідомте про це в першому повідомленні, і ми організуємо інший спосіб.

Що ми обіцяємо натомість: ми підтверджуємо інформацію протягом трьох робочих днів, інформуємо вас про роботу над цим, виправляємо правдиву інформацію перед публікацією та вказуємо вас тут, якщо ви хочете, щоб вас вказали. Ми не будемо вживати юридичних заходів щодо дослідження, проведеного добросовісно, ​​в межах, зазначених нижче.

У сфері застосування: додатки для iOS та Android, додатки для годинника, розширення для комп’ютера, asuredauth.com та його API. Поза сферою застосування: самі App Store та Google Play, перелічені вище постачальники, соціальна інженерія будь-кого та відмова в обслуговуванні.

Наразі винагороди немає. На скаргу відповідають виправленням та подякою, а не грошима.