Busca «cifrar archivo en el navegador» o «cifrado del lado del cliente online» y casi todas las fichas dicen lo mismo: el cálculo se queda aquí, el archivo no se sube, la clave no sale del dispositivo. Esas frases tranquilizan. No demuestran nada. Una página puede imprimirlas y, a la vez, un script hace fetch de la contraseña del formulario, de un trozo del archivo o de la clave que está en la barra de direcciones. Lo que hay que verificar no es el copy. Es si esta acción concreta sacó texto plano del navegador.
Este artículo no elige un producto ni recorre una ficha de herramienta. La pregunta es más estrecha: cuando un sitio afirma que cifra en el navegador, ¿qué puedes ver ahora mismo en las herramientas para desarrolladores y en la barra de direcciones? El cifrado de archivos y los enlaces de un solo uso de MyPassGen usan AES-256-GCM a través de la Web Crypto API, y todas las herramientas se abren sin cuenta. La misma comprobación vale para ellas. No hace falta creer «no almacenamos esto» de oídas.
El eslogan no se comprueba. El tráfico, sí
«Cifrado del lado del cliente» está gastado. Un sitio hace POST del archivo a su servidor, lo envuelve allí en AES y te devuelve un enlace de descarga —y aun así lo llama «cifrado online». Otro llama a crypto.subtle.encrypt en la pestaña, escribe un .lock o .enc y no manda ninguna subida de negocio. Las páginas de marketing pueden usar la misma frase para los dos. La pestaña Red, no.
El navegador no audita el eslogan. Lista la petición del documento, los scripts, las imágenes y las llamadas XHR / Fetch que produjo este clic. Puedes ver si la URL de la petición lleva texto plano, si el cuerpo lleva una contraseña y si un url de analytics incluye la clave que va detrás de #. Si esas cadenas no están, «por defecto no sale de esta máquina» sigue en pie. Si están, el eslogan ya murió.
No hace falta leer el código fuente. Basta una pasada repetible: abre el panel, haz una acción concreta (generar una contraseña, probar una clave desechable, cifrar un archivo pequeño o crear un enlace de un solo uso) y abre cada petición nueva. Primero distingue qué nombra «local». Luego separa el fragmento de la consulta. Después sigue los pasos.
Qué nombra de verdad «local»
La Web Crypto API es la superficie criptográfica del navegador. crypto.subtle resume, deriva, cifra y descifra. Los casos de uso del W3C incluyen un diseño lícito en el que el usuario elige una clave en el navegador, cifra un documento y después sube los bytes cifrados a un proveedor. La API garantiza que la cuenta puede hacerse en este dispositivo. No prohíbe enviar texto cifrado después, y no impide que alguien suba primero y cifre después.
Web Crypto también exige un contexto seguro: HTTPS en producción (localhost es la excepción habitual). Eso es un requisito previo, no un argumento de venta. Si una página en HTTP plano afirma que «usa Web Crypto», mira el candado de la barra de direcciones antes de discutir algoritmos.
Qué significa AES-256-GCM en este dispositivo
La primera versión de MyPassGen usa solo AES-256-GCM. Según MDN AesGcmParams y NIST SP 800-38D, que cita, GCM es cifrado autenticado: si el texto cifrado se altera, el descifrado falla. No obtienes un cuerpo ilegible que parezca un documento. El IV recomendado es de 96 bits —12 bytes— y hay que usar un IV nuevo en cada cifrado con la misma clave. El IV no es un secreto; puede viajar con el texto cifrado. La etiqueta de autenticación por defecto es de 128 bits. Esos números se pueden contrastar en una implementación. No son lemas para memorizar.
El cifrado de archivos también deriva una clave a partir de una contraseña. La caja de archivos de este sitio usa PBKDF2 con 100.000 iteraciones, SHA-256 y una sal de 16 bytes, y luego una clave AES-GCM de 256 bits. Un archivo puede llegar a 5 GB. La salida es .lock o .enc. Si la contraseña se envía por POST junto al archivo, el número de iteraciones no te salva. El primer objeto a inspeccionar sigue siendo el tráfico, no la función de derivación.
Tres maneras de «cifrar en el navegador»
Puestos en fila, los flujos se parten al menos en tres. Primero: la pestaña solo elige un archivo; los bytes van a un servidor; el cifrado ocurre al otro lado. Segundo: la pestaña cifra primero, luego sube solo texto cifrado, y la clave viaja por otro canal (por ejemplo el # de la URL). Tercero: el resultado se descarga en esta máquina y ninguna petición de negocio lleva un cuerpo de archivo. Los tres se pueden vender como «cifrado en una página web». Solo los dos últimos pueden afirmar que el texto plano no se sube por defecto. Tu trabajo es decidir a qué clase pertenece esta página, usando Red.
Nombra el objeto antes de pulsar Empezar
Para generar una contraseña, comprobar la fortaleza, limpiar un enlace o cifrar un archivo, la expectativa es «el texto plano no salió como dato de negocio». Un enlace de un solo uso es distinto: puedes ver un campo de texto cifrado, pero no deberías ver la frase original ni la clave que va detrás de # en la línea de la petición. Si mezclas esas dos expectativas, un POST normal de texto cifrado parece una fuga.
El fragmento y la consulta no son el mismo objeto
Una URL se parte en esquema, host, ruta, consulta (después de ?) y fragmento (después de #). RFC 3986 §3.5 llama fragmento a lo que va detrás de #: nombra una posición secundaria que el cliente interpreta cuando el recurso principal ya llegó. La nota de MDN sobre el fragmento de URI es más clara: cuando el navegador pide esa URI, el fragmento no se envía al servidor. El cliente lo trata después de que el recurso aterriza.
La cadena de consulta es lo contrario. Abre un enlace https y los pares nombre=valor que van detrás de ? entran en la línea de la petición y en los registros de acceso del otro extremo. El artículo anterior, qué parámetros de URL quitar al compartir un enlace, ya trataba utm_source e id= como nombres de consulta. Escribe una clave como ?key= y el servidor, el proxy inverso y los logs de la CDN pueden verla. Escríbela detrás de # y la línea de petición por defecto no incluye ese trozo.
El Referer también suelta el fragmento. MDN Referer dice que la cabecera puede llevar origen, ruta y consulta. No debe llevar un fragmento de URL ni un nombre de usuario y contraseña. La Referrer Policy del W3C también vacía el fragmento en el paso «strip for use as a referrer». Así que «pon la clave detrás de # y la máquina que hospeda el texto cifrado no la recibe por HTTP» es comportamiento del protocolo. No es una promesa de un proveedor.
Un enlace de un solo uso en este sitio tiene la forma s.html?id={id}#{key}: la consulta solo lleva el id del texto cifrado; la clave vive solo detrás de la almohadilla. Al crear, la pestaña construye una clave aleatoria de 32 bytes, ejecuta AES-256-GCM con un IV de 12 bytes y luego hace POST del texto cifrado. Al leer, el script toma la clave de location.hash y descifra en este dispositivo. El texto plano está limitado a 32 KB. Lo que compruebas: el JSON de creación debería tener un campo de texto cifrado y no debería tener la frase original; la petición del documento en la página de lectura debería mostrar id= y no debería mostrar el trozo que va detrás de #.
Compruébalo en la pestaña Red
Chrome, Edge, Firefox y Safari traen un panel de red. Los nombres cambian un poco. Los pasos, no. No hace falta una extensión, y no hace falta entregar el archivo a un «escáner» de terceros: volver a subir la URL completa o el archivo solo amplía la exposición.
- Abre las herramientas para desarrolladores y pasa a Red. Activa «Conservar registro» para que una navegación no borre la lista.
- Filtra por Fetch / XHR (o «XHR»). Los recursos estáticos pueden esperar. Las subidas de negocio casi siempre usan esta clase de petición.
- Haz la acción que viniste a comprobar: genera una contraseña, escribe una frase de paso desechable, pega una URL que aún lleve etiquetas UTM, elige un archivo pequeño para cifrar o escribe un secreto de usar y tirar y crea un enlace de un solo uso.
- Abre cada petición nueva. Lee la URL de solicitud: las direcciones del documento y de la API no deberían contener el texto plano que acabas de escribir, ni
#más la clave. - Abre Carga útil / Request. Los campos JSON o del formulario no deberían llevar el texto original, una contraseña, la contraseña que estás comprobando ni los bytes crudos del archivo. Una creación de un solo uso puede mostrar un campo de texto cifrado. Ese campo debería parecer binario aleatorio en Base64, no la frase que escribiste.
- Revisa peticiones de analytics o de recogida (los nombres suelen incluir
matomo,collectog/collect). Mira si la URL de página reportada o un parámetro personalizado enviólocation.hrefincluyendo el hash.
El cifrado de archivos tiene una comprobación más dura: desconéctate o activa el modo avión y cifra un archivo pequeño. Si la cuenta se supone que se queda en este dispositivo, la descarga .lock / .enc debería seguir funcionando. Un enlace de un solo uso no puede pasar esa prueba: tiene que aparcar texto cifrado en un servidor, así que fallar sin red es lo esperado, no un truco. Si tomas «cero peticiones» como única nota de aprobado, reprobarás por error un enlace de un solo uso de conocimiento cero.
Una página de fortaleza puede pedir una lista estática de contraseñas débiles (este sitio usa leaked-top10k.txt). Es una lista de palabras, no tu entrada. En Red puedes ver el archivo de la lista. No deberías ver la contraseña del cuadro de texto en la consulta ni en el cuerpo. Eso no es una consulta HIBP a toda la web. Las comprobaciones al estilo HIBP envían un hash o un fragmento de contraseña a una API externa.
| Qué estás haciendo | Permitido en Red | No debe aparecer |
|---|---|---|
| Generar una contraseña aleatoria | Scripts y estilos de la propia página | El resultado o el juego de caracteres elegido en un POST |
| Comprobar una frase de paso en local | Una lista estática de contraseñas débiles | La contraseña del cuadro de texto |
| Limpiar un enlace o redactar texto | Ninguna petición de negocio que lleve el original | La URL completa, un número de ID o un correo en crudo |
| Crear un enlace de un solo uso | Texto cifrado, un id, caducidad y número de lecturas |
Texto plano; la clave # en la línea de la petición |
| Cifrar un archivo | Ninguna subida de negocio de un cuerpo de archivo | Bytes del archivo, la contraseña |
MyPassGen está construido según esa tabla. Las contraseñas aleatorias tienen de 6 a 128 caracteres (16 por defecto; por debajo de 8 avisa de que el resultado es débil). Las comprobaciones de fortaleza usan una lista local, no una consulta a toda la web. Limpiar y cifrar o descifrar un archivo no suben el original como dato de negocio por defecto. Un enlace de un solo uso solo guarda texto cifrado. Todas las herramientas se abren sin registro. La columna «no debe aparecer» la puedes marcar tú en el panel. No hace falta aceptar primero una promesa de marca.
Que salga texto cifrado no es que salga texto plano
El intercambio de conocimiento cero y «totalmente sin conexión» se aplastan en una sola frase. La caja de archivos es del segundo tipo: el resultado aterriza en la carpeta de descargas y el servidor no tiene copia de negocio de ese archivo. Un enlace de un solo uso es del primero: la otra parte tiene que poder pedir un blob de texto cifrado para que el destinatario descifre en su propio navegador. Que el servidor vea el texto cifrado y no vea la clave es el diseño, no un accidente.
Separa la prueba de fuga. Al crear, una cadena Base64 larga en el cuerpo del POST es normal. Si ese mismo campo se lee como la «clave de API de prueba» que acabas de escribir, salió texto plano. La petición del documento en la página de lectura debería ser s.html?id=…. Según la especificación, la URL de solicitud que lista Red no lleva #. Abre Encabezados en esa petición y confirma que la línea de petición y el Referer omiten la clave.
La etiqueta de autenticación de GCM hace difícil «cambiar unos bytes y descifrar igual»: si la etiqueta no coincide, decrypt falla de golpe. Eso protege la integridad y la autenticidad. No significa que el enlace nunca se reenvíe. Quien tenga la URL completa —incluida la clave detrás del hash— puede descifrar hasta que se agote el número de lecturas. Red comprueba si el servidor recibió la clave. Los historiales de chat, el correo y las capturas son otro riesgo. La siguiente sección los trata por separado.
No pegues un enlace de un solo uso completo en un «escáner» que sube el original
La clave que va detrás de # es invisible para el servidor HTTP. Es totalmente visible para el siguiente sitio en el que la pegues. Verifica en tus propias herramientas para desarrolladores. No entregues s.html?id=…#… a una página de escaneo desconocida.
Fugas que el protocolo no cubre
Que HTTP no envíe el fragmento no significa que la clave nunca salga de este ordenador. El script de la página puede leer window.location.hash y hacer fetch por su cuenta: eso es un fallo de implementación, no un agujero del protocolo. El paso seis existe por eso: si analytics reporta location.href como URL de página, el trozo que va detrás del hash entra en el registro de estadísticas. El informe correcto es una ruta, o una URL con el hash recortado. «HTTP no lo enviará» no sustituye esa comprobación.
El historial del navegador, las pestañas sincronizadas y algunos informes de fallo conservan la URL completa. Dejas un enlace de un solo uso en la barra de direcciones y dejas la clave en el historial local. Compártelo por un canal de un solo disparo y, después de leerlo, no pegues la dirección con # en una plantilla de ticket. El Referer recorta el fragmento; los parámetros de consulta sí pueden viajar a un tercero. Nunca pases la clave a ?key=.
Las pantallas, el portapapeles y los historiales de un chat de grupo quedan fuera del protocolo. Un compañero que captura el enlace completo y lo pega en el chat no le dio la clave al servidor —y ahora todo el hilo la tiene. El cifrado local responde «dónde se hizo la cuenta y quién no puede ver el texto plano por defecto». No responde «la persona que recibió la URL completa la reenviará». El mismo corte vale para la contraseña de un archivo: el .lock puede ir a una unidad; la contraseña tiene que viajar por otro canal. Un secreto corto corresponde a un enlace de un solo uso, no al mismo cuerpo de correo que la contraseña.
Errores frecuentes
«Falla sin conexión, así que debe estar subiendo texto plano.» Un enlace de un solo uso tiene que aparcar texto cifrado. Fallar sin red solo muestra que depende de una transferencia de texto cifrado. Lee qué contiene esa transferencia. No te quedes en «hubo una petición».
«HTTPS ya cifra el camino, así que el cifrado local sobra.» HTTPS cubre a quien escucha en el cable. El servidor es el extremo TLS. Sigue pudiendo leer el cuerpo de la petición y la consulta. El cifrado local es la capa que impide que el servidor —o un salto de analytics por el medio— vea el texto plano por defecto. Se apila con TLS. Los trabajos son distintos.
«La página menciona Web Crypto, así que el texto plano no se sube.» Web Crypto solo ofrece primitivas. Cifrar primero y luego subir texto cifrado, y hacer POST de un FormData primero y cifrar en el servidor, pueden decorar el pie con el mismo nombre de API. La carga útil del panel manda más que el eslogan.
«No veo ninguna petición al host del producto, así que estoy a salvo.» Las extensiones, los proxies del sistema y algunas pasarelas de empresa no se dibujan en la lista Red de la página. El panel puede falsear un anuncio de «nada se sube». No puede demostrar que no exista un segundo canal en el mundo. Para elegir una herramienta online en el día a día, falsear basta: ves texto plano, paras.
Por dónde empezar
Elige una acción desechable que ya necesites hoy. El cifrado de archivos es el contraste más fácil: elige una captura sin nada sensible, escribe una contraseña temporal, abre Red, pulsa cifrar, confirma que no hay un POST del cuerpo del archivo y descarga .lock o .enc. Cuando envíes esa imagen a otra persona, el texto cifrado va a una unidad; la contraseña va en otro mensaje. Mantén un solo archivo en 5 GB o menos.
Si envías una contraseña de una línea o un código de recuperación, usa un enlace de un solo uso: escribe una frase de prueba, genera el enlace, confirma que la petición de creación solo lleva texto cifrado; abre la página de lectura en una ventana privada y comprueba que la línea de petición del documento solo tiene id=. No trates la página de lectura como una página de contenido indexable: es una escena de texto cifrado de un solo disparo. Limpiar un enlace sigue la tabla del artículo anterior: quita etiquetas UTM e IDs de clic en este dispositivo.
Tras una pasada ya puedes responder al título: si el cifrado en el navegador es real no es un eslogan. Es si este tráfico contenía texto plano, una contraseña o la clave que va detrás del hash. AES-256-GCM, Web Crypto y herramientas que se abren sin cuenta son restricciones que puedes comprobar en paralelo. No son promesas que tengas que registrarte para oír.
Preguntas frecuentes
¿Por qué el cifrado de archivos funciona sin conexión y un enlace de un solo uso no?
El cifrado de archivos termina como una descarga local. Un enlace de un solo uso tiene que dejar que el destinatario pida el texto cifrado más tarde, así que la creación hace POST del texto cifrado. Ambos pueden terminar AES-256-GCM en el navegador. Lo que puede salir es distinto: la caja de archivos no debería tener cuerpo de archivo; la creación de un solo uso puede enviar texto cifrado y no debe enviar texto plano ni la clave.
¿El servidor de verdad no recibe nunca la clave que va detrás de #?
En implementaciones habituales de URI y HTTP, la petición del documento y el Referer omiten el fragmento. Lo puedes ver en la petición del documento en Red. Si un script lee location.hash y lo reporta, es comportamiento de la propia página: búscalo en la lista Fetch.
¿No es más fácil poner la clave en la cadena de consulta?
Más fácil, y aterriza en los registros del servidor. ?id= puede localizar el texto cifrado. ?key= entrega la capacidad de descifrar al anfitrión y a cada log del camino. Cuando el destinatario debe descifrar y el anfitrión no, la clave va detrás de #.
¿Hace falta una cuenta para hacer esta comprobación? ¿Analytics se lleva el original?
No hace falta cuenta. Si analytics registra un tipo de página o una ruta con el hash recortado, no se lleva el contenido del cuadro de texto. Si reporta el href completo, la clave que va detrás de # puede entrar en el registro de estadísticas. Leer la consulta de la petición de analytics en Red es más directo que leer «nos importa la privacidad».