Resumen

Filez es mi alternativa a WeTransfer: una herramienta de envío de archivos que cifro en tu propio navegador, así que el servidor solo mueve y guarda bytes que no sabe leer. Nació el 27 de septiembre de 2026 para sustituir a un clon comercial que llevaba meses caído, y desde entonces ha ido creciendo: envíos por enlace, un plan gratuito sin cuenta, pools compartidos y una capa de integridad que deja comprobar, desde fuera, que el código que sirvo no se ha tocado. La vive en filez.lilpandemio.com.


El problema

Quería quitarme de encima un WeTransfer-clone comercial que tenía en producción: roto, sin mantenimiento y sin ningún control sobre lo que hacía con los archivos de quien lo usaba. La alternativa no era «buscar otro servicio de terceros», sino escribir el mío: si voy a mover archivos ajenos, prefiero que ni yo mismo pueda leerlos.

La premisa de partida (zero-knowledge) obliga a tomar decisiones que un WeTransfer normal no tiene que tomar: si el servidor no ve el contenido, tampoco puede generar una miniatura, escanear virus, ni —esto es importante— ayudarte a recuperar una contraseña olvidada.

Qué construí y por qué

Cifrado en el cliente, de verdad

Todo el cifrado ocurre en el navegador. La contraseña pasa por Argon2id en un Web Worker aparte y de ahí sale, por HKDF, tanto el verificador que ve el servidor (que lo vuelve a hashear) como la clave que envuelve tu clave privada. Esa privada solo vive en memoria: si recargas la página, te la vuelve a pedir. Cada archivo se cifra en segmentos AES-256-GCM de 8 MiB, con el nombre y el tipo de fichero también sellados. El servidor recibe ciphertext y nada más.

Sin recuperación de contraseña, por diseño

Esta es la decisión que más rara le suena a quien viene de un servicio normal. Si perdieras la contraseña, no hay «restablecer por email»: la clave que protege tus archivos deriva de esa contraseña, y yo no tengo ninguna copia en claro que pueda enviarte. Poner un «recuperar contraseña» habría significado, en la práctica, tener una puerta trasera. Lo cambié por lo contrario: ni yo puedo entrar en tu cuenta aunque quisiera.

Envíos por enlace, al estilo WeTransfer

Arrastras un archivo, se cifra, se sube, y sale un enlace con la clave metida en el fragmento de la URL (la parte después del #), que el servidor nunca llega a ver. Ese enlace abre solo esos archivos, nunca el resto de tu cuenta. Caduca solo (7 días por defecto), admite contraseña y límite de descargas, y al caducar o borrarse se lleva los archivos por delante.

Plan gratuito sin cuenta

Para quien solo quiere mandar un archivo sin registrarse: 5 GB por archivo, 5 archivos al día por IP, caduca a los 3 días, con un tope global para no dejar el disco sin espacio. El navegador genera un par de claves efímero que borra en cuanto crea el enlace, así que el resultado es el mismo cifrado de extremo a extremo que en una cuenta normal. El riesgo que asumo aquí es honesto: al ser zero-knowledge, no puedo revisar qué sube alguien anónimo. Lo compenso con límites de volumen y tiempo, y con una vía para retirar un envío si alguien lo denuncia.

Pools, para grupos

Además del envío 1 a 1, hay pools compartidos: un grupo entra por enlace, sin cuenta, cada uno sube y organiza en carpetas, y cada persona solo puede borrar lo suyo. Es el mismo cifrado de extremo a extremo, pero pensado para «cinco personas de viaje compartiendo fotos» en vez de «te mando un PDF».

SRI + manifiesto firmado: verificar que el código no se ha tocado

Me hice una pregunta incómoda: si alguien comprometiera mi servidor, ¿podría comprobarse desde fuera que el código servido sigue siendo el legítimo? La respuesta honesta es que desde la propia página, no —quien controla el servidor controla también la comprobación. Hace falta un ancla fuera de mi infraestructura.

Apliqué lo que sí es barato y efectivo: Subresource Integrity (SRI) en todo lo que se ejecuta o se lee en el navegador (scripts, hojas de estilo, incluso el worker que procesa tu contraseña, cargado desde un blob: verificado), y un manifiesto firmado, /integrity.txt, con el hash de cada fichero servido y de la política de seguridad de contenido. La clave privada que firma ese manifiesto no está en ningún servidor: vive aparte, en mi gestor de secretos. La pública está en el propio DNS, así que cualquiera puede verificarla sin fiarse de mí. Y para quien no quiera hacerlo a mano, dejé /verify.txt: un script que cualquiera puede ejecutar y que comprueba la firma, la política de seguridad y cada fichero servido.

Esto lo hace detectable, no imposible: un servidor comprometido podría, en teoría, servir una versión distinta solo a una persona concreta. Cerrar del todo esa puerta exigiría un ancla en el propio navegador (una extensión que verifique contra el manifiesto) o empaquetar el cliente como aplicación. Queda en el tintero.

Diagrama animado de Filez, paso 4 de 7: lo que viaja y lo que guarda el servidor son solo bytes cifrados

Páginas legales, con retenciones reales

Como herramienta gratuita hecha por una sola persona, quise dejar claro qué pasa con los datos: condiciones de uso sin garantías, una vía para denunciar abuso, y una página de privacidad que dice exactamente cuánto tiempo se guardan los registros (con IP) del servicio, y durante cuánto tiempo hay copias de seguridad. Nada de «hasta 6 años» por defecto de la plataforma de monitorización: fijé una retención concreta y cuidé que la documentación técnica coincidiera con lo que promete la página pública. Si cambia algo de eso, tengo que tocar los dos sitios a la vez.

Pruebas sin tocar producción

Un servicio donde ni yo puedo recuperar una cuenta no admite pruebas «a ver qué pasa». Filez tiene un entorno de desarrollo separado, con su propia base de datos, donde los tests crean y vacían datos libremente sin riesgo para nadie real; y cualquier paso destructivo (vaciar tablas, borrar datos) lleva una comprobación que corta el comando en seco si apunta a producción, en vez de limitarse a avisar. Todo cambio pasa primero por ese entorno antes de llegar al servicio real.

Resultado

Filez lleva en producción desde finales de septiembre de 2026, con dos dominios activos (el propio de LiLPandemio y el original), cifrado de extremo a extremo verificado con pruebas automáticas de integración y de navegador real en cada despliegue, y ha pasado por varias rondas de revisión de seguridad enfocadas a parchear (nunca a explotar) antes de tocar producción. El plan gratuito y los pools compartidos siguen en uso activo.

Lecciones y siguientes pasos

Zero-knowledge de verdad significa aceptar límites que un servicio convencional no tiene: sin recuperación de contraseña, sin poder moderar contenido antes de que se comparta. No son fallos, son la otra cara de la misma promesa. El principio de proceso —nunca mezclar pruebas con producción— lo aplico a todo lo que despliego, no solo a este proyecto. Como siguiente paso queda explorar un ancla de verificación dentro del propio navegador (extensión o cliente empaquetado) para cerrar del todo el hueco que deja el manifiesto firmado.

Stack

  • PHP 8.2 sin framework, MariaDB con permisos por tabla (auditoría de solo lectura/escritura, nunca borrado)
  • JavaScript vanilla en el navegador: libsodium, Argon2id vía Web Worker, AES-256-GCM
  • nginx + PHP-FPM, con reglas propias de WAF acotadas a los endpoints que las necesitan
  • SRI y manifiesto firmado (Ed25519) con clave pública distribuida por DNS
  • Entorno de desarrollo aislado con su propia base de datos, para tests de integración y de navegador real