TLS traffic with Chrome and Wireshark
TLS traffic inspection on Ubuntu/Wireshark can be easily configured. For each TLS handshake the encryption keys need to be made available at the middle man. For this to run automatically we need two things: 1) activate the dumping of the (pre)master-secret and 2) Wireshark needs to know where to look.
Following steps have been tested on Ubuntu Noble Numbat 24.04, Google Chrome 133.0.6943.141(official build)(64-bit) and Wireshark 4.2.2:
- add SSLKEYLOGFILE to the environment and start Chrome: export SSLKEYLOGFILE=/home/hiddenuser/.ssl-key.log && google-chrome
- browse to some https:// URL and verify the keylog file is being updated
- in Wireshark at the Edit->Preferences->Protocols->TLS under the (Pre)-Master-Secret log filename, use the above file “/home/hiddenuser/.ssl-key.log”
- generate traffic and inspect it by adding to Wireshark a general filter “tls && (http || http2)”
TLS Keylog File
The .ssl-key.log file format – each line contains a separate secret composed of 3 values:
- the label
- identifies the type of secret
- there can be multiple types, for ex: CLIENT_RANDOM, CLIENT_HANDSHAKE_TRAFFIC_SECRET, SERVER_HANDSHAKE_TRAFFIC_SECRET, CLIENT_TRAFFIC_SECRET_0, SERVER_TRAFFIC_SECRET_0, etc
- client random
- the string of random bytes generated on the client during the
Client Hellopart of the TLS handshake protocol - this is a 32 byte value represented as 64 hexa chars
- is used as a key in order to differentiate which labels belong to which connection
- the string of random bytes generated on the client during the
- secret
- variable length hex value
As example take a look at this section from my .ssl-key.log where we can observe entries from three independent negociations:
CLIENT_TRAFFIC_SECRET_0 a32eb0704df85d2c8dfed2ecf721ed512d33da179732965c721dc4ba935e53f5 cdf1b007b92e8aa77da7091cb81f0fd75132c83eab85865bb6a76432cc9f959ab4712636271f506665b1dfd97a1f8ce8
SERVER_TRAFFIC_SECRET_0 a32eb0704df85d2c8dfed2ecf721ed512d33da179732965c721dc4ba935e53f5 0c1e810216b76f388aa9179b852fa2b1f935c2224f082d51801118362e28567199ea7802446ce9e9d802042f2a95a6d0
EXPORTER_SECRET a32eb0704df85d2c8dfed2ecf721ed512d33da179732965c721dc4ba935e53f5 45db7b3bc67a4c700863cb9dce62d38329239db3eade797ea8e990065bda14e6fdf1e2768bc5be2ff78fef916e74bcb0
CLIENT_HANDSHAKE_TRAFFIC_SECRET ed0a238a60e290cb3864a899818b496f4de2bc4d8f9489e90e047ec9b9e6465c cf668ae741f57c7c42d44d35a1d71c0ce888f947de3056741cf394cf7ccd919e9c36574ca20c76f9cd6db9f709943702
SERVER_HANDSHAKE_TRAFFIC_SECRET ed0a238a60e290cb3864a899818b496f4de2bc4d8f9489e90e047ec9b9e6465c 2a093a96dc61bca91d9710444202d471f7175ee427242e2e572f186dfdd8f4096fa9c6a77a4dfdb2806ce609267310c8
CLIENT_RANDOM c382a546c4c5f47961c208aefc57dfce8d09c1ba8d23ab2b297a269d961bc816 2ec13a3622f4c60fba03f565f6bd701a3765582b1344879ae25a978b316cd4c04b1ae0547b1b9f239781659695d6d0a8
TLS pre-master secret vs master secret
To establish a fully encrypted communication over TLS 1.2 here are the steps involved. Please note the role of the pre-master secret:
- Client Hello – sends supported TLS version, supported ciphers, a client random string
- Server Hello – sends server’s SSL certificate, server chosen cipher, a server random string
- Authentication – client verifies server’s SSL certificate with the CA that issued it
- Server Hello Done – sends a message to client to confirm that Server Hello has been completed
- Client Key Exchange – client generates a pre-master secret, another random string. this is encrypted using the public key embedded in the received SSL certificate and is sent to the server
- Private key used – server decrypts the pre-master secret using its private key
- Session keys created – both client and server generate independently session keys from the: client random str, server random str and the pre-master secret. both should be the same
- Client Ready – client sends a “finished” message encrypted with a session key
- Server Ready – server sends a “finished” message encrypted with a session key
- Handshake Finished – communication goes on with a symmetric encryption
So the all wanted pre-master secret is a random string generated on the client, shared with the server and lastly used to generate the master secret on both ends.
A Pseudo-Random Function (PRF) is then employed to calculate the master_secret = PRF(pre-master-secret, “Master-Secret”, ClientHello.random + ServerHello.random). In the end the master_secret is used on the client and on the server to generate the session key.
Having described the steps for the old TLS 1.2, with TLS 1.3 which nowdays is almost ubiquous, we can see the process is simplified / accelerated. Based on the info received during the Client Hello – a client random string and a client key share, the server generates the pre-master secret and even advances generating the master secret. During the Server Hello, the server sends back the server random string along with a server key share. This data is sufficient for the client to independently generate the pre-master secret – which as you see is not that random anymore, and will advance to generating the master secret. Such method works because each party agrees and openly shares a set of parameters along with a public key – carefully crafted using the aforementioned params – see the Diffie–Hellman key exchange and the Elliptic-curve Diffie–Hellman.
Depending on the TLS version running, entries in the .ssl-key.log might contain either the pre-master secret or the master secret. For ex. in case of TLS 1.2 the CLIENT_RANDOM type is used to identify the “master” secret for the connection.
References
https://wiki.wireshark.org/TLS#using-the-pre-master-secret
https://datatracker.ietf.org/doc/html/draft-ietf-tls-keylogfile
https://medium.com/@thesslstore/tls-1-3-handshake-taking-a-closer-look-11667ff92645
https://www.cryptologie.net/article/340/tls-pre-master-secrets-and-master-secrets
https://cabulous.medium.com/tls-1-2-andtls-1-3-handshake-walkthrough-4cfd0a798164
https://en.wikipedia.org/wiki/Elliptic-curve_Diffie%E2%80%93Hellman
