Seguridad
Paano itinayo ang vault, at kung anong paglabag ang matutuklasan.
Huling na-update noong ika-21 ng Setyembre 2026 · AssuredAuth, ni CircleRoll LLC
Ito ang pampublikong paglalarawan kung paano pinoprotektahan ng AssuredAuth ang mga two-factor na sikreto, password, at card na itinatago mo rito. Isinulat ito upang masuri ng isang mambabasang may kamalayan sa seguridad ang bawat pahayag laban sa app at laban sa mga nailathalang test vector (makukuha ng sinumang tagasuri kapag hiniling sa hello@assuredauth.com). Sinasabi nito kung ano ang totoo at wala nang iba pa: walang sinasabi rito na hindi naaatake, at walang ipinapangako sa porsyento.
Ang maikling bersyon: ang vault ay nasa iisang lugar, ang iyong telepono. Ang bawat halaga nito ay naka-encrypt gamit ang isang susi na hawak ng security hardware ng telepono at hindi maaaring i-export. Nagpapatakbo kami ng walang vault server, walang hawak na kopya at walang hawak na susi. Ang isang backup file ay umaalis lamang sa telepono pagkatapos itong ma-encrypt sa ilalim ng isang passphrase na hindi kailanman iniimbak kahit saan.
Mag-ulat ng problema: hello@assuredauth.com. Tingnan ang "Pag-uulat ng kahinaan" sa dulo.
1. Ano ang naka-encrypt, gamit ang ano
| Datos | Sa telepono | Susi |
|---|---|---|
| Mga sikretong may dalawang salik (TOTP/HOTP/Mga butong pinasingaw) | Sa teleponoTindahan na sinusuportahan ng Keychain (iOS) / Android Keystore | SusiAng hardware-bound key ng platform; ang database row ay naglalaman lamang ng isang reference (secretRef), hindi kailanman ang seed |
| Mga Password (ang halaga ng password, mga tala) | Sa teleponoSelyadong hilera: AES-256-GCM, isang random na 96-bit na nonce bawat halaga | SusiIsang random na 256-bit na data key, na nakabalot mismo sa hardware key sa §2 |
| Mga Card (numero, expiry, pangalan sa card, CVC) | Sa teleponoParehong selyo ng mga password; opsyonal ang CVC at iniimbak lamang kung ilalagay mo ito | SusiParehong susi ng datos |
| Metadata (mga pangalan ng serbisyo, mga username, mga icon, pagkakasunud-sunod ng pag-uuri) | Sa teleponoAng database ng app (SwiftData / Room) | SusiPinoprotektahan ng pag-encrypt ng file ng operating system; itinuturing na hindi sikreto |
| File ng pag-backup (.authbackup) | Sa teleponoSaan mo man ito ilagay: Mga File, iCloud Drive, Google Drive appDataFolder, isang share sheet | SusiIsang susi na hango sa iyong passphrase (§3). Matatanggap ng Apple at Google ang selyadong file at wala nang iba pa |
| Companion app para sa Watch / Wear | Sa teleponoAng sariling Keychain / EncryptedSharedPreferences ng relo | SusiAng mga susi ng plataporma ng relo; inililipat sa pamamagitan ng channel ng nakapares na device ng plataporma |
| Trapiko ng mga extension ng desktop (mga minsanang code kapag hiniling) | Sa teleponoHindi nakaimbak; ipinapadala bilang mga end-to-end na naka-encrypt na sobre | SusiIsang pares ng X25519 key bawat pagpapares, pribadong key sa Keychain / Keystore; ciphertext lang ang nakikita ng relay |
Walang method ang Diagnostics na tumatanggap ng sikreto. Walang analytics event na may vault field. Walang value mula sa vault ang isinusulat sa isang log, sa anumang build.
2. Kung saan nakalagay ang mga susi, sa bawat plataporma
iOS. Ang data key ay nakabalot sa isang key na nabuo sa loob ng Secure Enclave (kSecAttrTokenIDSecureEnclave) na may access control na .privateKeyUsage + .userPresence, accessibility …ThisDeviceOnly, sa shared Keychain access group ng app para magamit ng AutoFill extension ang parehong key. Hindi mababasa ng app, ng backup, o ng debugger ang private key palabas ng Enclave; sumasang-ayon lamang ang Enclave na gamitin ito pagkatapos na naroroon ang user (Face ID, Touch ID o ang passcode ng device). Ang ibig sabihin ng ThisDeviceOnly ay walang key ang backup ng telepono sa iCloud o iTunes; ang isang na-restore na telepono ay nagsisimula sa isang walang laman na vault at hinihingi ang iyong backup file at passphrase. Hindi maaaring mag-gate ang isang teleponong walang passcode ng .userPresence key (tumanggi ang Enclave na gumawa nito), at ang simulator ay gumagamit ng parehong landas ayon sa disenyo (ang presence prompt nito ay isang alerto na hindi masasagot ng anumang test): doon, ang data key ay isang simpleng device-only na Keychain item — wala pa rin sa bawat backup, hindi pa rin mababasa habang naka-lock ang telepono, ngunit walang pangalawang prompt — at eksaktong sinasabi iyon ng Security screen at nagmumungkahi ng pagtatakda ng passcode.
Android. Ang data key ay nakabalot sa isang AndroidKeyStore AES-256 key, na nabubuo sa StrongBox kapag ang device ay may isa (maliban sa TEE), na may setUserAuthenticationRequired(true) at 30-segundong validity ng authentication pagkatapos ng biometric o device credential, setUnlockedDeviceRequired(true), at setInvalidatedByBiometricEnrollment(true) na naiwan. Ang huling flag na iyon ay honest sa halip na load-bearing: Inilalapat lamang ito ng Android sa mga key na humihingi ng biometric sa bawat paggamit, kaya sa 30-segundong key na ito na pinapayagan ang device credential, wala itong binabago — ang pumipigil sa isang estranghero na makapasok ay ang pag-enroll ay nangangailangan ng PIN, at ang pag-alis ng screen lock ay permanenteng nagpapawalang-bisa sa key. Ang mga keystore key ay hindi maaaring i-export at hindi kasama sa cloud backup ng Android. Ang isang domain na pinangalanan ng isang app sa sarili nitong mga view (webDomain) ay pinaniniwalaan lamang mula sa isang kilalang browser; mula sa anumang iba pang package, dapat din itong isa na na-verify ng system para sa package na iyon (Digital Asset Links), dahil maaaring i-claim ng anumang app ang anumang domain.
Ang ibig sabihin nito para sa isang ninakaw na database file. Ang SQLite file at ang mga selyadong hanay ay ciphertext. Ang susi na nagbubukas sa mga ito ay nasa security hardware ng teleponong pinagmulan ng file at hindi maaaring kopyahin kasama ng file. Walang dapat hulaan offline: ang data key ay random, hindi hinango sa anumang pinili ng isang tao.
3. Ang backup file
Ang mga backup ang tanging bagay na lumalabas sa telepono, kaya ang mga ito ang tanging lugar kung saan posible ang isang offline na pag-atake sa prinsipyo. Ginagawang magastos ng disenyo ang pag-atakeng iyon at binibigyan ito ng kaunting magagamit hangga't maaari:
- Ang passphrase ay hindi bababa sa 12 karakter (mas kaunti ang tinatanggihan ng sheet at nagpapakita ng strength bar).
- Walang pahiwatig ng passphrase na nakaimbak kahit saan, sa file o sa app.
- Isang sariwang random na 16-byte na salt at 12-byte na nonce para sa bawat file na isinulat.
- Ang buong katawan ay AES-256-GCM, kaya ang maling passphrase o sirang file ay tatanggihan, at hindi kailanman ide-decrypt at magiging basura.
- Ang header (format, bersyon, mga parameter ng KDF, salt) ay nakatali sa GCM tag bilang karagdagang napatunayang data, kaya ang isang file na ang work factor ay na-edit pababa ay hindi magbubukas.
Ang file ay JSON at mababasa sa anumang text editor; tanging ang ciphertext lamang ang hindi malinaw. Ang isang taong makakahanap ng file sa loob ng limang taon, nang wala na ang app, ay makikita nang eksakto kung paano ito naselyuhan at mabubuksan ito gamit ang OpenSSL o anumang Argon2 library.
Format v1 (ipinadala sa 1.0, nananatiling nababasa)
{
"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>"
}
| Hakbang | Mga Byte |
|---|---|
key | PBKDF2-HMAC-SHA256(passphrase as UTF-8, salt, 600000 rounds, 32 bytes) |
aad | UTF-8("authbackup:1:600000:") ‖ salt (mga hilaw na salt bytes, hindi base64) |
ciphertext, tag | AES-256-GCM(key, nonce, plaintext, aad); tag na 16 bytes, nakaimbak nang hiwalay |
plaintext | UTF-8 JSON, nakaayos na ang mga key: {"accounts":[…],"exportedAt":"…Z","passwords":[…],"version":1} |
Paalala sa pagiging tugma: Ang Android 1.0 ay sumulat ng isang variant ng v1 — kdf sa maliliit na titik, walang tag key (ang 16-byte na tag na nakadikit sa ciphertext), walang karagdagang data. Patuloy na binabasa ng parehong platform ang mga file na iyon (kapag walang tag: hatiin ang huling 16 na byte, buksan gamit ang walang laman na AAD; ihambing ang kdf nang hindi sensitibo sa malalaking titik) at pareho na ngayon ang nagsusulat lamang ng layout sa itaas.
Format v2 (kasalukuyan; ang default para sa mga bagong backup)
{
"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>"
}
| Hakbang | Mga Byte |
|---|---|
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); tag na 16 bytes, nakaimbak nang hiwalay |
plaintext | UTF-8 JSON, nakaayos na ang mga key: {"accounts":[…],"cards":[…],"exportedAt":"…Z","passwords":[…],"version":2} |
Ang Argon2id ay ang reference C implementation (phc-winner-argon2, CC0), na ibinebenta sa parehong platform. Ang 64 MiB at 3 pass ay tumatagal ng halos isang segundo sa isang kasalukuyang telepono at nagiging sanhi ng bawat hula na mawalan ng memorya at oras sa anumang hardware — ang katangiang wala ang PBKDF2 laban sa mga GPU rig, at ang dahilan kung bakit umiiral ang v2. Hindi pinapansin ng isang reader ang mga key na hindi nito alam, kaya ang isang v1 reader na binigyan ng v2 body ay hindi kailanman nakikita ang mga card.
Patunay
Tatlong test-vector file (backup v1, backup v2 at Argon2id) ang nabubuo ng ikatlong implementasyon, na hiwalay sa parehong app (Node's OpenSSL para sa PBKDF2 at AES-GCM, isang WebAssembly Argon2id na sinuri sa oras ng pagbuo laban sa mga nai-publish na sagot ng reference implementation). Ang bawat isa ay naglalaman ng passphrase, salt, nonce, plaintext, derived key, AAD, expected ciphertext at tag, at ang kumpletong file. Binabasa ng mga unit test sa iOS at sa Android ang parehong mga file at iginiit ang parehong mga byte — kaya ang isang backup na naselyuhan sa isang platform ay napatunayan, hindi ipinapalagay, na bubukas sa kabila, at ang pagkakasundo ng lahat ng tatlo ay hindi dalawang kopya ng parehong pagkakamali. Isang kasamang tool ang magbubukas ng file na aktwal na isinulat ng isang telepono gamit ang parehong ikatlong implementasyon at susuriin ang header laban sa mga panuntunan sa itaas (eksakto ang mga key ng format, kaya walang maaaring ipakitang pahiwatig o pangalan; 16-byte na salt, 12-byte na nonce, 16-byte na tag na nakaimbak nang hiwalay; bersyon 2 sa eksaktong 64 MiB / 3 / 1; hindi tinanggap ang maling passphrase); ang awtomatikong pagpapatakbo ng iOS ay magsusulat ng isa sa simulator at bubuksan ito sa ganoong paraan, at hahanapin ang app container, App Group container, at keychain database ng simulator para sa bawat seeded password at numero ng card bilang UTF-8 at UTF-16 (0 hits).
4. Modelo ng banta
| Sitwasyon | Kung ano ang mayroon sila | Ang nakukuha nila |
|---|---|---|
| Nawala o ninakaw na telepono, naka-lock | Kung ano ang mayroon silaAng device, ang database file, ang mga selyadong row | Ang nakukuha nilaCiphertext. Ang wrapping key ay nasa Secure Enclave / StrongBox at lalabas lamang pagkatapos ma-lock ang device kasama ang isang bagong biometric o passcode. Ang pag-wipe ng telepono nang malayuan (Find My / Find My Device) ay sisira sa key material kasama nito. |
| Ninakaw na backup file | Kung ano ang mayroon silaAng .authbackup file mula sa isang cloud account, isang email, isang laptop | Ang nakukuha nilaIsang AES-256-GCM body sa ilalim ng isang key na hango sa isang passphrase na hindi bababa sa 12 character, na may per-file salt at Argon2id sa 64 MiB × 3 passes (v2) o PBKDF2 sa 600,000 rounds (v1). Walang pahiwatig, walang username, walang listahan ng account na nalilinis. Ang bawat hula ay katumbas ng buong derivation; walang shortcut. Ang isang malakas na passphrase ang buong depensa dito, at sinasabi ito ng app sa sheet. |
| Ninakaw na device na naka-unlock ang screen | Kung ano ang mayroon silaIsang telepono sa iyong kamay, hindi naka-lock | Ang nakukuha nilaAng listahan ng mga Code. Ang vault (mga password, card) ay nasa likod ng lock ng app at muling nagla-lock sa auto-lock timer (kaagad / 1 minuto / 5 minuto); ang isang na-decrypt na value ay nasa memory lamang habang ipinapakita ito ng screen nito. Ang autofill at plain-text export ay humihingi ng bagong biometric kahit na bukas ang app. I-on ang app lock gamit ang "Kaagad" kung ito ang iyong ikinababahala. |
| Nakakahamak na app sa parehong telepono | Kung ano ang mayroon silaMga trick sa sandbox, clipboard, accessibility o overlay ng ibang app | Ang nakukuha nilaHindi nito mababasa ang ating mga file (platform sandboxing) o magagamit ang ating key (ang key ay nakatali sa ating pagkakakilanlan sa pagpirma at sa presensya ng user). Natatanggal ang mga kopya mula sa clipboard pagkalipas ng 30 segundo; sa Android, ang kopya ay minamarkahan bilang sensitibo at hindi kasama sa kasaysayan ng clipboard. Nakatakda ang mga screen ng vault na FLAG_SECURE sa Android (walang mga screenshot, walang pag-record ng screen, blangko sa switcher); Binubuwag ng iOS ang thumbnail ng switcher. Ang Autofill sa Android ay inihahatid lamang sa mga app na na-verify ng system laban sa naka-save na domain (Mga Digital Asset Link), kaya hindi maibibigay sa iyong password ang isang kamukhang app. |
| Pahina ng phishing | Kung ano ang mayroon silaIsang site na kamukha ng site na na-save mo | Ang nakukuha nilaWalang pumupuno. Ang pagtutugma ay ginagawa ayon sa registrable domain (publikong listahan ng hulapi, naka-bundle at ina-update kasama ng app): login.example.com at example.com match, example.com.evil.net at examp1e.com ay hindi. Ang in-app browser ay tumutugma sa parehong paraan at pinupunan lamang ang frame na nagtanong, na muling sinusuri laban sa pinagmulan ng frame na iyon sa sandaling punan; ang isang host na walang sariling registrable domain — isang IP address, isang simpleng pangalan sa lokal na network — ay eksaktong tumutugma at walang mas maluwag. Idinaragdag ng iOS AutoFill ang associated-domains check ng Apple. Ang isang password na kailangan mong i-paste nang manu-mano sa isang kamukha ay isang panganib pa rin; hindi iyon maaalis ng app, maiiwasan lamang ang pagtulong. |
| Ang aming sariling mga server | Kung ano ang mayroon sila— | Ang nakukuha nilaWalang vault server. Walang account, walang sign-in, at walang kopya ng iyong vault ang AssuredAuth, kaya walang anumang bagay sa amin na maaaring manakaw at ma-crack. Dalawang bagay ang tumatakbo sa server-side, na hindi nakakaapekto sa vault: isang relay mailbox para sa desktop extension, na nag-iimbak ng mga end-to-end na naka-encrypt na sobre (mga one-time code, na binubura kapag nabasa; ang relay ay hindi kailanman may susi), at ang mga exit server ng opsyonal na pribadong koneksyon, na nagdadala ng trapiko at walang itinatagong mga access log. |
| Isang subpoena o kahilingan ng gobyerno | Kung ano ang mayroon silaProsesong legal na naka-address sa amin | Ang nakukuha nilaWalang maibibigay: wala tayong hawak na vault, walang key, walang passphrase at walang backup. Maaari tayong mapilitang sabihin iyan; hindi tayo maaaring mapilitang gumawa ng kung ano ang wala. |
5. Clipboard, mga screenshot at memorya
- Inilalagay ng Copy ang value sa clipboard sa loob ng 30 segundo, pagkatapos ay binubura ito kung atin pa rin ito. Sa Android, ang clip ay minarkahan ng EXTRA_IS_SENSITIVE kaya itinatago ito ng system mula sa preview at history ng clipboard; sa iOS, ang pasteboard item ay local-only (hindi inililipat sa ibang device).
- Ang mga screen ng Vault (Mga Password, Password, Mga Card, Card, ang mga passphrase sheet, plain-text export) ay nagtatakda ng FLAG_SECURE sa Android. Ang iOS ay walang katumbas na flag; binubuwag ng app ang thumbnail nito sa app switcher at ang mga value ay nasa likod ng isang eye toggle bilang default.
- Ang mga na-decrypt na value ay nabubuhay lamang sa memorya habang ipinapakita ang mga ito ng screen at inaalis kapag nawala ito o kapag nag-lock ang app. Ang data key ay binubuksan para sa isang kahilingan at hindi naka-cache sa buong lock.
- May plain-text export (para makaalis ka palagi) at nasa likod ito ng confirm sheet at bagong biometric, at ang screen nito ay FLAG_SECURE rin.
6. Autofill: ano ang pumupuno, at ano ang hindi
| Saan | Mga Password | Mga Card |
|---|---|---|
| iOS: Safari at mga app (extension ng AutoFill) | Mga PasswordOo, pagkatapos ng isang bagong Face ID / Touch ID / passcode sa extension (LAContext), at para lamang sa registrable domain kung saan na-save ang entry, gamit ang associated-domains check ng Apple para sa mga app. | Mga CardHindi. Ang card autofill sa Safari ay sa Apple lamang; ang screen ng card ay nagsasabing "Pupunan ang AssuredAuth browser at may Kopyahin" at wala nang ibang ipinapangako. |
| Android: mga app at Chrome (AutofillService) | Mga PasswordOo, per-dataset authentication: ipinapakita ng system ang BiometricPrompt bago ang pagpuno; tumutugma lamang ang app package kapag iniuugnay ito ng Digital Asset Links sa naka-save na domain | Mga CardOo, ang mga pahiwatig ng creditCardNumber, creditCardExpiration* at creditCardSecurityCode ay parehong biometric gate. |
| Ang AssuredAuth browser (parehong platform) | Mga PasswordOo, sa pamamagitan ng registrable domain — isang host na wala sa sarili nitong eksaktong tugma — sa frame na nagtanong, biometric bago ang pagpuno | Mga CardOo, sa pamamagitan ng field detection, biometric bago ang pagpuno |
| Mga button ng pagkopya | Mga PasswordSa likod ng lock ng app, 30-segundong clipboard | Mga CardNumero, expiry, CVC (parehong mga patakaran) |
Walang makakapuno sa isang kamukha ng host. Walang makakapuno kung walang biometric.
7. Ang hindi kailanman nangyayari
Walang vault server. Walang analytics na may vault field. Walang plain-text export nang walang confirm sheet at bagong biometric. Walang third-party SDK na nilo-load sa vault screen. Walang screenshot ng vault screen. Walang passphrase hint. Walang pag-log ng mga value, sa anumang build.
8. Ang hindi natin kayang protektahan laban sa
Isang passphrase na sapat ang kahinaan para hulaan. Isang teleponong ang operating system ay nakompromiso sa root system (ang isang jailbroken o rooted device ay maaaring magsinungaling sa app tungkol sa lahat ng nasa itaas). Isang taong binabantayan habang nagta-type. Malware sa desktop na iyong pino-paste. Sinasabi namin ito para mabasa ang listahan sa itaas kung ano talaga ito: ang mga bagay na maaaring alisin ng isang disenyo, inaalis.
9. Katayuan ng pagsusuri
Ang disenyong ito ay nasubukan na gamit ang unit-tested laban sa mga nailathalang kilalang sagot sa parehong platform at laban sa sarili nitong mga cross-platform vector. May panlabas na pagsusuri na nasa listahan ng may-ari bago i-advertise ang vault sa listahan ng tindahan; hanggang sa mangyari ito, sasabihin ito ng dokumentong ito dito.
10. Kung saan tumatakbo ang mga bagay-bagay
Walang anumang bahagi ng vault ang lumalabas sa telepono, ngunit may ilang bagay sa paligid nito na tumatakbo sa mga makina ng ibang tao. Ito ang listahan, at kung ano ang laman ng bawat isa; ang mismong daloy ng data ay inilalarawan sa patakaran sa privacy sa https://assuredauth.com/privacy.
- Google Cloud / Firebase — ang relay mailbox para sa desktop extension (mga end-to-end na naka-encrypt na sobre, binubura kapag nabasa na), mga push token, estado ng pagbili, at ang mga mensaheng ipinapadala sa pamamagitan ng contact form.
- Vercel — assuretauth.com, ang mga pahina nito at ang maliliit na tungkulin sa likod ng mga ito.
- Vultr — ang mga exit server ng pribadong koneksyon. Ang trapiko ay dumadaan sa mga ito; walang iniimbak.
- Apple at Google Play — mga pagbili at subscription, sa sarili nilang mga tindahan.
- PostHog — product analytics: bilang ng mga ginamit, na walang kaugnayan sa pagkakakilanlan.
- RevenueCat — ang estado ng isang subscription: aktibo o nag-expire na, at sa aling plano.
Ang bawat isa ay naglalaman ng sinasabi ng linya nito at walang anumang bagay mula sa vault. Nagbabago ang listahan kapag nagbago ang produkto, at ang seksyong ito ay nagbabago rin kasama nito.
Pag-uulat ng kahinaan
Kung naniniwala kang may nakita kang kahinaan sa anumang inilarawan dito, sumulat sa hello@assuredauth.com na may paksang "Seguridad". Pakisama ang platform, ang bersyon ng app at ang mga hakbang; sapat na ang isang patunay na gumagamit ng iyong sariling data, at hinihiling namin na huwag mong subukan ito laban sa data ng ibang tao. Hindi kami nag-aalok ng PGP key; kung ang isang ulat ay hindi dapat maipadala sa pamamagitan ng simpleng email, sabihin ito sa unang mensahe at mag-aayos kami ng ibang paraan.
Ang aming ipinapangako bilang kapalit: kinikilala namin sa loob ng tatlong araw ng negosyo, pinapanatili kang may alam habang inaayos namin ito, inaayos kung ano ang totoo bago pa man mailathala ang anumang bagay tungkol dito, at binibigyan ka ng kredito dito kung nais mong mabigyan ng kredito. Hindi kami magsasagawa ng legal na aksyon laban sa pananaliksik na ginawa nang may mabuting hangarin sa loob ng saklaw sa ibaba.
Nasasaklaw: ang mga iOS at Android app, ang mga watch app, ang desktop extension, assuretauth.com at ang API nito. Labag sa saklaw: ang App Store at Google Play mismo, ang mga provider na nakalista sa itaas, social engineering ng sinuman, at pagtanggi sa serbisyo.
Walang pabuya sa ngayon. Ang ulat ay sinasagot ng isang pag-aayos at pasasalamat, hindi ng pera.