Seguridad
Cómo está construida la bóveda y qué se encontraría en caso de una brecha.
Última actualización: 21 de septiembre de 2026 · AssuredAuth, de CircleRoll LLC
Esta es la descripción pública de cómo AssuredAuth protege las claves de autenticación de dos factores, las contraseñas y las tarjetas que guardas en la aplicación. Está redactada de forma que cualquier persona interesada en la seguridad pueda comprobar cada afirmación comparándola con la aplicación y con los vectores de prueba publicados (disponibles para cualquier revisor previa solicitud a hello@assuredauth.com). Se expone la verdad sin rodeos: nada afirma ser inmune a los ataques ni promete porcentajes de seguridad.
En resumen: la bóveda se encuentra en un solo lugar: tu teléfono. Cada valor está cifrado con una clave que el hardware de seguridad del teléfono guarda y no puede exportar. No tenemos ningún servidor de bóveda, ni copias, ni claves. El archivo de copia de seguridad solo sale del teléfono después de haber sido cifrado con una contraseña que nunca se almacena en ningún lugar.
Informar de un problema: hello@assuredauth.com. Consulte la sección "Cómo informar sobre una vulnerabilidad" al final.
1. ¿Qué está cifrado y con qué?
| Datos | En el teléfono | Clave |
|---|---|---|
| Secretos de dos factores (TOTP/HOTP/Semillas de vapor) | En el teléfonoLlavero (iOS) / Tienda respaldada por Keystore de Android | ClaveLa clave vinculada al hardware de la plataforma; la fila de la base de datos contiene solo una referencia (secretRef), nunca la semilla. |
| Contraseñas (el valor de la contraseña, notas) | En el teléfonoFila sellada: AES-256-GCM, un valor aleatorio de 96 bits por valor. | ClaveUna clave de datos aleatoria de 256 bits, envuelta a su vez por la clave de hardware en §2 |
| Tarjetas (número, fecha de caducidad, nombre en la tarjeta, CVC) | En el teléfonoEl mismo sello que las contraseñas; el código CVC es opcional y se almacena solo si lo introduces. | ClaveMisma clave de datos |
| Metadatos (nombres de servicio, nombres de usuario, iconos, orden de clasificación) | En el teléfonoLa base de datos de la aplicación (SwiftData / Room) | ClaveProtegido por el cifrado de archivos del sistema operativo; tratado como información no secreta. |
| Archivo de copia de seguridad (.authbackup) | En el teléfonoDondequiera que lo guardes: Archivos, iCloud Drive, Google Drive, appDataFolder, una hoja para compartir | ClaveUna clave derivada de su contraseña (§3). Apple y Google reciben el archivo sellado y nada más. |
| Compañero para Watch / Wear | En el teléfonoLlavero del propio reloj / Preferencias compartidas encriptadas | ClaveLas claves de la plataforma del reloj; transferidas a través del canal de dispositivos emparejados de la plataforma. |
| Tráfico de extensiones de escritorio (códigos de un solo uso bajo petición) | En el teléfonoNo se almacenan; se transmiten como sobres cifrados de extremo a extremo. | ClaveUn par de claves X25519 por emparejamiento, clave privada en el llavero/almacén de claves; el relé solo ve el texto cifrado. |
El sistema de diagnóstico no admite ningún método que acepte un secreto. Ningún evento de análisis contiene un campo de bóveda. En ninguna compilación se escribe ningún valor de la bóveda en un registro.
2. Dónde se encuentran las claves, en cada plataforma.
iOS. La clave de datos está encapsulada por una clave generada dentro del Secure Enclave (kSecAttrTokenIDSecureEnclave) con control de acceso .privateKeyUsage + .userPresence, accesibilidad …ThisDeviceOnly, en el grupo de acceso compartido de Llavero de la aplicación para que la extensión AutoFill pueda usar la misma clave. La clave privada no puede ser leída fuera del Enclave por la aplicación, por una copia de seguridad o por un depurador; el Enclave solo acepta usarla después de que el usuario esté presente (Face ID, Touch ID o el código de acceso del dispositivo). ThisDeviceOnly significa que una copia de seguridad de iCloud o iTunes del teléfono no contiene la clave; un teléfono restaurado comienza con una bóveda vacía y solicita su archivo de copia de seguridad y frase de contraseña. Un teléfono sin código de acceso no puede proteger una clave .userPresence (el Enclave se niega a crear una), y el simulador sigue el mismo camino por diseño (su aviso de presencia es una alerta que ninguna prueba puede responder): allí la clave de datos es un simple elemento del llavero exclusivo del dispositivo, que sigue estando fuera de todas las copias de seguridad, sigue siendo ilegible mientras el teléfono está bloqueado, pero sin un segundo aviso, y la pantalla de seguridad dice exactamente eso y sugiere establecer un código de acceso.
Android. La clave de datos está envuelta por una clave AndroidKeyStore AES-256, generada en StrongBox cuando el dispositivo tiene una (de lo contrario, la TEE), con setUserAuthenticationRequired(true) y una validez de autenticación de 30 segundos después de una credencial biométrica o del dispositivo, setUnlockedDeviceRequired(true) y setInvalidatedByBiometricEnrollment(true) dejados activados. Esa última bandera es honesta en lugar de soportar carga: Android la aplica solo a las claves que requieren una biometría en cada uso, por lo que en esta clave de 30 segundos con la credencial del dispositivo permitida no cambia nada: lo que impide que un extraño tenga un dedo es que el registro de uno necesita el PIN y que quitar el bloqueo de pantalla invalida la clave para siempre. Las claves de Keystore no son exportables y están excluidas de la copia de seguridad en la nube de Android. Un dominio que una aplicación nombra en sus propias vistas (webDomain) solo se cree de un navegador conocido; De cualquier otro paquete, también debe ser uno que el sistema haya verificado para ese paquete (Enlaces de Activos Digitales), ya que cualquier aplicación puede reclamar cualquier dominio.
Esto es lo que significa para un archivo de base de datos robado. El archivo SQLite y las filas selladas están encriptadas. La clave para descifrarlas reside en el hardware de seguridad del teléfono de origen del archivo y no se puede copiar junto con él. No hay nada que adivinar sin conexión: la clave de datos es aleatoria y no se deriva de ninguna elección humana.
3. El archivo de copia de seguridad
Las copias de seguridad son lo único que sale del teléfono, por lo que, en principio, son el único lugar donde es posible un ataque sin conexión. El diseño hace que ese ataque sea costoso y le ofrece las mínimas posibilidades de éxito.
- La frase de contraseña tiene al menos 12 caracteres (la hoja no acepta menos y muestra una barra de seguridad).
- No se almacena ninguna pista de contraseña en ningún lugar, ni en el archivo ni en la aplicación.
- Se genera un valor aleatorio nuevo de 16 bytes (salt) y un valor aleatorio de 12 bytes (nonce) para cada archivo escrito.
- Todo el cuerpo del archivo está cifrado con AES-256-GCM, por lo que se rechaza una contraseña incorrecta o un archivo dañado, y nunca se descifra.
- El encabezado (formato, versión, parámetros KDF, sal) se vincula a la etiqueta GCM como datos autenticados adicionales, por lo que un archivo cuyo factor de trabajo se ha reducido no se abre.
El archivo está en formato JSON y se puede leer con cualquier editor de texto; solo el texto cifrado es opaco. Alguien que encuentre el archivo dentro de cinco años, cuando la aplicación ya no esté disponible, podrá ver exactamente cómo se selló y abrirlo con OpenSSL o cualquier biblioteca de Argon2.
Formato v1 (incluido en la versión 1.0, sigue siendo legible)
{
"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>"
}
| Paso | Bytes |
|---|---|
key | PBKDF2-HMAC-SHA256(passphrase as UTF-8, salt, 600000 rounds, 32 bytes) |
aad | UTF-8("authbackup:1:600000:") ‖ salt (bytes de sal sin procesar, no base64) |
ciphertext, tag | AES-256-GCM(key, nonce, plaintext, aad); etiqueta de 16 bytes, almacenada por separado |
plaintext | JSON UTF-8, claves ordenadas: {"accounts":[…],"exportedAt":"…Z","passwords":[…],"version":1} |
Nota de compatibilidad: Android 1.0 escribió una variante de v1: kdf en minúsculas, sin clave de etiqueta (la etiqueta de 16 bytes añadida al texto cifrado), sin datos adicionales. Ambas plataformas siguen leyendo esos archivos (cuando la etiqueta está ausente: dividen los últimos 16 bytes, abren con AAD vacío; comparan kdf sin distinguir entre mayúsculas y minúsculas) y ahora ambas escriben solo el formato anterior.
Formato v2 (actual; el predeterminado para las nuevas copias de seguridad)
{
"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>"
}
| Paso | 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); etiqueta de 16 bytes, almacenada por separado |
plaintext | JSON UTF-8, claves ordenadas: {"accounts":[…],"cards":[…],"exportedAt":"…Z","passwords":[…],"version":2} |
Argon2id es la implementación de referencia en C (phc-winner-argon2, CC0), disponible para ambas plataformas. 64 MiB y 3 pasadas tardan aproximadamente un segundo en un teléfono actual y hacen que cada intento consuma esa cantidad de memoria y tiempo en cualquier hardware; una propiedad de la que carece PBKDF2 frente a plataformas con GPU, y la razón de la existencia de la versión 2. Un lector ignora las claves que desconoce, por lo que un lector de la versión 1 con un cuerpo de la versión 2 simplemente nunca ve las tarjetas.
Prueba
Tres archivos de vectores de prueba (copia de seguridad v1, copia de seguridad v2 y Argon2id) son generados por una tercera implementación, independiente de ambas aplicaciones (OpenSSL de Node para PBKDF2 y AES-GCM, un Argon2id de WebAssembly que se verifica en tiempo de generación con las respuestas publicadas de la implementación de referencia). Cada archivo contiene la frase de contraseña, el salt, el nonce, el texto plano, la clave derivada, el AAD, el texto cifrado y la etiqueta esperados, y el archivo completo. Las pruebas unitarias en iOS y Android leen los mismos archivos y verifican los mismos bytes; por lo tanto, se demuestra, no se asume, que una copia de seguridad sellada en una plataforma se abre en la otra, y la coincidencia de los tres no implica dos copias del mismo error. Una herramienta complementaria abre un archivo que un teléfono escribió realmente con esa misma tercera implementación y verifica el encabezado con las reglas anteriores (exactamente las claves del formato, por lo que no puede haber ninguna pista o nombre; sal de 16 bytes, nonce de 12 bytes, etiqueta de 16 bytes almacenada por separado; versión 2 en exactamente 64 MiB / 3 / 1; se rechaza la frase de contraseña incorrecta); la ejecución automatizada de iOS escribe uno en el simulador y lo abre de esa manera, y busca en el contenedor de la aplicación del simulador, el contenedor del grupo de aplicaciones y la base de datos del llavero cada contraseña y número de tarjeta predefinidos como UTF-8 y UTF-16 (0 coincidencias).
4. Modelo de amenazas
| Situación | Lo que tienen | Lo que obtienen |
|---|---|---|
| Teléfono perdido o robado, bloqueado | Lo que tienenEl dispositivo, el archivo de base de datos, las filas selladas | Lo que obtienenTexto cifrado. La clave de cifrado se encuentra en el Enclave Seguro/Caja Fuerte y se libera únicamente tras bloquear el dispositivo e introducir un nuevo código biométrico o de acceso. Borrar el teléfono de forma remota (Buscar mi dispositivo) destruye la clave. |
| Archivo de copia de seguridad robado | Lo que tienenEl archivo .authbackup de una cuenta en la nube, un correo electrónico, una computadora portátil | Lo que obtienenCuerpo AES-256-GCM bajo una clave derivada de una frase de contraseña de al menos 12 caracteres, con un salt por archivo y Argon2id a 64 MiB × 3 pasadas (v2) o PBKDF2 a 600 000 rondas (v1). Sin pista, sin nombre de usuario, sin lista de cuentas en texto plano. Cada intento cuesta la derivación completa; no hay atajos. Una frase de contraseña segura es la defensa principal, y la aplicación lo indica en la hoja de cálculo. |
| Dispositivo robado con la pantalla desbloqueada. | Lo que tienenUn teléfono en tu mano, desbloqueado. | Lo que obtienenLista de códigos. La bóveda (contraseñas, tarjetas) está protegida por el bloqueo de la aplicación y se vuelve a bloquear automáticamente (inmediatamente / 1 min / 5 min); el valor descifrado solo permanece en memoria mientras la pantalla lo muestra. El autocompletado y la exportación de texto plano solicitan una nueva verificación biométrica incluso cuando la aplicación está abierta. Active el bloqueo de la aplicación con la opción "Inmediatamente" si esto le preocupa. |
| Aplicación maliciosa en el mismo teléfono. | Lo que tienenOtro entorno aislado de la aplicación, el portapapeles, la accesibilidad o los trucos de superposición. | Lo que obtienenNo puede leer nuestros archivos (sandboxing de la plataforma) ni usar nuestra clave (la clave está vinculada a nuestra identidad de firma y a la presencia del usuario). Las copias se borran del portapapeles después de 30 segundos; en Android, la copia se marca como confidencial y se excluye del historial del portapapeles. Las pantallas de la bóveda tienen la bandera FLAG_SECURE configurada en Android (sin capturas de pantalla, sin grabación de pantalla, en blanco en el selector); iOS deja en blanco la miniatura del selector. El autocompletado en Android solo se ofrece a las aplicaciones que el sistema ha verificado con el dominio guardado (Digital Asset Links), por lo que a una aplicación similar no se le ofrece su contraseña. |
| Página de phishing | Lo que tienenUn sitio que se parece al que guardaste | Lo que obtienenNada se rellena. La coincidencia se realiza mediante dominio registrable (lista pública de sufijos, incluida y actualizada con la aplicación): login.example.com y example.com coinciden, example.com.evil.net y examp1e.com no. El navegador integrado en la aplicación realiza la misma coincidencia y rellena solo en el marco que lo solicitó, comprobándolo nuevamente con el origen de ese marco en el momento del relleno; un host sin dominio registrable propio (una dirección IP, un nombre simple en la red local) coincide exactamente y nada menos. El autocompletado de iOS añade la comprobación de dominios asociados de Apple. Una contraseña que deba pegarse manualmente en un campo similar sigue siendo un riesgo; la aplicación no puede eliminarlo, solo evitar ayudar. |
| Nuestros propios servidores | Lo que tienen— | Lo que obtienenNo existe un servidor de bóveda. AssuredAuth no tiene cuentas, ni inicio de sesión, ni copia de su bóveda, por lo que no hay nada suyo en nuestro sistema que pueda ser robado o vulnerado. Dos elementos se ejecutan en el servidor, ninguno de los cuales accede a la bóveda: un buzón de retransmisión para la extensión de escritorio, que almacena sobres cifrados de extremo a extremo (códigos de un solo uso que se eliminan al leerse; el buzón nunca tiene una clave), y los servidores de salida de la conexión privada opcional, que gestionan el tráfico y no guardan registros de acceso. |
| Una citación o una solicitud del gobierno | Lo que tienenProceso legal dirigido a nosotros | Lo que obtienenNo tenemos nada que entregar: no poseemos bóveda, ni llave, ni contraseña, ni copia de seguridad. Podemos vernos obligados a decir eso; no podemos ser obligados a producir lo que no existe. |
5. Portapapeles, capturas de pantalla y memoria
- La función Copiar guarda el valor en el portapapeles durante 30 segundos y, si aún nos pertenece, lo borra. En Android, el elemento recortado se marca como EXTRA_IS_SENSITIVE, por lo que el sistema lo oculta de la vista previa y el historial del portapapeles; en iOS, el elemento del portapapeles es solo local (no se transfiere a otros dispositivos).
- Las pantallas de la bóveda (Contraseñas, Contraseña, Tarjetas, Tarjeta, hojas de frases de contraseña, exportación de texto plano) establecen FLAG_SECURE en Android. iOS no tiene un indicador equivalente; la aplicación oculta su miniatura en el selector de aplicaciones y los valores se encuentran detrás de un interruptor de ojo de forma predeterminada.
- Los valores descifrados permanecen en la memoria solo mientras se muestra una pantalla y se eliminan cuando esta desaparece o la aplicación se bloquea. La clave de datos se descifra para cada solicitud y no se almacena en caché durante el bloqueo.
- Existe la opción de exportar en texto plano (para que siempre puedas salir de ella), pero está protegida por una hoja de confirmación y un nuevo registro biométrico, y su pantalla también es FLAG_SECURE.
6. Autocompletar: qué se rellena y qué no.
| Dónde | Contraseñas | Tarjetas |
|---|---|---|
| iOS: Safari y aplicaciones (extensión AutoFill) | ContraseñasSí, después de un nuevo Face ID / Touch ID / código de acceso en la extensión (LAContext), y solo para el dominio registrable para el que se guardó la entrada, con la comprobación de dominios asociados de Apple para aplicaciones. | TarjetasNo. El autocompletado de tarjetas en Safari es exclusivo de Apple; la pantalla de la tarjeta dice "Rellena en el navegador AssuredAuth y con Copiar" y no promete nada más. |
| Android: aplicaciones y Chrome (AutofillService) | ContraseñasSí, autenticación por conjunto de datos: el sistema muestra BiometricPrompt antes de completar el formulario; el paquete de la aplicación solo coincide cuando Digital Asset Links lo vincula al dominio guardado. | TarjetasSí, las pistas creditCardNumber, creditCardExpiration* y creditCardSecurityCode, misma puerta biométrica |
| El navegador AssuredAuth (ambas plataformas) | ContraseñasSí, por dominio registrable —un host sin ninguno de los suyos que coincida exactamente— en el marco que solicitó, biométrico antes de rellenar | TarjetasSí, mediante detección de campo, biométrica antes del llenado. |
| Botones de copiar | ContraseñasDetrás del bloqueo de la aplicación, portapapeles de 30 segundos | TarjetasNúmero, fecha de caducidad, CVC (mismas reglas) |
Nada se completa en un huésped que se parece a otro. Nada se completa sin datos biométricos.
7. Lo que nunca sucede
Sin servidor de bóveda. Sin análisis que incluyan un campo de bóveda. Sin exportación de texto plano sin una hoja de confirmación y una nueva verificación biométrica. Sin SDK de terceros cargado en una pantalla de bóveda. Sin captura de pantalla de una pantalla de bóveda. Sin sugerencia de frase de contraseña. Sin registro de valores, en ninguna compilación.
8. Aquello contra lo que no podemos protegernos
Una contraseña demasiado débil para adivinarla. Un teléfono cuyo sistema operativo está comprometido de raíz (un dispositivo rooteado o con jailbreak puede engañar a la aplicación sobre todo lo anterior). Una persona vigilada mientras escribe. Malware en el escritorio donde se copia el código. Decimos esto para que la lista anterior se entienda por lo que es: las cosas que un diseño puede eliminar, eliminadas.
9. Estado de la revisión
Este diseño se ha probado unitariamente comparándolo con soluciones conocidas publicadas en ambas plataformas y con sus propios vectores multiplataforma. El propietario tiene previsto realizar una revisión externa antes de que la bóveda se anuncie en la tienda; hasta que esto ocurra, este documento lo indicará aquí.
10. Dónde se ejecuta cada cosa
Ningún elemento de la bóveda sale del teléfono, pero algunos procesos relacionados se ejecutan en equipos ajenos. Esta es la lista y el contenido de cada proceso; el flujo de datos se describe en la política de privacidad en https://assuredauth.com/privacy.
- Google Cloud / Firebase: el buzón de retransmisión para la extensión de escritorio (sobres cifrados de extremo a extremo, eliminados al leerse), tokens push, estado de compra y mensajes enviados a través del formulario de contacto.
- Vercel — assuredauth.com, sus páginas y las pequeñas funciones que las respaldan.
- Vultr: los servidores de salida de la conexión privada. El tráfico pasa a través de ellos; no se almacena nada.
- Apple y Google Play: compras y suscripciones en sus propias tiendas.
- PostHog: análisis de productos: recuento de lo que se usa, sin vincularlo a ninguna identidad.
- RevenueCat: el estado de una suscripción: activa o vencida, y en qué plan.
Cada una contiene lo que indica su descripción y nada del archivo. La lista cambia cuando el producto lo hace, y esta sección cambia con él.
Informar de una debilidad
Si crees haber encontrado una debilidad en algo de lo aquí descrito, escribe a hello@assuredauth.com con el asunto "Seguridad". Incluye la plataforma, la versión de la app y los pasos; basta con una prueba que use tus propios datos, y te pedimos que no pruebes con los de otras personas. No ofrecemos clave PGP; si un informe no debería viajar por correo sin cifrar, dilo en un primer mensaje y buscaremos otra vía.
Lo que prometemos a cambio: le responderemos en un plazo de tres días hábiles, le mantendremos informado mientras trabajamos en ello, corregiremos la información antes de su publicación y le daremos el crédito correspondiente si así lo desea. No emprenderemos acciones legales por investigaciones realizadas de buena fe dentro del ámbito que se detalla a continuación.
El alcance incluye: las aplicaciones para iOS y Android, las aplicaciones para relojes inteligentes, la extensión de escritorio, ensuredauth.com y su API. El alcance excluye: la App Store y Google Play, los proveedores mencionados anteriormente, la ingeniería social dirigida a cualquier persona y los ataques de denegación de servicio.
Por el momento no hay recompensa. A cada informe se le ofrece una solución y un agradecimiento, no dinero.