JEP draft: TLS Certificate Compression

OwnerXuelei Fan
TypeFeature
ScopeSE
StatusDraft
Componentsecurity-libs / javax.net.ssl
Discussionsecurity dash dev at openjdk dot java dot net
EffortM
DurationM
Created2022/02/14 07:14
Updated2023/08/26 17:11
Issue8281710

Summary

Support the TLS Certificate Compression standard, which reduces latency and improve security and performance of TLS and QUIC connections.

Goals

Non-Goals

It is not a goal to implement compression algorithms in JDK.

Motivation

For TLS connections, a client must authenticate the identity of the server. This typically involves verification that the identity of the server is included in a certificate and that the certificate is issued by a trusted entity.

Where servers provide certificates for authentication, the size of the certificate chain can consume a large number of bytes. Controlling the size of certificate chains is critical to performance and security in QUIC. TLS certificate compression has the potential to ameliorate the problems by reducing the size of the handshakes to a size compatible with the security restriction.

Besides, reducing the amount of information exchanged during a TLS handshake to a minimum helps to improve performance in environments, for example Internet of Things, where devices are connected to a network with a low bandwidth and lossy radio technology.

This feature is a part to improve the performance of TLS connections, and it is also a part of the path towards QUIC standards.

Chrome support TLS certificate compression with Brotil compression algorithm, and Safari support TLS certificate compression with Zlib compression algorithm.

Description

This feature adds new public APIs to define the certificate compression algorithms that can be used over the (D)TLS version 1.3 connections.

An application can use an extended SSLParameters class to get and set the certificate compression algorithms that can be used on a given TLS connection. The TLS implementation will also use this class to retrieve the certificate compression algorithms declared by the application.

Examples

Server authentication

For TLS connections, the server must send a Certificate message whenever the agreed-upon key exchange method uses certificate for authentication. For certificate-based server authentication, a client application could support TLS server certicicate compression by setting the certificate decompression algorithms and functions.

SSLParameters sslParameters = clientSocket.getSSLParameters();
    // Set server cerficate decompression algorithms and functions.
    sslParameters.setCertificateDeflaters(Map.of("zlib",
        (uncompressedCertificateMessage) -> {
            // Here goes the zlib compression function implementation.
            ...snipped...
        }));
    clientSocket.setSSLParameters(sslParameters);

On the other hand, a server application could support TLS server certificate compression by setting the certificate compression algorithms and functions.

SSLParameters sslParameters = serverSocket.getSSLParameters();
    // Set server certificate compression algorithms and functions.
    sslParameters.setCertificateInflaters(Map.of("zlib",
        (compressedCertificateMessage) -> {
            // Here goes the zlib decompression function implementation.
            ...snipped...
        }));
    serverSocket.setSSLParameters(sslParameters);

Client authentication

For TLS connections, client authentication is optional. However, the client must send a Certificate message if the server requires certificate-based client authentication.

For certificate-based client authentication, a client application could support TLS client certificate compression by setting the certificate compression algorithms and functions.

SSLParameters sslParameters = clientSocket.getSSLParameters();
    // Set client certificate compression algorithms and functions.
    sslParameters.setCertificateInflaters(Map.of("zlib",
        (compressedCertificateMessage) -> {
            // Here goes the zlib decompression function implementation.
            ...snipped...
        }));
    clientSocket.setSSLParameters(sslParameters);

On the other hand, a server application could support TLS client certificate compression by setting the certificate decompression algorithms and functions.

SSLParameters sslParameters = serverSocket.getSSLParameters();
    // Set client certificate decompression algorithms and functions.
    sslParameters.setCertificateDeflaters(Map.of("zlib",
        (uncompressedCertificateMessage) -> {
            // Here goes the zlib compression function implementation.
            ...snipped...
        }));
    serverSocket.setSSLParameters(sslParameters);

Two-ways authentication

If both certificate-based server and client authentication are required, in order to support two-ways certificate compression, each side should set both the certificate compression and decompression algorithms and functions.

Here is the client code for two-ways TLS certificate compression.

SSLParameters sslParameters = clientSocket.getSSLParameters();

    // Set server certificate decompression algorithms and functions.
    sslParameters.setCertificateDeflaters(Map.of("zlib",
        (uncompressedCertificateMessage) -> {
            // Here goes the zlib compression function implementation.
            ...snipped...
        }));

    // Set client certificate compression algorithms and functions.
    sslParameters.setCertificateInflaters(Map.of("zlib",
        (compressedCertificateMessage) -> {
            // Here goes the zlib decompression function implementation.
            ...snipped...
        }));

    clientSocket.setSSLParameters(sslParameters);

And here is the server code for two-ways TLS certificate compression.

SSLParameters sslParameters = serverSocket.getSSLParameters();

    // Set server certificate compression algorithms and functions.
    sslParameters.setCertificateInflaters(Map.of("zlib",
        (compressedCertificateMessage) -> {
            // Here goes the zlib decompression function implementation.
            ...snipped...
        }));

    // Set client certificate decompression algorithms and functions.
    sslParameters.setCertificateDeflaters(Map.of("zlib",
        (uncompressedCertificateMessage) -> {
            // Here goes the zlib compression function implementation.
            ...snipped...
        }));
    serverSocket.setSSLParameters(sslParameters);

Alternatives

Reducing the size of certificate chain, for example using small key size signature algorithms like Ed25519 and minimal certificate extensions, is helpful to reduces latency and improve security and performance of TLS and QUIC connections.

Dependencies

This feature provide ways to support different kind of compression algorithms and strategies so that application could balance compression ratio and compression speed. But in order to minimize the dependency, it is not a goal to implement compression algorithms in JDK.

JDK supports ZLIB compression in the java.util.zip package. An application could wrap zip classes into the SSLParameters class supported zlib Functions. There is no support of brotli and zstd compression algorithms in JDK currently. An application could wrap third party's brotli or zstd compression implementation into SSLParameters class supported Functions accordingly.

Testing

Interoperability between at least one browser and JDK server, JDK client and at least one third party's TLS certificate compression implementation should be verified.

Risks and Assumptions

It is applications responsibility of implementing the certificate decompression functions. To be safe, the implementation should bound the memory usage, and must limit the size of the decompressed certificate messages, which should be lower than the TLS framing 16777216-bytes size limit. This limitation will be described in the SSLParameters specification.