Código abierto · Cifrado completo · Sin nube

Análisis de seguridad de PlainApp

Cómo PlainApp protege tus datos en la red Wi-Fi local, con evidencia directa del código fuente abierto.

Android 9.0+ · Google Play · F-Droid · GitHub

Descargar

¿Por qué importa la seguridad en la red local?

Cuando usas una app para gestionar tu teléfono Android desde el navegador de un PC, tus SMS, fotos, contactos y archivos viajan por tu red Wi-Fi. La mayoría de las apps envían todo esto como texto legible sin cifrar. Cualquier persona en la misma red podría verlo.

Quizás pienses: "Es mi Wi-Fi de casa, ¿quién va a espiar?" Pero considera lo siguiente:

  • Wi-Fi público — Cafeterías, aeropuertos, hoteles: cualquiera cerca puede capturar el tráfico
  • Redes compartidas — Compañeros de piso, invitados o dispositivos IoT comprometidos
  • Vulnerabilidades del router — Firmware desactualizado con exploits conocidos

Si una app envía tus SMS como texto plano por HTTP, cualquiera con una herramienta gratuita como Wireshark puede leerlos. No es algo teórico: es extremadamente fácil.

La mayoría de las apps de gestión de teléfonos hacen exactamente esto. Abre Chrome DevTools (F12 → pestaña Network) mientras usas su interfaz web y podrás leer cada llamada a la API en JSON legible: cuerpos de SMS, rutas de archivos, nombres de contactos, todo.

En qué se diferencia PlainApp

PlainApp aplica múltiples capas de cifrado y autenticación. Esto es lo que hace cada capa, explicado de forma sencilla.

Security Architecture Comparison
1

GraphQL API — Pide solo lo que necesitas

La mayoría de las apps usan REST APIs clásicas: una URL por recurso, devolviendo todo sin importar si lo necesitas o no. PlainApp usa GraphQL, un enfoque moderno en el que el navegador solicita exactamente los datos que necesita, nada más.

Por qué es importante:

  • Menos datos expuestos — Si solo necesitas el nombre de un archivo, eso es lo único que se envía
  • Un solo endpoint — Hay una única URL /graphql en lugar de decenas, lo que reduce la superficie de ataque
  • Permisos por consulta — Cada consulta verifica sus propios permisos (p. ej., leer SMS requiere el permiso READ_SMS incluso después de iniciar sesión)
2

Llamadas a la API cifradas (XChaCha20-Poly1305)

Esta es la mayor diferencia entre PlainApp y la mayoría de sus competidores.

Cada solicitud y respuesta de API — incluyendo tráfico HTTP y WebSocket — se cifra con XChaCha20-Poly1305, tanto en modo HTTP como HTTPS. Es un algoritmo de cifrado AEAD moderno utilizado por WireGuard VPN, Cloudflare y la biblioteca Tink de Google.

En términos sencillos:

  1. 1Tu navegador construye una solicitud (ejemplo: "muéstrame mis SMS")
  2. 2Añade una marca de tiempo y un nonce aleatorio para protección contra repetición
  3. 3Cifra el payload completo en datos binarios ilegibles con XChaCha20-Poly1305
  4. 4El binario cifrado se envía por la red — sin base64, sin JSON, binario puro
  5. 5Solo tu teléfono puede descifrar y validar

Incluso si alguien intercepta el tráfico, solo verá datos binarios sin sentido, no JSON legible.

Encrypted API Flow

Sobre el cifrado:

  • Clave de 256 bits (extremadamente fuerte)
  • Nonce de 192 bits (previene ciertos tipos de ataque que afectan a otros cifrados)
  • Detección de manipulación integrada: si alguien modifica los datos en tránsito, el descifrado falla
  • Lado Android: basado en Google Tink
  • Lado web: basado en @noble/ciphers (una biblioteca criptográfica de JavaScript bien auditada)
3

Firmas digitales (Ed25519) — Dispositivo a dispositivo

Cuando dos dispositivos PlainApp se comunican entre sí (por ejemplo, chat de teléfono a teléfono), el cifrado solo no es suficiente — cada dispositivo necesita verificar que el mensaje realmente proviene del otro dispositivo y no fue falsificado.

marca de tiempo

El dispositivo receptor verifica la firma usando la clave pública del remitente y rechaza solicitudes con marca de tiempo superior a 5 minutos. Esto previene tanto la falsificación como los ataques de repetición.

4

Emparejamiento seguro de dispositivos (intercambio de claves ECDH)

Cuando dos dispositivos con PlainApp se emparejan entre sí (p. ej., dos teléfonos), necesitan una clave de cifrado compartida. Pero enviar una clave por la red anularía todo el propósito.

PlainApp resuelve esto con un intercambio de claves ECDH (Elliptic Curve Diffie-Hellman), la misma matemática utilizada en TLS, el Secure Enclave de Apple y WebAuthn:

  1. 1Cada dispositivo genera un par de claves (pública + privada)
  2. 2Solo intercambian sus claves públicas
  3. 3Cada dispositivo combina su clave privada con la clave pública del otro
  4. 4Ambos obtienen el mismo secreto compartido, sin que este haya cruzado nunca la red
ECDH Pairing Flow
5

URLs cifradas — Ocultando rutas de archivos

Un detalle que la mayoría de la gente no nota: las rutas en las URLs también revelan información.

Cuando descargas un archivo, la URL le indica al servidor qué archivo quieres. En muchas apps, la URL se ve así:

/fs?path=/sdcard/DCIM/Camera/photo_2024.jpg

Cualquiera que analice el tráfico (o revise el historial del navegador) puede ver exactamente a qué archivo accediste y la estructura de carpetas de tu teléfono.

PlainApp cifra la ruta del archivo en la URL:

/fs?id=AxK9f2mQ7vR3xP8nWz...

El parámetro id es la ruta del archivo cifrada con XChaCha20-Poly1305 usando una clave aleatoria llamada URL Token. Por defecto, esta clave es permanente y persiste tras reiniciar la app, de modo que los enlaces compartidos siguen funcionando. Sin la clave, nadie puede adivinar la ruta real, enumerar tus archivos ni construir URLs de descarga.

URL Encryption Comparison
6

HTTPS con certificados autofirmados

PlainApp genera un certificado TLS autofirmado en tu teléfono. Esto crea un túnel HTTPS cifrado, la misma tecnología que usan los bancos y los sitios web.

El certificado utiliza:

  • ECDSA con curva P-256 (igual que los principales sitios web)
  • Firma SHA256
  • Almacenado en el directorio privado de la app

Combinado con el cifrado XChaCha20 a nivel de aplicación, esto proporciona dos capas independientes de cifrado. Romper una no sirve de nada sin romper la otra.

7

Protección de inicio de sesión

PlainApp limita los intentos de inicio de sesión para prevenir la adivinación de contraseñas:

  • 5 intentos por cada 60 segundos por dirección IP
  • Después de eso, las conexiones se rechazan
  • Los registros de límite de intentos caducados se limpian automáticamente

HTTP vs HTTPS: una nota honesta

PlainApp ofrece tanto el modo HTTP como HTTPS. Esta es la diferencia real:

Modo HTTPModo HTTPS
URLs de archivosCifradas (XChaCha20)Cifradas (XChaCha20)
Llamadas a la APICifradas (XChaCha20)Cifradas (XChaCha20 + TLS)
Descargas de archivosSin cifrar en tránsitoCifradas con TLS
¿Para quién es?Principiantes (sin aviso SSL del navegador)Usuarios preocupados por la privacidad

Ambos modos cifran las llamadas a la API con XChaCha20-Poly1305: tus SMS, contactos y demás datos siempre están cifrados, independientemente de si usas HTTP o HTTPS.

El modo HTTP existe porque los certificados autofirmados generan un aviso en el navegador ("Tu conexión no es privada"). Para usuarios menos técnicos, este aviso resulta confuso e intimidante. El modo HTTP evita esta fricción.

Sin embargo, el modo HTTP no cifra las transferencias de archivos. Si estás en una red compartida o pública, usa siempre HTTPS.

Recomendación: usa HTTPS siempre que sea posible. Acepta el aviso del navegador sobre el certificado autofirmado; es normal y esperado para una app de red local.

8

Seguridad de la cadena de suministro — Menos dependencias, menos riesgo

Una amenaza de seguridad en la que muchos usuarios no piensan: los ataques a la cadena de suministro. Cuando una app usa cientos de bibliotecas de terceros, cualquiera de ellas podría verse comprometida, inyectando código malicioso que roba datos, mina criptomonedas o abre puertas traseras.

Esto es especialmente peligroso en el ecosistema de JavaScript. En los últimos años, paquetes populares de npm como event-stream, ua-parser-js y colors fueron secuestrados para inyectar código malicioso en millones de proyectos. Si la interfaz web de una app de gestión de teléfonos incluye cientos de paquetes JS, cada uno es un vector de ataque potencial.

PlainApp adopta un enfoque deliberado: usar la menor cantidad de dependencias posible y escribir código propio cuando tiene sentido.

App Android (plain-app)

  • Sin framework de inyección de dependencias (ni Hilt, ni Dagger): usa singletons simples
  • La criptografía se gestiona con solo 3 bibliotecas reconocidas: Google Tink, Bouncy Castle y la Java Cryptography Extension integrada
  • El servidor funciona con Ktor (framework oficial de Kotlin de JetBrains): sin bibliotecas de servidor de terceros desconocidas

Interfaz web (plain-desktop)

Solo 28 dependencias en tiempo de ejecución, muchas menos que las apps web típicas. Varias funcionalidades que normalmente requerirían paquetes de npm están desarrolladas desde cero:

FuncionalidadApp típicaPlainApp
Sonidos de notificaciónhowler.js / tone.jsSintetizador propio con Web Audio API
Generación de UUIDpaquete uuid de npmImplementación propia de RFC 4122
Subida de archivosuppy / axiosSubida chunked personalizada con cola
Vídeo WebRTCTwilio / Daily.co SDKCódigo PeerConnection escrito a mano
Cliente HTTPaxios / kyfetch nativo del navegador

La criptografía en el lado web usa @noble/ciphers, una biblioteca criptográfica de JavaScript bien auditada y sin dependencias, en lugar de alternativas pesadas e infladas.

Por qué es importante

Cada dependencia que añades es código que no controlas. El enfoque de PlainApp significa:

  • Menos lugares donde puede esconderse código malicioso
  • Menor superficie de ataque
  • Más fácil de auditar (todo el código fuente es abierto)
  • Sin riesgo por paquetes de npm abandonados o secuestrados

Lo que muchos competidores hacen mal

No se trata de señalar apps específicas, sino de patrones comunes en esta categoría:

Aspecto de seguridadPlainAppComún en competidores
Tráfico de la APICifrado (XChaCha20) tanto en HTTP como en HTTPSJSON en texto plano por HTTP
Tráfico WebSocketTramas binarias cifradas (XChaCha20)JSON en texto plano o sin WebSocket
Manejo de token de authUsado como clave de cifrado, nunca en cabecerasEnviado en cabeceras HTTP (fácil de filtrar)
URLs de archivosIDs de ruta cifradosRutas en texto plano expuestas
Intercambio de clavesECDH (P-256)Ninguno
Firma de solicitudesEd25519 (solo dispositivo a dispositivo)Ninguna
Protección contra repetición30 s + nonce (Web); 5 min + firma (dispositivo)Ninguna
Protección de inicio de sesiónLímite de intentos + confirmación de dos factoresIntentos ilimitados
Enrutamiento de datos100 % local, sin nubeAlgunos enrutan a través de la nube
DependenciasMínimas, bibliotecas reconocidasCientos de paquetes de npm
Código fuenteCódigo abierto (GPL-3.0)Mayoritariamente cerrado

La forma más fácil de comprobar cualquier app: abre Chrome DevTools (F12) → pestaña Network mientras usas la app. Si puedes leer las respuestas de la API como JSON, la app no tiene cifrado.

Verifícalo tú mismo

PlainApp es completamente de código abierto. Cada afirmación de este artículo puede verificarse en el código.

github.com/plainhub/plain-app (GPL-3.0)
Integridad de versión verificable

Pipeline de publicación automatizado, trazable y resistente a manipulaciones

Todos los paquetes de instalación se compilan automáticamente en la infraestructura de GitHub y F-Droid. Las compilaciones son trazables, seguras y sin intervención manual. PlainApp es una de las pocas apps Android con compilaciones verificables (SLSA) y versiones escaneadas con VirusTotal.

Compilaciones automáticas en GitHub y F-Droid

Los artefactos de lanzamiento se generan en pipelines de CI en lugar de empaquetado manual local. Cada artefacto puede rastrearse hasta commits de código y flujos reproducibles.

SLSA Provenance (Nivel 3) + análisis de VirusTotal

Cada versión incluye atestaciones de procedencia SLSA y resultados de VirusTotal, lo que hace auditable la cadena de suministro y ayuda a verificar la integridad antes de instalar.

Preguntas frecuentes

¿PlainApp realmente cifra los datos en modo HTTP?

Sí. Todas las llamadas a la API (SMS, contactos, lista de archivos, etc.) se cifran con XChaCha20-Poly1305 tanto en modo HTTP como HTTPS. El modo HTTP solo deja sin cifrar las descargas de archivos. Para una protección completa, usa HTTPS.

¿Por qué mi navegador muestra un aviso de seguridad?

PlainApp usa un certificado TLS autofirmado para el cifrado. Como no está emitido por una Autoridad de Certificación pública, tu navegador muestra un aviso. Es algo normal y esperado para una app de red local. Haz clic en "Avanzado" y "Continuar" para seguir.

¿Puede alguien en la misma red Wi-Fi ver mis datos?

Con PlainApp, no. Las llamadas a la API se cifran con XChaCha20-Poly1305, y en modo HTTPS las transferencias de archivos también se cifran con TLS. Con la mayoría de las apps competidoras, sí: sus llamadas a la API se envían como JSON en texto plano.

¿Cómo se compara PlainApp con una VPN?

Una VPN cifra el tráfico entre tu dispositivo y el servidor VPN. PlainApp cifra el tráfico entre tu teléfono y el navegador en la red local. Tienen propósitos diferentes: PlainApp protege la gestión local del dispositivo, mientras que una VPN protege el tráfico de internet.

¿El código es realmente de código abierto?

Sí. PlainApp tiene licencia GPL-3.0. El código fuente completo está disponible en github.com/plainhub/plain-app. Puedes inspeccionar cada implementación criptográfica, compilar desde el código fuente o contribuir.

Recupera el control de tu teléfono.

Sin intermediarios en la nube. Sin cuotas mensuales. Sólo tu teléfono y tu navegador.