The Illustrated TLS 1.3 Connection
The Illustrated TLS 1.3 Connection
Every byte explained and reproduced
In this demonstration a client connects to a server, negotiates a TLS 1.3 session, sends "ping", receives "pong", and then terminates the session. Click below to begin exploring.
+/- Client Key Exchange Generation
The client begins by generating a private/public keypair for key exchange. Key exchange is a technique where two parties can agree on the same number without an eavesdropper being able to tell what the number is.
An explanation of the key exchange can be found on my X25519 site, but doesn't need to be understood in depth for the rest of this page.
The private key is chosen by selecting an integer between 0 and 2256-1. The client does this by generating 32 bytes (256 bits) of random data. The private key selected is:
202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f
The public key is created from the private key as explained on the X25519 site. The public key calculated is:
358072d6365880d1aeea329adf9121383851ed21a28e3b75e965d0d2cd166254
The public key calculation can be confirmed at the command line:
### requires openssl 1.1.0 or higher
$ openssl pkey -noout -text < client-ephemeral-private.key
X25519 Private-Key:
priv:
20:21:22:23:24:25:26:27:28:29:2a:2b:2c:2d:2e:
2f:30:31:32:33:34:35:36:37:38:39:3a:3b:3c:3d:
3e:3f
pub:
35:80:72:d6:36:58:80:d1:ae:ea:32:9a:df:91:21:
38:38:51:ed:21:a2:8e:3b:75:e9:65:d0:d2:cd:16:
62:54
》Client Hello
- client random data (used later in the handshake)
- a list of cipher suites that the client supports
- a list of public keys that the server might find suitable for key exchange
- protocol versions that the client can support
16 03 01 00 f8
Record Header
TLS sessions are broken into the sending and receiving of "records", which are blocks of data with a type, a protocol version, and a length.- 16 - type is 0x16 (handshake record)
- 03 01 - protocol version is "3,1" (also known as TLS 1.0)
- 00 f8 - 0xF8 (248) bytes of handshake message follows
01 00 00 f4
Handshake Header
Each handshake message starts with a type and a length.- 01 - handshake message type 0x01 (client hello)
- 00 00 f4 - 0xF4 (244) bytes of client hello data follows
03 03
Client Version
A protocol version of "3,3" (meaning TLS 1.2) is given. Because middleboxes have been created and widely deployed that do not allow protocol versions that they do not recognize, the TLS 1.3 session must be disguised as a TLS 1.2 session. This field is no longer used for version negotiation and is hardcoded to the 1.2 version. Instead, version negotiation is performed using the "Supported Versions" extension below.The unusual version number ("3,3" representing TLS 1.2) is due to TLS 1.0 being a minor revision of the SSL 3.0 protocol. Therefore TLS 1.0 is represented by "3,1", TLS 1.1 is "3,2", and so on.
00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f 10 11 12 13 14 15 16 17 18 19 1a 1b 1c 1d 1e 1f
Client Random
The client provides 32 bytes of random data. This data will be used later in the session. In this example we've made the random data a predictable string.20 e0 e1 e2 e3 e4 e5 e6 e7 e8 e9 ea eb ec ed ee ef f0 f1 f2 f3 f4 f5 f6 f7 f8 f9 fa fb fc fd fe ff
Session ID
In previous versions of TLS the client could provide an ID of a previously negotiated session, which allows the server and client to skip the time and cost of negotiating new keys.In TLS 1.3 this "session resume" is done via the more flexible PSK (pre-shared keys) mechanism, so this field is no longer needed for that purpose. Instead, a non-empty value in this field is used to trigger "middlebox compatibility mode" which helps TLS 1.3 sessions to be disguised as resumed TLS 1.2 sessions. The client has generated random data to populate this field.
- 20 - 0x20 (32) bytes of session ID follow
- e0 e1 ... fe ff - fake session ID
00 08 13 02 13 03 13 01 00 ff
Cipher Suites
The client provides an ordered list of which cipher suites it will support for encryption. The list is in the order preferred by the client, with highest preference first.In TLS 1.3 the list of possible cipher suites has been greatly reduced. All the remaining suites are AEAD algorithms which provide stronger encryption guarantees than many previous suites with an easier all-in-one implementation.
- 00 08 - 8 bytes of cipher suite data
- 13 02 - assigned value for TLS_AES_256_GCM_SHA384
- 13 03 - assigned value for TLS_CHACHA20_POLY1305_SHA256
- 13 01 - assigned value for TLS_AES_128_GCM_SHA256
- 00 ff - assigned value for TLS_EMPTY_RENEGOTIATION_INFO_SCSV
01 00
Compression Methods
Previous versions of TLS supported compression, which was found to leak information about the encrypted data allowing it to be read (see CRIME).TLS 1.3 no longer allows compression, so this field is always a single entry with the "null" compression method which performs no change to the data.
- 01 - 1 bytes of compression methods
- 00 - assigned value for "null" compression
00 a3
Extensions Length
The client has provided a list of optional extensions which the server can use to take action or enable new features.- 00 a3 - the extensions will take 0xA3 (163) bytes of data
00 00 00 18 00 16 00 00 13 65 78 61 6d 70 6c 65 2e 75 6c 66 68 65 69 6d 2e 6e 65 74
Extension - Server Name
The client has provided the name of the server it is contacting, also known as SNI (Server Name Indication).Without this extension an HTTPS server would not be able to provide service for multiple hostnames (virtual hosts) on a single IP address because it couldn't know which hostname's certificate to send until after the TLS session was negotiated and the HTTP request was made.
- 00 00 - assigned value for extension "server name"
- 00 18 - 0x18 (24) bytes of "server name" extension data follows
- 00 16 - 0x16 (22) bytes of first (and only) list entry follows
- 00 - list entry is type 0x00 "DNS hostname"
- 00 13 - 0x13 (19) bytes of hostname follows
- 65 78 61 ... 6e 65 74 - "example.ulfheim.net"
00 0b 00 04 03 00 01 02
Extension - EC Point Formats
The client has indicated that it supports receiving elliptic curve data points in the following compression formats:- 00 0b - assigned value for extension "ec point formats"
- 00 04 - 4 bytes of format types follow
- 03 - 3 bytes of format types follow
- 00 - assigned value for format "uncompressed"
- 01 - assigned value for format "ansiX962_compressed_prime"
- 02 - assigned value for format "ansiX962_compressed_char2"
00 0a 00 16 00 14 00 1d 00 17 00 1e 00 19 00 18 01 00 01 01 01 02 01 03 01 04
Extension - Supported Groups
The client has indicated that it supports elliptic curve (EC) cryptography for ten curve types. To make this extension more generic for other cryptography types it calls these "supported groups" instead of "supported curves".This list is presented in descending order of the client's preference.
- 00 0a - assigned value for extension "supported groups"
- 00 16 - 0x16 (22) bytes of "supported group" extension data follows
- 00 14 - 0x14 (20) bytes of data are in the curves list
- 00 1d - assigned value for the curve "x25519"
- 00 17 - assigned value for the curve "secp256r1"
- 00 1e - assigned value for the curve "x448"
- 00 19 - assigned value for the curve "secp521r1"
- 00 18 - assigned value for the curve "secp384r1"
- 01 00 - assigned value for the curve "ffdhe2048"
- 01 01 - assigned value for the curve "ffdhe3072"
- 01 02 - assigned value for the curve "ffdhe4096"
- 01 03 - assigned value for the curve "ffdhe6144"
- 01 04 - assigned value for the curve "ffdhe8192"
00 23 00 00
Extension - Session Ticket
The client indicates it has no session ticket to provide for this connection.- 00 23 - assigned value for extension "Session Ticket"
- 00 00 - 0 bytes of "Session Ticket" extension data follows
00 16 00 00
Extension - Encrypt-Then-MAC
The client indicates it can support EtM, which prevents certain vulnerabilities in earlier versions of TLS. In TLS 1.3 this mechanism is always used, so this extension will have no effect in this session.- 00 16 - assigned value for extension "Encrypt Then MAC"
- 00 00 - 0 bytes of "Encrypt Then MAC" extension data follows
00 17 00 00
Extension - Extended Master Secret
The client indicates support for extra cryptographic operations which prevent vulnerabilities in earlier versions of TLS (see RFC 7627 for details). In TLS 1.3 the vulnerabilities are no longer present, so this extension will have no effect in this session.- 00 17 - assigned value for extension "Extended Master Secret"
- 00 00 - 0 bytes of "Extended Master Secret" extension data follows
00 0d 00 1e 00 1c 04 03 05 03 06 03 08 07 08 08 08 09 08 0a 08 0b 08 04 08 05 08 06 04 01 05 01 06 01
Extension - Signature Algorithms
This extension indicates which signature algorithms the client supports. This can influence the certificate that the server presents to the client, as well as the signature that is sent by the server in the CertificateVerify record.This list is presented in descending order of the client's preference.
- 00 0d - assigned value for extension "Signature Algorithms"
- 00 1e - 0x1E (30) bytes of "Signature Algorithms" extension data follows
- 00 1c - 0x1C (28) bytes of data are in the following list of algorithms
- 04 03 - assigned value for ECDSA-SECP256r1-SHA256
- 05 03 - assigned value for ECDSA-SECP384r1-SHA384
- 06 03 - assigned value for ECDSA-SECP521r1-SHA512
- 08 07 - assigned value for ED25519
- 08 08 - assigned value for ED448
- 08 09 - assigned value for RSA-PSS-PSS-SHA256
- 08 0a - assigned value for RSA-PSS-PSS-SHA384
- 08 0b - assigned value for RSA-PSS-PSS-SHA512
- 08 04 - assigned value for RSA-PSS-RSAE-SHA256
- 08 05 - assigned value for RSA-PSS-RSAE-SHA384
- 08 06 - assigned value for RSA-PSS-RSAE-SHA512
- 04 01 - assigned value for RSA-PKCS1-SHA256
- 05 01 - assigned value for RSA-PKCS1-SHA384
- 06 01 - assigned value for RSA-PKCS1-SHA512
00 2b 00 03 02 03 04
Extension - Supported Versions
The client indicates its support of TLS 1.3. This is the only indication in the Client Hello record that hints the client supports TLS 1.3, since for compatibility reasons it has otherwise pretended to be a TLS 1.2 connection attempt.- 00 2b - assigned value for extension "Supported Versions"
- 00 03 - 3 bytes of "Supported Versions" extension data follows
- 02 - 2 bytes of TLS versions follow
- 03 04 - assigned value for TLS 1.3
00 2d 00 02 01 01
Extension - PSK Key Exchange Modes
The client indicates the modes available for establishing keys from pre-shared keys (PSKs). Since we do not use PSKs in this session, this extension has no effect.- 00 2d - assigned value for extension "PSK Key Exchange Modes"
- 00 02 - 2 bytes of "PSK Key Exchange Modes" extension data follows
- 01 - 1 bytes of exchange modes follow
- 01 - assigned value for "PSK with (EC)DHE key establishment"
00 33 00 26 00 24 00 1d 00 20 35 80 72 d6 36 58 80 d1 ae ea 32 9a df 91 21 38 38 51 ed 21 a2 8e 3b 75 e9 65 d0 d2 cd 16 62 54
Extension - Key Share
The client sends one or more ephemeral public keys using algorithm(s) that it thinks the server will support. This allows the rest of the handshake after the ClientHello and ServerHello messages to be encrypted, unlike previous protocol versions where the handshake was sent in the clear.- 00 33 - assigned value for extension "Key Share"
- 00 26 - 0x26 (38) bytes of "Key Share" extension data follows
- 00 24 - 0x24 (36) bytes of key share data follows
- 00 1d - assigned value for x25519 (key exchange via curve25519)
- 00 20 - 0x20 (32) bytes of public key follows
- 35 80 ... 62 54 - public key from the step "Client Key Exchange Generation"
+/- Server Key Change Generation
The server generates a private/public keypair for key exchange. Key exchange is a technique where two parties can agree on the same number without an eavesdropper being able to tell what it is.
An explanation of the key exchange can be found on my X25519 site, but doesn't need to be understood in depth for the rest of this page.
The private key is chosen by selecting an integer between 0 and 2256-1. The server does this by generating 32 bytes (256 bits) of random data. The private key selected is:
909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeaf
The public key is created from the private key as explained on the X25519 site. The public key calculated is:
9fd7ad6dcff4298dd3f96d5b1b2af910a0535b1488d7f8fabb349a982880b615
The public key calculation can be confirmed at the command line:
### requires openssl 1.1.0 or higher
$ openssl pkey -noout -text < server-ephemeral-private.key
X25519 Private-Key:
priv:
90:91:92:93:94:95:96:97:98:99:9a:9b:9c:9d:9e:
9f:a0:a1:a2:a3:a4:a5:a6:a7:a8:a9:aa:ab:ac:ad:
ae:af
pub:
9f:d7:ad:6d:cf:f4:29:8d:d3:f9:6d:5b:1b:2a:f9:
10:a0:53:5b:14:88:d7:f8:fa:bb:34:9a:98:28:80:
b6:15
《 Server Hello
- server random data (used later in the handshake)
- a selected cipher suite
- a public key for key exchange
- the negotiated protocol version
Record Header
TLS sessions are broken into the sending and receiving of "records", which are blocks of data with a type, a protocol version, and a length.- 16 - type is 0x16 (handshake record)
- 03 03 - legacy protocol version of "3,3" (TLS 1.2)
- 00 7a - 0x7A (122) bytes of handshake message follows
Handshake Header
Each handshake message starts with a type and a length.- 02 - handshake message type 0x02 (server hello)
- 00 00 76 - 0x76 (118) bytes of server hello data follows
Server Version
A protocol version of "3,3" (meaning TLS 1.2) is given. Because middleboxes have been created and widely deployed that do not allow protocol versions that they do not recognize, the TLS 1.3 session must be disguised as a TLS 1.2 session. This field is no longer used for version negotiation and is hardcoded to the 1.2 version. Instead, version negotiation is performed using the "Supported Versions" extension below.The unusual version number ("3,3" representing TLS 1.2) is due to TLS 1.0 being a minor revision of the SSL 3.0 protocol. Therefore TLS 1.0 is represented by "3,1", TLS 1.1 is "3,2", and so on.
Server Random
The server provides 32 bytes of random data. This data will be used later in the session. In this example we've made the random data a predictable string.Session ID
This legacy field is no longer used to identify and re-use sessions. Instead, the server echos the session ID provided by the client, if any.- 20 - 0x20 (32) bytes of session ID follow
- e0 e1 ... fe ff - session ID copied from Client Hello
Cipher Suite
The server has selected cipher suite 0x1302 (TLS_AES_256_GCM_SHA384) from the list of options given by the client.Compression Method
The server has selected compression method 0x00 ("Null", which performs no compression) from the list of options given by the client.Extensions Length
The server has returned a list of extensions to the client. Because the server is forbidden from replying with an extension that the client did not send in its hello message, the server knows that the client will understand and support all extensions listed.- 00 2e - the extensions will take 0x2E (46) bytes of data
Extension - Supported Versions
The server indicates the negotiated TLS version of 1.3.- 00 2b - assigned value for extension "Supported Versions"
- 00 02 - 2 bytes of "Supported Versions" extension data follows
- 03 04 - assigned value for TLS 1.3
Extension - Key Share
The server sends a public key using the algorithm of the public key sent by the client. Once this is sent encryption keys can be calculated and the rest of the handshake will be encrypted, unlike previous protocol versions where the handshake was sent in the clear.- 00 33 - assigned value for extension "Key Share"
- 00 24 - 0x24 (36) bytes of "Key Share" extension data follows
- 00 1d - assigned value for x25519 (key exchange via curve25519)
- 00 20 - 0x20 (32) bytes of public key follows
- 9f d7 ... b6 15 - public key from the step "Server Key Exchange Generation"
+/- Server Handshake Keys Calc
- client public key (from Client Hello)
- server private key (from Server Key Exchange Generation)
- SHA384 hash of ClientHello and ServerHello
df4a291baa1eb7cfa6934b29b474baad2697e29f1f920dcc77c8a0a088447624I've provided a tool to perform this calculation:
$ cc -o curve25519-mult curve25519-mult.c
$ ./curve25519-mult server-ephemeral-private.key \
client-ephemeral-public.key | hexdump
0000000 df 4a 29 1b aa 1e b7 cf a6 93 4b 29 b4 74 ba ad
0000010 26 97 e2 9f 1f 92 0d cc 77 c8 a0 a0 88 44 76 24
We then calculate the SHA384 hash of all handshake messages to this point (ClientHello and ServerHello). The hash does not include the 5-byte "record" headers. This "hello_hash" is e05f64fcd082bdb0dce473adf669c2769f257a1c75a51b7887468b5e0e7a7de4f4d34555112077f16e079019d5a845bd:
$ (tail -c +6 clienthello; tail -c +6 serverhello) | openssl sha384
e05f64fcd082bdb0dce473adf669c2769f257a1c75a51b7887468b5e0e7a7de4f4d34555112077f16e079019d5a845bd
We then feed the hash and the shared secret into a set of key derivation operations, designed to ensure the integrity of the handshake process and to protect against known and possible attacks:
early_secret = HKDF-Extract(salt: 00, key: 00...) empty_hash = SHA384("") derived_secret = HKDF-Expand-Label(key: early_secret, label: "derived", ctx: empty_hash, len: 48) handshake_secret = HKDF-Extract(salt: derived_secret, key: shared_secret) client_secret = HKDF-Expand-Label(key: handshake_secret, label: "c hs traffic", ctx: hello_hash, len: 48) server_secret = HKDF-Expand-Label(key: handshake_secret, label: "s hs traffic", ctx: hello_hash, len: 48) client_handshake_key = HKDF-Expand-Label(key: client_secret, label: "key", ctx: "", len: 32) server_handshake_key = HKDF-Expand-Label(key: server_secret, label: "key", ctx: "", len: 32) client_handshake_iv = HKDF-Expand-Label(key: client_secret, label: "iv", ctx: "", len: 12) server_handshake_iv = HKDF-Expand-Label(key: server_secret, label: "iv", ctx: "", len: 12)This has introduced two new cryptographic methods:
- HKDF-Extract - given a salt and some bytes of key material create 384 bits (48 bytes) of new key material, with the input key material's entropy evenly distributed in the output.
- HKDF-Expand-Label - given the inputs of key material, label, and context data, create a new key of the requested length.
$ hello_hash=e05f64fcd082bdb0dce473adf669c2769f257a1c75a51b7887468b5e0e7a7de4f4d34555112077f16e079019d5a845bd
$ shared_secret=df4a291baa1eb7cfa6934b29b474baad2697e29f1f920dcc77c8a0a088447624
$ zero_key=000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
$ early_secret=$(./hkdf-384 extract 00 $zero_key)
$ empty_hash=$(openssl sha384 < /dev/null | sed -e 's/.* //')
$ derived_secret=$(./hkdf-384 expandlabel $early_secret "derived" $empty_hash 48)
$ handshake_secret=$(./hkdf-384 extract $derived_secret $shared_secret)
$ csecret=$(./hkdf-384 expandlabel $handshake_secret "c hs traffic" $hello_hash 48)
$ ssecret=$(./hkdf-384 expandlabel $handshake_secret "s hs traffic" $hello_hash 48)
$ client_handshake_key=$(./hkdf-384 expandlabel $csecret "key" "" 32)
$ server_handshake_key=$(./hkdf-384 expandlabel $ssecret "key" "" 32)
$ client_handshake_iv=$(./hkdf-384 expandlabel $csecret "iv" "" 12)
$ server_handshake_iv=$(./hkdf-384 expandlabel $ssecret "iv" "" 12)
$ echo hssec: $handshake_secret
$ echo ssec: $ssecret
$ echo csec: $csecret
$ echo skey: $server_handshake_key
$ echo siv: $server_handshake_iv
$ echo ckey: $client_handshake_key
$ echo civ: $client_handshake_iv
hssec: bdbbe8757494bef20de932598294ea65b5e6bf6dc5c02a960a2de2eaa9b07c929078d2caa0936231c38d1725f179d299
ssec: 23323da031634b241dd37d61032b62a4f450584d1f7f47983ba2f7cc0cdcc39a68f481f2b019f9403a3051908a5d1622
csec: db89d2d6df0e84fed74a2288f8fd4d0959f790ff23946cdf4c26d85e51bebd42ae184501972f8d30c4a3e4a3693d0ef0
skey: 9f13575ce3f8cfc1df64a77ceaffe89700b492ad31b4fab01c4792be1b266b7f
siv: 9563bc8b590f671f488d2da3
ckey: 1135b4826a9a70257e5a391ad93093dfd7c4214812f493b3e3daae1eb2b1ac69
civ: 4256d2e0e88babdd05eb2f27
From this we get the following key data:
- handshake secret: bdbbe8757494bef20de932598294ea65b5e6bf6dc5c02a960a2de2eaa9b07c929078d2caa0936231c38d1725f179d299
- server handshake traffic secret: 23323da031634b241dd37d61032b62a4f450584d1f7f47983ba2f7cc0cdcc39a68f481f2b019f9403a3051908a5d1622.
- client handshake traffic secret: db89d2d6df0e84fed74a2288f8fd4d0959f790ff23946cdf4c26d85e51bebd42ae184501972f8d30c4a3e4a3693d0ef0.
- server handshake key: 9f13575ce3f8cfc1df64a77ceaffe89700b492ad31b4fab01c4792be1b266b7f
- server handshake IV: 9563bc8b590f671f488d2da3
- client handshake key: 1135b4826a9a70257e5a391ad93093dfd7c4214812f493b3e3daae1eb2b1ac69
- client handshake IV: 4256d2e0e88babdd05eb2f27
+/- Client Handshake Keys Calc
- server public key (from Server Hello)
- client private key (from Client Key Exchange Generation)
- SHA384 hash of ClientHello and ServerHello
df4a291baa1eb7cfa6934b29b474baad2697e29f1f920dcc77c8a0a088447624I've provided a tool to perform this calculation:
$ cc -o curve25519-mult curve25519-mult.c
$ ./curve25519-mult client-ephemeral-private.key \
server-ephemeral-public.key | hexdump
0000000 df 4a 29 1b aa 1e b7 cf a6 93 4b 29 b4 74 ba ad
0000010 26 97 e2 9f 1f 92 0d cc 77 c8 a0 a0 88 44 76 24
Since the shared secret above is the same number calculated by the server in "Server Handshake Keys Calc", the rest of the calculation is identical and the same values are found:
- server handshake key: 9f13575ce3f8cfc1df64a77ceaffe89700b492ad31b4fab01c4792be1b266b7f
- server handshake IV: 9563bc8b590f671f488d2da3
- client handshake key: 1135b4826a9a70257e5a391ad93093dfd7c4214812f493b3e3daae1eb2b1ac69
- client handshake IV: 4256d2e0e88babdd05eb2f27
《 Server Change Cipher Spec
This record served a purpose in earlier versions on TLS but is no longer needed. In "middlebox compatibility mode" this record is sent to help disguise the session as a TLS 1.2 session.
14 03 03 00 01 01
Record Header
TLS sessions are broken into the sending and receiving of "records", which are blocks of data with a type, a protocol version, and a length.- 14 - type is 0x14 (ChangeCipherSpec record)
- 03 03 - legacy protocol version of "3,3" (TLS 1.2)
- 00 01 - the length of the record payload is 1 bytes
- 01 - the payload of this message is defined as the byte 0x01
《 Wraped Record
To reduce issues with middleboxes that block unrecognized TLS protocols, the encrypted handshake records are disguised as a TLS 1.2 session that has performed a successful session resume.
This wrapped record is discussed in its own section below this one.
17 03 03 00 17
Record Header
The TLS 1.3 records are encrypted into a TLS 1.2 record "wrapper" that looks like application data.- 17 - type is 0x17 (application data)
- 03 03 - legacy protocol version of "3,3" (TLS 1.2)
- 00 17 - 0x17 (23) bytes of wrapped data follows
6b e0 2f 9d a7 c2 dc
Encrypted Data
This data is encrypted with the server handshake key.9d de f5 6f 24 68 b9 0a df a2 51 01 ab 03 44 ae
Auth Tag
This is the AEAD authentication tag that protects the integrity of the encrypted data and the record header.Decryption
This data is encrypted using the server handshake key and the server handshake IV that were generated during the "Server Handshake Keys Calc" step. The IV will be modified by XOR'ing it by the count of records that have already been encrypted with this key, which in this case is 0. The process also takes as input the 5-byte record header that this record begins with, as authenticated data that must match for the decryption to succeed.Because the openssl command line tool does not yet support AEAD ciphers, I've written command line tools to both decrypt and encrypt this data.
### from the "Server Handshake Keys Calc" step
$ key=9f13575ce3f8cfc1df64a77ceaffe89700b492ad31b4fab01c4792be1b266b7f
$ iv=9563bc8b590f671f488d2da3
### from this record
$ recdata=1703030017
$ authtag=9ddef56f2468b90adfa25101ab0344ae
$ recordnum=0
### may need to add -I and -L flags for include and lib dirs
$ cc -o aes_256_gcm_decrypt aes_256_gcm_decrypt.c -lssl -lcrypto
$ echo "6b e0 2f 9d a7 c2 dc" | xxd -r -p > /tmp/msg1
$ cat /tmp/msg1 \
| ./aes_256_gcm_decrypt $iv $recordnum $key $recdata $authtag \
| hexdump -C
00000000 08 00 00 02 00 00 16 |.......|
08 00 00 02 00 00
Encrypted Extensions
This handshake message is represented in its own section below.16
Record Type
Each TLS 1.3 record disguised as TLS 1.2 application data has a final byte which indicates its actual record type.- 16 - type is 0x16 (handshake record)
-- Server Encrypted Extentions
08 00 00 02
Handshake Header
Each handshake message starts with a type and a length.- 08 - handshake message type 0x08 (encrypted extensions)
- 00 00 02 - 2 bytes of handshake message data follows
00 00
Extensions
- 00 00 - 0 bytes of extension data follows
《 Wrapped Record
To reduce issues with middleboxes that block unrecognized TLS protocols, the encrypted handshake records are disguised as a TLS 1.2 session that has performed a successful session resume.
This wrapped record is discussed in its own section below this one.
Record Header
The TLS 1.3 records are encrypted into a TLS 1.2 record "wrapper" that looks like application data.- 17 - type is 0x17 (application data)
- 03 03 - legacy protocol version of "3,3" (TLS 1.2)
- 03 43 - 0x343 (835) bytes of wrapped data follows
Encrypted Data
This data is encrypted with the server handshake key.Auth Tag
This is the AEAD authentication tag that protects the integrity of the encrypted data and the record header.Decryption
This data is encrypted using the server handshake key and the server handshake IV that were generated during the "Server Handshake Keys Calc" step. The IV will be modified by XOR'ing it by the count of records that have already been encrypted with this key, which in this case is 1. The process also takes as input the 5-byte record header that this record begins with, as authenticated data that must match for the decryption to succeed.Because the openssl command line tool does not yet support AEAD ciphers, I've written command line tools to both decrypt and encrypt this data.
### from the "Server Handshake Keys Calc" step
$ key=9f13575ce3f8cfc1df64a77ceaffe89700b492ad31b4fab01c4792be1b266b7f
$ iv=9563bc8b590f671f488d2da3
### from this record
$ recdata=1703030343
$ authtag=58faa5bafa30186c6b2f238eb530c73e
$ recordnum=1
### may need to add -I and -L flags for include and lib dirs
$ cc -o aes_256_gcm_decrypt aes_256_gcm_decrypt.c -lssl -lcrypto
$ echo "ba f0 0a 9b e5 0f 3f 23 07 e7 26 ed cb da cb e4 b1 86 16
... snip ...
a9 19 a7 0e 3a 10 e3 08 41" | xxd -r -p > /tmp/msg1
$ cat /tmp/msg1 \
| ./aes_256_gcm_decrypt $iv $recordnum $key $recdata $authtag \
| hexdump -C
00000000 08 00 00 02 00 00 0b 00 03 2e 00 00 03 2a 00 03 |.............*..|
00000010 25 30 82 03 21 30 82 02 09 a0 03 02 01 02 02 08 |58..!0..........|
00000020 15 5a 92 ad c2 04 8f 90 30 0d 06 09 2a 86 48 86 |.Z......0...*.H.|
00000000 0b 00 03 2e 00 00 03 2a 00 03 25 30 82 03 21 30 |.......*..58..!0|
00000010 82 02 09 a0 03 02 01 02 02 08 15 5a 92 ad c2 04 |...........Z....|
00000020 8f 90 30 0d 06 09 2a 86 48 86 f7 0d 01 01 0b 05 |..0...*.H.......|
00000030 00 30 22 31 0b 30 09 06 03 55 04 06 13 02 55 53 |.0"1.0...U....US|
00000040 31 13 30 11 06 03 55 04 0a 13 0a 45 78 61 6d 70 |1.0...U....Examp|
... snip ...
Server Certificate
This handshake message is represented in its own section below.Record Type
Each TLS 1.3 record disguised as TLS 1.2 application data has a final byte which indicates its actual record type.- 16 - type is 0x16 (handshake record)