Manually decrypting an HTTPS request

Recently I have spent some time on learning the internals of HTTPS. I wanted to know what makes it secure and how the communication actually looks like. Today I would like to show you the steps required to decrypt a sample HTTPS request. Imagine you got a .pcap file recorded by one of your company clients who complains that your application returned 500 HTTP status code with a strange error message. The client forgot to copy the error message but luckily had a Wireshark instance running in the background (I know it’s highly hypothetical, but just close your eyes to that :)) and he/she sent you the collected traces. Let’s then assume that your server has a certificate with a public RSA key and you are in possession of its private key. Finally the client was using a slightly outdated browser which supports TLS 1.0 (though I will inform you what would have been different if it had been TLS 1.2) and does not use ephemeral keys. My main point in writing this post is to present you the steps of the TLS communication. This post is not a guidance on how to create a secure TLS configuration, but a walk-through on how this protocol works and I will purposely use less secure ciphers to make things easier to explain.

Do it quickly with Wireshark

Wireshark has a fantastic feature which can decrypt the .pcap file for you. You just need to go to Edit -> Preferences and in the dialog that appears select SSL protocol as on the image below:

wireshark-ssl-preferences

As we have the private RSA key we need to add it to the Wireshark RSA key list. Click on the Edit button marked on the image and you should see a dialog similar to the one below (wit your own key definitions of course):

wireshark-rsa-key

My sample server had address 172.28.128.3 and my key file was saved in the PEM format. Another interesting option in the SSL preferences dialog is the Wireshark SSL debug file which you may save to a text file. It reveals a lot of information about Wireshark decryption process and helped me several times when I was struggling with my own decryption tools. After closing the window, Wireshark will decrypt the TLS frames and you could happily find out what the client saw. Let’s now forget about this Wireshark feature and decrypt the .pcap file on our own.

UPDATE (2024): When TLS session uses ephemeral keys (the standard behavior), you may create a new environment variable, SSLKEYLOGFILE, and point it to a path in disk (for example, C:\temp\sslkey.log). Then restart the browser and perform the HTTPS request you want to decrypt while recording the traffic in Wireshark. Later, use the configured path as the “(Pre)-Master-Secret log filename” value and Wireshark should be able to decrypt the request. Make sure you remove this environment variable when you no longer need it. This approach will work in Firefox, Chrome, and Edge browsers and is also described in Wireshark wiki.

Manual decryption

Everything starts with a handshake

The TLS handshake is the first part of the communication. It is a process in which the client and the server agree on the encryption protocols and exchange encryption keys. When the handshake is complete client and server should possess:

  • Client and Server Initialization Vectors (IV)
  • Client and Server Symmetric Encryption Keys
  • Client and Server MAC keys

and be ready to securely communicate.

Let’s move back to the data transmitted between our parties. Each TLS message can be represented by the structure (which is a part of the TLS record layer):

struct {
  ContentType type;
  ProtocolVersion version;
  uint16 length;
  opaque fragment[TLSPlaintext.length];
} TLSPlaintext;

where ContentType defines the type of a message (such as handshake, alert, application_data etc.) and ProtocolVersion describes the TLS version in use (where TLS1.0 is represented as 0x0301 and TLS1.2 is 0x0303). TLS is an onion protocol and next layers (handshake, application data etc.) are embedded in the record layer.

ClientHello

The handshake starts with a ClientHello message sent from the client to the server (the output is taken from Wireshark):

Internet Protocol Version 4, Src: 172.28.128.1, Dst: 172.28.128.3
Transmission Control Protocol, Src Port: 53835 (53835), Dst Port: 443 (443), Seq: 1, Ack: 1, Len: 87
Secure Sockets Layer
    TLSv1 Record Layer: Handshake Protocol: Client Hello
        Content Type: Handshake (22)
        Version: TLS 1.0 (0x0301)
        Length: 82
        Handshake Protocol: Client Hello
            Handshake Type: Client Hello (1)
            Length: 78
            Version: TLS 1.0 (0x0301)
            Random
                GMT Unix Time: Mar  4, 2016 13:20:45.000000000 Central European Standard Time
                Random Bytes: bec6ea9223c15fd63dfd22249013f234aa04edcc308af6c5...
            Session ID Length: 0
            Cipher Suites Length: 10
            Cipher Suites (5 suites)
                Cipher Suite: TLS_RSA_WITH_AES_256_CBC_SHA (0x0035)
                Cipher Suite: TLS_RSA_WITH_AES_128_CBC_SHA (0x002f)
                Cipher Suite: TLS_RSA_WITH_3DES_EDE_CBC_SHA (0x000a)
                Cipher Suite: TLS_RSA_WITH_RC4_128_SHA (0x0005)
                Cipher Suite: TLS_RSA_WITH_RC4_128_MD5 (0x0004)
            Compression Methods Length: 1
            Compression Methods (1 method)
                Compression Method: null (0)
            Extensions Length: 27
            Extension: server_name
            Extension: Extended Master Secret
            Extension: renegotiation_info

Just after the TLS header comes the payload which most important parts are: client random (32 bytes composed of the Unix time and 28 bytes of random bytes) and cipher suites supported by the client and extensions understood by the client. The full client random looks as follows (we will need this value later):

56 d9 7d 9d be c6 ea 92 23 c1 5f d6 3d fd 22 24
90 13 f2 34 aa 04 ed cc 30 8a f6 c5 09 f8 60 a5

TLS also supports compression, but it’s rarely used.

ServerHello, Certificate, ServerHelloDone

In response to the ClientHello server sends ServerHello, Certificate(s) and ServerHelloDone messages:

Internet Protocol Version 4, Src: 172.28.128.3, Dst: 172.28.128.1
Transmission Control Protocol, Src Port: 443 (443), Dst Port: 53835 (53835), Seq: 1, Ack: 88, Len: 950
Secure Sockets Layer
    TLSv1 Record Layer: Handshake Protocol: Server Hello
        Content Type: Handshake (22)
        Version: TLS 1.0 (0x0301)
        Length: 81
        Handshake Protocol: Server Hello
            Handshake Type: Server Hello (2)
            Length: 77
            Version: TLS 1.0 (0x0301)
            Random
                GMT Unix Time: Nov 26, 1981 02:33:35.000000000 Central European Standard Time
                Random Bytes: 2c1406b273a5e376a6254a818606d4759ab7efb797a1e559...
            Session ID Length: 32
            Session ID: f739bcc4a4ef4bb190115cc9705feaa9feaeffd6464b196f...
            Cipher Suite: TLS_RSA_WITH_AES_256_CBC_SHA (0x0035)
            Compression Method: null (0)
            Extensions Length: 5
            Extension: renegotiation_info
    TLSv1 Record Layer: Handshake Protocol: Certificate
        Content Type: Handshake (22)
        Version: TLS 1.0 (0x0301)
        Length: 850
        Handshake Protocol: Certificate
            Handshake Type: Certificate (11)
            Length: 846
            Certificates Length: 843
            Certificates (843 bytes)
                Certificate Length: 840
                Certificate: 308203443082022c020900a7a6bfffdfc4e090300d06092a... (id-at-countryName=PL,id-at-localityName=Warsaw,id-at-organizationName=MyCompany,pkcs-9-at-emailAddress=test@test.com,id-at-commonName=opensslvm)
    TLSv1 Record Layer: Handshake Protocol: Server Hello Done
        Content Type: Handshake (22)
        Version: TLS 1.0 (0x0301)
        Length: 4
        Handshake Protocol: Server Hello Done
            Handshake Type: Server Hello Done (14)
            Length: 0

ServerHello contains server random (also 32 bytes):

16 62 fe 6f 2c 14 06 b2 73 a5 e3 76 a6 25 4a 81
86 06 d4 75 9a b7 ef b7 97 a1 e5 59 f4 dd 04 7f

and the strongest cipher suite supported by both the client and the server – in our case it’s TLS_RSA_WITH_AES_256_CBC_SHA and extensions supported by both the client and the server.

Next server response part of the handshake is the Certificate message. My test server was using a self-signed certificate so only this certificate was sent back in the handshake. But it’s common that servers send a chain of certificates so the client can verify the highest certificate signature against its own cert store and does not need to perform any additional requests to certificate providers.

Finally server sends ServerHelloDone to communicate that it finished sending hello messages.

Client Key Exchange, Change Cipher Spec, Encrypted Handshake Message

Here comes the most important part of the handshake, i.e. the key exchange. The client generates a cryptographically random pre-master key, encrypts it with the public RSA key and sends it to the server. Just after the Client Key Exchange message the client sends the Change Cipher Spec message and the encrypted Client Finished (we will have a look at it in a moment):

Internet Protocol Version 4, Src: 172.28.128.1, Dst: 172.28.128.3
Transmission Control Protocol, Src Port: 53835 (53835), Dst Port: 443 (443), Seq: 88, Ack: 951, Len: 326
Secure Sockets Layer
    TLSv1 Record Layer: Handshake Protocol: Client Key Exchange
        Content Type: Handshake (22)
        Version: TLS 1.0 (0x0301)
        Length: 262
        Handshake Protocol: Client Key Exchange
            Handshake Type: Client Key Exchange (16)
            Length: 258
            RSA Encrypted PreMaster Secret
                Encrypted PreMaster length: 256
                Encrypted PreMaster: 0b3366f120198ce3839e0c5b106462da2b88105f3d9f2fe9...
    TLSv1 Record Layer: Change Cipher Spec Protocol: Change Cipher Spec
        Content Type: Change Cipher Spec (20)
        Version: TLS 1.0 (0x0301)
        Length: 1
        Change Cipher Spec Message
    TLSv1 Record Layer: Handshake Protocol: Encrypted Handshake Message
        Content Type: Handshake (22)
        Version: TLS 1.0 (0x0301)
        Length: 48
        Handshake Protocol: Encrypted Handshake Message

As we are in possession of the RSA private key corresponding to the public key used in this handshake it’s time to use it. First we need to save the Encrypted PreMaster (256 bytes = 2048 bits) to a premaster-encrypted.bin file. Then we may use OpenSSL to decrypt it:

PS> openssl pkeyutl -decrypt -in .\premaster-encrypted.bin -inkey .\key.pem -out premaster-decrypted.bin

PS> Format-Hex .\premaster-decrypted.bin

           00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F

00000000   03 01 82 BB 54 5E 61 A2 7C D2 B0 BD 59 9E E8 6A  ..?»T^ac|O°1Y?cj
00000010   41 9C 63 0C 4B B9 E1 25 DB 9F 9E 08 F4 D4 41 F6  A?c.K1á%U??.ôÔAö
00000020   1F 3B 1E C1 3E 88 BA DD 38 AE E3 73 E7 88 FC AB  .;.Á>?oÝ8Rasç?ü«

Note that if the keys were exchanged using a variant of a Diffie-Hellman algorithm (which is a very common and recommended practice) we won’t be able to generate the master secret without additional information (DH params).

Now, both client and server have material to create a master secret which will be later used in the symmetric encryption of the communication. In TLS 1.0 the master secret is generated using a PRF (Pseudo-Random Function) which uses both MD5 and SHA1. As you would see the same PRF function is also used to derive other communication parameters from the master secret. Note that TLS1.2 PRF function is based on SHA-256 or stronger hash (details can be found in RFC5246), but it is used in the same contexts as in TLS1.0. I created a sample application PRF.exe which you may download here. To create a master secret run:

PS> PRF.exe --label "master secret" --length 48 --secret .\premaster-decrypted.bin --data .\random_cs.bin  --output master-secret.bin
PS> Format-Hex .\master-secret.bin

           00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F

00000000   27 90 3D 7D 3F 40 B9 0E 64 84 40 87 A5 8D FF F0  '?=}?@1.d?@?Y?.?
00000010   1A 1D D7 6C 96 81 8E F9 62 4F 38 AF 38 60 9E 52  ..×l???ubO8─8`?R
00000020   D3 18 0F E8 07 3D 4A 81 EC 28 26 44 22 66 C8 CF  Ó..c.=J?i(&&D&"fEI

where random_cs.bin is a concatenation of the client random and the server random (in this order!). However, this way of calculating the master secret has a pitfall, which allows an active attacker to synchronize two TLS sessions so that they share the same “master_secret”. A remedy to this problem was described in RFC 7627 which recommends using the hash of all the previous handshake messages as a seed to the PRF function (instead of the client and server randoms). It’s more and more common, yet our example client does not use it.

With the master secret generated we may produce the other parameters required for the secure communication. In our case we will need:

  • 20 bytes for a client MAC key (SHA1)
  • 20 bytes for a server MAC key (SHA1)
  • 32 bytes for a client encryption key (AES256)
  • 32 bytes for a server encryption key (AES256)
  • 16 bytes for a client IV (AES uses 128-bit blocks)
  • 16 bytes for a server IV (AES uses 128-bit blocks)

This all sums up to 136 bytes which we will derive from our master secret using the PRF function:

PS> prf --secret .\master-secret.bin --label "key expansion&amp" --data .\random_sc.bin -n 136 -o key-expansion.bin

PS> Format-Hex .\key-expansion.bin

           00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F

00000000   13 E2 39 F0 75 02 5B F9 64 4F 58 27 5A FF 36 D9  .â9?u.[udOX'Z.6U
00000010   BB C1 6C 79 CA B0 4B 1F 91 94 73 F0 BF E9 94 37  »ÁlyE°K.??s??é?7
00000020   99 FE C5 EC FB D0 F8 72 1D 00 7E 17 B3 A4 54 83  ??Aiu?or..~.3¤T?
00000030   AA 92 1A D9 DE 06 CC 6B 47 57 18 69 CF 63 92 19  a?.U?.IkGW.iIc?.
00000040   C9 05 29 70 16 3B B8 A2 11 38 77 BB 10 53 8E 76  É.)p.;¸c.8w».S?v
00000050   B5 C9 EC 7B E6 83 F3 DA 8F 04 48 C2 EF C9 C5 B9  uÉi{a?óÚ?.HÂiÉA1
00000060   86 58 B5 72 1A B8 BA CE 3E 0F F5 34 87 FE FF 6B  ?Xur.¸oÎ>.o4??.k
00000070   73 60 BC FE 7B 08 48 D0 2D 85 BE 50 45 58 51 59  s`1?{.H?-?3PEXQY
00000080   8E 63 33 8A CF 38 A0 B0 2D 85 BE 50 45 58 51 59  ?c3?I8 °-?3PEXQY

Notice that we are now using random_sc.bin which is a concatenation of the server random and the client random (notice the order is reversed compared to the previous call!). As you remember, the next message sent from the client to the server was Changed Cipher Spec which indicates that from now on all the sent data will be encrypted using the negotiated keys. Thus the Client Finished (the last message from the last Wireshark output) is an encrypted message. Let’s decrypt it:

PS>  openssl enc -aes-256-cbc -d -K 1D007E17B3A45483AA921AD9DE06CC6B47571869CF639219C9052970163BB8A2 -iv 3E0FF53487FEFF6B7360BCFE7B0848D0 -in .\handshake-client-finished.bin -out .\handshake-client-finished-decrypted.bin -nopad

PS>; Format-Hex .\handshake-client-finished-decrypted.bin

           00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F

00000000   14 00 00 0C 9E B1 9A 29 27 A2 FA F8 F1 22 4B 46  ....?+?)'cúon"KF
00000010   07 94 C6 EE B0 8A CC E5 C1 AB 88 F4 49 34 19 45  .?Aî°?IaÁ«?ôI4.E
00000020   00 DF 4C 39 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B  .ßL9............

Starting from the end: the last 12 bytes are padding bytes, the next 20 bytes are a message HMAC. The algorithm for calculating message HMAC is quite complicated: you need to first append an 8 byte long message sequence number, then add TLS record header with the content size set to the actual content size (without HMAC size). The message sequence number is a counter (separate for the client and the server) which is incremented after each encrypted message is sent (Change Cipher Spec message sets its value to zero). In our case the HMAC calculation process looks as follows:

PS> Format-Hex .\handshake-client-finished-without-mac.bin

           00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F

00000000   00 00 00 00 00 00 00 00 16 03 01 00 10 14 00 00  ................
00000010   0C 9E B1 9A 29 27 A2 FA F8 F1 22 4B 46 14 00 00  .?+?)'cúon"KF...

PS> Format-Hex .\client-mac-key.bin

           00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F

00000000   13 E2 39 F0 75 02 5B F9 64 4F 58 27 5A FF 36 D9  .â9?u.[udOX'Z.6U
00000010   BB C1 6C 79 75 02 5B F9 64 4F 58 27 5A FF 36 D9  »Ályu.[udOX'Z.6U

PS> openssl dgst -sha1 -hmac $(cat .\client-mac-key.bin) .\handshake-client-finished-without-mac.bin
HMAC-SHA1(.\handshake-client-finished-without-mac.bin)= 0794c6eeb08acce5c1ab88f44934194500df4c39

The next 12 bytes are the PRF output of the MD5 and SHA1 hashes (again for TLS1.2 stronger hash will be used here) of all the previously exchanged handshake messages (without the TLS record layer part, without the Change Cipher Spec message and all eventual alert messages). The hashes are concatenated and used as a seed to the PRF function (the client-data-for-prf.bin file):

PS> openssl dgst -md5 .\client-before-finished-sent.bin
MD5(.\client-before-finished-sent.bin)= b22d98c8c97a236bc83b2eb5880e03bb
PS> openssl dgst -sha1 .\client-before-finished-sent.bin
SHA1(.\client-before-finished-sent.bin)= 83e2d22480e9cb0c4b5e05f882602deed99274b5
PS> prf -l "client finished" -s .\master-secret.bin -d .\client-data-for-prf.bin -o client-prf-result.bin -n 12
PS> Format-Hex .\client-prf-result.bin

           00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F

00000000   9E B1 9A 29 27 A2 FA F8 F1 22 4B 46 00 00 00 00  ?+?)'cúon"KF....
Change Cipher Spec, Encrypted Handshake Message

After decrypting the Client Finished message, the server responds with the Change Cipher Spec message and later the Server Finished message. The algorithm for generating the Server Finished message is actually almost the same as for the Client Finished message. The message to be hashed will contain the Client Finished message (decrypted, without HMAC and without padding) and the whole message will be HMACed and encrypted with the server variants of the keys. Now, the handshake is finally done and we can start sending the actual data.

Gimme some data

In our case the client sent a simple HTTP request:

Internet Protocol Version 4, Src: 172.28.128.1, Dst: 172.28.128.3
Transmission Control Protocol, Src Port: 53835 (53835), Dst Port: 443 (443), Seq: 414, Ack: 1010, Len: 85
Secure Sockets Layer
    TLSv1 Record Layer: Application Data Protocol: http
        Content Type: Application Data (23)
        Version: TLS 1.0 (0x0301)
        Length: 80
        Encrypted Application Data: 751f29ecf5227fbc89b25bb5ccfed9060db5506c0da9e42b...

Let’s decrypt it using the client key (an IV we will be the last block of the last message sent by the client as we use Cipher Block Chaining):

PS> openssl enc -aes-256-cbc -d -K 1D007E17B3A45483AA921AD9DE06CC6B47571869CF639219C9052970163BB8A2 -iv 0E03400DBE4A33B2D591960526AE0395 -in .\client-request.bin -out .\client-request-decrypted.bin

PS> cat .\client-request-decrypted.bin
GET / HTTP/1.1
Host: opensslvm
Connection: close

ýÎ↓¶čU,Ăâ-kťvľúęmĹ%♣

The last unprintable characters are of course HMAC of the message, but as you can see we managed to decrypt the message sent by the client. When the server responds we would use the server key to decrypt the response and so on.

The decryption process will be slightly different if we were using TLS1.2 as in TLS1.2 a unique IV is appended to each message.

Connection close

To shutdown a TLS connection one of the parties needs to send a special shutdown alert (01 00):

Internet Protocol Version 4, Src: 172.28.128.1, Dst: 172.28.128.3
Transmission Control Protocol, Src Port: 53835 (53835), Dst Port: 443 (443), Seq: 499, Ack: 2477, Len: 37
Secure Sockets Layer
    TLSv1 Record Layer: Encrypted Alert
        Content Type: Alert (21)
        Version: TLS 1.0 (0x0301)
        Length: 32
        Alert Message: Encrypted Alert

After decryption:

PS> openssl enc -aes-256-cbc -d -K 1D007E17B3A45483AA921AD9DE06CC6B47571869CF639219C9052970163BB8A2 -iv DAB4C0D0C65CB65DE8D678FD61369811 -in .\client-shutdown.bin -out .\client-shutdown-decrypted.bin -nopad

PS> Format-Hex .\client-shutdown-decrypted.bin

           00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F

00000000   01 00 DF 06 95 88 29 58 C3 7D 78 D5 21 DA 78 7F  ..ß.??)XA}xO!Úx⌂
00000010   A4 CD 25 2B 99 02 09 09 09 09 09 09 09 09 09 09  ¤Í%+?...........

Then the client might close the TCP connection too or continue the communication in plain text.

Miscellaneous

There is a lot more to write about TLS. It is amazing how much you may learn by simply studying the history of this protocol. You may observe how new extensions were and are added, how the protocol evolved and still evolves. I am actually still reading the RFCs. Quite a good description of the protocol (and a lot of links) can be also found on Wikipedia.

Setup your own lab

If you would like to experiment on your own and repeat all the steps described in this post (but with your own keys) I will show you the required steps in this paragraph.

You will need a private RSA key and a certificate:

openssl genpkey -algorithm RSA -out key.pem -pkeyopt rsa_keygen_bits:2048

openssl req -new -x509 -days 365 -key key.pem -out localhost.crt

The second command might require you to answer several questions unless you have the needed sections in the OpenSSL configuration file, for example:

...

[req]
prompt = no
distinguished_name = dn
req_extensions = ext

[dn]
CN = localhost
emailAddress = test@test.com
O = MyCompany
L = Warsaw
C = PL
[ext]
subjectAltName = DNS:localhost

...

Now you are ready to run a sample OpenSSL server:

PS> openssl s_server -cert .\certs\localhost.crt -key .\key.pem -cipher "AES256-SHA" -www

We are limiting the server to use only the RSA handshake and in response always return TLS session parameters. Additionally, with flags: -ssl2, -ssl3, -tls1, -tls1_1, -tls1_2, -no_ssl2, -no_ssl3, -no_tls1, -no_tls1_1, -no_tls1_2 we may configure which version of the TLS our test server will support. Now you may run Wireshark or TCPDump or any other sniffer to register the network traffic between a browser and the test server.

18 thoughts on “Manually decrypting an HTTPS request

  1. Ondrej Valenta March 9, 2016 / 13:02

    Man, I must say you never NEVER stop to amaze me.. I’m following you for several years and you still dig deeper and deeper.. My respect to you.. Ondrej

    • Sebastian Solnica March 9, 2016 / 14:42

      Great thanks, I’m really happy you are following my blog 🙂

  2. sadik September 19, 2017 / 22:47

    is there any HTTPS decryption source code available ?

  3. Samsuddin Sikder October 18, 2017 / 04:15

    can you explain how to decrypt TLS 1.2 Version. as far now i have implemented TLS 1.0 . I could not understand the IV vectors in TLS 1.2

  4. satyanarayana NV July 19, 2018 / 09:20

    Hi Sebastian, I read this blog and it is very interesting. I got into some situation where my server is sending “Encrypted Alert” message to client and closed the connection (FIN). I want to see the error code but not able to decrypt. I applied both server and client private keys on wireshark and could see appliation traffic (HTTP) decrypted but not the “Encryption Alert”. I thought of generating master key and try but failed as PRF.exe which I downloaded is 32bit and I am using Linux and need 64bit version. Would you be able to help?

    • Sebastian Solnica July 22, 2018 / 16:19

      Hi, when the server sends the “Encrypted Alert” message? Usually, you will see it in the handshake phase (so before any encryption happens). Collecting network trace on the client machine or on the server should show you what the problem is about (check especially initial handshake messages: maybe the cipher spec requested by the client is not supported by the server? or client certificate is invalid?). If the “Encryption Alert” message happens after establishing the connection this might indicate a problem in the TLS implementation on either the client or server side.

  5. Antonio Cesario April 11, 2019 / 14:51

    Great tutorial. I work in sector of development of a large company. Nossa company bought a remote monitoring equipment very expensive. The company that sold and developed the system also monitored our equipment. The company closed the doors and the owners left the country. I was assigned to make a new portal to try monitoring our equipment. Our company spent a lot on with this system. The hardware that does the monitoring sends several parameters through an https address was received at the company that closed the doors. On the hardware I have a configuration field where I can change the destination address. I do not know how the application works where the data where received and retrieved.
    I need to find the sending decryption key so I can read these parameters and put everything to work again.
    How do I do that ? I have already captured 100,000 encrypted packets. I can see the client “Hello” and the server “Hello”, TLS1.0 protocol.
    Thank you.

    “Hello Client”

    Frame 2970: 186 bytes on wire (1488 bits), 186 bytes captured (1488 bits) on interface 0
    Ethernet II, Src: Somat_c2:89:79 (00:d0:56:c2:89:79), Dst: IONTAM_20:f4:23 (c8:09:cf:20:f4:23)
    Internet Protocol Version 4, Src: 10.0.0.62, Dst: 198.169.188.10
    Transmission Control Protocol, Src Port: 3584, Dst Port: 443, Seq: 1, Ack: 1, Len: 132
    Source Port: 3584
    Destination Port: 443
    [Stream index: 79]
    [TCP Segment Len: 132]
    Sequence number: 1 (relative sequence number)
    [Next sequence number: 133 (relative sequence number)]
    Acknowledgment number: 1 (relative ack number)
    0101 …. = Header Length: 20 bytes (5)
    Flags: 0x018 (PSH, ACK)
    Window size value: 33580
    [Calculated window size: 33580]
    [Window size scaling factor: -2 (no window scaling used)]
    Checksum: 0x6ae8 [unverified]
    [Checksum Status: Unverified]
    Urgent pointer: 0
    [SEQ/ACK analysis]
    [iRTT: 0.150250990 seconds]
    [Bytes in flight: 132]
    [Bytes sent since last PSH flag: 132]
    [Timestamps]
    [Time since first frame in this TCP stream: 0.152993750 seconds]
    [Time since previous frame in this TCP stream: 0.002337708 seconds]
    TCP payload (132 bytes)
    Transport Layer Security
    TLSv1 Record Layer: Handshake Protocol: Client Hello
    Content Type: Handshake (22)
    Version: TLS 1.0 (0x0301)
    Length: 127
    Handshake Protocol: Client Hello
    Handshake Type: Client Hello (1)
    Length: 123
    Version: TLS 1.0 (0x0301)
    Random: 5cae9edeeb404d9cf5671914798fb97aa46acc892a7a35e1…
    GMT Unix Time: Apr 10, 2019 22:56:46.000000000 Hora oficial do Brasil
    Random Bytes: eb404d9cf5671914798fb97aa46acc892a7a35e1cce0f856…
    Session ID Length: 32
    Session ID: 79f009564e066a4cd33f03820cb8650fe9915b73144ac711…
    Cipher Suites Length: 52
    Cipher Suites (26 suites)
    Cipher Suite: TLS_DHE_RSA_WITH_AES_256_CBC_SHA (0x0039)
    Cipher Suite: TLS_DHE_DSS_WITH_AES_256_CBC_SHA (0x0038)
    Cipher Suite: TLS_RSA_WITH_AES_256_CBC_SHA (0x0035)
    Cipher Suite: TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA (0x0016)
    Cipher Suite: TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA (0x0013)
    Cipher Suite: TLS_RSA_WITH_3DES_EDE_CBC_SHA (0x000a)
    Cipher Suite: TLS_DHE_RSA_WITH_AES_128_CBC_SHA (0x0033)
    Cipher Suite: TLS_DHE_DSS_WITH_AES_128_CBC_SHA (0x0032)
    Cipher Suite: TLS_RSA_WITH_AES_128_CBC_SHA (0x002f)
    Cipher Suite: TLS_DHE_DSS_WITH_RC4_128_SHA (0x0066)
    Cipher Suite: TLS_RSA_WITH_RC4_128_SHA (0x0005)
    Cipher Suite: TLS_RSA_WITH_RC4_128_MD5 (0x0004)
    Cipher Suite: TLS_DHE_DSS_EXPORT1024_WITH_DES_CBC_SHA (0x0063)
    Cipher Suite: TLS_RSA_EXPORT1024_WITH_DES_CBC_SHA (0x0062)
    Cipher Suite: TLS_RSA_EXPORT1024_WITH_RC2_CBC_56_MD5 (0x0061)
    Cipher Suite: TLS_DHE_RSA_WITH_DES_CBC_SHA (0x0015)
    Cipher Suite: TLS_DHE_DSS_WITH_DES_CBC_SHA (0x0012)
    Cipher Suite: TLS_RSA_WITH_DES_CBC_SHA (0x0009)
    Cipher Suite: TLS_DHE_DSS_EXPORT1024_WITH_RC4_56_SHA (0x0065)
    Cipher Suite: TLS_RSA_EXPORT1024_WITH_RC4_56_SHA (0x0064)
    Cipher Suite: TLS_RSA_EXPORT1024_WITH_RC4_56_MD5 (0x0060)
    Cipher Suite: TLS_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA (0x0014)
    Cipher Suite: TLS_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA (0x0011)
    Cipher Suite: TLS_RSA_EXPORT_WITH_DES40_CBC_SHA (0x0008)
    Cipher Suite: TLS_RSA_EXPORT_WITH_RC2_CBC_40_MD5 (0x0006)
    Cipher Suite: TLS_RSA_EXPORT_WITH_RC4_40_MD5 (0x0003)
    Compression Methods Length: 1
    Compression Methods (1 method)

    “Hello server”

    Frame 3023: 192 bytes on wire (1536 bits), 192 bytes captured (1536 bits) on interface 0
    Ethernet II, Src: 3Com_a4:d1:01 (00:12:a9:a4:d1:01), Dst: ONTAM_20:f4:23 (c8:09:cf:20:f4:23)
    Internet Protocol Version 4, Src: 198.169.188.10, Dst: 10.0.0.62
    Transmission Control Protocol, Src Port: 443, Dst Port: 3584, Seq: 1, Ack: 133, Len: 138
    Source Port: 443
    Destination Port: 3584
    [Stream index: 79]
    [TCP Segment Len: 138]
    Sequence number: 1 (relative sequence number)
    [Next sequence number: 139 (relative sequence number)]
    Acknowledgment number: 133 (relative ack number)
    0101 …. = Header Length: 20 bytes (5)
    Flags: 0x018 (PSH, ACK)
    Window size value: 4512
    [Calculated window size: 4512]
    [Window size scaling factor: -2 (no window scaling used)]
    Checksum: 0x3ca4 [unverified]
    [Checksum Status: Unverified]
    Urgent pointer: 0
    [SEQ/ACK analysis]
    [This is an ACK to the segment in frame: 2970]
    [The RTT to ACK the segment was: 1.207002916 seconds]
    [iRTT: 0.150250990 seconds]
    [Bytes in flight: 138]
    [Bytes sent since last PSH flag: 138]
    [Timestamps]
    [Time since first frame in this TCP stream: 1.359996666 seconds]
    [Time since previous frame in this TCP stream: 1.206974947 seconds]
    TCP payload (138 bytes)
    Transport Layer Security
    TLSv1 Record Layer: Handshake Protocol: Server Hello
    Content Type: Handshake (22)
    Version: TLS 1.0 (0x0301)
    Length: 74
    Handshake Protocol: Server Hello
    Handshake Type: Server Hello (2)
    Length: 70
    Version: TLS 1.0 (0x0301)
    Random: 4a93773b392e000d96daffc04d983741253a4b22fe0f6887…
    GMT Unix Time: Aug 25, 2009 02:31:39.000000000 Hora oficial do Brasil
    Random Bytes: 392e000d96daffc04d983741253a4b22fe0f6887dbce24ff…
    Session ID Length: 32
    Session ID: 79f009564e066a4cd33f03820cb8650fe9915b73144ac711…
    Cipher Suite: TLS_RSA_WITH_AES_128_CBC_SHA (0x002f)
    Compression Method: null (0)
    TLSv1 Record Layer: Change Cipher Spec Protocol: Change Cipher Spec
    Content Type: Change Cipher Spec (20)
    Version: TLS 1.0 (0x0301)
    Length: 1
    Change Cipher Spec Message
    [Expert Info (Note/Sequence): This session reuses previously negotiated keys (Session resumption)]
    [This session reuses previously negotiated keys (Session resumption)]
    [Severity level: Note]
    [Group: Sequence]
    TLSv1 Record Layer: Handshake Protocol: Encrypted Handshake Message
    Content Type: Handshake (22)
    Version: TLS 1.0 (0x0301)
    Length: 48
    Handshake Protocol: Encrypted Handshake Message

    Very Thank you.

    • Sebastian Solnica April 12, 2019 / 08:53

      Hi, from the trace you pasted I see that the server chooses TLS_RSA_WITH_AES_128_CBC_SHA. So to decrypt the symmetric key you need to extract the certificate that the web server uses. It is often stored in the OS cert store but could be in other places too, depending on what web server you are using.

      • Antonio Cesario April 12, 2019 / 18:53

        Thanks

  6. Arjun Sharma January 3, 2020 / 17:14

    Hello SEBASTIAN,

    Does Client uses Client Random Number from the Client-Hello Message and Server Random Number from the Server-Hello Message to generate the pre-master key? What I mean is Pre-Master Key = Client Hello Random + Server Hello Random ?

    If answer to above question is no, then one more question:

    How does server verifies the integrity of the pre-master key submitted to it? How does server knows that the client who had initiated the ssl handshake is sending the pre-master key ? Any man-in-middle can generate and send the pre-master key to the server.

    • Sebastian Solnica January 3, 2020 / 19:31

      Hi Arjun,

      The answer to the first question is no. The pre-master key is an array of random byte values, generated by the client. The server does not verify the integrity of the pre-master key (if it decrypts with the server RSA private key, it uses the value). However, the server and client later use the pre-master key to calculate the final master key. If the computed master key differs between the server and the client, the handshake will fail.

  7. helloserver June 19, 2020 / 07:05

    how to get key.pem from my own .pfx file

    • helloserver June 19, 2020 / 07:09

      I use the command line:
      openssl pkcs212 in client.pfx -password pass:111111 -nocerts -nodes -out client1.pem
      openssl rsa -in client1.pem -out client2.pem
      openssl pkeyutl -decrypt -in .\premaster-encrypted.bin -inkey .\client2.pem -out premaster-decrypted.bin
      but it’s wrong

      • helloserver June 19, 2020 / 07:14

        I use the command line:
        openssl pkcs12 in client.pfx -password pass:111111 -nocerts -nodes -out client1.pem
        openssl rsa -in client1.pem -out client2.pem
        openssl pkeyutl -decrypt -in .\premaster-encrypted.bin -inkey .\client2.pem -out premaster-decrypted.bin
        but it’s wrong

      • Sebastian Solnica June 19, 2020 / 15:50

        What you did seems right. It’s really hard to tell what could be wrong. What is the error? Are you sure you exported premaster correctly? Also, is the .pfx certificate the one that server uses (the name suggests client)?

Leave a reply to Sebastian Solnica Cancel reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.