Internet Protocols · Real-Time Media

SRTP Key Derivation and Per-Packet IV Construction

How one master key produces separate encryption, authentication, and salting keys, and why the packet index rather than the sequence number feeds the counter block.

SRTP encrypts the payload of each RTP packet and appends an authentication tag, and it does so with a key schedule that is derived entirely from a single master key and master salt. The session description negotiates a key once, out of band or through a key management protocol; everything else is computed. The design constraint is that stream ciphers and authentication codes must never reuse a keystream or a tag key, while a media session sends thousands of packets per second from a counter that wraps every 65,536 packets.

Why the master key is not the working key

Using the negotiated key directly for both encryption and authentication would be a mistake with a specific consequence. AES in counter mode produces a keystream by encrypting successive counter blocks; the security of the mode depends on never encrypting the same counter block twice under the same key. If the same key also keyed an HMAC, the two uses would be related in ways that cryptanalysis can exploit, and a compromise of one would weaken the other.

SRTP therefore derives three session keys from the master: a session encryption key, a session authentication key, and a session salt. The session salt is not a secret in the same sense; it is an input to the counter block construction, and its purpose is to make the counter blocks of different streams distinct even when their packet indices coincide.

Derivation uses AES in counter mode as a pseudorandom generator. The master key is the AES key, and the input is the 112-bit master salt with a 56-bit identifier XORed into it: an 8-bit label selecting which key is wanted, in the high bits, and a 48-bit index derived from the key derivation rate, in the low bits. That value is shifted left by 16 bits so the low 16 bits form the block counter that increments per AES invocation. The labels are fixed by RFC 3711:

  • 0x00 for the session encryption key
  • 0x01 for the session authentication key
  • 0x02 for the session salt
  • 0x03, 0x04, 0x05 for the corresponding SRTCP keys

SRTCP needs its own set because it has a different index space and different replay semantics, and because the two protocols must not share a keystream.

The key derivation rate determines how often new session keys are produced. When it is zero, a single set of session keys serves the entire session, which is the common configuration. When it is nonzero, the index in the identifier advances every n packets, and the derived keys rotate. Rotation limits the volume of data encrypted under one key, at the cost of a derivation operation at each boundary. For a long session at a high packet rate, rotation is a defensible precaution; for a typical call, the single set is standard.

The output of the derivation is truncated to the required length: the encryption key to the cipher’s key size, the salt to 112 bits. Because the generator is a counter-mode stream, producing a longer key costs nothing extra in structure, only in AES invocations.

The packet index, not the sequence number

The 16-bit RTP sequence number is far too small to serve as a counter for a stream cipher. At 50 packets per second it repeats every 22 minutes, and at video rates much sooner. Reusing a counter block with the same key would leak the XOR of two plaintexts, which for media means two frames’ worth of recoverable structure.

SRTP therefore maintains a 48-bit packet index, formed as a 32-bit rollover counter in the high bits and the 16-bit sequence number in the low bits. The receiver reconstructs the rollover counter from the sequence number: when the sequence number jumps backwards by more than half the space, the counter has wrapped and increments; when it jumps forwards by a large amount, the sender may have restarted. This is the same modular reasoning that applies to RTP timestamps, applied to a wider counter, and it is why SRTP’s security depends on the receiver’s estimate of the rollover counter being correct.

The consequence of a wrong estimate is severe and asymmetric. If the receiver’s rollover counter is one too low, it derives a counter block that the sender never used, the decryption produces garbage, and the authentication tag fails. If it is one too high, the same. Either way the packet is discarded rather than silently corrupted, because authentication covers the result. The authentication tag is what makes the counter estimate self-checking: a wrong guess fails loudly.

The counter block itself is assembled from three inputs. The session salt occupies the high 112 bits, the packet index occupies the middle 48 bits, and the low 16 bits are a block counter that increments for each AES invocation needed to cover the payload. The construction is an XOR of the salt with the index and the SSRC, positioned so that the fields do not overlap:

IV (128 bits) = (salt << 16) XOR (index << 16) XOR (SSRC << 64)
                bits 0..15   : block counter, starts at 0
                bits 16..63  : 48-bit packet index
                bits 64..95  : 32-bit SSRC
                bits 96..127 : high bits of the salt

The SSRC in the IV is what separates streams that share a master key. Two streams in the same session, sending packets with the same index at the same instant, would otherwise produce identical counter blocks and therefore identical keystreams; the SSRC makes them distinct. This is a load-bearing dependency on the RTP header field: a relay that rewrites the SSRC without rekeying breaks decryption for every downstream receiver, and a sender that reuses an SSRC across sessions that share a key does the same.

Authentication covers more than the payload

The default SRTP authentication is HMAC-SHA1 over the packet, truncated to 80 bits. The truncation is a deliberate trade: a full 160-bit tag costs 20 bytes per packet, which at 50 packets per second is 8 kbit/s of pure authentication overhead. An 80-bit tag halves that, and forgery probability per attempt is 2^-80, which is far beyond what an attacker can exploit against a media stream. RFC 3711 also defines a 32-bit tag option for constrained links, where the per-packet saving matters more than the forgery bound.

The tag is computed over the RTP header and the encrypted payload together, so the header fields are authenticated even though they are not encrypted. That matters because the sequence number and SSRC feed the IV: an attacker who could modify the sequence number without detection could induce the receiver to derive a counter block of the attacker’s choosing. Authenticating the header closes that path.

What is not encrypted, by design, is the RTP header itself. Encrypting it would break every middlebox that needs to read sequence numbers and timestamps, and would prevent header compression. The header’s confidentiality is sacrificed for routability, which is the same trade IPsec’s transport mode makes.

SRTCP authenticates a 31-bit index plus an E flag, and optionally encrypts the RTCP payload. The E flag indicates whether that particular packet’s payload is encrypted, which allows a sender to leave some reports in the clear. The index, unlike the RTP packet index, is explicit in the packet rather than inferred from a sequence number, because RTCP packets are too sparse for reliable rollover reconstruction.

Failure modes specific to the key schedule

The first is salt reuse. Two sessions that use the same master key and the same master salt produce the same session keys, and if their packet indices overlap, they produce the same keystream. Key management protocols are supposed to generate fresh salts per session; an implementation that treats the salt as optional or that reuses a stored value across sessions undermines the cipher entirely, and nothing in SRTP detects it.

The second is index wraparound within a single key. The 48-bit packet index is large enough that exhausting it is not a practical concern at media rates, but an implementation that derives its index from a smaller counter, or that resets the rollover counter on a sender restart without rekeying, can collide. A sender that restarts mid-session and resumes from a fresh random sequence number must ensure its rollover counter estimate is consistent with the receiver’s; otherwise the two disagree about the index for every subsequent packet.

The third is replay. SRTP defines a replay window, and the receiver must maintain state to reject packets whose index has already been accepted. The window is typically a few hundred packets wide, and it must be updated on authentication success rather than on receipt, or an attacker can advance the window with forged packets and cause legitimate retransmissions to be rejected. The interaction with retransmission is direct: a NACK-driven resend arrives with an old sequence number, and the replay window must be wide enough to accept it or the retransmission is useless. That mechanism is described in early RTCP feedback.

Authenticated encryption changes the layout

AES-GCM, specified for SRTP in RFC 7714, replaces the separate encryption and authentication steps with one pass that produces both ciphertext and tag. The counter block construction is similar but not identical, and the tag length options differ. The practical differences are that GCM’s tag covers the additional authenticated data as a single construction rather than through HMAC, and that GCM is unforgiving about IV reuse: the same IV under the same key with GCM leaks the authentication key outright, not merely the plaintext.

The choice between the two families is a performance and interoperability decision rather than a security one at comparable tag lengths. AES-CM with HMAC-SHA1 has a longer deployment history and wider support in older stacks; AES-GCM is faster on hardware with dedicated instructions and produces a shorter combined output for the same security level. Both depend on the same discipline: the packet index must be unique per key, and the SSRC must be part of the IV. The rest of the format, including how the header’s fields are parsed, is unchanged, as described in the RTP fixed header.

References

  1. RFC 3711: The Secure Real-time Transport Protocol (SRTP) — IETF
  2. RFC 7714: AES-GCM Authenticated Encryption in the Secure Real-time Transport Protocol (SRTP) — IETF
  3. RFC 6188: The Use of AES-192 and AES-256 in Secure RTP — IETF
  4. NIST SP 800-38D: Recommendation for Block Cipher Modes of Operation: GCM and GMAC — NIST