HTTPS por dentro: del clic al candado, paso a paso

Escribes una dirección, pulsas Intro y, un instante después, aparece la página con un candado en la barra. En ese instante pasan muchas cosas: tu equipo busca una dirección IP, abre una conexión, comprueba que el servidor es quien dice ser, acuerda con él una clave secreta sin enviarla por el cable y, solo entonces, pide la página, que viaja envuelta en cifrado. Esta guía recorre ese camino paso a paso, con pruebas reales hechas con openssl, curl y una captura de paquetes, para que veas cada pieza en lugar de tener que creerla.

El problema: HTTP viaja a la vista de todos

HTTP, el protocolo con el que se piden las páginas, es texto. Entre tu equipo y el servidor hay routers, el wifi de la cafetería, tu proveedor de internet y otras máquinas que pasan los paquetes de mano en mano, y cualquiera de ellas puede leerlos. Para comprobarlo montamos dos servidores locales que sirven el mismo archivo con una «clave» inventada, uno por HTTP y otro por HTTPS, y capturamos los paquetes de cada uno. Esto es lo que contienen los paquetes del servidor HTTP, tal cual viajan:

captura de los paquetes TCP del servidor HTTP--- cliente → servidor, 90 bytes
GET /secreto.txt HTTP/1.1
Host: miweb.test:8080
User-Agent: curl/8.14.1
Accept: */*
--- servidor → cliente, 138 bytes
HTTP/1.0 200 OK
Server: BaseHTTP/0.6 Python/3.13.5
Date: Sun, 11 Oct 2026 14:34:06 GMT
Content-Type: text/plain
Content-Length: 36
--- servidor → cliente, 36 bytes
usuario=ana&clave=Tr3s-Gatos-Azules

Cualquiera que vea pasar los paquetes lee la dirección pedida, tu navegador y, lo peor, la contraseña. Además podría cambiar el contenido sin que ninguno de los dos extremos se enterase, y no hay forma de saber si el servidor es el verdadero o un impostor que se hizo pasar por él. HTTPS existe para arreglar esas tres cosas.

Qué promete HTTPS

HTTPS no es otro protocolo: es el mismo HTTP, pero dentro de una conexión protegida por TLS (Transport Layer Security, el sucesor de SSL). TLS aporta tres garantías distintas, cada una con su propia pieza:

GarantíaQué significaQué la consigue
ConfidencialidadQuien escucha el cable no puede leer el contenidoCifrado simétrico con una clave que solo conocen los dos extremos
IntegridadNadie puede cambiar un solo bit sin que se noteUna etiqueta de autenticación en cada registro
AutenticidadHablas con el servidor del dominio que pediste, no con un impostorEl certificado del servidor y una firma con su clave privada

El viaje completo: de la dirección a la página

Antes de que viaje ni un byte de la página hay varios pasos previos, y se pueden medir. Esto es lo que tardó una conexión nueva a decodigo.com desde mi equipo, con curl:

curl -so /dev/null -w 'dns %{time_namelookup}  tcp %{time_connect}  tls %{time_appconnect}  primer_byte %{time_starttransfer}  total %{time_total}\n' https://decodigo.com/
cinco conexiones nuevas, tiempos acumulados en segundosdns 0.023287  tcp 0.095844  tls 0.183346  primer_byte 0.515360  total 0.646221
dns 0.020266  tcp 0.092938  tls 0.177870  primer_byte 0.706273  total 0.846151
dns 0.018106  tcp 0.085600  tls 0.170987  primer_byte 0.571914  total 0.710526
dns 0.029140  tcp 0.097581  tls 0.173287  primer_byte 0.666224  total 0.800713
dns 0.018113  tcp 0.090188  tls 0.173125  primer_byte 1.257789  total 1.394926

Los números de curl son acumulados: cada columna incluye las anteriores. Restando, en la primera conexión: 23 ms para averiguar la IP, 73 ms para abrir la conexión TCP, 88 ms para el apretón de manos de TLS, 332 ms hasta que el servidor responde con el primer byte y 131 ms más hasta recibir todo.

Una conexión nueva a decodigo.com, medida con curl desde mi equipoel tiempo va de izquierda a derecha, a escala646 ms hasta recibir la página enteraDNSTCPTLSServidorPrimer byte de la página: 515 ms. Otras conexiones: 570-1,260 ms; la parte variable es el servidor.23 ms · DNS: averigua la IP73 ms · TCP: abre la conexión88 ms · TLS: cifrado y certificado332 ms · el servidor genera la páginaDescarga131 ms · llega el resto

Tiempos de la primera conexión de la tabla anterior, a escala.
  1. DNS. El navegador traduce decodigo.com en una dirección IP. Aquí todavía no hay cifrado, y por eso existe DNSSEC; lo contamos en el artículo sobre el cambio de clave raíz del DNS.
  2. TCP. Abre una conexión con la IP, puerto 443, con el saludo de tres pasos de TCP. El tiempo es casi todo el viaje de ida y vuelta por la red.
  3. TLS. El apretón de manos que veremos enseguida. Con TLS 1.3 cuesta aproximadamente una ida y vuelta más.
  4. HTTP. Por fin se pide la página, ya por dentro del canal cifrado.

Lo que varía de una conexión a otra es el tiempo hasta el primer byte, de 515 a 1,258 ms en estas cinco pruebas: lo que tarda el servidor en generar la página (aquí es WordPress con PHP). El apretón de manos, por el contrario, es estable, y ahora verás que no es un coste enorme.

Una pregunta típica: ¿viaja algo sin cifrar si escribo http://decodigo.com? El servidor responde con una redirección 301 a la versión https, pero ese primer pedido sí viajó sin cifrar. Más adelante vemos cómo se evita con HSTS.

El apretón de manos de TLS 1.3, mensaje a mensaje

Veamos el diálogo real con decodigo.com. Con curl -v se ve cada mensaje por su nombre, y con openssl s_client, los parámetros que se eligieron:

curl -v https://decodigo.com/ -o /dev/null

NavegadorServidor1 · ClientHelloversiones y cifrados que acepta · nombre del sitio (SNI) · ALPN · su mitad de la clave (key_share)2 · ServerHelloelige TLS 1.3 y un cifrado · envía su mitad de la claveCon las dos mitades, cada lado calcula la misma clave secreta · desde aquí todo viaja cifrado3 · EncryptedExtensionsacuerdan el protocolo de aplicación (ALPN): h24 · Certificatela cadena de certificados: sitio e intermedios5 · CertificateVerifyfirma con la clave privada del sitio: prueba que el certificado es suyo6 · Finishedresumen de todo el diálogo, para detectar manipulaciones7 · Finishedlo mismo, desde el navegador8 · GET / HTTP/2y la respuesta vuelve igual: todo en registros cifradosOrden real observado con curl y openssl s_client contra decodigo.com

Los ocho pasos. Los dos primeros mensajes salen sin cifrar; desde el tercero, todo lo cifra la clave recién acordada.

Cada mensaje tiene una función concreta:

  • ClientHello. El navegador dice qué versiones de TLS y qué cifrados entiende, a qué dominio quiere llegar (el campo SNI, para que un mismo servidor pueda alojar muchos sitios), qué protocolos de aplicación admite (ALPN: h2 para HTTP/2 y http/1.1) y, ya de entrada, su mitad de un intercambio de claves.
  • ServerHello. El servidor elige una versión y un cifrado y devuelve su mitad del intercambio de claves. Con las dos mitades, cada lado puede calcular el mismo secreto, y a partir de ahí todo va cifrado. En TLS 1.3 esto ocurre en una sola ida y vuelta, algo que en TLS 1.2 necesitaba dos.
  • EncryptedExtensions. Detalles como el protocolo de aplicación acordado (ALPN).
  • Certificate. La cadena de certificados del servidor, que ya viaja cifrada. Es una de las novedades de TLS 1.3: un espía ya no ve ni el certificado.
  • CertificateVerify. Una firma, hecha con la clave privada del sitio, sobre todo lo dicho hasta ahora. Demuestra que quien envió el certificado tiene la clave privada que le corresponde.
  • Finished (los dos lados). Un resumen criptográfico de todo el diálogo. Si alguien hubiera alterado un mensaje por el camino, los resúmenes no coincidirían.

Los parámetros elegidos con decodigo.com fueron estos:

líneas de openssl s_client -alpn h2,http/1.1 contra decodigo.comPeer signature type: rsa_pss_rsae_sha256
Verification: OK
New, TLSv1.3, Cipher is TLS_AES_256_GCM_SHA384
Protocol: TLSv1.3
Verify return code: 0 (ok)
ALPN protocol: h2

El intercambio de claves usado fue X25519, y el cifrado, AES-256 en modo GCM con SHA-384.

El servidor acepta TLS 1.2 y 1.3, y rechaza 1.0 y 1.1 (responde con una alerta de «versión de protocolo»), que están abandonados por inseguros. Que ALPN termine en h2 significa que la conversación siguiente usa HTTP/2, que el servidor tiene activo.

Cómo se acuerda una clave sin enviarla

Esta es la parte que más desconcierta: ¿cómo pueden dos extremos que nunca se han visto ponerse de acuerdo en una clave secreta por un cable que todos vigilan? Con un intercambio de claves de tipo Diffie-Hellman. La idea cabe en un ejemplo con números pequeños: ambos acuerdan públicamente dos números, p = 23 y g = 5; cada uno elige un número secreto y envía el resultado de una operación con él.

Diffie-Hellman con números pequeñosAna envía  A = g^a mod p = 5^6 mod 23 = 8
Beto envía B = g^b mod p = 5^15 mod 23 = 19
Ana calcula  B^a mod p = 2
Beto calcula A^b mod p = 2   <- el mismo número, sin haberlo enviado
lo que ve un espía: {'p': 23, 'g': 5, 'A': 8, 'B': 19}

Ana usa su secreto (6) y el valor que envió Beto (19); Beto usa el suyo (15) y el de Ana (8); y los dos llegan a 2. El espía ve 23, 5, 8 y 19, pero para llegar a 2 necesitaría uno de los dos secretos, y recuperarlos a partir de lo público es el problema difícil. Con números tan pequeños se resuelve a mano, pero con los tamaños reales, no.

TLS 1.3 usa una variante moderna sobre curvas elípticas, X25519. Esto es lo mismo con claves de verdad, hecho con openssl: cada lado genera una clave privada aleatoria y su clave pública de 32 bytes, se intercambian las públicas, y los dos terminan con idéntico secreto.

X25519 real; las claves son aleatorias, en tu equipo saldrá otro valorAna  calcula (su clave privada + la pública de Beto):
da6d10f790492d8af1fb7bfba21df898f02781e9c16ab2168c453bd066a5160f
Beto calcula (su clave privada + la pública de Ana):
da6d10f790492d8af1fb7bfba21df898f02781e9c16ab2168c453bd066a5160f

tamaño de cada clave pública (bytes): 32

De ese secreto compartido salen las claves de cifrado que se usarán en la conexión. Como las claves privadas se crean para cada conexión y se tiran, aunque alguien guardara hoy una captura y robase mañana la clave del servidor, no podría descifrarla. Esa propiedad se llama secreto hacia adelante (forward secrecy).

Un detalle curioso: mi servidor de pruebas local, con Python 3.13 y OpenSSL 3.5, negoció X25519MLKEM768 y no X25519. Es un intercambio híbrido que añade un algoritmo resistente a ordenadores cuánticos (ML-KEM) al de curva elíptica. El cliente de mi equipo lo ofrece también a decodigo.com, pero ese servidor eligió X25519. Lo que hay en juego es que alguien guarde hoy tráfico cifrado para descifrarlo en el futuro con un ordenador cuántico.

El certificado: qué demuestra y qué no

El intercambio de claves tiene un fallo: no dice con quién hablas. Si un impostor se interpone, acordaría una clave con cada lado y leería todo. La autenticidad la aporta el certificado: un documento que dice «esta clave pública pertenece a este dominio» y que está firmado por una autoridad certificadora (CA) de confianza. Así es el de decodigo.com, extraído del apretón de manos real:

openssl x509 sobre el certificado que envía decodigo.comsubject=CN=decodigo.com
issuer=C=US, O=GoDaddy.com, CN=GoDaddy TLS Intermediate CA DV - R1v1
notBefore=Sep 15 05:12:48 2026 GMT
notAfter=Apr  1 05:12:48 2027 GMT
serial=C79BE2AEA7234CFA
sha256 Fingerprint=88:38:F0:4A:2C:6A:C5:06:A0:84:22:35:4D:F5:C6:56:10:D6:E3:86:D8:1F:03:92:0D:45:F0:30:6E:1C:30:72
X509v3 Basic Constraints: critical
    CA:FALSE
X509v3 Extended Key Usage:
    TLS Web Server Authentication
X509v3 Key Usage: critical
    Digital Signature, Key Encipherment
X509v3 Subject Alternative Name:
    DNS:decodigo.com, DNS:www.decodigo.com
CampoQué dice
subject, Subject Alternative NameA quién se emitió: decodigo.com y www.decodigo.com. Es lo que el navegador compara con la dirección que escribiste.
issuerQuién lo firmó: una CA intermedia de GoDaddy.
notBefore / notAfterPeriodo de validez: del 15 de septiembre de 2026 al 1 de abril de 2027.
Clave públicaUna clave RSA de 2048 bits, la pareja de la clave privada que guarda el servidor. Con ella se comprueba la firma de CertificateVerify.
CA:FALSEEs un certificado de sitio: no puede usarse para firmar otros certificados.
Extended Key UsageSolo vale para autenticar servidores web (serverAuth).
Firma de la CAEl sello que hace que todo lo anterior sea creíble: si cambia un solo byte, la firma deja de cuadrar.

Fíjate en lo que no dice. Este certificado es de validación de dominio: la CA comprobó que quien lo pidió controla decodigo.com, y nada más. No dice que el sitio sea honesto, ni seguro, ni de una empresa concreta. Una página de estafa puede tener un candado perfecto: lo que garantiza es que hablas con ese dominio y que nadie lo escucha por el camino, no que debas fiarte de él.

La cadena de confianza

Si la CA firma, ¿quién garantiza a la CA? Otra CA, y así hasta llegar a una raíz. Las raíces no están firmadas por nadie más: tu sistema operativo o tu navegador las traen de fábrica en su almacén de confianza (mi equipo tiene 121), y esa es la base de todo. El servidor de decodigo.com envía tres certificados y openssl reconstruye la cadena entera:

openssl verify -show_chain sobre los certificados recibidoscert1.pem: OK
Chain:
depth=0: CN=decodigo.com (untrusted)
depth=1: C=US, O=GoDaddy.com, CN=GoDaddy TLS Intermediate CA DV - R1v1 (untrusted)
depth=2: C=US, O=GoDaddy.com, CN=GoDaddy TLS Root CA - R1 (untrusted)
depth=3: C=US, ST=Arizona, L=Scottsdale, O=GoDaddy.com, Inc., CN=Go Daddy Root Certificate Authority - G2

La cadena de decodigo.com, tal como la verificó opensslGo Daddy Root Certificate Authority - G2Raíz · ya está en el almacén de tu sistema o navegador (121 en mi equipo)firma al de abajoGoDaddy TLS Root CA - R1Firmada por la raíz anterior · el servidor la envíafirma al de abajoGoDaddy TLS Intermediate CA DV - R1v1Intermedia · CA:TRUE, pathlen:0 (puede firmar sitios, no otras CA) · el servidor la envíafirma al de abajodecodigo.comCertificado del sitio · CA:FALSE · nombres: decodigo.com y www.decodigo.com · válido del15/09/2026 al 01/04/2027Si la firma de un eslabón no se puede comprobar, o el nombre o la fecha no encajan, el navegador avisa.lo envíael servidor

Cada certificado lo firma el de arriba; el servidor envía los tres de abajo, y la raíz ya está en tu equipo.

El servidor envía los tres primeros y no la raíz, porque esa ya la tiene el navegador, y mandarla sería inútil: lo que importa es que viene de tu almacén, no del servidor. La intermedia existe por seguridad: la clave de la raíz se guarda fuera de línea y solo se usa para firmar unas pocas CA intermedias, que son las que firman a diario los certificados de los sitios. Si una intermedia se compromete, se revoca sin tocar la raíz. Según el certificado, la intermedia de decodigo.com tiene CA:TRUE, pathlen:0: puede firmar sitios, pero no otras CA.

Cómo falla una verificación: cinco casos reales

Para ver los errores de verdad creamos una autoridad certificadora de juguete y un certificado para miweb.test, y le pedimos a openssl que lo verifique en cinco situaciones:

openssl verify con una autoridad de prueba propia=== 1. verificar SIN conocer la autoridad
  CN=miweb.test
  error 20 at 0 depth lookup: unable to get local issuer certificate
=== 2. verificar CONOCIÉNDOLA
  miweb.crt: OK
=== 3. el nombre no coincide
  CN=miweb.test
  error 62 at 0 depth lookup: hostname mismatch
=== 4. caducado (dentro de 100 días, el certificado dura 90)
  CN=miweb.test
  error 10 at 0 depth lookup: certificate has expired
=== 5. alguien cambia un byte del certificado
  CN=liweb.test
  error 7 at 0 depth lookup: certificate signature failure
CasoQué pasóQué verías en el navegador
1La CA no está en el almacén de confianzaAviso de «conexión no privada» (autoridad desconocida o certificado autofirmado)
2La CA se conoce y la firma cuadraCandado, sin avisos
3El certificado es de otro nombreAviso de que el certificado no es válido para ese dominio
4Fuera de su periodo de validezAviso de certificado caducado
5Cambiamos miweb por liweb: la firma ya no cuadraAviso de certificado no válido: nadie puede retocarlo sin que se note

En el último caso basta cambiar una letra para que la firma falle: la CA firmó un resumen de todo el contenido del certificado, y cualquier cambio altera el resumen. Por eso un impostor no puede presentarte un certificado «de decodigo.com» con su propia clave pública: tendría que fabricar la firma de una CA, y no puede.

El envoltorio: cómo viaja el contenido cifrado

Tras el apretón de manos, el navegador y el servidor tienen claves de cifrado. TLS divide la conversación en registros y cifra cada uno con AES-256-GCM, el cifrado que eligieron ambos. GCM cifra y, a la vez, calcula una etiqueta de 16 bytes que depende de todo el contenido: sin la clave no se puede ni leer el mensaje ni fabricar una etiqueta válida. El registro viaja dentro de un segmento TCP, dentro de un paquete IP:

Lo que viaja por el cable cuando el navegador pide la páginalos bytes son los de la captura real: 90 de petición, 112 en el cablePaquete IPSegmento TCPRegistro TLS (los bytes de aquí dentro son los únicos que viajan protegidos)Cabecera5 bytes17 03 03 00 6b(tipo, versión, largo)Contenido cifrado: 90 bytesGET /secreto.txt HTTP/1.1 · Host · User-Agent · Accept…en el cable solo se ve una sucesión de bytes sin sentidoTipo1 byte(cifrado)Etiqueta de integridad16 bytesdetecta cualquier cambioLongitud del registro en la cabecera: 107 = 90 + 1 + 16. En el cable: 5 + 107 = 112 bytes.Sigue a la vista, aunque vaya cifrado: las IP, los puertos, el tamaño de cada registro y cuándo se envía.

El mismo GET de la captura, de 90 bytes, tal como viaja por el cable.

Los tamaños de la captura lo confirman al byte. Cada registro mide su contenido más 17 bytes: 1 del tipo de contenido (que también va cifrado) y 16 de la etiqueta. La petición de 90 bytes se convirtió en un registro de 107; la cabecera de la respuesta, de 138, en 155; el cuerpo, de 36, en 53. Esta es la lista de registros de la captura HTTPS, en orden. Todos son del tipo 23, «Application Data», excepto el saludo inicial y el ChangeCipherSpec, un resto de compatibilidad con versiones antiguas que no hace nada:

registros TLS de la captura HTTPS, con nuestra anotación entre paréntesiscliente → servidor  22 Handshake        longitud  1565
cliente → servidor  20 ChangeCipherSpec longitud     1
cliente → servidor  23 Application Data longitud    69   (Finished)
cliente → servidor  23 Application Data longitud   107   (la petición: 90 + 17)
cliente → servidor  23 Application Data longitud    19   (aviso de cierre)
servidor → cliente  22 Handshake        longitud  1210   (ServerHello)
servidor → cliente  20 ChangeCipherSpec longitud     1
servidor → cliente  23 Application Data longitud    23   (EncryptedExtensions)
servidor → cliente  23 Application Data longitud   887   (Certificate: 857 bytes + 30)
servidor → cliente  23 Application Data longitud   281   (CertificateVerify)
servidor → cliente  23 Application Data longitud    69   (Finished)
servidor → cliente  23 Application Data longitud   250   (NewSessionTicket)
servidor → cliente  23 Application Data longitud   250   (NewSessionTicket)
servidor → cliente  23 Application Data longitud   155   (cabecera de respuesta: 138 + 17)
servidor → cliente  23 Application Data longitud    53   (cuerpo: 36 + 17)

Las anotaciones las hemos añadido nosotros cuadrando tamaños, porque desde fuera no se ven. La cabecera de cada registro, que sí viaja en claro, solo dice su tipo, la versión y el largo (17 03 03 00 6b es «datos de aplicación, 107 bytes»).

La etiqueta de integridad, probada

Para verlo funcionar, cifré con AES-256-GCM el mismo texto de 90 bytes (con una clave fija, solo para que el resultado sea repetible; las reales son aleatorias):

AES-256-GCM con la biblioteca cryptography de Pythonmensaje: 90 bytes   cifrado: 106 bytes   (+16 de etiqueta de integridad)
mismo mensaje, número distinto -> cifrados distintos
cifrado 1: 00 47 82 3b ea 96 a7 78 ff 24 e3 e4 9f 9d 00 19 a3 9e d3 60 a0 54 6e 52 …
cifrado 2: 42 af 0e f5 c3 e7 95 e5 3e c7 17 28 3e 67 92 5c 62 0b b5 aa c7 42 61 eb …
descifrar con la clave buena -> b'GET /secreto.txt HTTP/1.1'
descifrar con 1 bit alterado -> InvalidTag: se rechaza entero, sin dar ni un byte
descifrar con otra clave     -> InvalidTag

Tres cosas a destacar. Con otro número de uso único (nonce), el mismo texto da un cifrado totalmente distinto, así que un espía no puede ni saber si repites una petición. Con la clave correcta se recupera el texto. Y si se altera un solo bit o se usa otra clave, el descifrado se rechaza por completo: no sale un mensaje corrompido, sale un error. Por eso un intermediario que intente modificar la página no puede hacerlo sin que se note: lo máximo que consigue es cortar la conexión.

Qué ve un espía

La captura HTTPS del mismo servidor, con la misma contraseña, deja este resultado:

búsqueda de texto en las dos capturas¿aparece el secreto en cada captura? (veces que sale 'clave=')
  http : 1
  https: 0
y el nombre del sitio, o el certificado, ¿se ven en la captura HTTPS?
  'miweb.test' (nombre pedido, SNI): 1 vez/veces
  'Autoridad de prueba' (el certificado): 0
  'GET /secreto.txt': 0

Lo que un espía no ve: la dirección completa pedida (/secreto.txt), las cabeceras, el contenido, las cookies, las contraseñas y, con TLS 1.3, tampoco el certificado. Lo que sí ve:

  • Las direcciones IP de origen y destino, y el puerto.
  • El nombre del sitio, miweb.test en la prueba, porque el campo SNI del ClientHello va en claro. Sabe que visitas decodigo.com, pero no qué artículo lees. Existe una extensión (ECH, Encrypted Client Hello) que lo oculta, aunque todavía no está generalizada.
  • El tamaño de cada registro y cuándo se envían. Con los tamaños, un observador paciente puede deducir bastante, por ejemplo qué página de un sitio conocido se descargó.

Lo que HTTPS no hace

  • No te protege de un sitio malicioso. Cifra la conexión con quien tengas en frente, sea quien sea, como vimos con la validación de dominio.
  • No protege el equipo de los extremos. Si tu ordenador tiene un virus, o el servidor está comprometido, lo que ve cada uno no depende del cifrado.
  • No esconde con quién hablas, como acabamos de ver (IP y SNI).
  • No obliga por sí solo a usar HTTPS. Si escribes http://decodigo.com, la primera petición va en claro y un atacante en medio podría impedir la redirección. La defensa es HSTS: una cabecera, Strict-Transport-Security, con la que el servidor dice «durante los próximos N segundos, usa siempre HTTPS conmigo». El navegador la recuerda y, a partir de ahí, nunca vuelve a intentar HTTP en ese sitio. decodigo.com la envía desde el 11 de octubre de 2026, de momento con max-age=300 (cinco minutos) para ir subiéndolo poco a poco: un valor largo y un certificado caducado dejarían el sitio inaccesible. Sin includeSubDomains ni preload.

Compruébalo tú

Con el candado del navegador puedes ver el certificado, pero los comandos enseñan más. Sustituye decodigo.com por cualquier sitio:

# el apretón de manos, mensaje a mensaje
curl -v https://decodigo.com/ -o /dev/null

# versión, cifrado y cadena de certificados que envía el servidor
openssl s_client -connect decodigo.com:443 -servername decodigo.com -showcerts </dev/null

# el certificado del sitio, legible
openssl s_client -connect decodigo.com:443 -servername decodigo.com </dev/null 2>/dev/null | openssl x509 -noout -subject -issuer -dates -ext subjectAltName

# ¿acepta TLS 1.1? Hay que bajar el nivel de seguridad de tu propio openssl para que llegue a intentarlo
openssl s_client -connect decodigo.com:443 -servername decodigo.com -tls1_1 -cipher 'ALL:@SECLEVEL=0' </dev/null

# ¿envía HSTS? (decodigo.com responde: strict-transport-security: max-age=300)
curl -sI https://decodigo.com/ | grep -i strict-transport

Y si te interesa mirar paquetes, tcpdump y Wireshark muestran los registros TLS tal como los hemos visto aquí. Para probarlo sin riesgos, hazlo con un servidor tuyo en local, como en esta guía, y no con tráfico de otras personas.

Resumen

PasoQué ocurreQué aporta
DNSSe averigua la IP del dominioSaber a dónde conectar
TCPSe abre la conexión al puerto 443Un canal fiable, todavía sin protección
ClientHello / ServerHelloSe eligen la versión y el cifrado, y se intercambian las mitades de la claveUna clave compartida que nunca viajó por el cable
Certificate / CertificateVerifyEl servidor presenta su cadena y firma con su clave privadaAutenticidad: el dominio es de quien lo pidió
FinishedLos dos lados comprueban un resumen del diálogoNadie alteró el apretón de manos
HTTP en registros TLSCada registro se cifra con AES-GCM y lleva una etiqueta de 16 bytesConfidencialidad e integridad

La lección práctica es que cada garantía tiene su pieza y ninguna sobra: sin el intercambio de claves, nadie puede cifrar; sin el certificado, el cifrado sería con un impostor; sin la etiqueta, nadie notaría una alteración. Y el coste real es pequeño: una ida y vuelta de más antes de la primera petición.

Todo lo medido se ejecutó el 11 de octubre de 2026 desde un equipo con openssl 3.5 y curl 8.14, contra decodigo.com y contra servidores locales; las salidas están copiadas de esas ejecuciones. Los estándares: RFC 8446 (TLS 1.3), RFC 5280 (certificados X.509) y RFC 6797 (HSTS).

Fuente: IETF, RFC 8446, «The Transport Layer Security (TLS) Protocol Version 1.3»