In his blog post, 'The First Few Milliseconds of an HTTPS Connection', Jeff Moser does a wonderful job of walking through the TLS/SSL handshake process, and explaining what is happening on the client side, what is happening on the server side, and what is going over the wire during each step of the process.

But, being that the post was written in 2009, the article describes the process using TLS 1.0 with the TLS_RSA_WITH_RC4_128_MD5 cipher suite. Of course, TLS 1.0 with this cipher suite is now considered to be deprecated.

I'm interested in seeing a similar walk-through based on SSL/TLS protocols and cipher suites that are considered to be secure today (preferably with perfect forward secrecy) - e.g. TLS 1.2 with TLS_ECHDE_RSA_WITH_AES_128_GCM_SHA256. Would anyone on here be interested in taking a crack at writing one?


1 Answer 1


Disclamer: I am NOT a professional cryptographer nor an expert on the subject, only a security enthusiast. Therefor, I strongly encourage anybody more qualified to improve this post.

Before we start, I assume you mean "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256" (0xC0,0x2F).

So based on the article you published, here what would change compared to TLS1.0.


[Client] ClientHello

First things first: the protocol version should be 1.2 (0x0303) and the client specifies the following parameters:

See below a capture of a ClientHello packet (Firefox 51 Nightly).

⚠ Some extension parameters aren't unfolded because empty/irrelevant.


[Server] ServerHello

The server picks its preferred cipher suite (TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) and point format (uncompressed (0) since it's listed as first choice) and send it back to the client.


[Server] Certificate

The server returns its RSA certificate, nothing changes here. The server authentication process is identical to the one detailed in your article.

[Server] ServerKeyExchange

The server send the curve type (named_curve), the selected named curve (secp384r1), its ephemeral public key (04:31:b9:9d:bc:66...) and the selected algorithms for hashing and signature.

The signature is defined as:

SHA-256(ClientHello.random + ServerHello.random + ServerKeyExchange.params);

and is signed by the server's private key.

The curve secp384r1 (also known as P-384 under NIST classification) is standard and defined by the following equation:

E: y2=x3+ax+b (mod p)

with the following domain parameters over the prime field Fp-384:

  • p = 2384 − 2128 − 296 + 232 − 1 = 39402006196394479212279040100143613805079739270465446667948293404245721771496870329047266088258938001861606973112319
  • a = -3
  • b = 27580193559959705877849011840389048093056905856361568521428707301988689241309860865136260764883745107765439761230575
  • g(X,Y) = 26247035095799689268623156744566981891852923491109213387815615900925518854738050089022388053975719786650872476732087, 8325710961489029985546751289520108179287853048861315594709205902480503199884419224438643760392947333078086511627871
  • n = 39402006196394479212279040100143613805079739270465446667946905279627659399113263569398956308152294913554433653942643
  • h = 1

All these parameters are public.

Side note: Both the client and server have agreed on using a named curve, resulting in a much smaller Server Key Exchange packet since the domain parameters are standardized and thus known by both parties.

The server public key is calculated as:

Kpub = Kpriv × G

The server private key is just a random number, defined as:

1 ≤ Kpriv ≤ n-1


[Server] ServerHelloDone

No difference with TLS1.0.


[Client] ClientKeyExchange / ChangeCipherSpec

This packet contains the client's ephemeral ECDH public key. It's calculated the same way as the server's public key (again, the generator G is common between the client and the server).

From that point, the client advise the server the next message(s) from it will be encrypted.


[Server] ChangeCipherSpec

The server acknowledges client's last message by returning the same ChangeCipherSpec message.


Beyond that point, all communications are encrypted using AES-GCM 128bit.

The symmetric key is calculated on both parties by multiplying its own private key by the other's public key i.e.:

  • Client : Symmetric Key = Client Kpriv * Server Kpub
  • Server : Symmetric key = Server Kpriv * Client Kpub

TLS 1.3 (bonus)

As of today (august 2016), TLS1.3 is still a draft so it would be premature to deep dive in it. Still, writing similar article based on packet sniffing would be tricky on TLS1.3 because the handshake is vastly different as illustrated below:

TLS 1.3 Full handshake Source

As you can see, sniffing the handshake sequence (using cloudflare server) won't tell you much since the relevant data are encrypted in the ServerHello packet (see "EncryptedExtension" field).

I couldn't illustrate the sequence using Wireshark since TLS 1.3 is not supported yet.

  • Some of the "irrelevant" extensions are related to TLS 1.3 (40 is key_share). Wireshark TLS 2.4.3 is up to date with the latest draft version (draft-22). Maybe useful to know is that the "RSA certificate" means that a RSA public key is embedded in the certificate, this can be used for signing the handshake messages by the server (in SKE). An alternative signature algorithm is ECDSA, this requires an EC public key.
    – Lekensteyn
    Dec 20, 2017 at 9:37

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .