Agent15 is an open source implementation of the handshake protocol of TLS 1.3 (RFC 8446), running on Java 11. It was developed for, and is used by Kwik, a 100% pure Java implementation of the QUIC protocol. QUIC uses TLS 1.3 for encryption, but only the handshake layer, not the record layer (see RFC 9001, sec 3).
Agent15 is created and maintained by Peter Doornbosch. The latest greatest can always be found on GitHub.
Agent15 implements all of the handshake protocol that is needed to setup and maintain a QUIC connection, including HelloRetryRequest, session resumption and 0-RTT.
Not all TLS 1.3 handshake messages are implemented because there are some that are not used in the QUIC protocol:
- EndOfEarlyData: see https://www.rfc-editor.org/rfc/rfc9001.html#name-removing-the-endofearlydata
- KeyUpdateRequest: see https://www.rfc-editor.org/rfc/rfc9001.html#name-key-update
Not all extensions listed in RFC 8446 are supported, see the source for an overview of which extensions are supported.
However, the message parser will create an UnknownExtension object for unsupported extensions, so parsing will not fail
(as it would for the unsupported handshake message types).
Agent15 also implements RFC 10024: "Post-Quantum Traditional (PQ/T) Hybrid Key Agreement Mechanisms for TLS 1.3" and "ML-DSA" as specified by Use of ML-DSA in TLS 1.3.
All Post-Quantum cryptography is provided by means of a separate module, agent15-pqc, which requires Java 25.
QUIC defines a custom TLS extension for carrying Transport parameters, this is supported by Agent15 by means of a custom extension parser function that can be injected by the client application.
Agent15 core supports the following digital signatures:
- rsa_pkcs1_sha256 (for certificates only, in accordance with TLS 1.3 specification)
- rsa_pss_rsae_sha256
- rsa_pss_rsae_sha384
- rsa_pss_rsae_sha512
- ecdsa_secp256r1_sha256
- ecdsa_secp384r1_sha384
- ecdsa_secp521r1_sha512
and the post-quantum module supports
- mldsa44
- mldsa65
- mldsa87
For key exchange, the following elliptic curves ("named groups") are supported:
- secp256r1, secp384r1 and secp521r1
- X25519, X448
and the post-quantum hybrid key exchanges:
- X25519MLKEM768
- SecP256r1MLKEM768 and SecP384r1MLKEM1024
As Agent15 does not implement the TLS record layer, it does not (need) to implement cipher suites either; however, it does limit settings ciphers to the ones defined in RFC 8446.
The engines support session resumption with a PSK (obtained via a NewSessionTicket message). The server uses an in-memory cache to store session tickets, so a restart invalidates all tickets. Client authentication (by means of a client certificate) is supported in the client engine, but not yet for the server engine.
Maven coordinates:
<dependency>
<groupId>tech.kwik</groupId>
<artifactId>agent15</artifactId>
<version>4.0</version>
</dependency>
Client: instantiate a TlsClientEngine with a ClientMessageSender and a TlsStatusEventHandler and call startHandshake() on it.
The startHandshake method that takes a list of key share groups makes the client offer a key share for each of them,
which avoids the extra round trip of a HelloRetryRequest when the server does not support the client's first choice.
The ClientMessageSender is the callback to let the client actually send the handshake messages.
The TlsStatusEventHandler enables to client to react TLS events that are needed for the QUIC handshake,
e.g. when the early secrets or the handshake secrets are known (QUIC computes its own secrets based on the TLS secrets).
Any TLS message received should be passed to the engine's received method, which is done automatically by the TlsMessageParser
when calling its parseAndProcessHandshakeMessage() method.
Server: instantiate a TlsServerEngine. In addition to a ServerMessageSender and a TlsStatusEventHandler that serve
analogous purpose as in the client case, the server certificate and its private key need to be provided as well.
As with the client, any TLS message received should be passed to the engine, which will take care of sending all necessary
messages back to the client.
Which named groups the server offers for key exchange can be configured with TlsServerEngine.setSupportedGroups;
by default it offers all groups its key exchange factory can provide, which is what makes the hybrid post-quantum
groups available as soon as the agent15-pqc module is on the class path.
Use the gradle wrapper to build the library: ./gradlew build (or on Windows: gradlew.bat build).
Certificates are checked using the default Java truststore. Other CA's can be used by setting a custom trustmanager.
All security aspects required by TLS are (supposed to be) implemented, I you find any discrepancies with the TLS 1.3
specification, please file a bug report or contact the author.
No security checks or reviews have been made for this library; use at your own risk.
If you have questions about this project, please mail the author (peter dot doornbosch) at luminis dot eu.
Many thanks to Michael Driscoll (@xargsnotbombs) for writing the brilliant "The New Illustrated TLS Connection, Every byte explained and reproduced"; I never would have succeeded in writing a functional TLS library without this help. Thanks to Piet van Dongen for creating the marvellous logo! Thanks to Chris Burdess for his help to implement RFC 10024 (Post-Quantum Traditional (PQ/T) Hybrid Key Agreement Mechanisms).
This program is open source and licensed under LGPL (see the LICENSE.txt and LICENSE-LESSER.txt files in the distribution). This means that you can use this program for anything you like, and that you can embed it as a library in other applications, even commercial ones. If you do so, the author would appreciate if you include a reference to the original.
As of the LGPL license, all modifications and additions to the source code must be published as (L)GPL as well.
If you want to use the source with a different open source license, contact the author.
