skip to content

How do you get an SSLKEYLOGFILE key log from a test client and make Wireshark decrypt your HTTPS capture with it?

level: middleimportance: must knowfreq 22%

answer

  1. environment read at process start
  2. one line per secret
  3. keyed by the ClientHello random
  4. tls.keylog_file, or tshark -o

basics

~10 s

Set SSLKEYLOGFILE before the client starts, reproduce the request while capturing, then point Wireshark's TLS preference (Pre)-Master-Secret log filename, tls.keylog_file, at the file; tshark takes the same setting as -o tls.keylog_file:path.

solid answer

~40 s

The client's TLS library reads `SSLKEYLOGFILE` when the process starts, so set it first: restart a browser that honours it (a running instance ignores it), run curl with it exported when curl's TLS library supports it, or register OpenSSL's key-log callback in your own program. Capture while you reproduce the request. The file gets one line per secret, keyed by the 32-byte `ClientHello` random: `CLIENT_RANDOM` lines for TLS 1.2, and TLS 1.3 labels such as `CLIENT_HANDSHAKE_TRAFFIC_SECRET` and `SERVER_TRAFFIC_SECRET_0`. In Wireshark set *Preferences > Protocols > TLS > (Pre)-Master-Secret log filename* (`tls.keylog_file`); with tshark use `-o tls.keylog_file:keys.log`. Wireshark 4.6's *Tools > TLS Keylog Launcher* can start a program with the variable already set. Treat the file like a password: one file per run, deleted afterwards.

code

bash · 7 lines
bash
export SSLKEYLOGFILE="$HOME/tls-test/run1-keys.log"
curl -s -o /dev/null https://app.example.internal/health
unset SSLKEYLOGFILE

tshark -r run1.pcapng \
  -o "tls.keylog_file:$HOME/tls-test/run1-keys.log" \
  -Y "http or http2"

go deeper

for a junior

Recall the sequence: set SSLKEYLOGFILE, start the client, capture, then point the (Pre)-Master-Secret log filename preference at the file.

for a middle

Explain why the variable must be set before the process starts, what a CLIENT_RANDOM line and the TLS 1.3 traffic-secret lines contain, and how tshark -o tls.keylog_file applies the log.

for a senior

Show how you run this on a test client without leaking secrets: one log per run, scoped sharing, and no global variable on a workstation that also browses.

for a principal

Set a team rule for when key logging is allowed, who may hold the logs, and how long they live next to the captures they unlock.

## What a key log is A **key log** is a plain-text file in which a TLS client writes the secrets of each session it makes, at the moment it derives them. Wireshark reads the file and uses each line to decrypt the matching session in a capture. It is the practical way to read modern TLS (ECDHE key exchange, TLS 1.3) after the fact, because those secrets never appear on the wire. The environment variable `SSLKEYLOGFILE` is the conventional switch: a TLS library that supports it appends lines to the file the variable names. Wireshark's own documentation describes it for browsers, and the format is the IETF key-log-file draft that editcap also references. ## Producing the file from a client you control 1. **Pick a fresh path per run**, for example a file under a test directory named after the run. Mixing runs makes later diagnosis harder. 2. **Set the variable before the client starts.** The library reads it at process start: - a browser that honours it must be fully closed and relaunched from an environment where the variable is set; an instance that is already running never sees it; - curl honours it when the TLS library it was built against supports key logging; - a program you wrote on OpenSSL usually registers OpenSSL's key-log callback and appends each line it receives to the file itself. 3. **Capture while you reproduce the request**, so the full handshake is in the capture. 4. Check the file is non-empty before you leave the test host. Wireshark 4.6 also offers **Tools > TLS Keylog Launcher**, which starts a program (set by the GUI preference *Program to launch with TLS Keylog*) with `SSLKEYLOGFILE` pointing at the key log file Wireshark is configured to read. ## What the lines look like Every line a client writes is a label, the 32-byte **client random** from that session's `ClientHello` in hex, and a secret in hex. | TLS version | Labels the client writes | What Wireshark derives | |---|---|---| | TLS 1.2 | `CLIENT_RANDOM` | The 48-byte master secret, then the record keys | | TLS 1.3 | `CLIENT_HANDSHAKE_TRAFFIC_SECRET`, `SERVER_HANDSHAKE_TRAFFIC_SECRET` | Keys for the encrypted handshake, including the certificate | | TLS 1.3 | `CLIENT_TRAFFIC_SECRET_0`, `SERVER_TRAFFIC_SECRET_0`, `EXPORTER_SECRET` | Keys for application data in each direction, and the exporter secret | The preference's own help text also accepts older forms, `RSA <first 8 bytes of encrypted premaster> <premaster>` and `PMS_CLIENT_RANDOM`, but the client-random forms above are what a client writes through `SSLKEYLOGFILE`. ## Pointing Wireshark and tshark at it - In the GUI, open **Preferences > Protocols > TLS** and set **(Pre)-Master-Secret log filename**. The preference is stored as `tls.keylog_file` in the profile, so it persists per profile. - With tshark, override it for one run with `-o tls.keylog_file:<path>`; tshark never saves preferences. - Wireshark keeps reading lines appended to the file, so a live capture can decrypt sessions as the client logs them; for packets already on screen, re-dissect after the log grows. A quick check that it worked: the packet bytes pane shows a **Decrypted TLS** tab, and a display filter such as `http or http2` now matches. ## Checking the log before blaming Wireshark When nothing decrypts, look at the file itself before changing preferences: - **Is it empty?** An empty file means the client never read the variable: it was already running, or its TLS library does not support key logging. - **Do the labels fit the traffic?** A TLS 1.3 session needs the traffic-secret labels; a log holding only `CLIENT_RANDOM` lines covers TLS 1.2 sessions. - **Is this session in it?** Copy the client random from the `ClientHello` (`tls.handshake.random`) and search the log for that hex string. No hit means the log came from another process, host or run. - **Is Wireshark reading this file?** Profiles keep their own preferences, so a second profile may still point at an old path. ## Handling the file safely A key log plus the capture equals the plaintext, which may include session cookies, tokens and personal data. - Keep **one key log per test run** and delete it when the investigation closes. - Never leave `SSLKEYLOGFILE` set in a shell profile or system environment; every TLS session from that user is then logged to disk. - Store the log under the same access control as the capture, and share it on a need-to-know basis. - Only log clients and traffic you are responsible for; the variable is a debugging aid for your own systems.

  • Why does the TLS 1.3 part of a key log hold several lines per session when TLS 1.2 needs one?
    TLS 1.2 derives every record key from a single master secret, so one `CLIENT_RANDOM` line suffices. TLS 1.3 uses separate traffic secrets for the handshake and for application data, in each direction, so the client logs `CLIENT_HANDSHAKE_TRAFFIC_SECRET`, `SERVER_HANDSHAKE_TRAFFIC_SECRET`, `CLIENT_TRAFFIC_SECRET_0` and `SERVER_TRAFFIC_SECRET_0`. Missing handshake lines leave the certificate encrypted; missing traffic lines leave the requests encrypted.
  • Can you load the key log after the capture is finished?
    Yes. Wireshark applies the key log whenever it dissects, so you can capture first and set `tls.keylog_file` days later, as long as the capture holds each session's `ClientHello` and the log holds that session's lines. What you cannot do is log secrets after the fact: the client had to have `SSLKEYLOGFILE` set when it made the connection.
  • How do you keep a key log from becoming a liability?
    Use a dedicated file per run, restrict its permissions, and delete it with the capture when the case closes. Never set `SSLKEYLOGFILE` globally, since every session from that user then lands on disk. If the capture must be shared, embed only the secrets it needs rather than the whole log, and share on a need-to-know basis.

saying these in an interview costs you the question

  • Exporting SSLKEYLOGFILE in a terminal affects a browser that is already running.
  • The key log must be configured before capturing starts or it cannot be used.
  • Every OpenSSL-based program writes a key log when the variable is set.
  • A key log from one machine decrypts any capture of the same server.
  • Leaving SSLKEYLOGFILE set permanently in a shell profile is harmless.