Beveiliging
Hoe de kluis is gebouwd en wat er bij een inbraak te vinden zou zijn.
Laatst bijgewerkt op 21 september 2026 · AssuredAuth, van CircleRoll LLC
Dit is de openbare beschrijving van hoe AssuredAuth de tweefactorauthenticatiegegevens, wachtwoorden en betaalkaarten die u erin bewaart, beschermt. De beschrijving is zo opgesteld dat een lezer met kennis van beveiliging elke bewering kan toetsen aan de app en aan de gepubliceerde testvectoren (beschikbaar voor elke recensent op aanvraag via hello@assuredauth.com). Het beschrijft de feiten en niets meer: er wordt nergens beweerd dat de app onkwetsbaar is voor aanvallen, en er worden geen percentages genoemd.
Kort gezegd: de kluis bevindt zich op één plek, namelijk uw telefoon. Elke waarde erin is versleuteld met een sleutel die de beveiligingshardware van de telefoon bewaart en niet kan exporteren. Wij beheren geen kluisserver, bewaren geen kopie en hebben geen sleutel. Een back-upbestand verlaat de telefoon pas nadat het is versleuteld met een wachtwoordzin die nergens wordt opgeslagen.
Een probleem melden: hello@assuredauth.com. Zie "Een zwak punt melden" aan het einde.
1. Wat is versleuteld, en waarmee?
| Gegevens | Op de telefoon | Sleutel |
|---|---|---|
| Geheimen met twee factoren (TOTP/HOTP/Steam-zaden) | Op de telefoonKeychain (iOS) / Android Keystore-ondersteunde winkel | SleutelDe hardware-gebonden sleutel van het platform; de database-rij bevat alleen een verwijzing (secretRef), nooit de seed. |
| Wachtwoorden (de wachtwoordwaarde, opmerkingen) | Op de telefoonVerzegelde rij: AES-256-GCM, een willekeurige 96-bits nonce per waarde | SleutelEen willekeurige 256-bits datasleutel, die zelf is ingekapseld door de hardwaresleutel in §2. |
| Kaartnummer, vervaldatum, naam op kaart, CVC-code | Op de telefoonHetzelfde zegel als wachtwoorden; de CVC-code is optioneel en wordt alleen opgeslagen als u deze invoert. | SleutelDezelfde gegevenssleutel |
| Metadata (servicenamen, gebruikersnamen, pictogrammen, sorteervolgorde) | Op de telefoonDe database van de app (SwiftData / Room) | SleutelBeschermd door de bestandsversleuteling van het besturingssysteem; wordt als niet-geheim beschouwd. |
| Back-upbestand (.authbackup) | Op de telefoonWaar je het ook plaatst: Bestanden, iCloud Drive, Google Drive appDataFolder, een deelmenu | SleutelEen sleutel afgeleid van uw wachtwoordzin (§3). Apple en Google ontvangen het verzegelde bestand en verder niets. |
| Companion voor Watch / Wear | Op de telefoonDe eigen Keychain / EncryptedSharedPreferences van het horloge | SleutelDe sleutels van het horlogeplatform; overgedragen via het kanaal voor gekoppelde apparaten van het platform. |
| Verkeer via desktop-extensie (eenmalige codes op aanvraag) | Op de telefoonNiet opgeslagen; verzonden als end-to-end versleutelde enveloppen. | SleutelEen X25519-sleutelpaar per koppeling, privésleutel in de sleutelbos/sleutelopslag; de relay ziet alleen de versleutelde tekst. |
Diagnostiek heeft geen methode die een geheim accepteert. Geen enkele analysegebeurtenis bevat een kluisveld. Er wordt in geen enkele build ooit een waarde uit de kluis naar een logboek geschreven.
2. Waar de sleutels zich bevinden, op elk platform
iOS. De gegevenssleutel is versleuteld met een sleutel die is gegenereerd binnen de Secure Enclave (kSecAttrTokenIDSecureEnclave) met toegangscontrole .privateKeyUsage + .userPresence, toegankelijkheid …ThisDeviceOnly, in de gedeelde Keychain-toegangsgroep van de app, zodat de AutoFill-extensie dezelfde sleutel kan gebruiken. De privésleutel kan niet door de app, een back-up of een debugger uit de Enclave worden gelezen; de Enclave stemt er alleen mee in om deze te gebruiken nadat de gebruiker aanwezig is (Face ID, Touch ID of de toegangscode van het apparaat). ThisDeviceOnly betekent dat een iCloud- of iTunes-back-up van de telefoon de sleutel niet bevat; een herstelde telefoon begint met een lege kluis en vraagt om uw back-upbestand en wachtwoordzin. Een telefoon zonder toegangscode kan geen .userPresence-sleutel blokkeren (de Enclave weigert er een aan te maken), en de simulator volgt opzettelijk dezelfde weg (de aanwezigheidsmelding is een waarschuwing die geen enkele test kan beantwoorden): daar is de gegevenssleutel een gewoon Keychain-item dat alleen op het apparaat staat — nog steeds niet opgenomen in back-ups, nog steeds onleesbaar wanneer de telefoon vergrendeld is, maar zonder tweede melding — en het beveiligingsscherm zegt precies dat en suggereert een toegangscode in te stellen.
Android. De datasleutel is verpakt in een AndroidKeyStore AES-256-sleutel, gegenereerd in StrongBox wanneer het apparaat er een heeft (anders de TEE), met setUserAuthenticationRequired(true) en een authenticatievaliditeit van 30 seconden na een biometrische authenticatie of apparaatreferentie, setUnlockedDeviceRequired(true) en setInvalidatedByBiometricEnrollment(true) ingeschakeld. Die laatste vlag is eerlijk en niet belastend: Android past deze alleen toe op sleutels die bij elk gebruik een biometrische authenticatie vereisen, dus bij deze sleutel met een geldigheid van 30 seconden en apparaatreferentie verandert dit niets — wat voorkomt dat een onbekende de sleutel kan gebruiken, is dat voor registratie de pincode nodig is en dat het verwijderen van de schermvergrendeling de sleutel definitief ongeldig maakt. Keystore-sleutels kunnen niet worden geëxporteerd en zijn uitgesloten van de cloudback-up van Android. Een domein dat een app in zijn eigen weergaven noemt (webDomain) wordt alleen als betrouwbaar beschouwd vanuit een bekende browser; vanuit elk ander pakket moet het ook een domein zijn dat het systeem voor dat pakket heeft geverifieerd (Digital Asset Links), aangezien elke app elk domein kan claimen.
Wat dit betekent voor een gestolen databasebestand. Het SQLite-bestand en de versleutelde rijen zijn gecodeerd. De sleutel waarmee ze geopend kunnen worden, bevindt zich in de beveiligingshardware van de telefoon waar het bestand vandaan komt en kan niet met het bestand worden gekopieerd. Er valt offline niets te raden: de gegevenssleutel is willekeurig en niet afgeleid van iets wat een persoon heeft gekozen.
3. Het back-upbestand
Backups zijn het enige dat de telefoon verlaat, dus dat is in principe de enige plek waar een offline aanval mogelijk is. Het ontwerp maakt die aanval kostbaar en geeft de aanvaller zo min mogelijk mogelijkheden:
- De wachtwoordzin is minimaal 12 tekens (het formulier accepteert niet minder en toont een sterktebalk).
- Er wordt nergens een wachtwoordhint opgeslagen, niet in het bestand en niet in de app.
- Voor elk geschreven bestand wordt een nieuwe, willekeurige salt van 16 bytes en een nonce van 12 bytes gegenereerd.
- Het hele systeem is beveiligd met AES-256-GCM, waardoor een onjuist wachtwoord of een beschadigd bestand wordt geweigerd en nooit wordt gedecodeerd tot onleesbare gegevens.
- De header (formaat, versie, KDF-parameters, salt) wordt als extra geauthenticeerde data aan de GCM-tag toegevoegd, waardoor een bestand waarvan de workfactor is verlaagd, niet kan worden geopend.
Het bestand is een JSON-bestand en kan in elke teksteditor worden gelezen; alleen de versleutelde tekst is ondoorzichtig. Iemand die het bestand over vijf jaar vindt, wanneer de app niet meer bestaat, kan precies zien hoe het is versleuteld en het openen met OpenSSL of een willekeurige Argon2-bibliotheek.
Formaat v1 (meegeleverd in versie 1.0, blijft leesbaar)
{
"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>"
}
| Stap | Bytes |
|---|---|
key | PBKDF2-HMAC-SHA256(passphrase as UTF-8, salt, 600000 rounds, 32 bytes) |
aad | UTF-8("authbackup:1:600000:") ‖ salt (onbewerkte salt-bytes, niet base64) |
ciphertext, tag | AES-256-GCM(key, nonce, plaintext, aad); tag 16 bytes, apart opgeslagen |
plaintext | UTF-8 JSON, sleutels gesorteerd: {"accounts":[…],"exportedAt":"…Z","passwords":[…],"version":1} |
Compatibiliteitsopmerking: Android 1.0 schreef een variant van v1 — kdf in kleine letters, zonder tag-sleutel (de 16-byte tag die aan de ciphertext werd toegevoegd), zonder extra gegevens. Beide platforms lezen deze bestanden nog steeds (wanneer de tag ontbreekt: splits de laatste 16 bytes, open met een lege AAD; vergelijk kdf zonder rekening te houden met hoofdletters en kleine letters) en schrijven nu beide alleen nog de bovenstaande lay-out.
Formaat v2 (huidig; de standaard voor nieuwe back-ups)
{
"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>"
}
| Stap | 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); tag 16 bytes, apart opgeslagen |
plaintext | UTF-8 JSON, sleutels gesorteerd: {"accounts":[…],"cards":[…],"exportedAt":"…Z","passwords":[…],"version":2} |
Argon2id is de referentie-implementatie in C (phc-winner-argon2, CC0), die op beide platforms beschikbaar is. 64 MiB en 3 passes duurt ongeveer een seconde op een moderne telefoon en zorgt ervoor dat elke gok evenveel geheugen en tijd kost op elke hardware – een eigenschap die PBKDF2 mist ten opzichte van GPU-systemen, en de reden waarom v2 bestaat. Een lezer negeert sleutels die hij niet kent, dus een v1-lezer met een v2-behuizing ziet simpelweg nooit kaarten.
Bewijs
Drie testvectorbestanden (back-up v1, back-up v2 en Argon2id) worden gegenereerd door een derde implementatie, onafhankelijk van beide apps (Node's OpenSSL voor PBKDF2 en AES-GCM, een WebAssembly Argon2id die tijdens het genereren wordt gecontroleerd aan de hand van de gepubliceerde antwoorden van de referentie-implementatie). Elk bestand bevat de wachtzin, salt, nonce, platte tekst, afgeleide sleutel, AAD, verwachte versleutelde tekst en tag, en het volledige bestand. De unit tests op iOS en Android lezen dezelfde bestanden en controleren dezelfde bytes — dus een back-up die op het ene platform is verzegeld, wordt bewezen, en niet verondersteld, dat deze ook op het andere platform kan worden geopend, en een overeenkomst tussen alle drie betekent niet dat er twee kopieën van dezelfde fout zijn. Een bijbehorende tool opent een bestand dat daadwerkelijk door een telefoon is geschreven met diezelfde derde implementatie en controleert de header aan de hand van de bovenstaande regels (exact de sleutels van het formaat, dus er mag geen hint of naam aanwezig zijn; 16-byte salt, 12-byte nonce, 16-byte tag apart opgeslagen; versie 2 op exact 64 MiB / 3 / 1; een onjuiste wachtzin wordt geweigerd); de geautomatiseerde iOS-uitvoering schrijft er een op de simulator en opent deze op die manier, en doorzoekt de app-container, de App Group-container en de sleutelbosdatabase van de simulator naar elk ingevoerd wachtwoord en kaartnummer als UTF-8 en UTF-16 (0 resultaten).
4. Dreigingsmodel
| Situatie | Wat ze hebben | Wat ze krijgen |
|---|---|---|
| Verloren of gestolen telefoon, vergrendeld | Wat ze hebbenHet apparaat, het databasebestand, de verzegelde rijen | Wat ze krijgenVersleutelde tekst. De versleutelde sleutel bevindt zich in de Secure Enclave/StrongBox en wordt pas vrijgegeven na het vergrendelen van het apparaat en het invoeren van een nieuwe biometrische gegevens of toegangscode. Het op afstand wissen van de telefoon (Zoek mijn apparaat) vernietigt ook het sleutelmateriaal. |
| Gestolen back-upbestand | Wat ze hebbenHet .authbackup-bestand van een cloudaccount, een e-mail of een laptop. | Wat ze krijgenEen AES-256-GCM-body onder een sleutel afgeleid van een wachtwoordzin van minimaal 12 tekens, met een salt per bestand en Argon2id op 64 MiB × 3 passes (v2) of PBKDF2 op 600.000 rondes (v1). Geen hint, geen gebruikersnaam, geen accountlijst in platte tekst. Elke gok kost de volledige afleiding; er is geen kortere weg. Een sterke wachtwoordzin is hier de enige verdediging, en de app vermeldt dit ook op het scherm. |
| Gestolen apparaat met ontgrendeld scherm. | Wat ze hebbenEen telefoon in je hand, ontgrendeld. | Wat ze krijgenDe lijst met codes. De kluis (wachtwoorden, kaarten) bevindt zich achter de app-vergrendeling en wordt opnieuw vergrendeld na de automatische vergrendelingstimer (direct / 1 min / 5 min); een onversleutelde waarde bestaat alleen in het geheugen zolang deze op het scherm wordt weergegeven. Bij automatisch invullen en exporteren in platte tekst wordt om een nieuwe biometrische authenticatie gevraagd, zelfs wanneer de app open is. Schakel de app-vergrendeling in met 'Direct' als dit een probleem voor u is. |
| Kwaadaardige app op dezelfde telefoon | Wat ze hebbenDe sandbox van een andere app, het klembord, toegankelijkheids- of overlaytrucs | Wat ze krijgenHet kan onze bestanden niet lezen (platform sandboxing) en onze sleutel niet gebruiken (de sleutel is gekoppeld aan onze ondertekeningsidentiteit en aan de aanwezigheid van de gebruiker). Kopieën worden na 30 seconden van het klembord verwijderd; op Android wordt de kopie gemarkeerd als gevoelig en uitgesloten van de klembordgeschiedenis. Vault-schermen worden op Android ingesteld op FLAG_SECURE (geen screenshots, geen schermopname, leeg scherm in de switcher); op iOS wordt de miniatuur in de switcher leeg gemaakt. Automatisch invullen op Android wordt alleen aangeboden aan apps die het systeem heeft geverifieerd aan de hand van het opgeslagen domein (Digital Asset Links), zodat een look-alike app uw wachtwoord niet aangeboden krijgt. |
| Phishingpagina | Wat ze hebbenEen site die eruitziet zoals de site die je hebt opgeslagen. | Wat ze krijgenNiets wordt automatisch ingevuld. De overeenkomst wordt gezocht op basis van het registreerbare domein (openbare lijst met achtervoegsels, meegeleverd en bijgewerkt met de app): login.example.com en example.com komen overeen, example.com.evil.net en examp1e.com niet. De ingebouwde browser in de app zoekt op dezelfde manier en vult alleen het gevraagde veld in, waarbij op het moment van invullen opnieuw wordt gecontroleerd of het veld afkomstig is van het oorspronkelijke veld; een host zonder eigen registreerbaar domein – een IP-adres, een kale naam op het lokale netwerk – komt exact overeen en niets komt minder overeen. iOS AutoFill voegt Apple's controle op gekoppelde domeinen toe. Een wachtwoord dat je handmatig moet plakken in een vergelijkbaar veld blijft een risico; de app kan dat risico niet wegnemen, alleen voorkomen dat het helpt. |
| Onze eigen servers | Wat ze hebben— | Wat ze krijgenEr is geen kluisserver. AssuredAuth heeft geen accounts, geen inloggegevens en geen kopie van uw kluis, dus er is niets van u aan onze kant dat gestolen of gekraakt kan worden. Twee dingen draaien wel aan de serverzijde, maar geen van beide heeft direct contact met de kluis: een relay-mailbox voor de desktop-extensie, die end-to-end versleutelde enveloppen opslaat (eenmalige codes, verwijderd na lezen; de relay heeft nooit een sleutel), en de exit-servers van de optionele privéverbinding, die het verkeer verwerken en geen toegangslogboeken bijhouden. |
| Een dagvaarding of een verzoek van de overheid | Wat ze hebbenJuridische procedure gericht aan ons | Wat ze krijgenNiets om over te dragen: we hebben geen kluis, geen sleutel, geen wachtwoord en geen back-up. We kunnen gedwongen worden om dat te zeggen, maar we kunnen niet gedwongen worden om iets te laten zien wat niet bestaat. |
5. Klembord, schermafbeeldingen en geheugen
- Met 'Kopiëren' wordt de waarde 30 seconden lang op het klembord geplaatst en vervolgens verwijderd als deze nog steeds van ons is. Op Android wordt de knipactie gemarkeerd als EXTRA_IS_SENSITIVE, waardoor het systeem deze verbergt in de klembordpreview en -geschiedenis; op iOS is het klemborditem alleen lokaal beschikbaar (en wordt niet via Handoff naar andere apparaten verzonden).
- De schermen van Vault (Wachtwoorden, Wachtwoord, Kaarten, Kaart, de wachtwoordzinbladen, exporteren in platte tekst) stellen FLAG_SECURE in op Android. iOS heeft geen vergelijkbare vlag; de app verbergt de miniatuur in de app-switcher en de waarden worden standaard achter een oogje weergegeven.
- Ontsleutelde waarden blijven alleen in het geheugen zolang een scherm ze weergeeft en verdwijnen zodra het scherm verdwijnt of de app vergrendelt. De gegevenssleutel wordt voor elk verzoek uitgepakt en niet in de cache opgeslagen, ook niet na een vergrendeling.
- Exporteren in platte tekst is mogelijk (zodat u altijd kunt vertrekken), maar dit gebeurt na een bevestigingspagina en een nieuwe biometrische verificatie, en het bijbehorende scherm is ook beveiligd (FLAG_SECURE).
6. Automatisch invullen: wat wordt wel en wat niet ingevuld?
| Waar | Wachtwoorden | Kaarten |
|---|---|---|
| iOS: Safari en apps (AutoFill-extensie) | WachtwoordenJa, na een nieuwe Face ID/Touch ID/toegangscode in de extensie (LAContext), en alleen voor het registreerbare domein waarvoor de invoer is opgeslagen, met de Apple-controle op gekoppelde domeinen voor apps. | KaartenNee. De automatische kaartinvulling in Safari is exclusief voor Apple; op het kaartscherm staat "Vult in in de AssuredAuth-browser en met kopiëren" en er wordt verder niets beloofd. |
| Android: apps en Chrome (AutofillService) | WachtwoordenJa, authenticatie per dataset: het systeem toont BiometricPrompt vóór het invullen; het app-pakket wordt alleen herkend als Digital Asset Links het koppelt aan het opgeslagen domein. | KaartenJa, de hints creditCardNumber, creditCardExpiration* en creditCardSecurityCode, dezelfde biometrische poort |
| De AssuredAuth-browser (beide platformen) | WachtwoordenJa, via een registreerbaar domein — een host die geen exacte overeenkomsten met zichzelf heeft — in het gevraagde kader, biometrisch vóór het invullen. | KaartenJa, door middel van velddetectie, biometrisch vóór het invullen. |
| Kopieerknoppen | WachtwoordenAchter de app-vergrendeling: klembord van 30 seconden | KaartenNummer, vervaldatum, CVC (zelfde regels) |
Niets werkt met een dubbelganger. Niets werkt zonder biometrische gegevens.
7. Wat nooit gebeurt
Geen kluisserver. Geen analyses die een kluisveld bevatten. Geen export in platte tekst zonder een bevestigingsblad en een nieuwe biometrische authenticatie. Geen SDK van derden geladen op een kluisscherm. Geen schermafbeelding van een kluisscherm. Geen wachtwoordhint. Geen logging van waarden, in geen enkele build.
8. Waar we ons niet tegen kunnen beschermen
Een wachtwoordzin die zo zwak is dat hij te raden valt. Een telefoon waarvan het besturingssysteem op de meest fundamentele manier is gecompromitteerd (een jailbroken of geroot apparaat kan de app misleiden over alles wat hierboven staat). Iemand die in de gaten wordt gehouden tijdens het typen. Malware op het bureaublad waarop je plakt. We zeggen dit zodat de bovenstaande lijst wordt gelezen voor wat hij is: de dingen die een ontwerp kan voorkomen, worden ook daadwerkelijk voorkomen.
9. Status van de beoordeling
Dit ontwerp is getest met behulp van gepubliceerde, bekende antwoorden op beide platformen en met zijn eigen platformoverschrijdende vectoren. Een externe beoordeling staat op de lijst van de eigenaar voordat de kluis in de winkel wordt aangeboden; totdat dit is gebeurd, zal dit in dit document worden vermeld.
10. Waar wat draait
Niets van de kluis verlaat de telefoon, maar een aantal processen eromheen draaien wel op de computers van anderen. Dit is de lijst en wat elk onderdeel bevat; de gegevensstromen zelf worden beschreven in het privacybeleid op https://assuredauth.com/privacy.
- Google Cloud / Firebase — de relay-mailbox voor de desktop-extensie (end-to-end versleutelde enveloppen, verwijderd na lezen), push-tokens, aankoopstatus en de berichten die via het contactformulier worden verzonden.
- Vercel — assuredauth.com, de pagina's ervan en de kleine functies die erachter schuilgaan.
- Vultr — de exit-servers van de privéverbinding. Het verkeer gaat erdoorheen; er wordt niets opgeslagen.
- Apple en Google Play: aankopen en abonnementen via hun eigen appwinkels.
- PostHog — productanalyse: tellingen van wat er gebruikt wordt, zonder koppeling aan een specifieke gebruiker.
- RevenueCat — de status van een abonnement: actief of verlopen, en op welk abonnement.
Elk item bevat de informatie die erbij staat en niets uit het archief. De lijst verandert wanneer het product verandert, en dit gedeelte verandert mee.
Een zwak punt melden
Als u denkt een zwak punt te hebben gevonden in iets dat hier beschreven staat, stuur dan een e-mail naar hello@assuredauth.com met als onderwerp "Beveiliging". Vermeld het platform, de app-versie en de stappen; een bewijs met uw eigen gegevens is voldoende en we vragen u om niet te testen met gegevens van anderen. We verstrekken geen PGP-sleutel; als een melding niet per gewone e-mail verzonden mag worden, geef dit dan aan in uw eerste bericht en we regelen een andere manier.
Wat wij in ruil daarvoor beloven: we bevestigen uw reactie binnen drie werkdagen, houden u op de hoogte van de voortgang, corrigeren eventuele onjuistheden voordat er iets over gepubliceerd wordt, en vermelden uw naam hier als u dat wenst. We zullen geen juridische stappen ondernemen tegen onderzoek dat te goeder trouw is uitgevoerd binnen de hieronder beschreven kaders.
Binnen het toepassingsgebied vallen: de iOS- en Android-apps, de smartwatch-apps, de desktop-extensie, assuredauth.com en de bijbehorende API. Buiten het toepassingsgebied vallen: de App Store en Google Play zelf, de hierboven genoemde aanbieders, social engineering van wie dan ook, en denial-of-service-aanvallen.
Er is momenteel geen beloning beschikbaar. Een melding wordt beantwoord met een oplossing en een bedankje, niet met geld.