Por qué un enlace de un solo uso puede demostrar que el servidor borró el texto cifrado, pero no que el destinatario no hizo una captura

Conviertes una contraseña de un solo uso en un enlace autodestructivo. La otra persona lo abre, refresca y la página dice «Incinerado». Eso suele contarse como «lo vio y no queda nada». Lo que se quemó es el texto cifrado del servidor. Una copia en su pantalla, una captura del sistema o la URL completa en el chat no pasan por ese borrado. Lo que puedes comprobar en el acto es si una segunda petición por el mismo id sigue devolviendo texto cifrado.

Empieza por la afirmación estrecha: cuando se alcanza el recuento de lecturas o el enlace caduca, el texto cifrado desaparece del servidor, así que otra petición por el mismo id no puede devolver los bytes originales. Esa afirmación no sostiene «el destinatario no hizo una captura», «nadie más del canal lo abrió» ni «las copias de seguridad del chat no guardan el enlace completo». La comprobación son dos aperturas más Network, no tratar «Incinerado» como una auditoría del otro dispositivo.

Responde a la intención de búsqueda en una frase

Un enlace de un solo uso puede sostener una sola conclusión: el anfitrión ya no guarda el texto cifrado. No puede sostener que se borraron la pantalla, el portapapeles o el historial de chat del destinatario. Tras la primera recogida correcta, abrir el mismo enlace otra vez muestra «Incinerado» o «Caducado». Según HTTP 410 Gone, el recurso destino ya no está disponible en el origen, y esa situación suele ser permanente. Eso responde «¿el servidor sigue entregándolo?». No responde «¿se quedó con una copia?».

Esta nota es para desarrolladores, operaciones y quien quiera separar «el enlace ya no vale» de «no se quedó con nada» antes de mandar una contraseña de un solo uso, una API Key o un código de recuperación. No sustituye las instrucciones de Burn-Link ni repite cómo generar una URL. Lo que te llevas es qué capa se quema, qué puede demostrar un refresco fallido, por qué la captura queda fuera de esa capa y cómo dos aperturas más Network te dejan contrastar el lado del anfitrión en este dispositivo.

«Incinerado» no es lo mismo que «no se quedó con copia»

El habla cotidiana junta tres hechos distintos en «este mensaje desaparece al leerlo». Primero: el servidor ya no almacena texto cifrado. El registro de ese id se ha ido, y una petición posterior solo obtiene «Incinerado» o «Caducado». Segundo: esta pestaña ya no muestra texto en claro. Cerrar la página, pulsar «Borrar de esta página» o un script que vacía el cuadro al salir pueden hacerlo. Tercero: el dispositivo del destinatario no guarda ninguna copia: ni captura, ni pegado, ni reenvío del enlace completo, ni texto en claro vuelto al chat.

El enlace autodestructivo puede imponer el primer hecho. Como mucho, puede limpiar la vista de esta pestaña en el segundo. Sobre el tercero no tiene fuerza. La página de lectura puede decir que no impide copiar ni hacer capturas. Eso es un límite, no una función a medias: una página web no puede impedir que otro teléfono fotografíe la pantalla, y no puede entrar en el portapapeles del sistema ni en el almacén local de WhatsApp o Slack después de que alguien pulse «Copiar texto en claro».

Así que «refresqué y ya no abre» sostiene una conclusión estrecha: esta petición por id no devolvió texto cifrado. No sostiene «solo lo vio ese compañero», «no hizo una captura» ni «esta cadena no volverá a salir en la búsqueda de un ticket». Esas frases posteriores piden otra observación: si el texto en claro o la URL completa salieron de esta pestaña, no si tu segunda apertura falló.

Qué capa quema de verdad el servidor

Un enlace de conocimiento cero separa la localización del descifrado. La forma es s.html?id={id}#{key}: la consulta solo lleva el id; la clave va detrás de la almohadilla. RFC 9110 indica que el URI de destino de la petición no incluye el fragmento. Cuando el navegador pide el documento al servidor, tira # y todo lo que sigue. Por diseño, el servidor ve el id, no la clave y no el texto en claro.

Al crear, esta pestaña usa Web Crypto para AES-256-GCM: una clave aleatoria de 32 bytes, un IV de 12 bytes y el texto en claro empaquetado en texto cifrado en este dispositivo antes del POST /secrets. Los campos de salida son texto cifrado, caducidad y recuento de lecturas. La clave solo aparece en la URL para compartir que se monta después. Un ítem tiene tope de 32 KB. La caducidad puede ser 1 hora, 24 horas, 7 días, o quemar solo tras una lectura. El recuento es de 1 a 10, 1 por defecto. Crear y leer están listos para usar. No hay cuenta, ni identidad de inicio de sesión para «quién lo abrió».

Al leer, cuando el servidor entrega el texto cifrado y se alcanza el recuento fijado, elimina ese texto cifrado. Si abres el enlace otra vez, ves «Incinerado» o «Caducado». Eso demuestra que el anfitrión ya no guarda esos bytes cifrados. No demuestra que la clave nunca estuviera en el historial del chat, que el texto en claro nunca llegara a la otra pantalla, o que un tercero nunca pulsara «Abrir y ver» en la misma URL completa.

Quien tenga la URL completa sigue teniendo la clave. Pegar https://…/s.html?id=…#… en un grupo entrega el id y la llave a la vez. Aunque el servidor ya haya quemado el texto cifrado, ese borrado no puede deshacer a quien ya lo abrió y se quedó el texto en claro. Si quedan lecturas, un clic posterior aún puede recoger el texto cifrado. Quemar el texto cifrado ataca el almacenamiento a largo plazo en el anfitrión. No ataca a «todo el que vio la cadena entera».

Qué puede demostrar un refresco fallido, y qué no

Una segunda apertura que falla no es un solo estado. Separa tres avisos. «Incinerado»: el texto cifrado ya no está, porque se usó el recuento o porque el id nunca fue válido. «Caducado»: se agotó el TTL elegido al crear, así que el servidor borró el registro aunque nadie lo leyera. «Falta la clave del fragmento»: el id puede seguir existiendo, pero este dispositivo no puede descifrar. WhatsApp, Slack, Teams y algunos clientes de correo recortan todo lo que va después de #. El destinatario ve entonces «Falta la clave del fragmento», que no es el mismo suceso que «otra persona ya lo leyó».

410 Gone significa que el recurso destino ya no está disponible en el origen, y que esa situación es probablemente permanente. La página de lectura parte el 410 en «Incinerado» y «Caducado»: si la respuesta marca expired, es TTL; si no, se trata como incinerado. Un 404 también se muestra como «Incinerado», porque el resultado para el destinatario es el mismo: ya no se puede recoger el texto cifrado. Un error de red no es una quema: si el corte ocurre después de «Abrir y ver» y al crear solo se permitió una lectura, el texto cifrado puede haberse retirado aunque esta pestaña nunca lo descifrara.

Así, «en mi refresco ya no abre» sostiene esto: una petición por este id ya no devuelve texto cifrado. No sostiene: quien abrió fue el compañero nombrado; no copió; no hizo una captura; un robot de vista previa o un escáner de seguridad no gastó una lectura antes. Sin cuentas, no hay acuse de lectura con nombre. El recuento vive en el servidor. No es una auditoría del dispositivo del destinatario.

No experimentes con una contraseña real, una API Key ni una cadena de conexión sin enmascarar. Escribe una frase que exista solo para esta comprobación. Estás contrastando la consulta de estado, la recogida del texto cifrado y el aviso de la segunda apertura, no volviendo a exponer una credencial viva.

Por qué captura, copia e historial de chat quedan fuera de esta capa

En cuanto el texto en claro se pinta en una pantalla, la pregunta deja de ser «¿el servidor sigue teniendo texto cifrado?» y pasa a ser «¿qué ocurrió en el otro extremo?». Una captura del sistema, una grabación de pantalla o un segundo teléfono apuntando al monitor no envían ninguna petición al anfitrión. La página de lectura no puede interceptar esas acciones ni avisarte después. No es una casilla de producto sin marcar. A una página web ordinaria no se le da un interruptor que prohíba a la otra persona grabar su propia pantalla.

Copiar queda al otro lado de la misma valla. La página de lectura puede ofrecer «Copiar texto en claro» y vaciar el cuadro al salir. Lo que vacía es este nodo del DOM, no el portapapeles del sistema ni un borrador de WhatsApp. macOS y algunos métodos de entrada guardan historial del portapapeles. «Borrado de esta página» solo significa que esta pestaña ya no muestra la frase. No significa que la frase nunca entrara en el portapapeles.

El historial del chat es otro almacén. Si el enlace completo apareció en un grupo, el historial, la búsqueda, la sincronización en varios dispositivos y una exportación posterior pueden volver a mostrar la clave que va tras la almohadilla. Aunque el servidor ya haya quemado el texto cifrado, la URL sigue siendo prueba de que el enlace funcionó, y basta para que quien no sepa que el recuento se agotó siga pulsando y concluya «el enlace está roto». La capa HTTP puede seguir limpia —Referer no debe llevar un fragmento—, pero esa protección ya no vale frente a quien pueda abrir el hilo.

Los tickets, el correo y el historial del navegador siguen el mismo corte. Un fragmento # que apareció en la barra de direcciones suele acabar en el historial local; un navegador con sesión puede sincronizar esa fila a otros dispositivos. Cerrar la pestaña no es borrar el historial. El enlace de un solo uso acorta cuánto tiempo guarda el servidor un bloque, y limita cuántas veces se puede recoger el mismo texto cifrado. No es gestión de derechos digitales, ni un informe forense.

Por qué una consulta de estado no gasta una lectura

Si la primera carga de la página de aterrizaje recogiera el texto cifrado, una vista previa de WhatsApp, una pasarela de seguridad de correo o un escáner de empresa podrían gastar la única lectura antes de que el destinatario pulsara. Entonces verían «Incinerado», aunque la clave nunca se hubiera dado al anfitrión de la vista previa. Lo que se quema es el recuento, no el secreto del fragmento. Una nota anterior cubre por qué la almohadilla se queda fuera de HTTP por defecto. Esta se queda en el recuento: una petición de vista previa y una recogida real de texto cifrado tienen que ir separadas; si no, «Incinerado» ni siquiera sostiene «el destinatario lo vio».

La página de lectura de FastPwd parte esos pasos. Abrir la página solo pide /secrets/{id}/status: ¿sigue ahí el texto cifrado? No se lleva el bloque. Después de que el destinatario pulse «Abrir y ver», la pestaña hace GET /secrets/{id} y descifra en local con la clave que va tras la almohadilla. Si falta la clave #, la página no pedirá el texto cifrado, para no gastar las lecturas que queden. Ni la página de creación ni la de lectura necesitan cuenta.

Los robots de vista previa suelen pedir la página de aterrizaje y no pulsan el botón. Eso baja la probabilidad de «previsualizar es quemar». No demuestra que todo escáner se detenga ahí. En Network deberías ver primero una consulta de estado y luego una recogida de texto cifrado; una carga sin clic no debería mostrar una recogida correcta del bloque. El recuento sigue siendo un contador en el servidor. No forma parte del fragmento.

Lo que ves Lo que puede sostener Lo que no puede sostener
La segunda apertura muestra «Incinerado» Una petición por este id ya no devuelve texto cifrado El destinatario no hizo captura ni copió
La página muestra «Caducado» Se agotó el TTL y el servidor borró el registro Alguien lo leyó con éxito
La página muestra «Falta la clave del fragmento» La dirección no tiene clave detrás de # El texto cifrado ya se ha retirado
La página cargó; no se pulsó el botón Una consulta de estado no debería gastar una lectura Todo robot de vista previa se niega a recoger texto cifrado
Network muestra solo texto cifrado en el POST Esta creación no envió la frase original como campo de negocio Tras pegar el enlace completo en el chat, solo tú puedes verlo
El texto en claro se borró de esta página Esta pestaña ya no muestra esa frase El portapapeles y las capturas también están vacíos

Compruébalo ahora: dos aperturas, estado y Network

Un eslogan no es una prueba. Prepara un canario desechable, por ejemplo canary-fp-20260905-burn-vs-shot. No reutilices una contraseña viva. Deja el recuento en el valor por defecto de 1 y la caducidad en 24 horas.

  1. Pon el canario en la página de creación y genera un enlace. Abre Network en las herramientas para desarrolladores y marca Preserve log. Busca por separado el canario y la clave que va tras la almohadilla: el cuerpo de POST /secrets debe llevar texto cifrado, caducidad y recuento de lecturas, no la frase original ni la clave.
  2. Abre la página de lectura con el mismo enlace completo. Aún no pulses «Abrir y ver». Network debería mostrar /secrets/{id}/status y no debería mostrar un GET /secrets/{id} que se llevara el bloque. La página debería esperar confirmación.
  3. Pulsa «Abrir y ver». Solo entonces debería pedirse el texto cifrado por id y descifrarse en este dispositivo con AES-256-GCM. La nota de éxito dirá que el servidor ya eliminó este texto cifrado o, si subiste el recuento por encima de 1, que el borrado espera a alcanzar ese número.
  4. Refresca la página de lectura, o abre el mismo enlace en un contexto de navegador nuevo. Con una lectura, deberías ver «Incinerado». Busca otra vez en Network: la recogida de texto cifrado debería devolver 410 o una respuesta tratada como incinerada. El canario no debería reaparecer como texto en claro en ningún cuerpo de petición.

Esos cuatro pasos demuestran un solo cambio: entre dos aperturas que controlas, el texto cifrado del servidor pasó de estar a no estar. No demuestran que, si esto hubiera sido una contraseña real para un compañero, no hiciera una captura. «¿Se quedará con una copia?» pertenece a la nota de entrega —no hagas captura, no pegues el texto en claro otra vez en el canal, rota el secreto tras usarlo—, no a la esperanza de que «Incinerado» audite el otro extremo por ti.

No mandes el enlace completo y el texto cifrado por el mismo camino. Deja un archivo .lock en un disco o en el correo, y envía la frase por Burn-Link. No sueltes la URL completa de Burn-Link en las notas de esa carpeta. Si la llave y la caja viajan en el mismo mensaje, quemar el texto cifrado no ayuda a quien ya vio la cadena entera.

Tres formas de leer «Incinerado» más de la cuenta

Primera: tratar «Caducado» como prueba de que alguien lo leyó. Al crear se eligió 1 hora; el compañero pulsó al día siguiente; la página dice «Caducado». El servidor borró el texto cifrado, pero la razón es el TTL, no un recuento agotado. El contenido no leído que caduca no se puede recuperar. Eso no es lo mismo que «ya se había abierto».

Segunda: tratar un fragmento ausente como ya incinerado. WhatsApp, Slack y algunos clientes de correo cortan todo lo que va después de #. El destinatario abre s.html?id=… sin clave. La página de lectura no pedirá el texto cifrado sin clave. Si más tarde abres el enlace completo, el contenido puede seguir ahí. Pídele que reenvíe la cadena que incluye la almohadilla. No decidas «alguien llegó antes».

Tercera: tratar «Borrar de esta página» como un borrado global. La página de lectura puede vaciar el cuadro al salir, y puede usar history.replaceState para quitar el fragmento de la barra de direcciones. Eso solo cambia lo que muestra esta pestaña y si un refresco posterior sigue llevando la clave. Las capturas del sistema, el historial del portapapeles, las copias de seguridad del chat y el historial sincronizado del navegador quedan fuera de ese borrado.

Preguntas frecuentes

Si refresca y ve «Incinerado», ¿significa que no se quedó con nada?

No. Solo significa que el texto cifrado ya no está en el servidor, así que otra petición por id no puede devolver los bytes originales. Una captura, una copia, una grabación de pantalla, una copia de seguridad del chat o reenviar el enlace completo no pasan por ese borrado. «Incinerado» no prueba que el dispositivo del destinatario esté limpio.

¿Puede la vista previa de un chat quemar el secreto antes?

Una vista previa suele cargar solo la página de aterrizaje. La página de lectura pregunta primero si el texto cifrado sigue ahí y no se lo lleva; «Abrir y ver» es lo que pide el texto cifrado por id. La mayoría de los robots de vista previa no pulsan ese botón por ti, pero no puedes asumir que todo escáner se detiene en la página de aterrizaje. El recuento de lecturas es un contador en el servidor. La comprobación: en una carga sin clic, Network no debería mostrar una recogida correcta de texto cifrado.

¿Un enlace de un solo uso puede demostrar quién lo abrió?

No. Crear y leer no piden cuenta, y el servidor no etiqueta al lector por identidad de inicio de sesión. Lo que puedes comprobar es si el id sigue teniendo texto cifrado después de una recogida. No puedes convertir «Incinerado» en un nombre, ni escribirlo como un acuse de lectura.

¿Hay que registrarse para crear o leer? ¿Se sube el texto en claro?

No. Esta pestaña cifra con AES-256-GCM y luego sube texto cifrado. La clave va en el fragmento #. Busca en Network con un canario: el cuerpo debe llevar texto cifrado, no la frase original ni la clave que va tras la almohadilla. Si supera los 32 KB, o si es un archivo entero, usa la caja de cifrado en este dispositivo. No trates un Burn-Link como un disco.

Pasa el mismo canario por una herramienta lista para usar

Si quieres una página que deja escrito el límite de cálculo, abre el Burn-Link de FastPwd. No hace falta cuenta. Pega el canario de arriba, deja el recuento en 1, genera el enlace y termina las dos aperturas de la sección de comprobación. Mira Network al mismo tiempo: deberías ver el POST de texto cifrado al crear, el status en la página de lectura, la recogida tras el clic y una respuesta incinerada en la segunda apertura. No deberías ver la frase original ni la clave que va tras la almohadilla como campo de negocio.

Usa este camino solo cuando una contraseña tenga que llegar a un compañero. Puedes generar primero la contraseña aleatoria en el generador de contraseñas, en local, de 6 a 128 caracteres, 16 por defecto; por debajo de 8 se marca como menos segura. La generación no se sube. Un contrato entero, un escaneo de DNI o cualquier cosa de más de 32 KB pertenece a la caja de cifrado, con el mismo AES-256-GCM hacia .lock / .enc, un archivo de hasta 5 GB. Envía la frase por un Burn-Link aparte. No la escribas en las notas del disco.

Antes del siguiente envío, quédate con tres hechos. Primero: «Incinerado» demuestra que el texto cifrado desapareció del servidor, no que la otra persona no hizo una captura. Segundo: cargar la página de aterrizaje no debería gastar una lectura; «Abrir y ver» es lo que recoge el texto cifrado. Tercero: tras pegar el enlace completo en el chat, la clave que va tras la almohadilla es visible para quien pueda ver ese mensaje. Solo una observación que puedas repetir merece entrar en vuestras propias notas de entrega.

Para seguir leyendo

Por qué lo que va detrás de la almohadilla se queda fuera de HTTP por defecto, y qué capa cae al pegar el enlace completo, está en Por qué el hash de una URL puede guardar una clave, y cuándo esa protección falla. «Cifrado local, no se sube nada» no es prueba hasta que buscas en Network con un canario: Cómo comprobar que el cifrado local del navegador no envió el original. Si aún tienes que enmascarar números de documento en un ticket antes de que salgan de este equipo, véase Antes de pegar un ticket o un registro en una IA, comprueba qué campos salen de este equipo.