Class HeaderKey

java.lang.Object
io.github.mahmoudimus.quic.crypto.HeaderKey

public final class HeaderKey extends Object
A header protection key (RFC 9001 section 5.4): masks the low bits of the first byte and the packet number with five bytes derived from a 16-byte sample of the ciphertext. AES suites use AES-ECB on the sample; ChaCha20 uses the sample's first four bytes as the little-endian block counter and the remaining twelve as the nonce, through the JDK's "ChaCha20" cipher.

Header keys do not change on a key update.

Thread confinement. A key holds one reusable Cipher and scratch buffers, which are not thread-safe: use a key from one thread at a time.

  • Field Summary

    Fields
    Modifier and Type
    Field
    Description
    static final int
    The mask length in bytes: one for the first byte and up to four for the packet number.
    static final int
    The sample length for every QUIC header protection algorithm, in bytes.
  • Method Summary

    Modifier and Type
    Method
    Description
    static HeaderKey
    fromSecret(CipherSuite suite, byte[] secret, QuicVersion version)
    Derives a key from a traffic secret with the version's "quic hp" label.
    byte[]
    mask(byte[] sample)
    The mask for a sample.
    static HeaderKey
    of(CipherSuite suite, byte[] key)
    A key from its raw bytes.
    void
    protect(ByteBuffer packet, int start, int packetNumberOffset)
    Applies header protection in place to a packet whose payload is already sealed.
    The cipher suite.
    int
    unprotect(ByteBuffer packet, int start, int packetNumberOffset)
    Removes header protection in place.

    Methods inherited from class java.lang.Object

    clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
  • Field Details

    • SAMPLE_LENGTH

      public static final int SAMPLE_LENGTH
      The sample length for every QUIC header protection algorithm, in bytes.
      See Also:
    • MASK_LENGTH

      public static final int MASK_LENGTH
      The mask length in bytes: one for the first byte and up to four for the packet number.
      See Also:
  • Method Details

    • of

      public static HeaderKey of(CipherSuite suite, byte[] key)
      A key from its raw bytes.
      Parameters:
      suite - the cipher suite
      key - the key, CipherSuite.keyLength() bytes
      Returns:
      the key
    • fromSecret

      public static HeaderKey fromSecret(CipherSuite suite, byte[] secret, QuicVersion version)
      Derives a key from a traffic secret with the version's "quic hp" label.
      Parameters:
      suite - the cipher suite the secret belongs to
      secret - the traffic secret
      version - the QUIC version, which picks the label
      Returns:
      the key
    • suite

      public CipherSuite suite()
      The cipher suite.
      Returns:
      the suite
    • mask

      public byte[] mask(byte[] sample)
      The mask for a sample.
      Parameters:
      sample - 16 bytes of ciphertext
      Returns:
      a new 5-byte mask
    • protect

      public void protect(ByteBuffer packet, int start, int packetNumberOffset)
      Applies header protection in place to a packet whose payload is already sealed. The packet number length comes from the unprotected first byte. Indexes are absolute; the buffer's position and limit are not changed.
      Parameters:
      packet - the packet buffer
      start - the index of the packet's first byte
      packetNumberOffset - the index of the packet number; the sample starts four bytes later
      Throws:
      IndexOutOfBoundsException - if the packet is too short to sample
    • unprotect

      public int unprotect(ByteBuffer packet, int start, int packetNumberOffset)
      Removes header protection in place. Indexes are absolute; the buffer's position and limit are not changed.
      Parameters:
      packet - the packet buffer
      start - the index of the packet's first byte
      packetNumberOffset - the index of the packet number; the sample starts four bytes later
      Returns:
      the packet number length read from the unmasked first byte, 1 to 4
      Throws:
      IndexOutOfBoundsException - if the packet is too short to sample