Cada petición HTTPS empieza con una conversación que la mayoría de los ingenieros nunca mira. Antes de que tu navegador envíe GET /, él y el servidor acuerdan una versión del protocolo, intercambian claves, comprueban un certificado y demuestran que nadie ha manipulado nada de ello. Cuando eso sale mal, recibes errores crípticos como handshake_failure o bad_certificate, y cuando va lento, cada página lo paga.
TLS 1.3 hizo el handshake más corto y más privado que TLS 1.2. Este artículo lo recorre mensaje a mensaje con un diagrama de secuencia y después cubre las variantes que encontrarás en producción: HelloRetryRequest, reanudación de sesión y 0-RTT, TLS mutuo, Encrypted Client Hello e intercambio de claves poscuántico.
Lo que tiene que lograr el handshake
Un handshake de TLS cumple cuatro tareas antes de que fluya ningún dato de la aplicación:
- Negociar parámetros: la versión del protocolo, la suite de cifrado y el grupo de intercambio de claves.
- Establecer claves compartidas: ambos lados derivan los mismos secretos sin enviarlos nunca.
- Autenticar al servidor, y opcionalmente al cliente, con certificados.
- Confirmar la integridad: ambos lados comprueban que vieron los mismos mensajes del handshake, para que un atacante no pueda degradar ni alterar la negociación.
La especificación actual es la RFC 9846, publicada en julio de 2026. Sustituye a la RFC 8446 pero mantiene la misma versión del protocolo, así que un cliente TLS 1.3 hecho según la RFC antigua sigue hablando con un servidor hecho según la nueva.
El handshake completo, mensaje a mensaje
TLS 1.3 necesita un solo viaje de ida y vuelta. El cliente adivina qué intercambio de claves aceptará el servidor y envía su mitad del intercambio en el primerísimo mensaje.
| Mensaje | Dirección | Cifrado | Qué lleva |
|---|---|---|---|
| ClientHello | cliente → servidor | No | Valor aleatorio, suites de cifrado, supported_versions, key_share, signature_algorithms, server_name (SNI), ALPN |
| ServerHello | servidor → cliente | No | Suite de cifrado elegida, el key_share del servidor |
| EncryptedExtensions | servidor → cliente | Sí | Resto de extensiones negociadas, como el protocolo ALPN |
| Certificate | servidor → cliente | Sí | La cadena de certificados del servidor |
| CertificateVerify | servidor → cliente | Sí | Una firma sobre el handshake hasta ese punto, hecha con la clave privada del certificado |
| Finished | servidor → cliente | Sí | Un MAC sobre toda la transcripción |
| Finished | cliente → servidor | Sí | El MAC del cliente sobre la transcripción |
La línea importante es la que sigue a ServerHello. En cuanto el cliente tiene el key share del servidor, ambos lados ejecutan el key schedule (HKDF sobre el secreto compartido y la transcripción) y derivan las claves de tráfico del handshake. A partir de ahí, todos los mensajes del handshake van cifrados. En TLS 1.2, un observador en la red podía leer el certificado del servidor; en TLS 1.3 no puede.
CertificateVerify demuestra que el servidor tiene la clave privada del certificado que acaba de enviar. Finished demuestra que ambos lados vieron los mismos mensajes. Si un atacante quitara una suite de cifrado del ClientHello, las transcripciones serían distintas y la comprobación de Finished fallaría.
El servidor puede enviar datos de la aplicación justo después de su Finished, y el cliente envía su primera petición inmediatamente después del suyo. Un viaje de ida y vuelta después del ClientHello, la conexión cifrada está lista.
Qué cambió respecto a TLS 1.2
| TLS 1.2 | TLS 1.3 | |
|---|---|---|
| Idas y vueltas para una conexión nueva | 2 | 1 |
| Intercambio de claves | Transporte de clave RSA o (EC)DHE | Solo (EC)DHE, o PSK con (EC)DHE |
| Secreto hacia adelante | Opcional | Siempre, salvo en la reanudación solo con PSK |
| Suites de cifrado | Decenas, incluidas CBC y RC4 | Cinco, todas AEAD |
| Certificado del servidor en la red | En texto claro | Cifrado |
| Compresión y renegociación | Admitidas | Eliminadas |
La lista de suites se redujo a TLS_AES_128_GCM_SHA256, TLS_AES_256_GCM_SHA384, TLS_CHACHA20_POLY1305_SHA256 y dos suites CCM. Una suite de cifrado de TLS 1.3 ahora solo nombra el cifrado de los registros y el hash; el intercambio de claves y el algoritmo de firma se negocian por separado. Los certificados RSA siguen funcionando. Lo que desapareció es el transporte de clave RSA, en el que el cliente cifraba el secreto con la clave pública del servidor y una clave robada descifraba todas las sesiones grabadas.
Cuando un viaje de ida y vuelta se convierte en dos: HelloRetryRequest
El handshake de un solo viaje de ida y vuelta depende de una suposición. El cliente envía key shares para los grupos que espera que el servidor acepte, normalmente X25519. Si el servidor no admite ninguno, responde con un HelloRetryRequest que nombra un grupo que sí acepta, y el cliente empieza de nuevo con un ClientHello nuevo. Eso cuesta un viaje de ida y vuelta completo adicional.
Lo verás cuando un cliente y un servidor no coincidan en los grupos, por ejemplo un servidor configurado solo para P-256 y un cliente que solo envía un share X25519. La solución es de configuración: asegúrate de que los grupos que tus clientes ofrecen primero son los que prefieren tus servidores.
Reanudación y 0-RTT
Después del handshake, el servidor puede enviar mensajes NewSessionTicket. Un ticket permite al cliente reanudar más tarde con una clave precompartida (PSK) en lugar de un intercambio completo de certificados. La reanudación normalmente sigue ejecutando un intercambio (EC)DHE nuevo, así que la sesión reanudada conserva el secreto hacia adelante.
Con un ticket, el cliente también puede enviar datos tempranos, llamados 0-RTT: la primera petición viaja en el mismo vuelo que el ClientHello. Ahorra un viaje de ida y vuelta, pero la RFC 9846 deja claro que los datos 0-RTT no tienen ninguna garantía contra la repetición (replay) entre conexiones. Un atacante que capture el primer vuelo puede volver a enviarlo.
Las reglas prácticas:
- Envía como datos tempranos solo peticiones idempotentes:
GETsin efectos secundarios, nunca un pago ni un pedido. - En el servidor, activa 0-RTT solo donde la aplicación pueda rechazar o tolerar repeticiones. Muchos servidores marcan las peticiones con datos tempranos (por ejemplo, con la cabecera
Early-Data: 1definida en la RFC 8470) para que la aplicación pueda responder425 Too Early. - No uses 0-RTT para acciones autenticadas a menos que hayas pensado bien en la repetición.
TLS mutuo
En TLS mutuo (mTLS), el servidor también pide un certificado al cliente. El servidor añade un CertificateRequest después de EncryptedExtensions, y el cliente responde con su propio Certificate y CertificateVerify antes de su Finished. El número de viajes de ida y vuelta no cambia.
mTLS es lo habitual entre servicios en una malla: cada carga de trabajo recibe un certificado de corta duración, y los sidecars o proxies se encargan del handshake. El diagrama de arquitectura de service mesh muestra de dónde salen esos certificados, y el diagrama de arquitectura zero trust explica por qué la identidad por petición importa más que la red de la que viene la petición.
Privacidad y claves poscuánticas: qué hay de nuevo en 2026
Dos RFC recientes cambian el aspecto del handshake en la red.
Encrypted Client Hello. El ClientHello se envía antes de que exista ninguna clave, así que el SNI, el nombre de host que quiere el cliente, viaja en texto claro. La RFC 9849, publicada en marzo de 2026, define Encrypted Client Hello (ECH): el cliente cifra un ClientHello interior, con el nombre de host real, usando una clave que el servidor publica en el DNS. Los observadores solo ven un nombre exterior público, normalmente el de un gran proveedor.
Intercambio de claves poscuántico híbrido. El tráfico grabado hoy podría descifrarse más adelante con un ordenador cuántico, así que el intercambio de claves es lo primero en cambiar. La RFC 10024, publicada en agosto de 2026, define híbridos como X25519MLKEM768, que combina X25519 con ML-KEM-768. Ambos shares alimentan el key schedule, así que la conexión sigue siendo segura mientras cualquiera de los dos algoritmos aguante. Chrome y Edge 131 y posteriores, y Firefox 132 y posteriores, lo ofrecen por defecto.
El coste es el tamaño. Un share de cliente X25519MLKEM768 ocupa 1216 bytes y el del servidor 1120 bytes, frente a 32 bytes cada uno con X25519 a secas. Un ClientHello puede ocupar ahora dos paquetes, lo que dejó en evidencia a middleboxes que suponían que eso nunca pasaría.
El coste en viajes de ida y vuelta
Son los viajes de ida y vuelta, no el ancho de banda, los que deciden lo rápido que está lista una conexión. Con un viaje de ida y vuelta de 100 ms entre cliente y servidor, sin contar el DNS:
| Configuración | Idas y vueltas antes de la respuesta | Tiempo |
|---|---|---|
| TCP + TLS 1.2 + petición | 4 | 400 ms |
| TCP + TLS 1.3 + petición | 3 | 300 ms |
| TCP + TLS 1.3 con 0-RTT | 2 | 200 ms |
| QUIC (HTTP/3), conexión nueva | 2 | 200 ms |
| QUIC con 0-RTT | 1 | 100 ms |
QUIC lleva el mismo handshake de TLS 1.3 dentro de sus propios paquetes (RFC 9001) y lo fusiona con el handshake de transporte, que es donde desaparece el viaje de ida y vuelta extra. Terminar TLS cerca de los usuarios, en un CDN o en un balanceador de carga en el edge, acorta el propio viaje de ida y vuelta; el diagrama de balanceador de carga explica dónde suele hacerse la terminación.
El diagrama del handshake
Contenido del diagrama
- Client (browser)
- Server
- mutual TLS only
- ClientHello: key_share, supported_versions, SNI, ALPN
- ServerHello: key_share, chosen cipher suite
- {EncryptedExtensions}
- {CertificateRequest} (mTLS only)
- {Certificate}: server chain
- {CertificateVerify}: signature over the transcript
- {Finished}: MAC over the transcript
- {Certificate}: client chain
- {CertificateVerify}
- {Finished}
- [Application data], both directions
- NewSessionTicket (for resumption)
Cómo leerlo:
- Dos líneas de vida. El cliente a la izquierda, el servidor a la derecha. El tiempo corre hacia abajo.
- Las flechas simples se envían en texto claro: ClientHello y ServerHello. Todo lo que está debajo de la línea marcada «handshake keys» va cifrado.
- El vuelo del servidor lleva EncryptedExtensions, Certificate, CertificateVerify y Finished de una vez, y por eso el handshake cabe en un solo viaje de ida y vuelta.
- El fragmento opcional contiene el Certificate y el CertificateVerify del cliente, que solo se envían en TLS mutuo. El CertificateRequest discontinuo en el vuelo del servidor es lo que los pide.
- El bloque Markdown enumera las extensiones que deciden si el handshake tiene éxito: versiones, grupos, algoritmos de firma, SNI y ALPN.
Dibujar diagramas de protocolo que sirvan para depurar
- Marca la frontera del cifrado. La pregunta más común sobre TLS es qué puede ver un observador. Traza la línea.
- Nombra las extensiones que importan, no todas.
key_shareysupported_versionsexplican la mayoría de los fallos. - Pon los caminos opcionales y alternativos en fragmentos. Un fragmento
optpara los certificados de cliente y un fragmentoaltpara HelloRetryRequest mantienen legible el flujo principal. - Un diagrama por pregunta. Un handshake completo, una reanudación con 0-RTT y un intercambio mTLS son tres diagramas si cada uno necesita detalle.
El ejemplo de diagrama de secuencia trata con más profundidad las líneas de vida, los fragmentos y las convenciones de nombres.
Constrúyelo en Archboard
- Inicia sesión con Google o GitHub y crea un diagrama.
- Añade dos nodos Línea de vida del pack Secuencia, llamados Client y Server.
- Dibuja los mensajes como aristas entre las líneas de vida, de arriba abajo: ClientHello, ServerHello, después los cuatro mensajes cifrados del servidor y el Finished del cliente. Etiqueta cada arista con el nombre del mensaje y sus campos clave.
- Añade un Fragmento combinado del pack Secuencia con el operador
optalrededor del Certificate y el CertificateVerify del cliente, y dibuja el CertificateRequest del servidor como una arista discontinua. - Añade un bloque Markdown del pack Básico con las extensiones y el número de viajes de ida y vuelta, y una Nota que marque dónde empieza el cifrado.
El ejemplo usa 4 nodos de diagrama, dentro del plan Free.
Preguntas frecuentes
¿Cuántos viajes de ida y vuelta necesita un handshake de TLS 1.3? Uno para una conexión nueva, frente a dos en TLS 1.2. Un HelloRetryRequest añade un segundo, y la reanudación con 0-RTT permite al cliente enviar su primera petición sin ningún viaje de ida y vuelta de handshake.
¿Va cifrado el certificado del servidor en TLS 1.3? Sí. Todo lo que sigue a ServerHello, incluido el mensaje Certificate, se cifra con las claves del handshake. El ClientHello no, y ese es el hueco que cierra Encrypted Client Hello.
¿Es seguro activar 0-RTT? Solo para peticiones que se puedan repetir sin riesgo. Los datos tempranos pueden capturarse y volver a enviarse, así que limítalos a peticiones idempotentes y deja que la aplicación rechace todo lo demás con 425 Too Early.
¿TLS 1.3 sigue admitiendo certificados RSA? Sí. Las firmas RSA se siguen usando para autenticar servidores. TLS 1.3 eliminó el transporte de clave RSA, en el que el secreto de la sesión se cifraba con la clave RSA del servidor y una clave filtrada exponía el tráfico pasado.
¿Cuál es la diferencia entre TLS y mTLS? En TLS normal solo el servidor presenta un certificado. En TLS mutuo el servidor también pide un certificado al cliente, de modo que ambos lados se autentican en el mismo handshake.