Сигурност
Как е построен трезорът и какво би разкрил евентуално проникване в него.
Последна актуализация 21 септември 2026 г. · AssuredAuth, от CircleRoll LLC
Това е публичното описание на това как AssuredAuth защитава двуфакторните тайни, пароли и карти, които съхранявате в него. Написано е така, че читател, загрижен за сигурността, да може да провери всяко твърдение спрямо приложението и спрямо публикуваните тестови вектори (достъпни за всеки рецензент при поискване на hello@assuredauth.com). То казва истината и нищо повече: нищо тук не твърди, че е извън контрол, и нищо не е обещано в проценти.
Накратко: трезорът съществува на едно място – вашият телефон. Всяка стойност в него е криптирана с ключ, който се съхранява от защитния хардуер на телефона и не може да се експортира. Ние не използваме сървър за трезори, не съхраняваме копие и не съхраняваме ключ. Архивният файл напуска телефона само след като е криптиран с парола, която никога не се съхранява никъде.
Съобщете за проблем: hello@assuredauth.com. Вижте „Докладване на слабост“ в края.
1. Какво е криптирано, с какво
| Данни | На телефона | Ключ |
|---|---|---|
| Двуфакторни тайни (TOTP/HOTP/Steam seeds) | На телефонаМагазин, поддържан от Keychain (iOS) / Android Keystore | КлючХардуерно обвързаният ключ на платформата; редът в базата данни съдържа само препратка (secretRef), никога seed-а. |
| Пароли (стойността на паролата, бележки) | На телефонаЗапечатан ред: AES-256-GCM, произволен 96-битов nonce за всяка стойност | КлючСлучаен 256-битов ключ за данни, сам по себе си обвит в хардуерния ключ в §2 |
| Карти (номер, срок на валидност, име на картата, CVC) | На телефонаСъщият печат като за паролите; CVC кодът е по избор и се съхранява само ако го въведете | КлючСъщият ключ за данни |
| Метаданни (имена на услуги, потребителски имена, икони, ред на сортиране) | На телефонаБазата данни на приложението (SwiftData / Room) | КлючЗащитено от криптирането на файловете на операционната система; третира се като несекретно |
| Резервен файл (.authbackup) | На телефонаКъдето и да го поставите: Файлове, iCloud Drive, приложение Google Drive, папка с данни, лист за споделяне | КлючКлюч, извлечен от вашата парола (§3). Apple и Google получават запечатания файл и нищо друго |
| Приложение за Watch / Wear | На телефонаСобственият ключодържател на часовника / EncryptedSharedPreferences | КлючКлючовете на платформата за часовници; прехвърлени през канала на сдвоеното устройство на платформата |
| Трафик от разширение за настолни компютри (еднократни кодове при поискване) | На телефонаНе се съхранява; препредава се като пликове с криптиране от край до край | КлючДвойка ключове X25519 за сдвояване, частен ключ в ключодържателя / хранилището на ключове; релето вижда само шифрован текст |
Диагностиката няма метод, който да приема тайна. Никое аналитично събитие не носи поле за хранилище. Никаква стойност от хранилището никога не се записва в лог, при нито една компилация.
2. Къде се намират ключовете, на всяка платформа
iOS. Ключът за данни е обвит от ключ, генериран в Secure Enclave (kSecAttrTokenIDSecureEnclave) с контрол на достъпа .privateKeyUsage + .userPresence, достъпност ...ThisDeviceOnly, в споделената група за достъп Keychain на приложението, така че разширението AutoFill може да използва същия ключ. Частният ключ не може да бъде прочетен от Enclave от приложението, от резервно копие или от дебъгер; Enclave се съгласява да го използва само след като потребителят присъства (Face ID, Touch ID или паролата на устройството). ThisDeviceOnly означава, че резервно копие на телефона в iCloud или iTunes не съдържа ключа; възстановеният телефон започва с празен трезор и иска вашия файл с резервно копие и парола. Телефон без парола не може да защити ключ .userPresence (Enclave отказва да създаде такъв) и симулаторът поема по същия път по дизайн (подканата му за присъствие е предупреждение, на което никой тест не може да отговори): там ключът за данни е обикновен елемент от веригата за ключове, достъпен само за устройството — все още извън всяко резервно копие, все още нечетлив, докато телефонът е заключен, но без втора подкана — и екранът за сигурност казва точно това и предлага задаване на парола.
Android. Ключът за данни е обвит от AES-256 ключ на AndroidKeyStore, генериран в StrongBox, когато устройството има такъв (в противен случай TEE), със setUserAuthenticationRequired(true) и 30-секундна валидност за удостоверяване след биометрични или идентификационни данни на устройството, setUnlockedDeviceRequired(true) и setInvalidatedByBiometricEnrollment(true) оставени включени. Последният флаг е по-скоро честен, отколкото носещ натоварване: Android го прилага само към ключове, които изискват биометрични данни при всяка употреба, така че при този 30-секунден ключ с разрешени идентификационни данни на устройството, това не променя нищо - това, което държи пръста на непознат навън, е, че за регистрацията е необходим ПИН кодът и че премахването на заключването на екрана прави ключа невалиден завинаги. Ключовете от хранилището за ключове не могат да се експортират и са изключени от облачното архивиране на Android. Домейн, който приложението назовава в собствените си изгледи (webDomain), се приема само от известен браузър; от всеки друг пакет той също трябва да е такъв, който системата е проверила за този пакет (Digital Asset Links), тъй като всяко приложение може да претендира за всеки домейн.
Какво означава това за откраднат файл от база данни. SQLite файлът и запечатаните редове са шифрован текст. Ключът, който ги отваря, се намира в защитния хардуер на телефона, от който е дошъл файлът, и не може да бъде копиран заедно с него. Няма какво да се гадае офлайн: ключът за данни е случаен, не е извлечен от нещо, което човек е избрал.
3. Резервният файл
Резервните копия са единственото нещо, което напуска телефона, така че те са единственото място, където по принцип е възможна офлайн атака. Дизайнът прави тази атака скъпа и ѝ дава възможно най-малко възможности за работа:
- Паролата е поне 12 знака (листът отхвърля по-малко и показва лента за сила).
- Никъде, нито във файла, нито в приложението, не се съхранява подсказка за парола.
- Нова произволна 16-байтова salt стойност и 12-байтов nonce стойност за всеки записан файл.
- Цялото тяло е AES-256-GCM, така че грешна парола или повреден файл се отхвърлят и никога не се декриптират в боклук.
- Заглавката (формат, версия, KDF параметри, salt) е обвързана с GCM тага като допълнителни удостоверени данни, така че файл, чийто работен фактор е бил редактиран надолу, не се отваря.
Файлът е 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>"
}
| Стъпка | Байтове |
|---|---|
key | PBKDF2-HMAC-SHA256(passphrase as UTF-8, salt, 600000 rounds, 32 bytes) |
aad | UTF-8("authbackup:1:600000:") ‖ salt (сурови salt байтове, не base64) |
ciphertext, tag | AES-256-GCM(key, nonce, plaintext, aad); етикет 16 байта, съхраняван отделно |
plaintext | UTF-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>"
}
| Стъпка | Байтове |
|---|---|
key | Argon2id(version 0x13, passphrase as UTF-8, salt, m = 65536 KiB, t = 3, p = 1, tagLength 32, no secret, no associated data) |
aad | UTF-8("authbackup:2:argon2id:65536:3:1:") ‖ salt |
ciphertext, tag | AES-256-GCM(key, nonce, plaintext, aad); етикет 16 байта, съхраняван отделно |
plaintext | UTF-8 JSON, сортирани ключове: {"accounts":[…],"cards":[…],"exportedAt":"…Z","passwords":[…],"version":2} |
Argon2id е референтната C имплементация (phc-winner-argon2, CC0), предлагана и на двете платформи. 64 MiB и 3 преминавания отнемат около секунда на текущ телефон и всяко предположение струва толкова памет и време на всеки хардуер - свойството, което PBKDF2 няма срещу GPU устройства, и причината, поради която v2 съществува. Четецът игнорира ключове, които не знае, така че четец v1 с тяло v2 просто никога не вижда карти.
Доказателство
Три файла с тестови вектори (backup v1, backup v2 и Argon2id) се генерират от трета имплементация, независима от двете приложения (OpenSSL на Node за PBKDF2 и AES-GCM, Argon2id на WebAssembly, проверен по време на генериране спрямо публикуваните отговори на референтната имплементация). Всеки съдържа паролата, salt, nonce, обикновения текст, производния ключ, AAD, очаквания шифрован текст и етикет, както и целия файл. Модулните тестове на iOS и Android четат едни и същи файлове и потвърждават едни и същи байтове - така че резервно копие, запечатано на едната платформа, е доказано, а не се предполага, че се отваря на другата, а съгласието и на трите не е две копия на една и съща грешка. Съпътстващ инструмент отваря файл, който телефон действително е написал със същата трета имплементация, и проверява заглавката спрямо правилата по-горе (точно ключовете на формата, така че не може да има подсказка или име; 16-байтова salt, 12-байтов nonce, 16-байтов таг, съхранявани отделно; версия 2 с точно 64 MiB / 3 / 1; грешната парола е отказана); автоматизираното изпълнение на iOS записва файл в симулатора и го отваря по този начин, след което търси в контейнера за приложения, контейнера за App Group и базата данни за ключове на симулатора за всяка зададена парола и номер на карта като UTF-8 и UTF-16 (0 попадения).
4. Модел на заплахата
| Ситуация | Какво имат | Какво получават |
|---|---|---|
| Изгубен или откраднат телефон, заключен | Какво иматУстройството, файлът на базата данни, запечатаните редове | Какво получаватШифрован текст. Ключът за опаковане е в Secure Enclave / Trezor и се освобождава само след заключване на устройството плюс нов биометричен код или парола. Дистанционното изтриване на телефона (Find My / Find My Device) унищожава ключовия материал заедно с него. |
| Откраднат резервен файл | Какво иматФайлът .authbackup от облачен акаунт, имейл, лаптоп | Какво получаватТяло на AES-256-GCM под ключ, извлечен от парола от поне 12 знака, със сол за всеки файл и Argon2id при 64 MiB × 3 преминавания (v2) или PBKDF2 при 600 000 рунда (v1). Без подсказка, без потребителско име, без списък с акаунти в ясен вид. Всяко предположение струва пълното извличане; няма пряк път. Силната парола е цялата защита тук и приложението го казва на листа. |
| Откраднато устройство с отключен екран | Какво иматТелефон в ръката ви, отключен | Какво получаватСписъкът с кодове. Трезорът (пароли, карти) е зад заключването на приложението и се заключва отново с таймера за автоматично заключване (веднага / 1 мин / 5 мин); декриптирана стойност съществува в паметта само докато екранът ѝ я показва. Автоматичното попълване и експортирането в обикновен текст изискват нови биометрични данни, дори когато приложението е отворено. Включете заключването на приложението с „Веднага“, ако това е случаят, който ви притеснява. |
| Злонамерено приложение на същия телефон | Какво иматПясъчникът на друго приложение, клипбордът, достъпността или триковете за наслагване | Какво получаватНе може да чете нашите файлове (платформена пясъчник) или да използва нашия ключ (ключът е обвързан с нашата самоличност за подписване и с присъствието на потребителя). Копията се изчиства от клипборда след 30 секунди; на Android копието се маркира като чувствително и се изключва от историята на клипборда. Екраните на Vault са с FLAG_SECURE на Android (без снимки на екрана, без запис на екрана, празно в превключвателя); iOS изпразва миниатюрата на превключвателя. Автоматичното попълване на Android се предоставя само за приложения, които системата е проверила спрямо запазения домейн (Digital Asset Links), така че на приложение, което изглежда подобно, не се предлага вашата парола. |
| Фишинг страница | Какво иматСайт, който изглежда като този, който сте запазили | Какво получаватНищо не се попълва. Съвпадението е по регистрируем домейн (списък с публични суфикси, включен и актуализиран с приложението): login.example.com и example.com съвпадат, example.com.evil.net и examp1e.com не съвпадат. Вграденият в приложението браузър съвпада по същия начин и попълва само рамката, която е поискала, след повторна проверка спрямо собствения произход на тази рамка в момента на попълване; хост без собствен регистрируем домейн - IP адрес, име в локалната мрежа - съвпада точно и нищо по-слабо. iOS AutoFill добавя проверката за свързани домейни на Apple. Паролата, която трябва да поставите на ръка в подобен файл, все още е рискована; приложението не може да премахне това, а само да избегне подпомагането. |
| Нашите собствени сървъри | Какво имат— | Какво получаватНяма сървър за трезор. AssuredAuth няма акаунти, няма вход и няма копие на вашия трезор, така че няма нищо ваше от наша страна, което да бъде откраднато и разбито. Две неща работят от страна на сървъра, нито едно от които не докосва трезора: пощенска кутия за реле за разширението за десктоп, която съхранява криптирани от край до край пликове (еднократни кодове, изтривани при четене; релето никога няма ключ), и изходните сървъри на опционалната частна връзка, които пренасят трафик и не съхраняват регистрационни файлове за достъп. |
| Призовка или искане от правителството | Какво иматПравен процес, адресиран до нас | Какво получаватНямаме нищо за предаване: нямаме трезор, нямаме ключ, нямаме парола и нямаме резервно копие. Можем да бъдем принудени да кажем това; не можем да бъдем принудени да предоставим нещо, което не съществува. |
5. Клипборд, екранни снимки и памет
- Копирането поставя стойността в клипборда за 30 секунди, след което я изчиства, ако все още е наша. В Android клипът е маркиран като EXTRA_IS_SENSITIVE, така че системата го скрива от визуализацията и историята на клипборда; в iOS елементът от картона е само локален (не се прехвърля на други устройства).
- Екраните на трезора (Пароли, Парола, Карти, Карта, листове с пароли, експортиране в обикновен текст) задават FLAG_SECURE на Android. iOS няма еквивалентен флаг; приложението изчиства миниатюрата си в превключвателя на приложения, а стойностите са зад превключвател с око по подразбиране.
- Декриптираните стойности се съхраняват в паметта само докато са показани на екрана и се изтриват, когато екранът изчезне или приложението се заключи. Ключът за данни се разопакова за заявка и не се кешира в заключването.
- Съществува експортиране в обикновен текст (така че винаги можете да си тръгнете) и е зад лист за потвърждение и нова биометрична информация, а екранът му също е FLAG_SECURE.
6. Автоматично попълване: какво се попълва и какво не
| Къде | Пароли | Карти |
|---|---|---|
| iOS: Safari и приложения (разширение за автоматично попълване) | ПаролиДа, след нов 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. От какво не можем да се защитим
Паролна фраза, достатъчно слаба за отгатване. Телефон, чиято операционна система е компрометирана в root-а (устройство с джейлбрейк или руут може да лъже приложението за всичко по-горе). Човек, който е наблюдаван, докато пише. Зловреден софтуер на работния плот, в който поставяте съдържание. Казваме това, за да се чете горният списък такъв, какъвто е: нещата, които даден дизайн може да премахне, премахнати.
9. Статус на прегледа
Този дизайн е тестван спрямо публикувани известни отговори на двете платформи и спрямо собствените си междуплатформени вектори. В списъка на собственика е включен външен преглед, преди трезорът да бъде рекламиран в списъка на магазина; докато това не се случи, този документ ще го указва тук.
10. Къде се движат нещата
Нищо от трезора не напуска телефона, но няколко неща около него работят на машините на други хора. Това е списъкът и какво съдържа всяко от тях; самите потоци от данни са описани в политиката за поверителност на адрес https://assuredauth.com/privacy.
- Google Cloud / Firebase — пощенската кутия за релейна връзка за разширението за десктоп (пликове с криптиране от край до край, изтривани при четене), push токени, състояние на покупката и съобщенията, изпратени чрез формата за контакт.
- Vercel — asuredauth.com, неговите страници и малките функции зад тях.
- Vultr — изходните сървъри на частната връзка. Трафикът преминава през тях; нищо не се съхранява.
- Apple и Google Play — покупки и абонаменти в собствените им магазини.
- PostHog — продуктов анализ: брой на използваното, без да е обвързан с идентичност.
- RevenueCat — състоянието на абонамента: активен или изтекъл и за кой план е предназначен.
Всеки съдържа това, което пише на неговия ред, и нищо от трезора. Списъкът се променя, когато се променя продуктът, и този раздел се променя заедно с него.
Докладване на слабост
Ако смятате, че сте открили слабост в нещо от описаното тук, пишете на hello@assuredauth.com с тема „Сигурност“. Моля, включете платформата, версията на приложението и стъпките; доказателство, което използва ваши собствени данни, е достатъчно и ви молим да не тествате спрямо тези на други хора. Ние не предлагаме PGP ключ; ако даден доклад не трябва да пътува по обикновен имейл, кажете го в първото съобщение и ние ще организираме друг начин.
Какво обещаваме в замяна: ще потвърдим получаването в рамките на три работни дни, ще ви държим в течение, докато работим по него, ще коригираме достоверните данни, преди да бъдат публикувани, и ще ви посочим тук, ако желаете да бъдете посочени. Няма да предприемаме съдебни действия относно добросъвестно проведени изследвания в рамките на посочения по-долу обхват.
В обхвата: приложенията за iOS и Android, приложенията за часовници, разширението за десктоп, asuredauth.com и неговият API. Извън обхвата: самите App Store и Google Play, доставчиците, изброени по-горе, социалното инженерство на когото и да било и отказът на услуга.
В момента няма награда. На сигнала се отговаря с поправка и благодарност, а не с пари.