Seguridad
Cómo funciona la bóveda
Sin vaguedades: aquí están las construcciones reales, los parámetros y por qué se eligió cada uno.
Contra qué nos defendemos
Tres situaciones dan forma a cada decisión de abajo. Un servidor de sincronización que guarda tus datos y nunca debería poder leerlos. Un portátil robado, con el archivo de base de datos en manos de otra persona. Y un atacante con ese archivo sin conexión, probando conjeturas tan rápido como se lo permita el hardware.
La tercera es la que decide la derivación de clave, porque es la única en la que el ritmo lo marca el presupuesto del atacante y no tu contraseña.
Un segundo factor, y para qué sirve
La verificación en dos pasos protege la cuenta, no la bóveda, y la diferencia importa más de lo que parece. Una contraseña robada o adivinada deja de bastar para registrar un dispositivo nuevo y descargar tus claves selladas: el paquete cifrado y, porque esa misma contraseña deriva la clave que lo abre, todo lo que hay dentro. Ese es el ataque que un código detiene de verdad.
Sigue bastando para abrir una bóveda en una máquina que alguien ya tiene. La bóveda está cifrada aquí, en tu propio disco, sin ningún servidor de por medio al que preguntarle nada: ahí no hay nada que un código pueda custodiar. La verificación en dos pasos tampoco cierra la sesión de los dispositivos que ya la tienen abierta, ni hace recuperable una contraseña olvidada.
Al activarla se te muestran diez códigos de recuperación, una sola vez. Esos, y cualquier máquina con la sesión abierta —que puede desactivar el factor con tu contraseña—, son las dos maneras de volver si pierdes el autenticador. No hay una tercera: aquí nadie puede dejarte pasar por encima de un factor, porque de nuestro lado no hay nada que pudiera hacerlo.
Argon2id, no un hash rápido
Tu contraseña maestra se estira hasta una clave de 32-byte con Argon2id a 64 MiB de memoria y tres pasadas: el `crypto_pwhash` de libsodium, que ejecuta Argon2id en un solo carril. La memoria es el punto: una GPU puede ejecutar cantidades enormes de operaciones de hash en paralelo, pero no puede dar a cada una 64 MiB de memoria rápida. Eso convierte un ataque paralelo amplio otra vez en uno estrecho.
Para comparar, una derivación PBKDF2-SHA256 con mil iteraciones —todavía un valor por defecto común— le cuesta al atacante menos de un milisegundo por conjetura y paraleliza casi a la perfección. Argon2id con estos parámetros tarda unos 130 ms en un portátil y resiste exactamente ese paralelismo.
Los parámetros quedan registrados junto a la bóveda, así que subirlos más adelante afecta a las derivaciones nuevas mientras las bóvedas existentes siguen abriéndose.
Cada registro sellado por separado
Cada bóveda tiene su propia clave aleatoria de 32-byte, envuelta bajo la clave maestra. Los registros se cifran con XChaCha20-Poly1305 usando un nonce nuevo de 24-byte, y la identidad del propio registro —su tipo, su bóveda y su id— se ata como associated data.
Esto último importa más de lo que parece. Sin ello, cualquiera que tuviera el texto cifrado podría mover un bloque cifrado válido a otro registro y el cliente lo aceptaría. Con ello, un registro reetiquetado simplemente no se abre.
Claves de host, fijadas
La primera vez que Termiyo ve un servidor te muestra la clave y su huella SHA-256, y fija la que aceptes. Cada reconexión se comprueba contra esa fijación.
Cuando una clave cambia, Termiyo lo dice claramente en lugar de enterrarlo: un servidor reconstruido y una conexión interceptada son idénticos para el software, y solo tú sabes cuál esperabas.
Dónde viven realmente los secretos
Las conexiones corren en un proceso separado de la interfaz. La ventana que dibuja tu terminal no tiene acceso a la red, ni al sistema de archivos, y nunca recibe una contraseña ni una clave privada: pide conectarse a un host guardado por su nombre, y otro proceso decide qué significa eso.
Todo lo que se muestra en la interfaz va censurado antes. Guardar un registro con un campo enmascarado deja intacto el secreto almacenado.
Verificar lo que has descargado
Dos comprobaciones distintas, y responden a preguntas distintas. El SHA-256 que aparece junto a cada descarga en la página de descargas te dice que los bytes que tienes son los bytes que compilamos: `shasum -a 256 <file>` en macOS y Linux, `certutil -hashfile <file> SHA256` en Windows.
La firma te dice quién los compiló, y tu sistema operativo la comprueba por ti antes de ejecutar la aplicación. Puedes comprobarla tú primero. En macOS: `spctl -a -t open --context context:primary-signature -vv <file>.dmg` debería responder "accepted" con "source=Notarized Developer ID".
El instalador de Windows no está firmado, por lo que no hay pestaña Firmas digitales en Propiedades. La ausencia de esa pestaña no permite saber si el archivo fue modificado. Guarda el instalador sin ejecutarlo y después ejecuta `certutil -hashfile "<file>" SHA256`, sustituyendo `<file>` por la ruta del archivo guardado. Compara el resultado con el SHA-256 que aparece junto a esa misma descarga en la página de descargas antes de abrir el instalador. Si no coinciden, no lo ejecutes. Un hash coincidente confirma que los bytes corresponden a nuestro archivo publicado; no es una firma del editor. A diferencia del caso de Linux de abajo, esto es una carencia nuestra y no una propiedad de la plataforma: Windows comprueba firmas sin problema, lo que falta es que le demos una que comprobar. Esta página lo seguirá diciendo hasta que el instalador que descargas lleve una firma que puedas comprobar tú.
En Linux no hay equivalente: un .deb o un AppImage no llevan una firma que tu sistema compruebe, así que el hash es todo lo que puedes verificar. Es una propiedad de la plataforma y no una elección nuestra, y conviene saberlo en lugar de suponer lo contrario.
Qué sale de tu máquina
Dos cosas, y las dos están enumeradas. Termiyo envía un informe breve sobre sí mismo como máximo una vez cada 24 horas — versión, plataforma, procesador, cómo se instaló, idioma de la interfaz, si la búsqueda de actualizaciones está activada y un recuento de los volcados de fallo que hay en su propia carpeta — sin identificador alguno y sin nada de tus sesiones dentro; está activado por defecto y se desactiva con un clic, en el primer arranque o en Configuración → Ayuda. Un fallo escribe un volcado en una carpeta de tu propio disco, y enviarnos uno de esos es un interruptor aparte que sigue desactivado hasta que lo actives; Configuración → Ayuda la indica, dice qué puede contener un volcado, y la abre.
Enviarnos uno es un interruptor de esa pantalla. Está desactivado en una instalación nueva, desactivado después de actualizar, y mientras lo esté ningún volcado sale de la máquina: adjuntarlo a mano a un informe de error sigue siendo la única forma de que viaje. Actívalo: si «Buscar actualizaciones cuando Termiyo inicia» está activado, el siguiente fallo subirá su volcado por HTTPS, junto con el nombre que tu propia máquina le dio a ese archivo, la versión, la plataforma, la arquitectura del procesador y un identificador de esa instalación creado en esa primera subida, y nada más; la misma pantalla enumera lo enviado y tiene un botón que pide a nuestro servidor borrarlo. Este párrafo decía antes que los informes de fallos estaban ausentes y no solo desactivados, lo cual era cierto de todas las versiones anteriores a la que añadió la dirección. La página de privacidad tiene el detalle. Con la comprobación de actualizaciones apagada, un volcado que aceptaste enviar espera en esta máquina y sale en el primer arranque después de volver a encenderla.
Con la comprobación de actualizaciones desactivada, el actualizador nunca se carga: la biblioteca se importa en el primer uso, así que con la comprobación apagada el módulo nunca está ahí y no tiene con qué hacer una petición. Eso sí es estructural, y no una promesa sobre una rama.
Lo que aquí teníamos mal, y estamos corrigiendo: esto decía que con la comprobación apagada un arranque no hace ninguna petición saliente, y ofrecía tcpdump como la forma de comprobarlo. Un arranque que nadie toca ya es silencioso con la comprobación apagada — medido en la red, en Linux —, pero al abrir la bóveda empieza un tráfico que no tiene nada que ver con el ajuste de actualizaciones, y esta página solo nombraba una parte. Lo primero son las terminales que dejaste abiertas: las pestañas SSH que seguían abiertas cuando Termiyo se cerró por última vez se vuelven a abrir en cuanto se abre la bóveda, cada una con un inicio de sesión completo en su host — es lo que deja tu trabajo donde lo dejaste, y una pestaña que cierras antes de salir no vuelve sola. Sin la sesión iniciada, hasta que respondas a la oferta de una cuenta, la pantalla de primer arranque pregunta si termiyo.com responde, para saber si vale la pena ofrecerte una cuenta — una vez por arranque, en el primer desbloqueo; mientras no se puede llegar a termiyo.com la oferta no se muestra, así que el siguiente arranque vuelve a preguntar. Con la sesión iniciada, Termiyo pregunta si tu dirección ha sido confirmada — una vez por arranque, y una vez más mientras no lo esté, porque el panel que entonces te pide el código vuelve a leer la respuesta —, sincroniza cuando se abre la bóveda y luego cada cinco minutos, pregunta en cuál de tus bóvedas puede guardarse un host, un grupo o un proxy cuando abres su formulario, y, si no tienes una clave de IA propia, pregunta cuánto queda de la asignación de IA de tu cuenta cuando abres el panel de IA o empiezas a escribir en una terminal. Mientras la lista de hosts está abierta, cada host SSH o telnet guardado al que Termiyo puede llegar directamente se comprueba cada 15 segundos — una conexión a su puerto que se cierra sin enviar un solo byte — para que el punto a su lado esté al día; esas conexiones van a tus servidores, no a nosotros, y aparecen en sus registros. Un host guardado por nombre y no por dirección cuesta además una consulta DNS cada vez, y esa va al resolvedor que use tu máquina. Ocultar la lista de hosts detiene esas comprobaciones, pero no otra del mismo tipo: mientras la pestaña al frente sea una terminal conectada a uno de esos hosts, la barra de estado comprueba ese host cada 10 segundos para la latencia que muestra, con lista o sin ella, mientras la barra diga «Conectado», y, para un host guardado por nombre, además pregunta por él a tu resolvedor cada vez. Y lo que configuras hace aquello para lo que lo configuraste: una copia de seguridad programada se copia a la réplica que le indicaste, los webhooks llaman a sus direcciones, y las tareas programadas y los reenvíos se conectan a sus hosts — una tarea programada una vez por ejecución, y cierra la sesión cuando termina su snippet. Así que la afirmación era falsa justo en la única forma que dijimos que valía la pena hacer, la comprobable.
Una terminal que compartes es un segundo lugar donde existe la sesión, y ese segundo lugar es una pestaña de navegador. Los bytes van de tu máquina a la de la otra persona y no pasan por nada más: ningún relé los transporta, y es una elección — un servidor TURN vería el tráfico, así que Termiyo no usa ninguno, y nuestro propio servidor solo presenta a las dos partes. Lo que sí usamos es STUN público, el de Google y el de Cloudflare, para preguntar cómo se ve tu dirección desde fuera; esos dos conocen esa dirección, y nada más. Al navegador del invitado no se le entrega ningún servidor STUN. Y luego el coste: un invitado mira desde un navegador, así que las extensiones pueden leer esa página y el navegador puede guardar una imagen de ella para la vista previa de la pestaña. Un invitado entra en solo lectura y no puede escribir hasta que tú lo autorices, y la sesión compartida termina cuando tú la detienes, o a las cuatro horas. Lo que no es: la misma protección que da la propia aplicación, y la página del invitado lo dice en la pantalla del propio invitado, no solo aquí.
Lo que no podemos afirmar: el archivo SQLite en sí no está cifrado, solo los registros que contiene. Quien tenga el archivo sabrá cuántos servidores tienes, cuándo tocaste cada uno por última vez y las etiquetas que les pusiste. Sus direcciones, usuarios, contraseñas y claves están cifradas. Preferimos decirlo aquí antes de que lo descubras.
¿Has encontrado algo?
Los informes de seguridad van a info@termiyo.com. Confirmaremos la recepción en dos días laborables.