
I measured 320 Chilean sites: half already use post-quantum cryptography, and almost none of them chose to
I probed the 320 most visited .cl domains: 145 negotiate X25519MLKEM768 (47.7%), but only 9 of the 128 with their own infrastructure. Measured cost: 0 ms.
A day ago I published that I had built a fully post-quantum handshake on my own server. It left me with an uncomfortable question: very nice on a laptop, but who actually has it? Not in a demo, not in a vendor’s blog. On the sites where a Chilean types their password every day.
So I measured it. I took the 320 best-ranked .cl domains and asked each one, one at a time, what cryptography it accepts for agreeing the key to the conversation. The short answer is that half already use post-quantum. The long answer is more interesting, because almost none of them chose it.
What is being replaced, and why the clock is running
When you open a page with a padlock, two things happen before the first useful byte. Both use cryptography, but they solve different problems and run on different clocks.
The first is agreeing a secret key while talking over a channel anyone can read. That is the key exchange, and it is what makes the rest of the conversation travel encrypted.
The second is proving who each side is, with a certificate signed by someone your browser trusts.
A quantum computer with enough capacity breaks both. But only one of them is urgent today, and that reason is what makes this impossible to postpone.
Encrypting is putting the letter in a sealed envelope. Somebody can steal the envelope this afternoon, store it in a warehouse and wait. The day the machine exists, they open it, and inside is what you sent today. It is called harvest now, decrypt later, and it is why the key exchange races a clock that is already running.
Signing is different. It is the guard checking your ID at the door: it only has to hold for the second the check lasts. Nobody can come back in 2035 to forge the ID you showed today, because today they already let you in.
That is why the ecosystem fixed the envelope first and left the ID for later. It was not an oversight: it was the right order. And what I measured across these 320 sites is exactly that first half, the urgent one: the key exchange.
- 01clientClientHello307 B1,485 B1,480 Bthis one grows
- 02serverServerHello122 B1,210 B—this one growsAlert · fatal handshake_failure (40)
- 03serverEncryptedExtensions10 B10 B—
- 04serverCertificate3,416 B3,416 B—
- 05serverCertificateVerify79 B79 B—
- 06serverFinished36 B36 B—
- 07clientFinished36 B36 B—
- 08serverNewSessionTicket122 B122 B—
handshake total: 4,128 Bhandshake total: 6,394 B · difference +2,266 B1,480 B sent before the connection died
The certificate weighs exactly the same in both runs that complete: it is still signed with a classic algorithm. That is the other half of the handshake, the one no server has switched on yet.
Against a server that does not know the algorithm there is no negotiation and no fallback: it answers alert 40 and closes. The browser avoids this because it offers both the classic and the post-quantum key in the same ClientHello; forcing only the post-quantum one, as here, is what makes the failure visible.
Full trace, as it comes out of the terminal
$ openssl s_client -connect efraingaray.com:443 -servername efraingaray.com \
-groups X25519MLKEM768 -msg -state </dev/null
SSL_connect:before SSL initialization
SSL_connect:SSLv3/TLS write client hello
>>> TLS 1.3, Handshake [length 05cd], ClientHello
SSL_connect:SSLv3/TLS read server hello
<<< TLS 1.3, Handshake [length 04ba], ServerHello
<<< TLS 1.3, ChangeCipherSpec [length 0001]
SSL_connect:TLSv1.3 read encrypted extensions
<<< TLS 1.3, Handshake [length 000a], EncryptedExtensions
<<< TLS 1.3, Handshake [length 0d58], Certificate
depth=3 C=US, O=Internet Security Research Group, CN=ISRG Root X2
verify return:1
depth=2 C=US, O=ISRG, CN=Root YE
verify return:1
depth=1 C=US, O=Let's Encrypt, CN=YE2
verify return:1
depth=0 CN=efraingaray.com
verify return:1
SSL_connect:SSLv3/TLS read server certificate
<<< TLS 1.3, Handshake [length 004f], CertificateVerify
SSL_connect:TLSv1.3 read server certificate verify
<<< TLS 1.3, Handshake [length 0024], Finished
SSL_connect:SSLv3/TLS read finished
>>> TLS 1.3, ChangeCipherSpec [length 0001]
>>> TLS 1.3, Handshake [length 0024], Finished
SSL_connect:SSLv3/TLS write finished
SSL_connect:SSL negotiation finished successfully
<<< TLS 1.3, Handshake [length 007a], NewSessionTicket
Negotiated TLS1.3 group: X25519MLKEM768
Protocol : TLSv1.3
Cipher : TLS_AES_128_GCM_SHA256
Verify return code: 0 (ok)Full trace of the failure
$ openssl s_client -connect www.sii.cl:443 -servername www.sii.cl \
-groups X25519MLKEM768 -msg -state </dev/null
SSL_connect:before SSL initialization
>>> TLS 1.3, Handshake [length 05c8], ClientHello
SSL_connect:SSLv3/TLS write client hello
<<< TLS 1.3, Alert [length 0002], fatal handshake_failure
SSL3 alert read:fatal:handshake failure
SSL_connect:error in error
error:0A000410:SSL routines:ssl3_read_bytes:ssl/tls alert handshake failure:
ssl/record/rec_layer_s3.c:918:SSL alert number 40
Negotiated TLS1.3 group: <NULL>How I measured it
I took the idea from Cloudflare, which published today how it probes its customers’ servers every 24 hours to find out what they can speak. The home-made version fits in one line:
openssl s_client -groups X25519MLKEM768 -connect bci.cl:443 -servername bci.cl </dev/null
If the server knows, it answers with the agreed key. If it does not, the connection never establishes, and then the question has to be repeated with the classic list to find out what it does speak. That second pass is what separates “no post-quantum” from “no answer”.
The 320 domains come from the Tranco ranking filtered by .cl, which is not the same as 320 Chilean companies: google.cl, airbnb.cl and adidas.cl are in there. Each one was measured with OpenSSL 3.6.3 from a home connection in Chile, on 8 September 2026.
The stumble that almost ruined the sample
The first results said Santander, BancoEstado and Scotiabank supported nothing. That was false: those domains do not resolve their apex name. Only www. in front exists. If you type santander.cl on its own, there is no IP address to go to.
Same with the Central Bank, which does not even have bancocentral.cl: its domain is bcentral.cl. In the end 31 of the 320 only answered with www. in front, several of them among the most visited sites in the country. The probe now retries before giving up.
The second flaw I found while reviewing the results, and it is subtler. Asking with only the post-quantum group on offer is not what a browser does: a browser also sends a classic fallback key in the same greeting. An edge that requires that fallback answers alert 40 to my question and post-quantum to the browser. That gave me one false negative, minvu.cl, which does have it. I asked the remaining 160 again the way a browser asks and only that one turned up: which is why the number in this article is 145 and not 144.
How many Chilean sites negotiate post-quantum
Of the 320 domains, 304 answer TLS and 16 did not answer: some do not resolve, four are state DNS servers and the rest timed out.
Of the 304 .cl domains answering TLS on 8 September 2026, 145 negotiate X25519MLKEM768: 47.7%.
It is better than I expected before measuring, and it does not mean what it looks like.
Who put it there
While the probe asked about cryptography, it also recorded who owns the IP address that answers. That separates two populations that look identical from the outside: the one that switched something on, and the one that received something.
9 with post-quantum / 9 sites
Nine out of nine. Banco de Chile, Transbank, Enel and Aguas Andinas sit here: none of them had to ask for it.
8 with post-quantum / 8 sites
Eight out of eight, and they carry the most weight: Santander, BancoEstado and Scotiabank serve their TLS from here.
77 with post-quantum / 79 sites
The most common edge in the sample, 79 sites, and 77 negotiate post-quantum. The two that do not are the exception that shows how this ships: by default and for everyone at once.
14 with post-quantum / 15 sites
Fourteen of fifteen. Same pattern: the provider made the call.
25 with post-quantum / 49 sites
Exactly half. CloudFront ships it, but hand-configured EC2 instances behave like any self-hosted server.
2 with post-quantum / 10 sites
Two out of ten, and it is the result I least expected from an edge this size.
1 with post-quantum / 6 sites
One out of six. A warning that applies to the whole table: what is grouped here is the owner of the IP address, not the product. These six sit on Microsoft addresses, which is not the same as being behind its CDN.
9 with post-quantum / 128 sites
Here is the whole story. 128 sites serve their own TLS and only 9 negotiate post-quantum. Most likely it is not that they decided against it: they run software older than OpenSSL 3.5 or Go 1.24, where it did not ship on yet.
Of 304 domains measured, 145 negotiate post-quantum: 47.7%. The 128 with their own infrastructure is a floor: Amazon and Google mix their CDN with hand-run machines.
There is the whole article. Of the 128 sites that serve TLS from their own infrastructure, nine have it. The other 136 that show up in the good column got it from their edge, without having to do anything.
That 47.7% is not a decision by the Chilean industry. It is a decision by Cloudflare, Akamai, Imperva and Fastly, applied to their customers without any of them having to ask.
A warning about this table: what I group is not the CDN, it is the owner of the IP address. Amazon and Google mix their CDN with machines someone runs by hand, so 128 is the floor for sites with their own infrastructure, not an exact count. Of the six on Microsoft addresses, one has it.
The nine that did decide
They are worth naming, because they are the ones who actually did something:
spensiones.cl (the Pensions Regulator), aiep.cl, uahurtado.cl, uft.cl, desis.cl, ibus.cl, creattiva.cl, v2net.cl and tecnoinver.cl.
The first is the striking one. The Pensions Regulator runs on the Interior Ministry’s infrastructure, the same address block where interior.gob.cl, registrocivil.cl and minsal.cl live. Those three do not have it and spensiones.cl does. Same provider, same network: the difference is in the software that answers, not in the network.
The Chilean map, with names
Among those that already negotiate post-quantum: Santander, BancoEstado, Scotiabank, Banco de Chile, BCI, Banco Falabella, Banco Ripley, Coopeuch, Consorcio, Transbank, ClaveÚnica, ChileAtiende, the General Treasury at tgr.gob.cl, the Central Bank, Ripley, Líder, Sodimac, Enel and Aguas Andinas.
Among those that do not: the Internal Revenue Service, the Financial Market Commission, the Civil Registry, the Health Ministry, Mercado Público, FONASA, SENCE, the Labour Directorate, Entel, Movistar, WOM, Emol, BioBioChile, Diario Financiero, Universidad de Chile, Universidad Católica, and NIC Chile, which runs the .cl domain.
Four names you would expect here are not in the sample, because the Tranco ranking does not carry them or carries them on another domain. I measured those separately, same command, same day: Itaú, Tenpo and falabella.com do negotiate it; Comisaría Virtual, VTR and La Tercera do not.
Of the 12 .gob.cl domains in the sample, 3 have it. All three sit behind a CDN.
What it costs: nothing
The obvious question is what you pay for this. ML-KEM sends more bytes than an elliptic curve, and more bytes in the handshake should cost time.
- ClientHello
- 306 B
- ServerHello
- 122 B
- on the wire
- 351 B
- whole handshake
- 428 B
- times X25519
- 1.0×
The elliptic curve half the internet uses. Its public key is 32 bytes, so the whole greeting fits comfortably in one packet.
TCP initial window · 14,600 B · 3%
- ClientHello
- 339 B
- ServerHello
- 155 B
- on the wire
- 384 B
- whole handshake
- 494 B
- times X25519
- 1.2×
The classic NIST curve, used by 48 of the Chilean sites that have not made the jump. It weighs 66 bytes more than X25519 and offers the same protection against a quantum computer: none.
TCP initial window · 14,600 B · 3%
- ClientHello
- 1,484 B
- ServerHello
- 1,210 B
- on the wire
- 1,529 B
- whole handshake
- 2,694 B
- times X25519
- 6.3×
The hybrid. It sends both keys: the curve’s 32 bytes and ML-KEM’s 1,184. The ClientHello grows to 1,484 bytes and reaches 1,529 with headers: it crosses the 1,500 MTU and the system splits it into two packets. Even so the whole handshake, 2,694 bytes, fits five times inside TCP’s initial window, so both packets travel together without waiting for a reply. Six times the bytes, zero milliseconds.
TCP initial window · 14,600 B · 18%
Here is a trap worth telling, because I fell into it. My first comparison took the median of the post-quantum sites (202 ms) against the classic ones (100 ms) and seemed to say post-quantum doubles the time. That number measures nothing. Sites behind a CDN are closer to the visitor than a server in a Chilean datacenter: what I measured was distance, not the algorithm.
The only valid comparison is each server against itself. Twelve handshakes of each type, alternated so a passing congestion hits both equally:
| Server | post-quantum | classic | difference |
|---|---|---|---|
| bci.cl | 80.1 ms | 87.7 ms | −7.6 ms |
| transbank.cl | 80.2 ms | 87.0 ms | −6.8 ms |
| cloudflare.com | 81.1 ms | 82.7 ms | −1.6 ms |
| coopeuch.cl | 79.6 ms | 80.3 ms | −0.7 ms |
| claveunica.gob.cl | 82.0 ms | 81.6 ms | +0.4 ms |
| www.bancoestado.cl | 92.8 ms | 92.2 ms | +0.7 ms |
| efraingaray.com | 263.5 ms | 262.7 ms | +0.8 ms |
| falabella.com | 86.2 ms | 83.6 ms | +2.7 ms |
Median difference: −0.1 ms. Worst case: +2.7 ms.
It is indistinguishable from zero, and in four of the eight the post-quantum run came out faster, which only means the network noise is larger than the effect we are looking for. That is the conclusion: the cost sits below the noise.
How to switch on post-quantum cryptography on a server
Here comes the part that surprised me: you almost never switch it on, you inherit it.
I went to my own Caddyfile to find the line where I configured this so I could explain it. It does not exist. In 373 lines of configuration there is not a single curve or key-exchange directive. My server runs the official caddy:2-alpine image, version 2.11.3, and it negotiates X25519MLKEM768 because the binary is compiled with a Go that ships it on by default. In the previous article I recompiled that same Caddy with Go 1.27, but that was a lab test for the certificates: production runs the official image, untouched.
I am in the same position as the 136 sites that got it from their edge. The only difference is who gave it to me: their provider to them, the Caddy team to me.
These are the versions from which it ships on by default:
| Software | from version |
|---|---|
| OpenSSL | 3.5.0 |
| Go | 1.24 |
| Caddy | 2.10.0 |
| Traefik | 3.4.2 (and 2.11.26) |
| nginx | compiled against OpenSSL 3.5+ |
| Node.js | 22.20.0 and 24.5.0 |
| Chrome | 131 |
| Firefox | 132 |
None of those rows asks for configuration: they ask for an update.
That reframes the 7% of sites with their own infrastructure. Most likely it is not that they decided against post-quantum cryptography: it is that they run software older than those versions. The 110 negotiating X25519 have modern TLS 1.3 and are one library version away. The 48 on old NIST curves have a bit further to go.
To check it yourself
On your own server, with OpenSSL 3.5 or newer:
openssl s_client -groups X25519MLKEM768 -connect yourdomain.cl:443 \
-servername yourdomain.cl </dev/null 2>/dev/null | grep "Negotiated TLS1.3 group"
If it answers X25519MLKEM768, you already have it. If it answers nothing, your server does not know how to speak it yet.
And a warning that cost me time in the previous article: check with the binary your program uses, not the one in your terminal. On the same Mac, the command-line OpenSSL 3.6.3 and the 3.0.16 that Python ships give different answers to the same question.
What I would do today
Post-quantum cryptography in the key exchange
✓ Aquí puedes
- Check what your server negotiates today: it is one command and it changes nothing
- Update the TLS library instead of hunting for a directive that mostly does not exist: on OpenSSL 3.5+, Go 1.24+ or Caddy 2.10+ it ships on
- If you are behind a CDN, verify it also speaks it to your origin and not only to the visitor
- Check whether your apex domain resolves without www: five large sites in this sample do not
✗ Aquí nunca
- Disable the hybrid to keep only the post-quantum algorithm: the classic half is the safety net
- Assume a site is insecure because it lacks it: TLS 1.3 with X25519 is still solid against any attacker today
- Compare timings across different servers to decide whether it costs much: that measures distance, not the algorithm
The concrete task fits in an afternoon: run the command above against your own domains, and for the ones that do not answer, check which OpenSSL or Go version the binary serving them has. In most cases the fix is an update you already had pending for other reasons.
What stayed with me from this measurement is not the 47%. It is that the Pensions Regulator and the Civil Registry run on the same network, with the same provider, and one has it and the other does not. There was no policy decision and no budget involved. The difference is in the software answering the connection.
The full list
Publishing only the percentage asks you to take my word for it. Here are the 304 domains one by one, with the group each negotiated and who serves its TLS, so anyone can take their own, run the command above and correct me if I got it wrong.
A domain with www. means its apex name does not resolve: only the www. host exists.
Sources
The standards.
- FIPS 203: Module-Lattice-Based Key-Encapsulation Mechanism Standard. ML-KEM, the post-quantum half of X25519MLKEM768.
- NIST IR 8547: Transition to Post-Quantum Cryptography Standards. The 2030 and 2035 deadlines.
- draft-kwiatkowski-tls-ecdhe-mlkem-03. The draft defining the
X25519MLKEM768group measured here.
What set off the measurement.
- Cloudflare: Automatic Key Exchange, 8 September 2026. How they probe origins every 24 hours to pick the most secure key agreement each one accepts.
- Cloudflare: post-quantum cryptography support by product. The minimum versions in the table come from here.
The sample.
- Tranco list. The ranking the 320
.cldomains came from.
Comments
No comments yet. The first one is yours.