When can Wireshark 4.6's RSA keys list decrypt a captured TLS 1.2 session, and how does it match the key to the session?
answer
- a secret sent to the key
- TLS_RSA_WITH suites only
- ClientKeyExchange must be captured
- certificate public key, not address
basics
~20 sOnly when the session used static-RSA key exchange and its full handshake is in the capture. Wireshark 4.6 picks the key by matching it to the public key in the captured server Certificate; the list's IP address column is unused.
solid answer
~50 sIn a static-RSA handshake (a `TLS_RSA_WITH_*` suite) the client encrypts the premaster secret to the server's RSA public key and sends it in `ClientKeyExchange`. With the private key in the TLS *RSA keys list* (a PEM file, or PKCS#12 with the *Password* column), Wireshark unwraps it and derives the record keys. In 4.6 the key is chosen by the server certificate's public key, so the `Certificate` message must be captured; the *IP address* column is marked unused and *Port* and *Protocol* are optional. With DHE or ECDHE suites the RSA key only signs, so the debug log says the session cannot be decrypted using an RSA private key file; TLS 1.3 has no static-RSA exchange. A resumed TLS 1.2 session sends no `ClientKeyExchange`, so it decrypts only if its original full handshake is in the same capture.
go deeper
Recall that a server's RSA private key decrypts only static-RSA sessions, not ECDHE ones and never TLS 1.3.
Explain why the premaster secret in ClientKeyExchange is the only thing the key can unwrap, and which handshake messages the capture must hold for Wireshark to use it.
Read the ServerHello to decide whether the key can help at all, account for resumed sessions, and share exported session keys instead of the private key.
Weigh keeping static-RSA enabled for inspection convenience against losing forward secrecy for every session, and set who may ever hold a production private key for analysis.
## Static RSA: the one case a server key helps **Key exchange** is how the two ends of a TLS session agree on the secret that all record keys derive from. TLS 1.2 and earlier offer two broad families: - **Static RSA** (cipher suites named `TLS_RSA_WITH_...`, such as `TLS_RSA_WITH_AES_128_GCM_SHA256`). The client generates a 48-byte **premaster secret**, encrypts it with the RSA public key in the server's certificate, and sends it in the `ClientKeyExchange` message. Anyone holding the server's RSA private key can decrypt that message, then and years later. - **Ephemeral Diffie-Hellman** (`TLS_DHE_...`, `TLS_ECDHE_...`, for example `TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256`). Each side contributes a temporary private value that never leaves it. The certificate's RSA key only **signs** the server's parameters, so no secret is ever encrypted to it. TLS 1.3 removed static-RSA key exchange altogether, and many modern servers no longer offer it in TLS 1.2 either. Wireshark's TLS debug log states the consequence plainly for a DH session: it "cannot be decrypted using a RSA private key file". ## What the capture must contain For the RSA keys list to decrypt one TLS 1.2 session, Wireshark needs, in order: 1. The **`ClientHello`**, for the client random used in key derivation. 2. The **`ServerHello`**, for the negotiated version and cipher suite. 3. The server **`Certificate`** message, because Wireshark 4.6 computes a SHA-1 identifier of the certificate's public key and uses it to look up the matching private key. 4. The **`ClientKeyExchange`** carrying the encrypted premaster secret. A capture that starts after the handshake has none of this and cannot be decrypted with a key, whatever you configure. ## Configuring the RSA keys list in 4.6 The list lives at **Preferences > Protocols > TLS > RSA keys list** and is saved in the profile. Its columns: | Column | Meaning in 4.6 | |---|---| | **IP address** | Marked *unused*; matching is by the certificate's public key | | **Port** | Optional | | **Protocol** | Optional; the dissector for the decrypted payload | | **Key File** | The server's private key file | | **Password** | Blank for a PEM key; the passphrase when the file is PKCS#12 | Older walkthroughs insist on filling in the server address and port; in 4.6 that is not what selects the key. Wireshark 4.6 also has a global **RSA Keys** preference page for key files and hardware tokens. ## Why it fails on traffic you actually see - **An (EC)DHE cipher suite.** The suite name contains `RSA` because the certificate is RSA, but the key exchange is ephemeral. This is the most common surprise. - **TLS 1.3.** No static-RSA exchange exists; only a key log helps. - **A resumed session.** An abbreviated TLS 1.2 handshake reuses an earlier master secret and sends no `ClientKeyExchange`. Wireshark can restore the secret by session ID or session ticket only if the original full handshake is earlier in the same capture. Resumed sessions carry the expert note `tls.resumed`. - **The wrong key or a non-RSA certificate.** A key that does not match the captured certificate is never selected; an ECDSA certificate means no RSA key applies at all. ## Checking before you ask for a key A private key is sensitive enough that you should prove it can help before anyone hands it over: 1. Filter the capture on `ServerHello` messages and read the chosen cipher suite in `tls.handshake.ciphersuite`. 2. If the `ServerHello` carries a supported-version extension selecting TLS 1.3 (`tls.handshake.extensions.supported_version`), stop: the key cannot help. 3. If the suite is `TLS_DHE_...` or `TLS_ECDHE_...`, stop for the same reason, and ask for a client key log instead. 4. Only for `TLS_RSA_WITH_...` sessions whose full handshake is captured is the key worth requesting, and then through whatever change control protects that key. ## Sharing results without sharing the key The private key is far more powerful than the investigation needs: it decrypts every static-RSA session to that server and lets its holder impersonate the server. Once Wireshark has decrypted the sessions you care about, **File > Export TLS Session Keys** writes a key log holding only the secrets for sessions in that capture; `tshark --export-tls-session-keys <file>` does the same from the command line. Hand that key log to colleagues and keep the private key where it belongs.
- How do you tell from the capture alone whether a TLS 1.2 session used static-RSA key exchange?Read the cipher suite the server chose in the `ServerHello` (`tls.handshake.ciphersuite`). A `TLS_RSA_WITH_...` suite means static RSA; `TLS_DHE_...` or `TLS_ECDHE_...` means ephemeral key exchange even when `RSA` appears later in the name. A static-RSA handshake also has no `ServerKeyExchange` message, while an ephemeral one does.
- What does File > Export TLS Session Keys give you that the server's private key does not?A key log of the secrets Wireshark derived for the sessions in this capture. It decrypts those sessions and nothing else, and it cannot be used to impersonate the server, so it is safe to share with an analyst in a way the private key never is. tshark's `--export-tls-session-keys` option, added in 3.6, writes the same file.
A static-RSA handshake posts a sealed envelope addressed to the server, holding the session secret; whoever holds the server's private key can open every envelope ever addressed to it, including ones in an old capture. An (EC)DHE handshake posts no envelope at all: each end computes the secret from a private half it never sends, so the server's key has nothing in the capture to open.
saying these in an interview costs you the question
- Any cipher suite with RSA in its name can be decrypted with the server key.
- The IP address and port must be filled in or Wireshark 4.6 ignores the key.
- The server key decrypts TLS 1.3 sessions as long as the certificate is RSA.
- Handing an analyst the server's private key is the normal way to share a capture.
- A resumed session decrypts from the private key alone.