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.
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)
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:
- 1Tu navegador construye una solicitud (ejemplo: "muéstrame mis SMS")
- 2Añade una marca de tiempo y un nonce aleatorio para protección contra repetición
- 3Cifra el payload completo en datos binarios ilegibles con XChaCha20-Poly1305
- 4El binario cifrado se envía por la red — sin base64, sin JSON, binario puro
- 5Solo tu teléfono puede descifrar y validar
Incluso si alguien intercepta el tráfico, solo verá datos binarios sin sentido, no JSON legible.
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)
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.
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:
- 1Cada dispositivo genera un par de claves (pública + privada)
- 2Solo intercambian sus claves públicas
- 3Cada dispositivo combina su clave privada con la clave pública del otro
- 4Ambos obtienen el mismo secreto compartido, sin que este haya cruzado nunca la red
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.jpgCualquiera 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.
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.
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 HTTP | Modo HTTPS | |
|---|---|---|
| URLs de archivos | Cifradas (XChaCha20) | Cifradas (XChaCha20) |
| Llamadas a la API | Cifradas (XChaCha20) | Cifradas (XChaCha20 + TLS) |
| Descargas de archivos | Sin cifrar en tránsito | Cifradas 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.
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:
| Funcionalidad | App típica | PlainApp |
|---|---|---|
| Sonidos de notificación | howler.js / tone.js | Sintetizador propio con Web Audio API |
| Generación de UUID | paquete uuid de npm | Implementación propia de RFC 4122 |
| Subida de archivos | uppy / axios | Subida chunked personalizada con cola |
| Vídeo WebRTC | Twilio / Daily.co SDK | Código PeerConnection escrito a mano |
| Cliente HTTP | axios / ky | fetch 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 seguridad | PlainApp | Común en competidores |
|---|---|---|
| Tráfico de la API | Cifrado (XChaCha20) tanto en HTTP como en HTTPS | JSON en texto plano por HTTP |
| Tráfico WebSocket | Tramas binarias cifradas (XChaCha20) | JSON en texto plano o sin WebSocket |
| Manejo de token de auth | Usado como clave de cifrado, nunca en cabeceras | Enviado en cabeceras HTTP (fácil de filtrar) |
| URLs de archivos | IDs de ruta cifrados | Rutas en texto plano expuestas |
| Intercambio de claves | ECDH (P-256) | Ninguno |
| Firma de solicitudes | Ed25519 (solo dispositivo a dispositivo) | Ninguna |
| Protección contra repetición | 30 s + nonce (Web); 5 min + firma (dispositivo) | Ninguna |
| Protección de inicio de sesión | Límite de intentos + confirmación de dos factores | Intentos ilimitados |
| Enrutamiento de datos | 100 % local, sin nube | Algunos enrutan a través de la nube |
| Dependencias | Mínimas, bibliotecas reconocidas | Cientos de paquetes de npm |
| Código fuente | Có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)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.