TLS is a beast of a protocol with at least 50 extensions and over 20 years of history. This indicates that implementing can be challenging and that it is important to take a close look at its security. TLS drives the web of today. The web can not exist without it anymore. Not only that secrecy and authentication is a must-have today, it is also required by specifications like getUserMedia for WebRTC streaming.
The State Machine
Implementations of TLS usually expose an API which allows to parse and generate messages. Each time a new message is received the TLS library is responsible to update the client or server state and send out the next message 1. Cryptographic operations are executed below the API layer.
Messages can be intercepted or tampered with while they travel from one endpoint to the other. Also new messages can be injected. The task of TLS is to make sure that specific security properties of the connection like Secrecy, Forward Secrecy or Authentication are enforced.
The state machine of TLS is not formally specified 1. Therefore, each TLS library has some freedom in handling the state transitions and edge cases.
Steps in the TLS Handshake
@XargsNotBombs has illustrated the TLS handshake beautifully here. I will describe it here in a more texty way.
I am also doing here something similar like the above illustration. My approach is just more manual and simpler. I will create here a connection to the HTTP server of this blog and send some data: openssl s_client -msg -connect maxammann.org:443
. This command logs all messages of the handshake as hex.
This approach has the advantage that it requires just OpenSSL and some tool to interpret binary messages like WireShark. It does not require any complex setup to look inside of encrypted TLS messages.
๐ป denotes a client and โ๏ธ a server which could be hosted in the cloud.
๐ป โ โ๏ธ ClientHello
We will start by generating a client private $sk_C$ and public $pk_C$ key for which will be used in the elliptic curve Diffie-Hellman key exchange (ECDH).
In TLS 1.3 “static RSA and Diffie-Hellman cipher suites have been removed” 2. Key exchanges are only done using DHE. That means the names of cipher suites also are simpler now. You can query cipher suits of OpenSSL using these commands for TLS 1.2 and 1.3:
1openssl ciphers -v -s -tls1_2
2openssl ciphers -v -s -tls1_3
In my case the output for TLS 1.3 is significantly smaller. You also notice that the key exchange algorithm is no longer specified in the name of the cipher suite. The key exchange algorithm is determined in Client and Server Hello. For example the cipher suite TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 states that the key exchange should happen through Elliptic Curve Diffie-Hellman Ephemeral. The site ciphersuite.info is actually quite cool as it documents all the available cipher suits out there.
Now back to the key generation. We can generate the private key using OpenSSL.
1openssl genpkey -algorithm x25519 -out -
2-----BEGIN PRIVATE KEY-----
3MC4CAQAwBQYDK2VuBCIEIAhAXnd7oaF01rCz5dUfnh8oVSONL4J0kh4I10OwljlH
4-----END PRIVATE KEY-----
For the public key:
1$ openssl pkey -in - -pubout -out -
2-----BEGIN PUBLIC KEY-----
3MCowBQYDK2VuAyEAr84Q+eKbCCSFmvV89tgxd6lRL57rpQYCX4C7eNlb1Wc=
4-----END PUBLIC KEY-----
Now we are sending the ClientHello, which starts with a Record Header:
116 03 01 01 36
- Type is
0x16
- Protocol Version is 3,1 (TLS 1.0) for interoperability reasons
- Handshake Length is
0x0137
The ClientHello includes 0x0136 bytes of Handshake data:
100000000 16 03 01 01 36 01 00 01 32 03 03 aa 17 95 f6 4f |....6...2......O|
200000010 48 fc fc d0 12 13 68 f8 8f 17 6f e2 57 0b 07 68 |H.....h...o.W..h|
300000020 bb c8 5e 9f 2c 80 c5 57 55 3d 7d 20 e1 e1 5d 00 |..^.,..WU=} ..].|
400000030 28 93 2f 4f 74 79 cf 25 63 02 b7 84 7d 81 a6 8e |(./Oty.%c...}...|
500000040 70 85 25 f9 d3 8d 94 fc 6e f7 42 a3 00 3e 13 02 |p.%.....n.B..>..|
600000050 13 03 13 01 c0 2c c0 30 00 9f cc a9 cc a8 cc aa |.....,.0........|
700000060 c0 2b c0 2f 00 9e c0 24 c0 28 00 6b c0 23 c0 27 |.+./...$.(.k.#.'|
800000070 00 67 c0 0a c0 14 00 39 c0 09 c0 13 00 33 00 9d |.g.....9.....3..|
900000080 00 9c 00 3d 00 3c 00 35 00 2f 00 ff 01 00 00 ab |...=.<.5./......|
1000000090 00 00 00 12 00 10 00 00 0d 6d 61 78 61 6d 6d 61 |.........maxamma|
11000000a0 6e 6e 2e 6f 72 67 00 0b 00 04 03 00 01 02 00 0a |nn.org..........|
12000000b0 00 0c 00 0a 00 1d 00 17 00 1e 00 19 00 18 00 23 |...............#|
13000000c0 00 00 00 16 00 00 00 17 00 00 00 0d 00 30 00 2e |.............0..|
14000000d0 04 03 05 03 06 03 08 07 08 08 08 09 08 0a 08 0b |................|
15000000e0 08 04 08 05 08 06 04 01 05 01 06 01 03 03 02 03 |................|
16000000f0 03 01 02 01 03 02 02 02 04 02 05 02 06 02 00 2b |...............+|
1700000100 00 09 08 03 04 03 03 03 02 03 01 00 2d 00 02 01 |............-...|
1800000110 01 00 33 00 26 00 24 00 1d 00 20 9b 8a 24 e2 97 |..3.&.$... ..$..|
1900000120 70 f7 ed 95 bf 33 0e 7e 39 29 b2 10 90 35 0a 41 |p....3.~9)...5.A|
2000000130 5a b4 cd f0 1b 04 e9 ff c0 fc 50 |Z.........P|
Now we can simply import this data into Wireshark to analyze it in a simple way. I fist used CyberChef to create a properly formatted hex dump from the values and then loaded them in Wirehark. The plain OpenSSL output can be seen in openssl_messages.txt. From this file I cleaned it up by adding missing TLS record headers like 16 03 01 01 36
where the last 2 bytes specify the length of the next message. These were crafted manually in order to make it possible to parse them with wireshark. Finally, I removed the comments and put it into CyberChef to create a hexdump.
You have to tell Wireshark to generate a dummy TCP header around it, else the detection fails. The final pcap file can be downloaded here. You can now export this as JSON or use a pretty printed version (Right-click on TLS packet and “Copy > All Visible Items”)
Client Hello Header
1TLSv1.3 Record Layer: Handshake Protocol: Client Hello
2 Content Type: Handshake (22)
3 Version: TLS 1.0 (0x0301)
4 Length: 310
5 Handshake Protocol: Client Hello
6 Handshake Type: Client Hello (1)
7 Length: 306
8 # Version represents TLS 1.2 for interoparability reasons
9 Version: TLS 1.2 (0x0303)
10 # Random value for later use
11 Random: aa1795f64f48fcfcd0121368f88f176fe2570b0768bbc85e9f2c80c557553d7d
12 # Random data as TLS 1.3 uses the PSK method for session resuming
13 Session ID Length: 32
14 Session ID: e1e15d0028932f4f7479cf256302b7847d81a68e708525f9d38d94fc6ef742a3
Advertise Ciphers and Compression
1 # Available cipher suits
2 Cipher Suites Length: 62
3 Cipher Suites (31 suites)
4 Cipher Suite: TLS_AES_256_GCM_SHA384 (0x1302)
5 Cipher Suite: TLS_CHACHA20_POLY1305_SHA256 (0x1303)
6 Cipher Suite: TLS_AES_128_GCM_SHA256 (0x1301)
7 Cipher Suite: TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 (0xc02c)
8 Cipher Suite: TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (0xc030)
9 Cipher Suite: TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 (0x009f)
10 Cipher Suite: TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 (0xcca9)
11 Cipher Suite: TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 (0xcca8)
12 Cipher Suite: TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256 (0xccaa)
13 Cipher Suite: TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 (0xc02b)
14 Cipher Suite: TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (0xc02f)
15 Cipher Suite: TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 (0x009e)
16 Cipher Suite: TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 (0xc024)
17 Cipher Suite: TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 (0xc028)
18 Cipher Suite: TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 (0x006b)
19 Cipher Suite: TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 (0xc023)
20 Cipher Suite: TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 (0xc027)
21 Cipher Suite: TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 (0x0067)
22 Cipher Suite: TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA (0xc00a)
23 Cipher Suite: TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA (0xc014)
24 Cipher Suite: TLS_DHE_RSA_WITH_AES_256_CBC_SHA (0x0039)
25 Cipher Suite: TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA (0xc009)
26 Cipher Suite: TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA (0xc013)
27 Cipher Suite: TLS_DHE_RSA_WITH_AES_128_CBC_SHA (0x0033)
28 Cipher Suite: TLS_RSA_WITH_AES_256_GCM_SHA384 (0x009d)
29 Cipher Suite: TLS_RSA_WITH_AES_128_GCM_SHA256 (0x009c)
30 Cipher Suite: TLS_RSA_WITH_AES_256_CBC_SHA256 (0x003d)
31 Cipher Suite: TLS_RSA_WITH_AES_128_CBC_SHA256 (0x003c)
32 Cipher Suite: TLS_RSA_WITH_AES_256_CBC_SHA (0x0035)
33 Cipher Suite: TLS_RSA_WITH_AES_128_CBC_SHA (0x002f)
34 Cipher Suite: TLS_EMPTY_RENEGOTIATION_INFO_SCSV (0x00ff)
35 # Compression, in TLS 1.3 compression is not allowed because of CRIME attack
36 Compression Methods Length: 1
37 Compression Methods (1 method)
38 Compression Method: null (0)
Extensions
1 Extensions Length: 171
2 # Used when using multiple virtual servers in NGINX/Apache for example
3 Extension: server_name (len=18)
4 Type: server_name (0)
5 Length: 18
6 Server Name Indication extension
7 Server Name list length: 16
8 Server Name Type: host_name (0)
9 Server Name length: 13
10 Server Name: maxammann.org
11 # Supported curves for EC cryptography
12 Extension: supported_groups (len=12)
13 Type: supported_groups (10)
14 Length: 12
15 Supported Groups List Length: 10
16 Supported Groups (5 groups)
17 Supported Group: x25519 (0x001d)
18 Supported Group: secp256r1 (0x0017)
19 Supported Group: x448 (0x001e)
20 Supported Group: secp521r1 (0x0019)
21 Supported Group: secp384r1 (0x0018)
22 # Supported signature algorithms of the client, determines the certificate sent by server
23 Extension: signature_algorithms (len=48)
24 Type: signature_algorithms (13)
25 Length: 48
26 Signature Hash Algorithms Length: 46
27 Signature Hash Algorithms (23 algorithms)
28 Signature Algorithm: ecdsa_secp256r1_sha256 (0x0403)
29 Signature Hash Algorithm Hash: SHA256 (4)
30 Signature Hash Algorithm Signature: ECDSA (3)
31 Signature Algorithm: ecdsa_secp384r1_sha384 (0x0503)
32 Signature Hash Algorithm Hash: SHA384 (5)
33 Signature Hash Algorithm Signature: ECDSA (3)
34 Signature Algorithm: ecdsa_secp521r1_sha512 (0x0603)
35 Signature Hash Algorithm Hash: SHA512 (6)
36 Signature Hash Algorithm Signature: ECDSA (3)
37 Signature Algorithm: ed25519 (0x0807)
38 Signature Hash Algorithm Hash: Unknown (8)
39 Signature Hash Algorithm Signature: Unknown (7)
40 Signature Algorithm: ed448 (0x0808)
41 Signature Hash Algorithm Hash: Unknown (8)
42 Signature Hash Algorithm Signature: Unknown (8)
43 Signature Algorithm: rsa_pss_pss_sha256 (0x0809)
44 Signature Hash Algorithm Hash: Unknown (8)
45 Signature Hash Algorithm Signature: Unknown (9)
46 Signature Algorithm: rsa_pss_pss_sha384 (0x080a)
47 Signature Hash Algorithm Hash: Unknown (8)
48 Signature Hash Algorithm Signature: Unknown (10)
49 Signature Algorithm: rsa_pss_pss_sha512 (0x080b)
50 Signature Hash Algorithm Hash: Unknown (8)
51 Signature Hash Algorithm Signature: Unknown (11)
52 Signature Algorithm: rsa_pss_rsae_sha256 (0x0804)
53 Signature Hash Algorithm Hash: Unknown (8)
54 Signature Hash Algorithm Signature: Unknown (4)
55 Signature Algorithm: rsa_pss_rsae_sha384 (0x0805)
56 Signature Hash Algorithm Hash: Unknown (8)
57 Signature Hash Algorithm Signature: Unknown (5)
58 Signature Algorithm: rsa_pss_rsae_sha512 (0x0806)
59 Signature Hash Algorithm Hash: Unknown (8)
60 Signature Hash Algorithm Signature: Unknown (6)
61 Signature Algorithm: rsa_pkcs1_sha256 (0x0401)
62 Signature Hash Algorithm Hash: SHA256 (4)
63 Signature Hash Algorithm Signature: RSA (1)
64 Signature Algorithm: rsa_pkcs1_sha384 (0x0501)
65 Signature Hash Algorithm Hash: SHA384 (5)
66 Signature Hash Algorithm Signature: RSA (1)
67 Signature Algorithm: rsa_pkcs1_sha512 (0x0601)
68 Signature Hash Algorithm Hash: SHA512 (6)
69 Signature Hash Algorithm Signature: RSA (1)
70 Signature Algorithm: SHA224 ECDSA (0x0303)
71 Signature Hash Algorithm Hash: SHA224 (3)
72 Signature Hash Algorithm Signature: ECDSA (3)
73 Signature Algorithm: ecdsa_sha1 (0x0203)
74 Signature Hash Algorithm Hash: SHA1 (2)
75 Signature Hash Algorithm Signature: ECDSA (3)
76 Signature Algorithm: SHA224 RSA (0x0301)
77 Signature Hash Algorithm Hash: SHA224 (3)
78 Signature Hash Algorithm Signature: RSA (1)
79 Signature Algorithm: rsa_pkcs1_sha1 (0x0201)
80 Signature Hash Algorithm Hash: SHA1 (2)
81 Signature Hash Algorithm Signature: RSA (1)
82 Signature Algorithm: SHA224 DSA (0x0302)
83 Signature Hash Algorithm Hash: SHA224 (3)
84 Signature Hash Algorithm Signature: DSA (2)
85 Signature Algorithm: SHA1 DSA (0x0202)
86 Signature Hash Algorithm Hash: SHA1 (2)
87 Signature Hash Algorithm Signature: DSA (2)
88 Signature Algorithm: SHA256 DSA (0x0402)
89 Signature Hash Algorithm Hash: SHA256 (4)
90 Signature Hash Algorithm Signature: DSA (2)
91 Signature Algorithm: SHA384 DSA (0x0502)
92 Signature Hash Algorithm Hash: SHA384 (5)
93 Signature Hash Algorithm Signature: DSA (2)
94 Signature Algorithm: SHA512 DSA (0x0602)
95 Signature Hash Algorithm Hash: SHA512 (6)
96 Signature Hash Algorithm Signature: DSA (2)
97 # Specify suppor of the client for example for TLS 1.0 - 1.3
98 Extension: supported_versions (len=9)
99 Type: supported_versions (43)
100 Length: 9
101 Supported Versions length: 8
102 Supported Version: TLS 1.3 (0x0304)
103 Supported Version: TLS 1.2 (0x0303)
104 Supported Version: TLS 1.1 (0x0302)
105 Supported Version: TLS 1.0 (0x0301)
106 # Specifies the available modes for use of PSK (for example for 0-RTT)
107 Extension: psk_key_exchange_modes (len=2)
108 Type: psk_key_exchange_modes (45)
109 Length: 2
110 PSK Key Exchange Modes Length: 1
111 PSK Key Exchange Mode: PSK with (EC)DHE key establishment (psk_dhe_ke) (1)
112 # Public key sent by the client for encrypting the following messages (see above how pk_C and sk_C are created)
113 Extension: key_share (len=38)
114 Type: key_share (51)
115 Length: 38
116 Key Share extension
117 Client Key Share Length: 36
118 Key Share Entry: Group: x25519, Key Exchange length: 32
119 Group: x25519 (29)
120 Key Exchange Length: 32
121 Key Exchange: 9b8a24e29770f7ed95bf330e7e3929b21090350a415ab4cdf01b04e9ffc0fc50
Other Extensions
1 Extension: session_ticket (len=0)
2 Type: session_ticket (35)
3 Length: 0
4 Data (0 bytes)
5 Extension: encrypt_then_mac (len=0)
6 Type: encrypt_then_mac (22)
7 Length: 0
8 Extension: extended_master_secret (len=0)
9 Type: extended_master_secret (23)
10 Length: 0
11 Extension: ec_point_formats (len=4)
12 Type: ec_point_formats (11)
13 Length: 4
14 EC point formats Length: 3
15 Elliptic curves point formats (3)
16 EC point format: uncompressed (0)
17 EC point format: ansiX962_compressed_prime (1)
18 EC point format: ansiX962_compressed_char2 (2)
โ๏ธ โ ๐ป Server Hello
The server will also generate a public and private key for DH key exchange. This is done in the same way as in Client Hello (openssl genpkey -algorithm x25519
). So now we have the keys $sk_S$ and public $pk_S$.
Disassembly
1TLSv1.3 Record Layer: Handshake Protocol: Server Hello
2 Content Type: Handshake (22)
3 Version: TLS 1.2 (0x0303)
4 Length: 122
5 Handshake Protocol: Server Hello
6 Handshake Type: Server Hello (2)
7 Length: 118
8 # Same as in Client Hello: We need to disguise as TLS 1.2
9 Version: TLS 1.2 (0x0303)
10 # Random value which will be used later on (TODO: Where?!)
11 Random: debc41503f1f52ec094f9bdf2c0f941db8928069d202f352201b337bea4ed436
12 Session ID Length: 32
13 # Session ID of the client, this is no longer sued in TLS 1.3
14 Session ID: e1e15d0028932f4f7479cf256302b7847d81a68e708525f9d38d94fc6ef742a3
15 # The selected cipher suite
16 Cipher Suite: TLS_AES_256_GCM_SHA384 (0x1302)
17 # Compression method selected by client
18 Compression Method: null (0)
19 Extensions Length: 46
20 # Specifies that we are using TLS 1.3
21 Extension: supported_versions (len=2)
22 Type: supported_versions (43)
23 Length: 2
24 Supported Version: TLS 1.3 (0x0304)
25 # Contains the public key of the server which is used in DH (see above how pk_S and sk_S are created)
26 Extension: key_share (len=36)
27 Type: key_share (51)
28 Length: 36
29 Key Share extension
30 Key Share Entry: Group: x25519, Key Exchange length: 32
31 Group: x25519 (29)
32 Key Exchange Length: 32
33 Key Exchange: 8cbdb10a727ffe655f368521b39a16146d55ff144a0f95235ccd1925c31f6137
Now we are ready to calculate the keys which are used in the encryption of the following handshake messages. The server calculates $sk_S * pk_C$. Now we calculate the SHA256 hash of all sent bytes so far, except the record headers. This includes Client and Server Hello so far. This is also called the transcript hash.
The transcript hash and secret are now fed to a KDF procedure. From this data we derive multiple secrets using HKDF-Extract
and HKDF-Expand-Label
specified in RFC-5869.
We have now (RFC8446 7.1)
- client_handshake_traffic_secret
- server_handshake_traffic_secret.
From these secrets we can derive keys and IVs: (RFC8446 7.3):
- client_handshake_key & client_handshake_iv
- server_handshake_key & server_handshake_iv.
The cool thing is that because of the Diffie Hellman key exchange the client can calculate the same values as it has the transcript hash, client private key and the server public key. That means client_handshake_traffic_secret = server_handshake_traffic_secret and the same for the IV.
โ๏ธ โ ๐ป Change Cipher Spec
This record is sent to disguise as TLS 1.2.
Disassembly
1TLSv1.3 Record Layer: Change Cipher Spec Protocol: Change Cipher Spec
2 Content Type: Change Cipher Spec (20)
3 Version: TLS 1.2 (0x0303)
4 Length: 1
5 Change Cipher Spec Message
โ๏ธ โ ๐ป Encrypted Extensions (Encrypted ๐)
This is the first message which is encrypted using the server handshake keys and IVs like described in Server Hello. An AEAD authentification tag possibly is included to achive integrity.
This handshake record contains more extensions which are transmitted encrypted.
Other Extensions
1TLSv1.3 Record Layer: Handshake Protocol: Encrypted Extensions
2 Content Type: Handshake (22)
3 Version: TLS 1.2 (0x0303)
4 Length: 10
5 Handshake Protocol: Encrypted Extensions
6 Handshake Type: Encrypted Extensions (8)
7 Length: 6
8 Extensions Length: 4
9 Extension: server_name (len=0)
10 Type: server_name (0)
11 Length: 0
โ๏ธ โ ๐ป Certificate (๐)
This message contains the certificate chain. Certificates are encoded in DER. Wireshark makes it easy to look into the certificates. Certificate chains are basically just a list of certificates. If you want to play with certificates then you can use the OpenSSL CLI. The command openssl verify -verbose -CAfile ca.pem chain.pem
verifies a chain. ca.pem
would be a root certificate which you trust. chain.pem
contains all the files in an ASCII format separated by new lines. OpenSSl reports then whether it is fine or not. When using the openssl s_client -connect
command you also see the certificates and verbose output about the validation.
Certificate Hello
1TLSv1.3 Record Layer: Handshake Protocol: Certificate
2 Content Type: Handshake (22)
3 Version: TLS 1.2 (0x0303)
4 Length: 2485
5 Handshake Protocol: Certificate
6 Handshake Type: Certificate (11)
7 Length: 2481
8 Certificate Request Context Length: 0
9 Certificates Length: 2477
10 Certificates (2477 bytes)
Let's Encrypt Certificate for maxammann.org
1 Certificate Length: 1338
2 Certificate: 308205363082041ea00302010202120400ca5961d39c1622093596f2132488f93e300d06โฆ (id-at-commonName=www.maxammann.org)
3 signedCertificate
4 version: v3 (2)
5 serialNumber: 0x0400ca5961d39c1622093596f2132488f93e
6 signature (sha256WithRSAEncryption)
7 Algorithm Id: 1.2.840.113549.1.1.11 (sha256WithRSAEncryption)
8 issuer: rdnSequence (0)
9 rdnSequence: 3 items (id-at-commonName=R3,id-at-organizationName=Let's Encrypt,id-at-countryName=US)
10 RDNSequence item: 1 item (id-at-countryName=US)
11 RelativeDistinguishedName item (id-at-countryName=US)
12 Id: 2.5.4.6 (id-at-countryName)
13 CountryName: US
14 RDNSequence item: 1 item (id-at-organizationName=Let's Encrypt)
15 RelativeDistinguishedName item (id-at-organizationName=Let's Encrypt)
16 Id: 2.5.4.10 (id-at-organizationName)
17 DirectoryString: printableString (1)
18 printableString: Let's Encrypt
19 RDNSequence item: 1 item (id-at-commonName=R3)
20 RelativeDistinguishedName item (id-at-commonName=R3)
21 Id: 2.5.4.3 (id-at-commonName)
22 DirectoryString: printableString (1)
23 printableString: R3
24 validity
25 notBefore: utcTime (0)
26 utcTime: 2021-03-28 01:43:58 (UTC)
27 notAfter: utcTime (0)
28 utcTime: 2021-06-26 01:43:58 (UTC)
29 subject: rdnSequence (0)
30 rdnSequence: 1 item (id-at-commonName=www.maxammann.org)
31 RDNSequence item: 1 item (id-at-commonName=www.maxammann.org)
32 RelativeDistinguishedName item (id-at-commonName=www.maxammann.org)
33 Id: 2.5.4.3 (id-at-commonName)
34 DirectoryString: printableString (1)
35 printableString: www.maxammann.org
36 subjectPublicKeyInfo
37 algorithm (rsaEncryption)
38 Algorithm Id: 1.2.840.113549.1.1.1 (rsaEncryption)
39 subjectPublicKey: 3082010a0282010100b8ad1a3825f4aa8f8cdf5221a5d98d29f93be72f470397e07e1cecโฆ
40 modulus: 0x00b8ad1a3825f4aa8f8cdf5221a5d98d29f93be72f470397e07e1ceca379376bf1b148d1โฆ
41 publicExponent: 65537
42 extensions: 9 items
43 Extension (id-ce-keyUsage)
44 Extension Id: 2.5.29.15 (id-ce-keyUsage)
45 critical: True
46 Padding: 5
47 KeyUsage: a0
48 1... .... = digitalSignature: True
49 .0.. .... = contentCommitment: False
50 ..1. .... = keyEncipherment: True
51 ...0 .... = dataEncipherment: False
52 .... 0... = keyAgreement: False
53 .... .0.. = keyCertSign: False
54 .... ..0. = cRLSign: False
55 .... ...0 = encipherOnly: False
56 0... .... = decipherOnly: False
57 Extension (id-ce-extKeyUsage)
58 Extension Id: 2.5.29.37 (id-ce-extKeyUsage)
59 KeyPurposeIDs: 2 items
60 KeyPurposeId: 1.3.6.1.5.5.7.3.1 (id-kp-serverAuth)
61 KeyPurposeId: 1.3.6.1.5.5.7.3.2 (id-kp-clientAuth)
62 Extension (id-ce-basicConstraints)
63 Extension Id: 2.5.29.19 (id-ce-basicConstraints)
64 critical: True
65 BasicConstraintsSyntax [0 length]
66 Extension (id-ce-subjectKeyIdentifier)
67 Extension Id: 2.5.29.14 (id-ce-subjectKeyIdentifier)
68 SubjectKeyIdentifier: 12b43a1e54091741afc831d1e4de7babcb110ebe
69 Extension (id-ce-authorityKeyIdentifier)
70 Extension Id: 2.5.29.35 (id-ce-authorityKeyIdentifier)
71 AuthorityKeyIdentifier
72 keyIdentifier: 142eb317b75856cbae500940e61faf9d8b14c2c6
73 Extension (id-pe-authorityInfoAccess)
74 Extension Id: 1.3.6.1.5.5.7.1.1 (id-pe-authorityInfoAccess)
75 AuthorityInfoAccessSyntax: 2 items
76 AccessDescription
77 accessMethod: 1.3.6.1.5.5.7.48.1 (id-ad-ocsp)
78 accessLocation: 6
79 uniformResourceIdentifier: http://r3.o.lencr.org
80 AccessDescription
81 accessMethod: 1.3.6.1.5.5.7.48.2 (id-ad-caIssuers)
82 accessLocation: 6
83 uniformResourceIdentifier: http://r3.i.lencr.org/
84 Extension (id-ce-subjectAltName)
85 Extension Id: 2.5.29.17 (id-ce-subjectAltName)
86 GeneralNames: 2 items
87 GeneralName: dNSName (2)
88 dNSName: maxammann.org
89 GeneralName: dNSName (2)
90 dNSName: www.maxammann.org
91 Extension (id-ce-certificatePolicies)
92 Extension Id: 2.5.29.32 (id-ce-certificatePolicies)
93 CertificatePoliciesSyntax: 2 items
94 PolicyInformation
95 policyIdentifier: 2.23.140.1.2.1 (joint-iso-itu-t.23.140.1.2.1)
96 PolicyInformation
97 policyIdentifier: 1.3.6.1.4.1.44947.1.1.1 (iso.3.6.1.4.1.44947.1.1.1)
98 policyQualifiers: 1 item
99 PolicyQualifierInfo
100 Id: 1.3.6.1.5.5.7.2.1 (id-qt-cps)
101 DirectoryString: http://cps.letsencrypt.org
102 Extension (SignedCertificateTimestampList)
103 Extension Id: 1.3.6.1.4.1.11129.2.4.2 (SignedCertificateTimestampList)
104 Serialized SCT List Length: 239
105 Signed Certificate Timestamp (Cloudflare 'Nimbus2021' Log)
106 Serialized SCT Length: 118
107 SCT Version: 0
108 Log ID: 4494652eb0eeceafc44007d8a8fe28c0dae682bed8cb31b53fd33396b5b681a8
109 Timestamp: Mar 28, 2021 02:43:58.350000000 UTC
110 Extensions length: 0
111 Signature Algorithm: ecdsa_secp256r1_sha256 (0x0403)
112 Signature Hash Algorithm Hash: SHA256 (4)
113 Signature Hash Algorithm Signature: ECDSA (3)
114 Signature Length: 71
115 Signature: 304502201c5b58adfa5df8abf6077d94b765750a24d32b49b3af2dcf5c65efaf32c949d6โฆ
116 Signed Certificate Timestamp (Google 'Xenon2021' log)
117 Serialized SCT Length: 117
118 SCT Version: 0
119 Log ID: 7d3ef2f88fff88556824c2c0ca9e5289792bc50e78097f2e6a9768997e22f0d7
120 Timestamp: Mar 28, 2021 02:43:58.382000000 UTC
121 Extensions length: 0
122 Signature Algorithm: ecdsa_secp256r1_sha256 (0x0403)
123 Signature Hash Algorithm Hash: SHA256 (4)
124 Signature Hash Algorithm Signature: ECDSA (3)
125 Signature Length: 70
126 Signature: 30440220030a54d2296566cab9b5fa3e6505566e5e014d48f15f6cd8727896e2cc352eb3โฆ
127 algorithmIdentifier (sha256WithRSAEncryption)
128 Algorithm Id: 1.2.840.113549.1.1.11 (sha256WithRSAEncryption)
129 Padding: 0
130 encrypted: 8c770bcf525fc99d9f8f04d279b724bbb2bebc42184e671aa392b058265b097de2d9f668โฆ
131 Extensions Length: 0
DST Root CA X3 Certificate for Let's Encrypt
1 Certificate Length: 1129
2 Certificate: 308204653082034da0030201020210400175048314a4c8218c84a90c16cddf300d06092aโฆ (id-at-commonName=R3,id-at-organizationName=Let's Encrypt,id-at-countryName=US)
3 signedCertificate
4 version: v3 (2)
5 serialNumber: 0x400175048314a4c8218c84a90c16cddf
6 signature (sha256WithRSAEncryption)
7 Algorithm Id: 1.2.840.113549.1.1.11 (sha256WithRSAEncryption)
8 issuer: rdnSequence (0)
9 rdnSequence: 2 items (id-at-commonName=DST Root CA X3,id-at-organizationName=Digital Signature Trust Co.)
10 RDNSequence item: 1 item (id-at-organizationName=Digital Signature Trust Co.)
11 RelativeDistinguishedName item (id-at-organizationName=Digital Signature Trust Co.)
12 Id: 2.5.4.10 (id-at-organizationName)
13 DirectoryString: printableString (1)
14 printableString: Digital Signature Trust Co.
15 RDNSequence item: 1 item (id-at-commonName=DST Root CA X3)
16 RelativeDistinguishedName item (id-at-commonName=DST Root CA X3)
17 Id: 2.5.4.3 (id-at-commonName)
18 DirectoryString: printableString (1)
19 printableString: DST Root CA X3
20 validity
21 notBefore: utcTime (0)
22 utcTime: 2020-10-07 19:21:40 (UTC)
23 notAfter: utcTime (0)
24 utcTime: 2021-09-29 19:21:40 (UTC)
25 subject: rdnSequence (0)
26 rdnSequence: 3 items (id-at-commonName=R3,id-at-organizationName=Let's Encrypt,id-at-countryName=US)
27 RDNSequence item: 1 item (id-at-countryName=US)
28 RelativeDistinguishedName item (id-at-countryName=US)
29 Id: 2.5.4.6 (id-at-countryName)
30 CountryName: US
31 RDNSequence item: 1 item (id-at-organizationName=Let's Encrypt)
32 RelativeDistinguishedName item (id-at-organizationName=Let's Encrypt)
33 Id: 2.5.4.10 (id-at-organizationName)
34 DirectoryString: printableString (1)
35 printableString: Let's Encrypt
36 RDNSequence item: 1 item (id-at-commonName=R3)
37 RelativeDistinguishedName item (id-at-commonName=R3)
38 Id: 2.5.4.3 (id-at-commonName)
39 DirectoryString: printableString (1)
40 printableString: R3
41 subjectPublicKeyInfo
42 algorithm (rsaEncryption)
43 Algorithm Id: 1.2.840.113549.1.1.1 (rsaEncryption)
44 subjectPublicKey: 3082010a0282010100bb021528ccf6a094d30f12ec8d5592c3f882f199a67a4288a75d26โฆ
45 modulus: 0x00bb021528ccf6a094d30f12ec8d5592c3f882f199a67a4288a75d26aab52bb9c54cb1afโฆ
46 publicExponent: 65537
47 extensions: 8 items
48 Extension (id-ce-basicConstraints)
49 Extension Id: 2.5.29.19 (id-ce-basicConstraints)
50 critical: True
51 BasicConstraintsSyntax
52 cA: True
53 pathLenConstraint: 0
54 Extension (id-ce-keyUsage)
55 Extension Id: 2.5.29.15 (id-ce-keyUsage)
56 critical: True
57 Padding: 1
58 KeyUsage: 86
59 1... .... = digitalSignature: True
60 .0.. .... = contentCommitment: False
61 ..0. .... = keyEncipherment: False
62 ...0 .... = dataEncipherment: False
63 .... 0... = keyAgreement: False
64 .... .1.. = keyCertSign: True
65 .... ..1. = cRLSign: True
66 .... ...0 = encipherOnly: False
67 0... .... = decipherOnly: False
68 Extension (id-pe-authorityInfoAccess)
69 Extension Id: 1.3.6.1.5.5.7.1.1 (id-pe-authorityInfoAccess)
70 AuthorityInfoAccessSyntax: 1 item
71 AccessDescription
72 accessMethod: 1.3.6.1.5.5.7.48.2 (id-ad-caIssuers)
73 accessLocation: 6
74 uniformResourceIdentifier: http://apps.identrust.com/roots/dstrootcax3.p7c
75 Extension (id-ce-authorityKeyIdentifier)
76 Extension Id: 2.5.29.35 (id-ce-authorityKeyIdentifier)
77 AuthorityKeyIdentifier
78 keyIdentifier: c4a7b1a47b2c71fadbe14b9075ffc41560858910
79 Extension (id-ce-certificatePolicies)
80 Extension Id: 2.5.29.32 (id-ce-certificatePolicies)
81 CertificatePoliciesSyntax: 2 items
82 PolicyInformation
83 policyIdentifier: 2.23.140.1.2.1 (joint-iso-itu-t.23.140.1.2.1)
84 PolicyInformation
85 policyIdentifier: 1.3.6.1.4.1.44947.1.1.1 (iso.3.6.1.4.1.44947.1.1.1)
86 policyQualifiers: 1 item
87 PolicyQualifierInfo
88 Id: 1.3.6.1.5.5.7.2.1 (id-qt-cps)
89 DirectoryString: http://cps.root-x1.letsencrypt.org
90 Extension (id-ce-cRLDistributionPoints)
91 Extension Id: 2.5.29.31 (id-ce-cRLDistributionPoints)
92 CRLDistPointsSyntax: 1 item
93 DistributionPoint
94 distributionPoint: fullName (0)
95 fullName: 1 item
96 GeneralName: uniformResourceIdentifier (6)
97 uniformResourceIdentifier: http://crl.identrust.com/DSTROOTCAX3CRL.crl
98 Extension (id-ce-subjectKeyIdentifier)
99 Extension Id: 2.5.29.14 (id-ce-subjectKeyIdentifier)
100 SubjectKeyIdentifier: 142eb317b75856cbae500940e61faf9d8b14c2c6
101 Extension (id-ce-extKeyUsage)
102 Extension Id: 2.5.29.37 (id-ce-extKeyUsage)
103 KeyPurposeIDs: 2 items
104 KeyPurposeId: 1.3.6.1.5.5.7.3.1 (id-kp-serverAuth)
105 KeyPurposeId: 1.3.6.1.5.5.7.3.2 (id-kp-clientAuth)
106 algorithmIdentifier (sha256WithRSAEncryption)
107 Algorithm Id: 1.2.840.113549.1.1.11 (sha256WithRSAEncryption)
108 Padding: 0
109 encrypted: d94ce0c9f584883731dbbb13e2b3fc8b6b62126c58b7497e3c02b7a81f2861ebcee02e73โฆ
110 Extensions Length: 0
โ๏ธ โ ๐ป Certificate Verify (๐)
Because the server is generating ephemeral keys for each session (optional in TLS 1.2, mandatory in TLS 1.3) the session is not inherently tied to the certificate as it was in previous versions of TLS, when the certificate’s public/private key were used for key exchange.
To prove that the server owns the server certificate (giving the certificate validity in this TLS session), it signs a hash of the handshake messages using the certificate’s private key. The signature can be proven valid by the client by using the certificate’s public key. (@XargsNotBombs)
Disassembly
1TLSv1.3 Record Layer: Handshake Protocol: Certificate Verify
2 Content Type: Handshake (22)
3 Version: TLS 1.2 (0x0303)
4 Length: 264
5 Handshake Protocol: Certificate Verify
6 Handshake Type: Certificate Verify (15)
7 Length: 260
8 Signature Algorithm: rsa_pss_rsae_sha256 (0x0804)
9 Signature Hash Algorithm Hash: Unknown (8)
10 Signature Hash Algorithm Signature: Unknown (4)
11 Signature length: 256
12 Signature: 9adbef9d1b56a66dcd7e86eb8fbc826e66c3ea46802d757fc700576594835ad7bc66f1adโฆ
โ๏ธ โ ๐ป Finish (๐)
The Finish contains verify data. A finished key is derived from the server_handshake_traffic_secret (RFC8446 4.4.4). This key is used to create an HMAC of the hash of the transcript of sent messages.
Disassembly
1TLSv1.3 Record Layer: Handshake Protocol: Finished
2 Content Type: Handshake (22)
3 Version: TLS 1.2 (0x0303)
4 Length: 52
5 Handshake Protocol: Finished
6 Handshake Type: Finished (20)
7 Length: 48
8 Verify Data
๐ป โ โ๏ธ Change Cipher Spec
This message if not encrypted and is only here for backward compatibility with TLS 1.2.
Disassembly
1TLSv1.3 Record Layer: Change Cipher Spec Protocol: Change Cipher Spec
2 Content Type: Change Cipher Spec (20)
3 Version: TLS 1.2 (0x0303)
4 Length: 1
5 Change Cipher Spec Message
๐ป โ โ๏ธ Finished (๐)
This is the first message which is encrypted using the client handshake keys and IVs like described in Server Hello. The verify data is constructed in the same way as the last Finished, just that client_handshake_traffic_secret is used.
Disassembly
1TLSv1.3 Record Layer: Handshake Protocol: Finished
2 Content Type: Handshake (22)
3 Version: TLS 1.2 (0x0303)
4 Length: 52
5 Handshake Protocol: Finished
6 Handshake Type: Finished (20)
7 Length: 48
8 Verify Data
โ๏ธ โ ๐ป New Session Ticket (๐)
The server provides a session ticket that the client can use to start a new session later. Successfully resuming a connection in this way will skip most of the computation and network delay in session startup.
Because each session ticket is meant to be single-use, and because the server expects a browser to open multiple connections, it makes a size vs. speed decision to provide the client with two session tickets for each negotiated session. (@XargsNotBombs)
One could think that the server just has a database of valid Session Ticket and looks them up if a ticket is received. This is not needed usually though. The server has a ticket encryption key $k_t$. When creating a ticket the server encrypts some pre shared key $psk$ with $k_t$ and sends $enc(psk)$ and $psk$ to the client. When a session ticket is received the server can check it by decrypting $enc(psk)$ and comparing it with $psk$.
Disassembly
1TLSv1.3 Record Layer: Handshake Protocol: New Session Ticket
2 Content Type: Handshake (22)
3 Version: TLS 1.2 (0x0303)
4 Length: 265
5 Handshake Protocol: New Session Ticket
6 Handshake Type: New Session Ticket (4)
7 Length: 261
8 TLS Session Ticket
9 # Lifetime of this ticket
10 Session Ticket Lifetime Hint: 300 seconds (5 minutes)
11 # Milliseconds which have to be added to the generation date when sending this ticket back to the server. This prevents correlaction between the resumed session and the session which created this ticket.
12 Session Ticket Age Add: 4125054233
13 # A unique per ticket value
14 Session Ticket Nonce Length: 8
15 Session Ticket Nonce: 0000000000000000
16 Session Ticket Length: 240
17 # Data which is meaningful to the server to resume the session.
18 Session Ticket: 85d9d71b78d02770ec876056db0e96cdb56cf40a05269064b9eb082759fdea509db4bca2โฆ
19 Extensions Length: 0
โ๏ธ โ ๐ป New Session Ticket (๐)
An additional ticket for session resumption.
Disassembly
1TLSv1.3 Record Layer: Handshake Protocol: New Session Ticket
2 Content Type: Handshake (22)
3 Version: TLS 1.2 (0x0303)
4 Length: 265
5 Handshake Protocol: New Session Ticket
6 Handshake Type: New Session Ticket (4)
7 Length: 261
8 TLS Session Ticket
9 Session Ticket Lifetime Hint: 300 seconds (5 minutes)
10 Session Ticket Age Add: 763549134
11 Session Ticket Nonce Length: 8
12 Session Ticket Nonce: 0000000000000001
13 Session Ticket Length: 240
14 Session Ticket: 85d9d71b78d02770ec876056db0e96cd3f58b452a549a597259c839dec496d4d37dc6296โฆ
15 Extensions Length: 0
Application Data
For transmitting application data a new key is derived from the secrets. The procedure is similar to that in Server Hello. Just some other derivation function are used. See RFC8446 4.4.4 - Master Secret.