Package io.github.mahmoudimus.quic.tls
Class Ticketer
java.lang.Object
io.github.mahmoudimus.quic.tls.Ticketer
A stateless session ticket encrypter for a server (RFC 8446 section 4.6.1, RFC 5077 section 4):
the session state is sealed into the ticket with AES-256-GCM under a server key, so the server
keeps nothing per session. The key rotates once per lifetime; tickets
sealed under the previous key are still opened during the following lifetime, so every ticket
stays usable for at least one lifetime and at most two.
key_name (16) | nonce (12) | AES-256-GCM(state) with the key name as additional data | tag (16)
The nonce is random for every ticket (a counter would let observers link tickets). A ticket longer than any this ticketer sealed is rejected before decryption.
Servers that must accept each other's tickets need to share a ticketer, which this class does not provide across processes: each instance has its own random keys.
Threads. Thread-safe without locks: the key state is an immutable value swapped
atomically, and every operation uses its own Cipher.
-
Field Summary
Fields -
Method Summary
Modifier and TypeMethodDescriptionstatic Ticketercreate()A ticketer with random keys rotated everyDEFAULT_LIFETIME.static Ticketercreate(Duration lifetime, InstantSource clock) A ticketer with random keys.byte[]decrypt(byte[] ticket) Opens a ticket sealed by this ticketer under its current key, or its previous key while that is within its grace lifetime.byte[]encrypt(byte[] plaintext) Seals session state into a ticket under the current key.lifetime()The lifetime of a key, announced as the ticket lifetime.
-
Field Details
-
DEFAULT_LIFETIME
The default lifetime of a ticket key, and so of tickets: 6 hours, as rustls uses. -
MAX_LIFETIME
The longest ticket lifetime TLS 1.3 allows: 7 days (RFC 8446 section 4.6.1).
-
-
Method Details
-
create
A ticketer with random keys rotated everyDEFAULT_LIFETIME.- Returns:
- the ticketer
-
create
A ticketer with random keys.- Parameters:
lifetime- how long a key seals tickets, which is also the lifetime announced in each ticket; at most 7 daysclock- the wall clock that times rotation- Returns:
- the ticketer
- Throws:
IllegalArgumentException- if the lifetime is not positive or exceeds 7 days
-
lifetime
The lifetime of a key, announced as the ticket lifetime.- Returns:
- the lifetime
-
encrypt
public byte[] encrypt(byte[] plaintext) Seals session state into a ticket under the current key.- Parameters:
plaintext- the encoded session state- Returns:
- the ticket
-
decrypt
public byte[] decrypt(byte[] ticket) Opens a ticket sealed by this ticketer under its current key, or its previous key while that is within its grace lifetime.- Parameters:
ticket- the ticket from a client- Returns:
- the session state, or null if the ticket is not one of ours, has been tampered with, or its key is gone
-