GNU ZRTP: Media Encryption Architecture
Comprehensive documentation of GNU ZRTP (libzrtpcpp), the free software implementation of RFC 6189 for RTP media path key agreement, Short Authentication String (SAS) verification, and SRTP session encryption.
Historical Cryptographic Document
This document describes ZRTP implementations from the 2006-2015 era. While RFC 6189 remains an open standard, cryptographic best practices have evolved. Do not use legacy builds for production security without modern verification.
§1What is ZRTP?
ZRTP (RFC 6189) is a cryptographic key-agreement protocol developed by Phil Zimmermann, Alan Johnston, and Jon Callas. It negotiates session keys for the Secure Real-time Transport Protocol (SRTP, RFC 3711) directly inside the media path (RTP), rather than relying on signaling channels such as SIP (which often pass through untrusted intermediaries).
GNU ZRTP (implemented in the `libzrtpcpp` library) was developed as an official GNU project led by Werner Dittmann and David Sugar. It provided a thread-safe, modular C++ implementation designed to plug into GNU ccRTP, GNU SIP Witch, Twinkle, Linphone, and other free software VoIP clients.
§2The VoIP Threat Model and Signaling Security
In conventional VoIP systems, call signaling is handled by SIP, while audio/video payloads are carried over RTP. Standard attempts to encrypt VoIP often suffered from fatal architectural flaws:
1. SIP Signaling Vulnerability: Many protocols (such as SDES, RFC 4568) placed the SRTP encryption keys in the SIP SDP (Session Description Protocol) message. Because SIP messages pass through SIP proxies, PBX servers, and corporate routers, anyone with access to an intermediate SIP proxy could intercept the cleartext master key and decrypt the call. 2. The PKI Vulnerability: Systems requiring X.509 digital certificates or public-key authorities required centralized certificate authorities (CAs). Centralized CAs are subject to government coercion, compromised private keys, and man-in-the-middle attacks.
ZRTP bypassed both traps: - In-Band Negotiation: ZRTP performs an ephemeral Diffie-Hellman key exchange directly within the RTP media channel after the call is established. - No Central PKI Required: To defeat Man-in-the-Middle (MitM) eavesdroppers who might intercept the Diffie-Hellman exchange, ZRTP uses a Short Authentication String (SAS). The users verbally read a 4-character phonetic code (or two PGP phonetic words) aloud to each other over the voice connection.
§3Short Authentication String (SAS) & Key Continuity
The SAS is derived by hashing the cryptographic session exchange values:
Alice Bob
| |
|--- ZRTP Hello ------------>|
|<-- ZRTP Hello -------------|
| |
|--- Commit (DH-2048) ------>|
|<-- DHPart1 ----------------|
|--- DHPart2 --------------->|
| |
|=== Compute Shared Key =====|
|=== Compute 4-char SAS =====|
| |
|-- "SAS: Echo-Foxtrot" ---->| (Vocal exchange over audio)
| |
|--- Confirm1 (MAC) -------->|
|<-- Confirm2 (MAC) ---------|
| |
|==== SRTP Audio Encrypted ==|If an active attacker (e.g., an intelligence agency or rogue ISP) intercepts the connection and runs two separate Diffie-Hellman exchanges, the attacker cannot make their hash outputs match the endpoints without solving the discrete logarithm problem. Consequently, Bob and Alice will calculate different SAS values. When Alice speaks her SAS code, Bob immediately detects the mismatch and terminates the call.
Furthermore, ZRTP implements Key Continuity. After the first call, both endpoints securely cache a shared secret (retained secret). On subsequent calls, this secret is factored into the key derivation, protecting even against future MitM attempts where the users might forget to verify the SAS.
§4Integration with GNU ccRTP and SIP Witch
GNU ZRTP was built as an extension to `ccrtp`. By sub-classing `ZrtpQueue`, applications could activate cryptographic state machines with minimal boilerplate:
// Historical example: initializing ZRTP over a ccRTP socket
#include <ccrtp/rtp.h>
#include <libzrtpcpp/ZrtpQueue.h>class SecureCallSession : public ost::TRTPSession<ost::DualSocketHost> { public: SecureCallSession(const InetHostAddress& host, tport_t port) : TRTPSession<DualSocketHost>(host, port) { // Attach ZRTP processor zrtpContext = new ZrtpQueue(); enableZRTP(zrtpContext); } void onZrtpSecureOn(const std::string& cipher, const std::string& sas) { std::cout << "[SECURITY] Session encrypted with " << cipher << std::endl; std::cout << "[SECURITY] Verify SAS with peer: " << sas << std::endl; } }; ```
GNU SIP Witch leveraged this capability to enforce secure media policies: if an incoming or forwarded call could not negotiate ZRTP, the administrator could configure the daemon to drop the call or trigger an audible warning beep.
Authoritative External References
- RFC 6189: ZRTP Specification →(IETF Standards Track document)
- Werner Dittmann libzrtpcpp Savannah Archive →(Official GNU source repository)
This page reconstructs material originally published at gnutelephony.org. It has been formatted and annotated for archival preservation.
Historical source: GNU ZRTP. Reproduced or adapted under the GNU Free Documentation License (GFDL) 1.2 or later where stated.
Historical revision date: 2006-08-12 (Revised 2011-04-18). Restored to permanent static archive in October 2026.