Skip to main content

MoQ End-to-End Encryption Profile
draft-lcurley-moq-e2ee-00

Document Type Active Internet-Draft (individual)
Author Luke Curley
Last updated 2026-09-24
RFC stream (None)
Intended RFC status (None)
Formats
Stream Stream state (No stream defined)
Consensus boilerplate Unknown
RFC Editor Note (None)
IESG IESG state I-D Exists
Telechat date (None)
Responsible AD (None)
Send notices to (None)
draft-lcurley-moq-e2ee-00
moq                                                            L. Curley
Internet-Draft                                         24 September 2026
Intended status: Informational                                          
Expires: 28 March 2027

                   MoQ End-to-End Encryption Profile
                       draft-lcurley-moq-e2ee-00

Abstract

   This document specifies moq-e2ee-00, a versioned profile for end-to-
   end encryption of MoQ application payloads.  Authorized publishers
   and subscribers share a 32-byte broadcast secret out of band.  Each
   publisher instance mints an epoch and publishes under an opaque
   broadcast path ending in it.  HKDF-SHA-256 derives opaque physical
   track names and per-track AES-128-GCM keys from the secret and the
   epoch; grouped frames and datagrams use separate key domains.  Media
   frames and datagrams carry only ciphertext plus a 16-byte tag.  The
   profile binds object identity through derivation and the nonce, not
   an on-wire header.

Note to Readers

   This document was generated by an AI model from the implementation at
   github.com/moq-dev/moq (https://github.com/moq-dev/moq) and is
   maintained alongside it.  Submit an issue (https://github.com/moq-
   dev/moq/issues) or PR (https://github.com/moq-dev/moq/pulls) if this
   spec sucks and you want to fix anything.

Status of This Memo

   This Internet-Draft is submitted in full conformance with the
   provisions of BCP 78 and BCP 79.

   Internet-Drafts are working documents of the Internet Engineering
   Task Force (IETF).  Note that other groups may also distribute
   working documents as Internet-Drafts.  The list of current Internet-
   Drafts is at https://datatracker.ietf.org/drafts/current/.

   Internet-Drafts are draft documents valid for a maximum of six months
   and may be updated, replaced, or obsoleted by other documents at any
   time.  It is inappropriate to use Internet-Drafts as reference
   material or to cite them other than as "work in progress."

   This Internet-Draft will expire on 28 March 2027.

Curley                    Expires 28 March 2027                 [Page 1]
Internet-Draft                  moq-e2ee                  September 2026

Copyright Notice

   Copyright (c) 2026 IETF Trust and the persons identified as the
   document authors.  All rights reserved.

   This document is subject to BCP 78 and the IETF Trust's Legal
   Provisions Relating to IETF Documents (https://trustee.ietf.org/
   license-info) in effect on the date of publication of this document.
   Please review these documents carefully, as they describe your rights
   and restrictions with respect to this document.  Code Components
   extracted from this document must include Revised BSD License text as
   described in Section 4.e of the Trust Legal Provisions and are
   provided without warranty as described in the Revised BSD License.

Table of Contents

   1.  Conventions and Definitions . . . . . . . . . . . . . . . . .   3
   2.  Introduction  . . . . . . . . . . . . . . . . . . . . . . . .   3
   3.  Relationship to Other Formats . . . . . . . . . . . . . . . .   3
   4.  Profile Version . . . . . . . . . . . . . . . . . . . . . . .   4
   5.  Credential  . . . . . . . . . . . . . . . . . . . . . . . . .   4
   6.  Epoch and Broadcast Path  . . . . . . . . . . . . . . . . . .   5
   7.  Canonical Encoding  . . . . . . . . . . . . . . . . . . . . .   6
   8.  Key Derivation  . . . . . . . . . . . . . . . . . . . . . . .   6
   9.  Object Identity . . . . . . . . . . . . . . . . . . . . . . .   8
     9.1.  Grouped Frames  . . . . . . . . . . . . . . . . . . . . .   8
     9.2.  Datagrams . . . . . . . . . . . . . . . . . . . . . . . .   8
     9.3.  Nonce . . . . . . . . . . . . . . . . . . . . . . . . . .   8
   10. Payload Protection  . . . . . . . . . . . . . . . . . . . . .   8
     10.1.  Plaintext Ceiling  . . . . . . . . . . . . . . . . . . .   9
     10.2.  Catalogs . . . . . . . . . . . . . . . . . . . . . . . .   9
   11. Bounds  . . . . . . . . . . . . . . . . . . . . . . . . . . .   9
   12. Failure Behavior  . . . . . . . . . . . . . . . . . . . . . .  10
   13. Test Vectors  . . . . . . . . . . . . . . . . . . . . . . . .  11
   14. Security Considerations . . . . . . . . . . . . . . . . . . .  11
   15. IANA Considerations . . . . . . . . . . . . . . . . . . . . .  12
   16. References  . . . . . . . . . . . . . . . . . . . . . . . . .  12
     16.1.  Normative References . . . . . . . . . . . . . . . . . .  12
     16.2.  Informative References . . . . . . . . . . . . . . . . .  13
   Changelog . . . . . . . . . . . . . . . . . . . . . . . . . . . .  14
     draft-lcurley-moq-e2ee-00 . . . . . . . . . . . . . . . . . . .  14
   Acknowledgments . . . . . . . . . . . . . . . . . . . . . . . . .  14
   Author's Address  . . . . . . . . . . . . . . . . . . . . . . . .  14

Curley                    Expires 28 March 2027                 [Page 2]
Internet-Draft                  moq-e2ee                  September 2026

1.  Conventions and Definitions

   The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT",
   "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and
   "OPTIONAL" in this document are to be interpreted as described in
   BCP 14 [RFC2119] [RFC8174] when, and only when, they appear in all
   capitals, as shown here.

2.  Introduction

   MoQ relays forward named tracks of groups and frames ([moql], [moqt])
   without parsing application payloads.  This profile encrypts those
   payloads and hides the semantic broadcast and track names that would
   otherwise describe them, so a relay cannot recover content.  It
   reuses AES-128-GCM and the 96-bit group/frame nonce shape of [secure]
   where those identities map, and specifies the moq-lite and datagram
   bindings that draft does not cover.

   The profile does not distribute keys, sign senders, pad payloads, or
   rotate a key inside an epoch.  Applications that need those
   properties terminate this profile and run a different one.

3.  Relationship to Other Formats

   [secure] encrypts a MoQ Transport object under a per-track base key.
   Its nonce is a per-track salt XOR uint64_be(group) ||
   uint32_be(object), its AAD includes publisher priority and immutable
   properties, and the Key ID rides in those properties.  The object
   payload is a length-prefixed plaintext plus an optional encrypted-
   properties list.

   This profile keeps AES-128-GCM, HKDF-SHA-256, a 96-bit nonce of
   uint64_be(group) || uint32_be(frame), and the rule that an identity
   is used at most once.  It differs where the models diverge:

   *  One 32-byte broadcast secret authorizes every track.  Per-track
      keys are derived, not supplied.

   *  The Key ID is part of the out-of-band credential.  No per-frame
      header or immutable property carries it.

   *  The salt is not derived from the key.  The publisher instance's
      epoch is an input to every derivation and the last segment of the
      broadcast path (Section 6), so a restarted publisher derives new
      keys instead of needing a new Key ID.

Curley                    Expires 28 March 2027                 [Page 3]
Internet-Draft                  moq-e2ee                  September 2026

   *  The nonce is the identity counter itself, not a salt XOR.  The
      derived key is already unique per credential, epoch, physical
      name, and domain.

   *  The payload is ciphertext concatenated with the 16-byte tag, with
      no inner length prefix, encrypted properties, or padding.

   *  moq-lite frame indices are implied by position in the group
      ([moql] Section "Frame"), not an on-wire object ID.  This profile
      still uses that index as the 32-bit nonce half, because it is the
      only canonical end-to-end frame identity on both moq-lite and MoQ
      Transport.

   *  moq-lite datagrams share the group sequence namespace of the same
      track ([moql] Section "Datagrams").  A grouped frame 0 and a
      datagram with that sequence would collide under one AES-GCM key,
      so datagrams use a separate key domain with frame ID zero.

   SFrame [sframe] is the cryptographic ancestor of [secure].  This
   profile is not SFrame: it has no SFrame header, no CTR field on the
   wire, and no per-object KID.

   The experimental moq-secure format (https://github.com/cathode-ray-
   tube/moq-secure) is prior art only.  Its independent counter, 17-byte
   per-frame header, ChaCha20-Poly1305 suite, signing lease, payload
   padding, and bytes-only processor are not compatibility requirements.

4.  Profile Version

   This document defines profile moq-e2ee-00.  The profile is named out
   of band alongside the credential; an application MUST refuse a
   credential that names any other profile.  A new profile is a new
   document; implementations MUST NOT fall back to plaintext or to an
   older profile because a catalog, announcement, or peer suggested one.

5.  Credential

   The application supplies an immutable credential:

   Credential {
     context (b)
     kid (u64)
     secret (32)
   }

Curley                    Expires 28 March 2027                 [Page 4]
Internet-Draft                  moq-e2ee                  September 2026

   *context*: Opaque bytes chosen by the application as the broadcast's
   end-to-end identity.  Both ends MUST use identical bytes.  The MoQ
   broadcast path is visible to relays and may be remounted under
   another prefix, so it is not this field unless the application copies
   it in.

   *kid*: Selects among credentials the application retains.  It never
   changes in place; rotating the secret is a new kid.

   *secret*: Exactly 32 bytes from a cryptographically secure random
   generator.  It MUST NOT be a password, passphrase, or other guessable
   input.

   kid MUST be in 0..=2^53-1 inclusive, the largest integer TypeScript
   can represent exactly. context, every epoch, and every semantic
   broadcast or track name MUST be at most 65535 bytes, the bytes
   encoding width.  An implementation MUST refuse a credential outside
   those ranges (identity) or whose secret is not 32 bytes
   (invalid_secret).

   Applications distribute credentials over their own authenticated
   channel.  MoQ announcements, catalogs, paths, and relay authorization
   MUST NOT carry the secret or authenticate it.  Implementations MUST
   let the application retain more than one credential and select among
   them; they MUST NOT infer the kid from the transport.

6.  Epoch and Broadcast Path

   A generation is one credential under one epoch.  Every derivation and
   every nonce is scoped to a generation.

   *epoch*: Opaque nonempty bytes minted by the publisher instance,
   containing no /. Each instance of a broadcast MUST mint an epoch that
   no other instance under the same credential has used or will use.
   Two instances MUST NOT share an epoch: they would derive the same
   keys and collide on nonces.  The RECOMMENDED epoch is the lowercase
   text of a UUID version 7 ([RFC9562]): its leading 48-bit timestamp
   makes epochs sort by creation time and its random bits make
   collisions negligible.

   A protected broadcast is published at <opaque>/<epoch>, where
   <opaque> is the 22-character base64url segment derived from the
   credential and the application's semantic broadcast name according to
   Section 8, and <epoch> is the epoch text.  The opaque derivation does
   not include the epoch, so every instance of the same semantic
   broadcast shares a discovery prefix.  The path carries no format or
   protection marker; for example, the semantic name meeting.hang
   appears only as an input to the opaque derivation.  A plaintext

Curley                    Expires 28 March 2027                 [Page 5]
Internet-Draft                  moq-e2ee                  September 2026

   consumer that opens the protected broadcast fails because it cannot
   find the plaintext catalog it expects, not because of a path naming
   rule.  Subscribers discover instances by the <opaque>/ prefix and
   select the greatest epoch when epochs are UUID version 7 text, where
   greatest is newest.  Opaque epochs carry no creation order, so any
   other epoch form needs an application rule for which instance is
   current.  A subscriber that already knows the full path takes the
   epoch from its last segment.

   The epoch and the path are not secret and are not authenticated.  A
   relay that presents a wrong epoch causes authentication failure; a
   relay that withholds a newer instance denies service.  Neither can
   cause a nonce to repeat, because only the publisher instance chooses
   the epoch it encrypts under.

   A restart or replacement of a publisher is a new instance and mints a
   new epoch.  Transport sequence numbers therefore restart freely
   without any coordination between instances.  Ended instances remain
   readable at their own path for as long as relays or archives retain
   them.

7.  Canonical Encoding

   HKDF info fields use unique encodings, not varints.

   *  u16 / u32 / u64: unsigned big-endian integers of that width.

   *  bytes: u16(length) || data, length at most 65535.

   *  ASCII labels are the UTF-8 bytes of the quoted string, with no
      length prefix of their own.

   Integers used as group, frame, or kid identities are refused before
   encoding if they fail Section 11.

8.  Key Derivation

   Keys and physical names are derived with HKDF-SHA-256 [RFC5869].  Let
   salt be the ASCII bytes of "moq-e2ee-00".

   prk = HKDF-Extract(salt, secret)

   Opaque broadcast path material is 16 bytes:

Curley                    Expires 28 March 2027                 [Page 6]
Internet-Draft                  moq-e2ee                  September 2026

   path_info = "moq-e2ee-00 path"
               || bytes(context)
               || u64(kid)
               || bytes(semantic_broadcast)
   opaque    = HKDF-Expand(prk, path_info, 16)

   semantic_broadcast is the UTF-8 bytes of the application's semantic
   broadcast name.  The opaque path segment is the unpadded base64url
   encoding of opaque ([RFC4648] Section 5): 22 ASCII characters.  The
   epoch is deliberately absent from this derivation, so a subscriber
   can derive the prefix before discovering an instance.

   Physical track name material is 16 bytes:

   name_info = "moq-e2ee-00 name"
               || bytes(context)
               || bytes(epoch)
               || u64(kid)
               || bytes(semantic_name)
   physical  = HKDF-Expand(prk, name_info, 16)

   semantic_name is the UTF-8 bytes of the application's track name
   (catalog.json, video, and so on).  The physical track name is the
   unpadded base64url encoding of physical ([RFC4648] Section 5): 22
   ASCII characters, which is a valid moq-lite track name.  This
   function may hide any track-shaped name the application wants a relay
   not to read; it is not limited to media tracks.

   AEAD keys are 16 bytes, one per physical name and domain:

   key_info = "moq-e2ee-00 key"
              || bytes(context)
              || bytes(epoch)
              || u64(kid)
              || bytes(physical_name)
              || domain
   key      = HKDF-Expand(prk, key_info, 16)

   domain is a single byte: 0x00 for grouped frames, 0x01 for datagrams.
   physical_name here is the 22-character ASCII string, not the raw
   16-byte material.

   A given (generation, physical_name, domain) tuple has one key.
   Implementations MUST derive names from semantic names, then keys from
   the resulting physical names.  A subscriber that learns a physical
   name from a decrypted catalog derives its key without ever knowing
   the semantic name.

Curley                    Expires 28 March 2027                 [Page 7]
Internet-Draft                  moq-e2ee                  September 2026

9.  Object Identity

   A protected object is the tuple (generation, physical_name, domain,
   group, frame).

9.1.  Grouped Frames

   A grouped frame uses domain = 0x00, the group's sequence as group,
   and the frame index within that group as frame. moq-lite numbers
   frames from 0 in write order ([moql]).  On MoQ Transport, frame is
   the explicit Object ID, never its arrival ordinal.  Publishers
   supporting both transports MUST assign contiguous Object IDs from
   zero so that each matches its moq-lite write-order index; relays MUST
   NOT renumber protected objects.  An Object ID above 2^32-1 MUST be
   refused as identity before encryption or decryption.

9.2.  Datagrams

   A datagram uses domain = 0x01, its 64-bit sequence as group, and
   frame = 0.  MoQ Transport has no datagram mapping in this profile;
   shared vectors cover grouped tracks on both transports and datagrams
   on moq-lite only.

9.3.  Nonce

   The 96-bit AES-GCM nonce is:

   nonce = u64(group) || u32(frame)

   AES-GCM's internal block counter is not frame.  Implementations MUST
   call a standard AEAD API [RFC5116] with this nonce and an empty AAD.

   The empty AAD is deliberate: profile version, context, epoch, kid,
   physical name, and domain are bound by HKDF; group and frame are
   bound by the nonce.  Rewritten timestamps and mutable routing
   properties are not authenticated.

10.  Payload Protection

   Let Nt = 16.  AES-128-GCM encrypts the application bytes with key,
   nonce, and empty AAD.  The bytes placed in the MoQ frame or datagram
   payload are ciphertext concatenated with the 16-byte tag, in the
   [RFC5116] convention.  There is no inner header.

Curley                    Expires 28 March 2027                 [Page 8]
Internet-Draft                  moq-e2ee                  September 2026

   Within a generation a publisher MUST allocate group and datagram
   sequences monotonically and frame indices in write order, so an
   identity is encrypted at most once.  Encrypting at an identity the
   same instance already used is reuse and MUST be refused.  Relays and
   caches forward ciphertext unchanged, so replay from a cache never re-
   encrypts.

10.1.  Plaintext Ceiling

   Protected payload length is plaintext length plus Nt.  A publisher
   MUST refuse plaintext that would make the protected payload exceed
   the transport payload limit for that object (oversize), before it
   touches the network.

   The interoperable grouped-frame payload cap matching current moq-net
   implementations is 32 MiB, so grouped plaintext MUST be at most 32
   MiB - 16 bytes. moq-lite datagram bodies MUST remain at most 1200
   bytes including Subscribe ID, Group Sequence, and Timestamp ([moql]
   Section "Datagrams").  Those three varints are at most 24 bytes, so
   datagram plaintext MUST be at most 1200 - 24 - 16 = 1160 bytes; a
   publisher cannot observe the Subscribe ID each hop will encode and
   MUST NOT budget for a smaller header.

10.2.  Catalogs

   A catalog is a track like any other: published under the physical
   name derived from its semantic name, with each snapshot or delta
   protected at its own group and frame identity.  Hang [hang]
   catalog.json and catalog.json.z and MSF's catalog are semantic names;
   authorized clients derive those physical names from the generation,
   then learn the remaining opaque names from the decrypted catalog.  A
   Hang rendition-map key in that catalog is the physical name of the
   track.

   If a representation is compressed, compression is applied to the
   catalog bytes before AEAD and reversed after decryption.  Encrypting
   then compressing is forbidden: ciphertext does not compress, and the
   .z sibling would leak the uncompressed size ratio.

11.  Bounds

   Implementations MUST refuse non-integer identities (including NaN and
   infinities) and identities outside these bounds before encoding or
   AEAD:

   *  group (grouped sequence or datagram sequence) and kid: 0..=2^53-1.
      Above that is identity.

Curley                    Expires 28 March 2027                 [Page 9]
Internet-Draft                  moq-e2ee                  September 2026

   *  frame: 0..=2^32-1. 2^32 and above is identity.

   *  AEAD operations with one key: at most 2^24 invocations and at most
      2^36 plaintext bytes (2^32 16-byte blocks).  Exceeding either is
      exhausted.

   2^53-1 is Number.MAX_SAFE_INTEGER.  It is the strictest exact integer
   bound across current TypeScript and Rust implementations.  The 32-bit
   frame width is the nonce field.  The 2^24 invocation cap is the
   interoperable AES-GCM record limit from [aeadlimits].  GCM
   authenticity also depends on total processed blocks, so 2^24 frames
   at the 32 MiB transport ceiling would be about 2^45 blocks; the
   2^36-byte cap is the matching total-block bound.  Small records hit
   the invocation cap first; large records hit the byte cap first.  A
   receiver counts failed opens too, since each is an AEAD invocation
   under that key.

12.  Failure Behavior

   E2EE is an explicit per-broadcast mode.  There is no plaintext
   fallback.

   Typed failures:

   *  invalid_secret: secret is not 32 bytes.

   *  identity: an integer is outside Section 11, a bytes field exceeds
      65535, an epoch is empty or contains /, a physical name is not 22
      base64url characters, or domain is not 0x00/0x01.

   *  exhausted: the next AEAD operation would exceed 2^24 uses of that
      key or 2^36 plaintext bytes under that key.

   *  reuse: encrypting at an identity this instance already used.

   *  oversize: plaintext plus tag exceeds the transport payload limit,
      or a ciphertext is shorter than Nt or larger than that limit.

   *  authentication: AEAD open fails.  Relocation across context,
      epoch, kid, physical name, domain, group, or frame is this
      failure.

   *  duplicate: a receiver has already opened this datagram sequence
      inside its retained window.  Operational, not a cryptographic
      event.

Curley                    Expires 28 March 2027                [Page 10]
Internet-Draft                  moq-e2ee                  September 2026

   Authentication failure on a grouped track MUST end that track with
   authentication.  Authentication failure on a datagram MUST drop that
   datagram and emit authentication; the track continues.

   Grouped frames need no duplicate window: a transport delivers each
   frame of a group once, in order, at its index.  Receivers SHOULD
   suppress datagram sequences they still retain; the window MUST be
   bounded, and 1024 sequences below the greatest opened is RECOMMENDED.
   The AEAD identity and epoch rules are the security boundary; a relay
   may still delay, reorder, suppress, or replay ciphertext outside a
   receiver's window.

   A late subscriber MAY start at any group the publisher still holds.
   Gaps are not errors.  A receiver MUST NOT require group 0 or any
   prior identity before opening a later authentic object.

13.  Test Vectors

   Known-answer and negative vectors live in moq-e2ee-00.json beside
   this draft.  Hex strings are octet sequences.  The JSON is
   authoritative for primitive interop; an implementation of this
   profile MUST pass every vector.  Each negative row specifies an
   operation, its inputs, and its expected typed error.  Non-finite
   frame inputs use the strings NaN, Infinity, and -Infinity; group
   inputs in identity tests are decimal strings.  Implementations whose
   types cannot represent an invalid input MUST reject it at their input
   boundary.

   The file covers opaque path derivation, key derivation, physical
   naming, grouped frames, a datagram at the fixed budget, the same
   identity under two epochs, relocation across every identity
   dimension, tag failure, malformed physical names, identity bounds,
   and oversize plaintext.

   The shared verifier is stateless.  It does not verify reuse,
   exhausted, duplicate, or failure propagation.  Each language core
   MUST test those lifecycle requirements, including monotonic
   allocation, per-key invocation and plaintext-byte accounting, bounded
   datagram suppression, and that a new instance under a new epoch
   authenticates while the old epoch does not.  Passing the primitive
   vectors alone is not profile conformance.

14.  Security Considerations

   Relays, caches, recorders, and control planes are untrusted for
   content.  Authorized endpoints that hold the broadcast secret are
   trusted.  Sender authenticity against another endpoint that also
   holds the secret is not a goal of moq-e2ee-00.

Curley                    Expires 28 March 2027                [Page 11]
Internet-Draft                  moq-e2ee                  September 2026

   A relay can still observe the outer broadcast path including the
   opaque segment and epoch, opaque physical names, group and frame
   structure, timestamps, sizes, and traffic patterns.  Padding and
   metadata-flow confidentiality are out of scope.

   The opaque segment hides the application's semantic broadcast name
   from a relay only while the application does not publish or otherwise
   expose the same name in plaintext.  The epoch remains visible to
   every relay on the path.

   Nonce reuse under one key is catastrophic for AES-GCM.  The profile
   prevents it by deriving every key from an epoch that only one
   publisher instance ever uses, allocating identities monotonically
   within that instance, separating datagram and grouped domains, and
   capping invocations and plaintext bytes per key.  No state survives
   an instance: nothing needs to be persisted across restarts to stay
   safe.

   Empty AAD does not weaken the binding: every immutable end-to-end
   field is in the HKDF info or the nonce.  Timestamps are excluded
   because relays rewrite them; a relay can therefore shift or reorder
   authentic objects in time within a receiver's tolerance.

   The opaque path segment is a deterministic function of the secret and
   semantic broadcast name; physical track names are deterministic
   functions of the secret and epoch.  An attacker without the secret
   cannot predict them; an attacker with the secret can derive every
   name, which is intended.

15.  IANA Considerations

   This document requests no registrations.

16.  References

16.1.  Normative References

   [moql]     Curley, L., "Media over QUIC - Lite", Work in Progress,
              Internet-Draft, draft-lcurley-moq-lite-05, 30 June 2026,
              <https://datatracker.ietf.org/doc/html/draft-lcurley-moq-
              lite-05>.

   [moqt]     Nandakumar, S., Vasiliev, V., Swett, I., and A. Frindell,
              "Media over QUIC Transport", Work in Progress, Internet-
              Draft, draft-ietf-moq-transport-21, 8 September 2026,
              <https://datatracker.ietf.org/doc/html/draft-ietf-moq-
              transport-21>.

Curley                    Expires 28 March 2027                [Page 12]
Internet-Draft                  moq-e2ee                  September 2026

   [RFC2119]  Bradner, S., "Key words for use in RFCs to Indicate
              Requirement Levels", BCP 14, RFC 2119,
              DOI 10.17487/RFC2119, March 1997,
              <https://www.rfc-editor.org/rfc/rfc2119>.

   [RFC4648]  Josefsson, S., "The Base16, Base32, and Base64 Data
              Encodings", RFC 4648, DOI 10.17487/RFC4648, October 2006,
              <https://www.rfc-editor.org/rfc/rfc4648>.

   [RFC5116]  McGrew, D., "An Interface and Algorithms for Authenticated
              Encryption", RFC 5116, DOI 10.17487/RFC5116, January 2008,
              <https://www.rfc-editor.org/rfc/rfc5116>.

   [RFC5869]  Krawczyk, H. and P. Eronen, "HMAC-based Extract-and-Expand
              Key Derivation Function (HKDF)", RFC 5869,
              DOI 10.17487/RFC5869, May 2010,
              <https://www.rfc-editor.org/rfc/rfc5869>.

   [RFC8174]  Leiba, B., "Ambiguity of Uppercase vs Lowercase in RFC
              2119 Key Words", BCP 14, RFC 8174, DOI 10.17487/RFC8174,
              May 2017, <https://www.rfc-editor.org/rfc/rfc8174>.

   [RFC9562]  Davis, K., Peabody, B., and P. Leach, "Universally Unique
              IDentifiers (UUIDs)", RFC 9562, DOI 10.17487/RFC9562, May
              2024, <https://www.rfc-editor.org/rfc/rfc9562>.

16.2.  Informative References

   [aeadlimits]
              Günther, F., Thomson, M., and C. A. Wood, "Usage Limits on
              AEAD Algorithms", Work in Progress, Internet-Draft, draft-
              irtf-cfrg-aead-limits-13, 3 September 2026,
              <https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-
              aead-limits-13>.

   [hang]     Curley, L., "Media over QUIC - Hang", Work in Progress,
              Internet-Draft, draft-lcurley-moq-hang-02, 3 August 2026,
              <https://datatracker.ietf.org/doc/html/draft-lcurley-moq-
              hang-02>.

   [secure]   Jennings, C. F., Nandakumar, S., and R. Barnes, "End-to-
              End Secure Objects for Media over QUIC Transport", Work in
              Progress, Internet-Draft, draft-ietf-moq-secure-objects-
              01, 6 July 2026, <https://datatracker.ietf.org/doc/html/
              draft-ietf-moq-secure-objects-01>.

Curley                    Expires 28 March 2027                [Page 13]
Internet-Draft                  moq-e2ee                  September 2026

   [sframe]   Omara, E., Uberti, J., Murillo, S. G., Barnes, R., Ed.,
              and Y. Fablet, "Secure Frame (SFrame): Lightweight
              Authenticated Encryption for Real-Time Media", RFC 9605,
              DOI 10.17487/RFC9605, August 2024,
              <https://www.rfc-editor.org/rfc/rfc9605>.

Changelog

draft-lcurley-moq-e2ee-00

   *  Initial moq-e2ee-00 profile: out-of-band credential, opaque
      broadcast path with a publisher-minted epoch as its last segment,
      HKDF physical names and keys, AES-128-GCM payloads, identity
      bounds, typed failures, and shared primitive vectors.

Acknowledgments

   This document was drafted with the assistance of Grok, an AI
   assistant by xAI.

Author's Address

   Luke Curley
   Email: kixelated@gmail.com

Curley                    Expires 28 March 2027                [Page 14]