2026-07-035 min readhls encryption m3u8 key, ext-x-key, aes-128 hls

Understanding HLS Encryption: M3U8 EXT-X-KEY Explained

Learn about HLS encryption and the EXT-X-KEY tag. How AES-128 encryption protects HLS streams and how to work with encrypted playlists.

How HLS Encryption Works

HLS supports AES-128 encryption to protect video content. Each segment is encrypted with a key before being served. The player must fetch the key from a URL specified in the playlist to decrypt and play the content.

Key details about HLS encryption:

  • The encryption key is a 16-byte (128-bit) AES key
  • Each segment is encrypted as a complete AES-128-CBC block
  • The Initialization Vector (IV) can be specified or derived from the segment sequence number
  • Keys can be rotated during playback (key rotation)

The EXT-X-KEY Tag

The encryption key is specified in the M3U8 playlist using the EXT-X-KEY tag:

#EXT-X-KEY:METHOD=AES-128,URI="https://keyserver.com/key.bin",IV=0x1234567890abcdef1234567890abcdef

Parameters explained:

  • METHOD — Encryption method: AES-128, SAMPLE-AES, or NONE
  • URI — URL to fetch the encryption key
  • IV — Initialization Vector (hexadecimal, 32 digits)
  • KEYFORMAT — Key format identifier (for advanced DRM)
  • KEYFORMATVERSIONS — Version of the key format

Encrypting HLS with OpenSSL

Generate an encryption key and encrypt segments:

# Generate a random 16-byte key
openssl rand 16 > encrypt.key

# Create a key info file for FFmpeg
echo "https://example.com/encrypt.key" > key_info
echo "$(cat encrypt.key | xxd -p)" >> key_info
echo "$(openssl rand -hex 16)" >> key_info

# Encrypt during segmenting
ffmpeg -i input.mp4 -c:v libx264 -c:a aac -f hls
-hls_time 6 -hls_key_info_file key_info
-hls_playlist_type vod playlist.m3u8

Playing Encrypted Streams

Most modern HLS players support AES-128 decryption automatically, including our online player. The player reads the EXT-X-KEY tag, fetches the key from the specified URI, and decrypts each segment before playback. If the key server requires authentication, you may need to configure the player with custom HTTP headers.

Related Articles