Tus paquetes no son asunto de nadie más que tuyo.
Wi-Fi es un medio compartido. Cafeterías, hoteles, residencias, LAN parties. Cualquiera en la misma red puede ver tu tráfico. Dish se construyó pensando en eso.
Modelo de amenazas
Dish está hecho para mantenerse seguro en redes en las que no confías del todo:
- Un compañero de piso o vecino en la misma Wi-Fi no debería poder inyectar entradas de mando en tu juego.
- Alguien ejecutando
tcpdumpen el router no debería ver a qué juegas ni cómo juegas. - Un paquete capturado no debería poder reproducirse una hora después.
- El emparejamiento debería fallar cerrado. Nunca un retroceso silencioso a texto plano.
- La superficie de configuración no debería ser alcanzable desde la LAN. Solo la ruta cifrada del mando.
Emparejamiento
La primera vez que conectas Dish con Satellite, Satellite lanza un PIN de 4 dígitos en tu PC gaming. El PIN vive durante cinco minutos y luego expira. Lo escribes en Dish en tu teléfono, portátil u otro dispositivo cliente.
El emparejamiento ocurre sobre HTTPS en el puerto 9443, en un certificado autofirmado que Satellite genera localmente. El transporte protege contra escuchas pasivas; el PIN protege contra quien intente engañar a Satellite para que confíe en él. El cliente envía una clave pública X25519 de 32 bytes, Satellite calcula el secreto compartido con crypto_scalarmult, y a partir de ahí ambos extremos sostienen una clave simétrica de 256 bits derivada sin haberse enviado nunca por el cable. El propio PIN se destruye en cuanto termina el emparejamiento.
La clave compartida se guarda localmente en ambos extremos y se usa para autenticar cada reconexión posterior. En el lado de Satellite vive en el directorio de configuración por usuario de tu plataforma, protegido por modo a tu cuenta (Windows DPAPI en V1); en el lado del cliente Android vive en las SharedPreferences privadas de la app, aisladas por Android a la app Dish y excluidas de la copia de seguridad en la nube y la transferencia de dispositivo. Ninguna clave sale jamás de ninguno de los dos dispositivos.
AEAD por paquete
Cada paquete del mando (entrada del mando, latido, alta de mando, vibración, movimiento, batería, touchpad, lightbar) se sella con ChaCha20-Poly1305 (IETF), el mismo AEAD que TLS 1.3, WireGuard y SSH usan. ChaCha20 es rápido y de tiempo constante en cada CPU que nos importa, incluidos el ARMv8 de Android y Apple Silicon.
El formato del cable es pequeño y rígido: token de sesión de 4 bytes, contador de 4 bytes, ciphertext, etiqueta de autenticación Poly1305 de 16 bytes. El token funciona también como dato autenticado adicional (AAD), así que cambiarlo en un paquete reproducido hace que la verificación falle. El nonce es el contador con zero-padding hasta 12 bytes: sin reutilización de nonce posible sin rotar la sesión.
Protección contra repetición
Satellite guarda el contador más alto que ha aceptado en cada conexión. Cualquier paquete cuyo contador sea menor o igual a esa marca de agua alta se descarta antes de llegar al backend del mando. El ciphertext capturado de la sesión de ayer (o incluso de hace un segundo) no se puede reproducir para activar una pulsación.
De qué no tienes que preocuparte
- Escuchas. Nadie en la LAN sabe qué botones pulsaste.
- Suplantación. Sin la clave de sesión, ningún atacante puede inyectar una pulsación del "botón B", aunque conozca tu IP.
- Repetición. El paquete de "disparo" de ayer no disparará hoy. Tampoco el latido de ayer ni el paquete de emparejamiento.
- Downgrade. Sin retroceso a texto plano. Si la verificación criptográfica falla, el paquete muere en silencio.
- Manipulación de configuración remota. La API admin (
localhost:9877) se vincula solo a127.0.0.1. La API HTTPS cara a la LAN en 9443 solo expone los endpoints de emparejamiento y sesión, todos protegidos por un ID de dispositivo emparejado.
Cero analíticas, cero anuncios
Dish y Satellite no recopilan datos de uso, identificadores, analíticas ni IDs publicitarios. El único flujo saliente que toca TinkerNorth en Dish para Android es Firebase Crashlytics opt-out para informes de crash y ANR: stack trace, modelo de dispositivo, UUID de instalación, y eso es todo. Nunca entradas de mando, nunca IPs de Satellite, nunca SSIDs de Wi-Fi. Hay un opt-out de un toque en los Ajustes de la app bajo Diagnósticos, respetado antes de que cualquier crash se pueda subir en el siguiente arranque. Satellite en sí no incluye ningún SDK de informe de crash. El alcance completo está en la política de privacidad de Dish para Android.
No operamos un sistema de cuentas. No hay nube. Nada que filtrar porque no hay nada en un servidor que pueda filtrarse.
Cadena de suministro auditable
Cada release etiquetado se envía con:
- Un fichero de checksum SHA-256 por cada artefacto, firmado keyless vía
cosigny la identidad OIDC del workflow de release de GitHub Actions. - Una atestación de procedencia SLSA Level 3 que demuestra que el artefacto se construyó desde el commit etiquetado en CI.
- Un software bill of materials en formatos SPDX y CycloneDX para que puedas auditar cada dependencia transitiva.
La receta verify-blob vive en SECURITY.md en el repo de Satellite. Si una descarga no coincide con el checksum publicado, no la instales.
Código abierto y auditable
Cada línea de código que toca criptografía vive en un repo público. Satellite usa libsodium; Dish para Android usa libsodium-stable compilado vía NDK y el Conscrypt estándar de Android para el transporte HTTPS de emparejamiento. Sin criptografía casera. Sin "escribimos nuestro propio ChaCha".
Distribuido bajo la GNU Lesser General Public License v3.0 or later. ¿Encontraste algo raro? SECURITY.md en el repo de Satellite tiene nuestra política de divulgación.