Recently TLS 1.2 got updated to TLS 1.3, a process that took took eight years. The final version got published on August 2018. As deployments roll out, developers and administrators will start encountering TLS 1.3 in their daily work. In this post we will look at the improvements and mention the situation from a Java and browser perspective.
TLS (Transport Layer Security) — Is the underlying technology that enables secure communication on the Internet is a protocol called Transport Layer Security (TLS), which is an evolution of Secure Sockets Layer (SSL) developed by Netscape in the 1990s. Many IP-based protocols, such as HTTPS, SMTP, POP3, FTP support TLS to encrypt data.
One of the best ways to write software, is to remove stuff that is no longer needed or is obsolete. Here are some of the ciphers and algorithms discontinued in TLS 1.3:
- RC4 Stream Cipher
- RSA Key Transport
- SHA-1 Hash Function
- CBC Mode Ciphers
- MD5 Algorithm
- Various Diffie-Hellman groups
- EXPORT-strength ciphers
The TLS 1.3 hanshake
A closer view at the handshake is given below. In a previous post I explained the TLS 1.2 handshake. For reference you can read up that post.
If two machines are corresponding over TLS 1.3, they coordinate which cipher suite to use by using the TLS 1.3 Handshake Protocol. The handshake in TLS 1.3 was minimized to only one round trip compared to the two round trips required in previous versions of TLS/SSL.
In TLS 1.3 a client starts by sending not only the
ClientHello and the list of supported ciphers, but it also makes a guess as to which key agreement algorithm the server will choose, and sends a key share for that.
After receiving the
ClientHello, the server selects the cipher suite and key agreement algorithm, it’s ready to generate the key, as it already has the client key share. So it can switch to encrypted packets one whole round-trip in advance.
So the server sends the
ServerHello, its key share, the certificate (now encrypted, since it has a key!), and already the
The client receives all that, generates the keys using the key share, checks the certificate and
Finished, and it's ready to send the HTTP request(encrypted), after only one round-trip.
In TLS 1.2 there is an existing way to speed up TLS connections which is called resumption. It’s what happens when the client has connected to that server before, and uses what they remember from the last time handshake was done.
There are two primary mechanisms for TLS Session Resumption. In TLS 1.2 servers would send the client either a Session ID or a Session Ticket. The former is just a reference number that the server can trace back to a session, while the latter is an encrypted serialized session which allows the server not to keep state.
In TLS 1.2 performing a resumption handshake is very quick. This comes at a security cost though. Each time a client resumes a session, the same session ID or Session Ticket in the
ClientHellois used and the same master secret is used so it would jump straight to
Finished, saving a round-trip. This is called 1-RTT resumption(“RTT” means “round trip time”). The security risk in here is, that if the master secret is compromised, then all resumed sessions are revealed.
The TLS 1.2 Session Resumption via Session Tickets and Session Identifiers mentioned earlier is outdated in TLS 1.3. Both methods are replaced by a Pre-Shared Key (PSK) mode. When resumption is available, TLS 1.3 allows us to do 0-RTT connections, again saving one round trip and ending up with no round trip at all.
0-RTT Handshakes (also known as “Zero-RTT “) is a TLS 1.3 TLS Handshake proposal when clients and servers share a PSK. Pre-Shared Key (PSK) is a Cryptographic Key that is shared between the parties before the session begins. The Pre-Shared Key may be referred to as a Shared Secret TLS 1.3 allows clients to send data on the first flight (“early data”).
If you have connected to a TLS 1.3 server before you can immediately start sending encrypted data, like an HTTP request, without any round-trip at all, making TLS essentially zero overhead :)
When a 1.3 client connects to a 1.3 server they agree on a resumption key (or PSK, pre-shared key), and the server gives the client a Session Ticket that will help it remember it. The Ticket can be an encrypted copy of the PSK — to avoid state — or a reference number.
The next time the client connects, it sends the Session Ticket in the
ClientHello and then immediately, without waiting for any round trip, sends the HTTP request encrypted with the PSK. The server figures out the PSK from the Session Ticket and uses that to decrypt the 0-RTT data.
The client also sends a key share, so that client and server can switch to a new fresh key for the actual HTTP response and the rest of the connection.
One of the problems of previous TLS releases, was a lack of protection against downgrade attacks. With TLS 1.3 this is covered. Fore more on protection against downgrade attacks, read up here.
0-RTT Resumption: The Bad
There are few concerns when it comes to the security in 0-RTT resumption sessions. The first being the lack of full forward secrecy. It means that if these session ticket keys are compromised, an attacker can decrypt the 0-RTT data sent by the client on the first flight. Of course, this can easily be avoided by rotating session keys regularly. But considering TLS 1.2 doesn’t support full forward secrecy at all, TLS 1.3 is definitely an improvement.
The second security concern when it comes to TLS 1.3 0-RTT is that it doesn’t provide a guarantee of non-replay between connections. If an attacker somehow manages to get hold of your 0-RTT encrypted data, it can fool the server into believing that the request came from the server since it has no way of knowing where the data came from. If an attacker sends this request multiple times, it’s called ‘replay attack.’ It’s not as easy as it sounds and obviously, there are certain mechanisms to prevent that (more on that in another post).
TLS 1.3 and Java
To make use of TLS 1.3 you have to use Java 11. The TLS 1.3 implementation in Java 11 doesn’t not support all the features of the new TLS protocol. The following is what JSSE supports (see more details in JEP 332):
- Protocol version negotiation
- Full handshake for both client and server sides
- Session resumption
- Key and IV(Initialization Vector) update
- Updated OCS(Online Certificate Status Protocol) stapling
- Backward compatibility mode
- Required extensions and algorithms
- Two new cipher suites: TLS_AES_128_GCM_SHA256 and TLS_AES_256_GCM_SHA384
- RSASSA-PSS signature algorithms
- Both SSLSocket and SSLEngine
Below a list of what is currently not supported:
- Post-handshake authentication
- Signed certificate timestamps (SCT)
- ChaCha20/Poly1305 cipher suites (targeted to Java 12)
- x25519/x448 elliptic curve algorithms (targeted to Java 12)
- edDSA signature algorithms (targeted to Java 12)
Java 11 doesn’t introduce new public classes and methods for TLS 1.3. It just adds a couple of new constants for the new protocol name, cipher suites, etc. This is actually great because it makes it very easy to switch to the new TLS version. You as a developer just need to configure JSSE to use new protocol and ciphers, and the rest of the code should not change. Depending on an application, migration to the new version may not even require any modification of the application code, that sounds great :)
The current browser compatibility for TLS 1.3 can be found here: https://caniuse.com/#feat=tls1-3