Internet-Draft | PQ Algoritms in ZRTP | September 2024 |
Zimmermann, et al. | Expires 16 March 2025 | [Page] |
TODO¶
This note is to be removed before publishing as an RFC.¶
Source for this draft and an issue tracker can be found at https://github.com/jeannotlapin/rfc6189bis.¶
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 16 March 2025.¶
Copyright (c) 2024 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.¶
ZRTP [RFC6189] is a key agreement protocol that performs a Diffie-Hellman (DH) key exchange during call setup in the media path and is transported over the same port as the Real-time Transport Protocol (RTP) [RFC3550] media stream which has been established using a signaling protocol such as Session Initiation Protocol (SIP) [RFC3261]. This generates a shared secret, which is then used to generate keys and salt for a Secure RTP (SRTP) [RFC3711] session.¶
ZRTP design is based on the DH key exchange. The NIST Post-Quantum Cryptography Standardization [NIST-PQC] process requests the key exchange algorithms to use a Key Encapsulation Mechanism (KEM) API. The KEM form of a key exchange cannot substitute straightforwardly the DH key exchange used in ZRTP. In order to support Post-Quantum Key Exchange as defined in the NIST standardization process, a new Key Agreement Mode is introduced in ZRTP: KEM Mode.¶
Post-Quantum Key exchange algorithms are still in early stage of analysis and a common approch in their usage is to combine them with established algorithm. This is referred in this document as hybrid-KEM. In order to simplify the protocol, the hybrid mode is defined as a combination of two key exchange algorithms in KEM format. To this end, a definition of ECDH-based KEM similar to the one defined in Section 4.1 in [RFC9180] is given. The ECDH-based KEM is then combined with a PQ KEM to provide an hybrid KEM using the same public interface than a simple KEM.¶
Post-Quantum Key exchange may produce large public values to be exchanged with the other endpoint. UDP datagrams are often limited to <1500 bytes if fragmentation is not desired. In order to compensate for this limitation ZRTP message may be fragmented over several ZRTP packets.¶
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 [RFC2119].¶
In this document, a "call" is synonymous with a "session".¶
A || B denotes the concatenation of byte sequences A and B.¶
After both endpoints exchange Hello and HelloACK messages, the key agreement exchange can begin with the ZRTP Commit message. ZRTP supports a number of key agreement modes including DH, KEM, PreShared or Multistream modes as described in the following sections.¶
The Commit message may be sent immediately after both endpoints have completed the Hello/HelloACK discovery handshake, or it may be deferred until later in the call, after the participants engage in some unencrypted conversation. The Commit message may be manually activated by a user interface element, such as a GO SECURE button, which becomes enabled after the Hello/HelloACK discovery phase. This emulates the user experience of a number of secure phones in the Public Switched Telephone Network (PSTN) world. However, it is expected that most simple ZRTP user agents will omit such buttons and proceed directly to secure mode by sending a Commit message immediately after the Hello/HelloACK handshake.¶
Examples ZRTP call flow are shown in Figure 1 and Figure 2. Note that the order of the Hello/HelloACK exchanges in F1/F2 and F3/F4 may be reversed. That is, either Alice or Bob might send the first Hello message. Note that the endpoint that sends the Commit message is considered the initiator of the ZRTP session and drives the key agreement exchange.¶
ZRTP authentication uses a Short Authentication String (SAS), which is ideally displayed for the human user. Alternatively, the SAS can be authenticated by exchanging an optional digital signature (sig) over the SAS in the Confirm1 or Confirm2 messages (described in Section 8.2).¶
The ZRTP Confirm1 and Confirm2 messages are sent for a number of reasons, not the least of which is that they confirm that all the key agreement calculations were successful and thus the encryption will work. They also carry other information such as the Disclosure flag (D), the Allow Clear flag (A), the SAS Verified flag (V), and the Private Branch Exchange (PBX) Enrollment flag (E). All flags are encrypted to shield them from a passive observer.¶
The DH public values are exchanged in the DHPart1 and DHPart2 messages. SRTP keys and salts are then calculated.¶
The initiator needs to generate its ephemeral key pair before sending the Commit, and the responder generates its key pair before sending DHPart1.¶
Alice Bob | | | Alice and Bob establish a media session. | | They initiate ZRTP on media ports | | | | F1 Hello (version, options, Alice's ZID) | |-------------------------------------------------->| | HelloACK F2 | |<--------------------------------------------------| | Hello (version, options, Bob's ZID) F3 | |<--------------------------------------------------| | F4 HelloACK | |-------------------------------------------------->| | | | Bob acts as the initiator. | | | | Commit (Bob's ZID, options, hash value) F5 | |<--------------------------------------------------| | F6 DHPart1 (pvr, shared secret hashes) | |-------------------------------------------------->| | DHPart2 (pvi, shared secret hashes) F7 | |<--------------------------------------------------| | | | Alice and Bob generate SRTP session key. | | | | F8 Confirm1 (MAC, D,A,V,E flags, sig) | |-------------------------------------------------->| | Confirm2 (MAC, D,A,V,E flags, sig) F9 | |<--------------------------------------------------| | F10 Conf2ACK | |-------------------------------------------------->| | SRTP begins | |<=================================================>| | |
The KEM public values (public key and ciphertext) are exchanged in the Commit and KEMPart1 messages. SRTP keys and salts are then calculated.¶
The initiator generates its ephemeral key pair (pvi,sk) and a random nonce before sending the Commit. He sends the public key (pvi) in the Commit message and the random nonce (ni) in the KEMPart2 message.¶
The responder generates and encapsulates the shared secret using the initiator public key (pvi) and send his ciphertext (pvr) in the KEMPart1 message.¶
Alice Bob | | | Alice and Bob establish a media session. | | They initiate ZRTP on media ports | | | | F1 Hello (version, options, Alice's ZID) | |-------------------------------------------------->| | HelloACK F2 | |<--------------------------------------------------| | Hello (version, options, Bob's ZID) F3 | |<--------------------------------------------------| | F4 HelloACK | |-------------------------------------------------->| | | | Bob acts as the initiator. | | | | Commit (Bob's ZID, options, hash value, pvi) F5 | |<--------------------------------------------------| | F6 KEMPart1 (pvr, shared secret hashes) | |-------------------------------------------------->| | KEMPart2 (ni, shared secret hashes) F7 | |<--------------------------------------------------| | | | Alice and Bob generate SRTP session key. | | | | F8 Confirm1 (MAC, D,A,V,E flags, sig) | |-------------------------------------------------->| | Confirm2 (MAC, D,A,V,E flags, sig) F9 | |<--------------------------------------------------| | F10 Conf2ACK | |-------------------------------------------------->| | SRTP begins | |<=================================================>| | |
Multistream mode is an alternative key agreement method used when two endpoints have an established SRTP media stream between them with an active ZRTP Session key. ZRTP can derive multiple SRTP keys from a single DH exchange. For example, an established secure voice call that adds a video stream uses Multistream mode to quickly initiate the video stream without a second DH exchange.¶
When Multistream mode is indicated in the Commit message, a call flow similar to Figure 1 is used, but no DH calculation is performed by either endpoint and the DHPart1 and DHPart2 messages are omitted. The Confirm1, Confirm2, and Conf2ACK messages are still sent. Since the cache is not affected during this mode, multiple Multistream ZRTP exchanges can be performed in parallel between two endpoints.¶
Each Hello message lists the algorithms in the order of preference for that ZRTP endpoint. Endpoints eliminate the non-intersecting choices from each of their own lists, resulting in each endpoint having a list of algorithms in common that might or might not be ordered the same as the other endpoint's list.¶
Unfavorable choices will never be made by this method, because each endpoint will omit from their respective lists choices that are too slow or not secure enough to meet their security policy.¶
A method is provided to allow the two parties to mutually and deterministically choose the same DH key size and algorithm before a Commit message is sent.¶
After removing non intersecting algorithms from the Hello message lists, each endpoint compares the first item on their own list with the first item on the other endpoint's list and SHOULD choose the faster of the two algorithms. For example:¶
Alice's full list: DH2k, DH3k, EC25¶
Bob's full list: EC38, EC25, DH3k¶
Alice's intersecting list: DH3k, EC25¶
Bob's intersecting list: EC25, DH3k¶
Alice's first choice is DH3k, and Bob's first choice is EC25.¶
Thus, both parties choose EC25 (ECDH-256) because it's faster.¶
To decide which DH algorithm is faster, the following ranking, from fastest to slowest is defined: DH-2048, X25519, ECDH-256, DH-3072, ECDH-384, X41417, X448, ECDH-521. These are all defined in Section 5.2.5.¶
If both endpoints follow this method, they may each start their DH calculations as soon as they receive the Hello message, and there will be no need for either endpoint to discard their DH calculation if the other endpoint becomes the initiator.¶
The initiator simply selects any key agreement from the algorithms in common.¶
When both KEM and DH algorithms end up in the common ordered algo lists.¶
If Alice's and Bob's intersecting list first algorithm is a KEM, the KEM Mode only selection applies.¶
If Alice's and Bob's intersecting list first algorithm is a DH, KEM algos are dropped from the lists and the DH Mode only selection applies.¶
If one is DH and the other is KEM, the DH algorithm is selected.¶
Example:¶
Alice's full list: X25519, X25519+Kyber512, X448¶
Bob's full list: X25519+Kyber512, X25519¶
Alice's intersecting list: X25519, X25519+Kyber512¶
Bob's intersecting list: X25519+Kyber512, X25519¶
Alice's first choice is a DH algorithn (X25519), and Bob's first choice is KEM algorithm (X25519+Kyber512).¶
Thus, both parties choose X25519.¶
Example:¶
Alice's full list: X448, X25519, X25519+Kyber512, DH3k¶
Bob's full list: DH3k, X25519+Kyber512, X25519¶
Alice's intersecting list: X25519, X25519+Kyber512, DH3k¶
Bob's intersecting list: DH3k, X25519+Kyber512, X25519¶
Alice's first choice is a DH algorithn (X25519), and Bob's first choice is DH algorithm (DH3k): drop X25519+Kyber512 from the intersecting lists.¶
Thus, both parties choose X25519 because it is faster than DH3k.¶
Example:¶
Alice's full list: X448+Kyber1024, X25519+Kyber512, X448, X25519¶
Bob's full list: X25519+Kyber512, X448+Kyber1024, X25519¶
Alice's intersecting list: X448+Kyber1024, X25519+Kyber512, X25519¶
Bob's intersecting list: X25519+Kyber512, X448+kyber1024, X25519¶
Alice's first choice is a KEM algorithn (X448+Kyber1024), and Bob's first choice is KEM algorithm (X25519+Kyber512).¶
The initiator chooses X448+Kyber1024 because it provides a higher security level¶
For the rest of the algorithm choices, it is simply whatever the initiator selects from the algorithms in common. Note that the DH or KEM key size influences the Hash Type and the size of the symmetric cipher key, as explained in Section 5.2.5.¶
The next step is the generation of a secret for deriving SRTP keying material. ZRTP uses for modes: DH, KEM, PreShared and Multistream, described in the following subsections.¶
The purpose of the key exchange is for the two ZRTP endpoints to generate a new shared secret, s0. In addition, the endpoints discover if they have any cached or previously stored shared secrets in common, and they use them as part of the calculation of the session keys. Because the key exchange affects the state of the retained shared secret cache, only one in-process ZRTP key exchange may occur at a time between two ZRTP endpoints. Otherwise, race conditions and cache integrity problems will result. When multiple media streams are established in parallel between the same pair of ZRTP endpoints (determined by the ZIDs in the Hello messages), only one can be processed. Once that exchange completes with Confirm2 and Conf2ACK messages, another ZRTP key exchange can begin. This constraint does not apply when Multistream mode key agreement is used since the cached shared secrets are not affected.¶
From the intersection of the algorithms in the sent and received Hello messages, the initiator chooses a hash, cipher, auth tag, Key Agreement Type, and SAS Type to be used.¶
A DH mode is selected by setting the Key Agreement Type in the Commit to one of the DH or Elliptic Curve Diffie-Hellman (ECDH) values from the table in Section 5.2.5. In this mode, the key agreement begins with the initiator choosing a fresh random DH secret value (svi) based on the chosen Key Agreement Type value, and computing the public value. (Note that to speed up processing, this computation can be done in advance.) For guidance on generating random numbers, see Section 4.8.¶
For Finite Field DH, the value for the DH generator g, the DH prime p, and the length of the DH secret value, svi, are defined in Section 5.2.5.¶
pvi = g^svi mod p¶
where g and p are determined by the Key Agreement Type value. The DH public value pvi value is formatted as a big-endian octet string and fixed to the bit-length of the DH prime; leading zeros MUST NOT be truncated.¶
For Elliptic Curve DH, pvi is calculated and formatted according to the ECDH specification in Section 5.2.5, which refers in detail to certain sections of [NIST-SP800-56A].¶
The hash commitment is performed by the initiator of the ZRTP exchange. The hash value of the initiator, hvi, includes a hash of the entire DHPart2 message as shown in Figure 9 (which includes the DH public value, pvi), and the responder's Hello message. The hvi hash is truncated to 256 bits:¶
hvi = hash(initiator's DHPart2 message || responder's Hello message)¶
Note that the Hello message includes the fields shown in Figure 5.¶
The information from the responder's Hello message is included in the hash calculation to prevent a bid-down attack by modification of the responder's Hello message.¶
The initiator sends the hvi in the Commit message.¶
The use of hash commitment in the DH exchange constrains the attacker to only one guess to generate the correct Short Authentication String (SAS) (Section 8) in his attack, which means the SAS can be quite short. A 16-bit SAS, for example, provides the attacker only one chance out of 65536 of not being detected. Without this hash commitment feature, a MiTM attacker would acquire both the pvi and pvr public values from the two parties before having to choose his own two DH public values for his MiTM attack. He could then use that information to quickly perform a bunch of trial DH calculations for both sides until he finds two with a matching SAS. To raise the cost of this birthday attack, the SAS would have to be much longer. The Short Authentication String would have to become a Long Authentication String, which would be unacceptable to the user. A hash commitment precludes this attack by forcing the MiTM to choose his own two DH public values before learning the public values of either of the two parties.¶
Upon receipt of the Commit message, the responder generates its own fresh random DH secret value, svr, and computes the public value. (Note that to speed up processing, this computation can be done in advance, with no need to discard this computation if both endpoints chose the same algorithm via Section 4.1.2). For guidance on random number generation, see Section 4.8.¶
For Finite Field DH, the value for the DH generator g, the DH prime p, and the length of the DH secret value, svr, are defined in Section 5.2.5.¶
pvr = g^svr mod p¶
The pvr value is formatted as a big-endian octet string, fixed to the bit-length of the DH prime; leading zeros MUST NOT be truncated.¶
For Elliptic Curve DH, pvr is calculated and formatted according to the ECDH specification in Section 5.2.5, which refers in detail to certain sections of [NIST-SP800-56A].¶
Upon receipt of the DHPart2 message, the responder checks that the initiator's DH public value is not equal to 1 or p-1. An attacker might inject a false DHPart2 message with a value of 1 or p-1 for g^svi mod p, which would cause a disastrously weak final DH result to be computed. If pvi is 1 or p-1, the user SHOULD be alerted of the attack and the protocol exchange MUST be terminated. Otherwise, the responder computes its own value for the hash commitment using the DH public value (pvi) received in the DHPart2 message and its own Hello message and compares the result with the hvi received in the Commit message. If they are different, a MiTM attack is taking place and the user is alerted and the protocol exchange terminated.¶
The responder then calculates the DH result:¶
DHResult = pvi^svr mod p¶
Upon receipt of the DHPart1 message, the initiator checks that the responder's DH public value is not equal to 1 or p-1. An attacker might inject a false DHPart1 message with a value of 1 or p-1 for g^svr mod p, which would cause a disastrously weak final DH result to be computed. If pvr is 1 or p-1, the user should be alerted of the attack and the protocol exchange MUST be terminated.¶
The initiator then sends a DHPart2 message containing the initiator's DH public value and the set of calculated shared secret IDs as defined in Section 4.3.1.¶
The initiator calculates the same DH result using:¶
DHResult = pvr^svi mod p¶
For both the initiator and responder, the DHResult is formatted as a big-endian octet string and fixed to the width of the DH prime; leading zeros MUST NOT be truncated. For example, for a 3072-bit p, DHResult would be a 384 octet value, with the first octet the most significant. DHResult may also be the result of an ECDH calculation, which is discussed in Section 5.2.5.¶
Key Agreement | Size of DHResult |
---|---|
DH-3072 | 384 octets |
DH-2048 | 256 octets |
ECDH P-256 | 32 octets |
ECDH P-384 | 48 octets |
ECDH X25519 | 32 octets |
ECDH X41417 | 52 octets |
ECDH X448 | 56 octets |
The KEM is based on an interface providing three functions:¶
Generate a fresh set of key pair:¶
publicKey, secretKey = KEMgenKey()¶
Generate a sharedSecret and encapsulates it in cipherText using the given publicKey:¶
sharedSecret, cipherText = KEMencaps( publicKey )¶
Use the given secretKey to compute the sharedSecret encapsulated in cipherText:¶
sharedSecret = KEMdecaps( cipherText, secretKey )¶
This mode is used to support Post-Quantum algorithms defined with this interface imposed by the NIST Post-Quantum Cryptography Standardization process [NIST-PQC].¶
A KEM mode is selected by setting the Key Agreement Type in the Commit to one of the KEM values from the table in Section 5.2.5. In this mode, the key agreement begins with the initiator generating a fresh random key pair (public key pvi and secret key svi) based on the chosen Key Agreement Type value and a 256-bit random nonce. For guidance on generating random numbers, see Section 4.8.¶
pvi,svi = KEMgenKey()¶
The generated public key (pvi) is inserted in the Commit message as shown in Figure 7, the random nonce (ni) is inserted in the KEMPart2 message which does not convey data directly related to the key exchange itself as shown in Figure 11.¶
The hash commitment is performed by the initiator of the ZRTP exchange. The hash value of the initiator, hvi, includes a hash of the entire KEMPart2 message as shown in Figure 11 and the responder's Hello message. The hvi hash is truncated to 256 bits:¶
hvi = hash(initiator's KEMPart2 message || responder's Hello message)¶
Note that the Hello message includes the fields shown in Figure 5.¶
The information from the responder's Hello message is included in the hash calculation to prevent a bid-down attack by modification of the responder's Hello message.¶
The initiator sends the hvi in the Commit message.¶
As detailed in Section 4.4.1.3, shared secret calculation in Key Exchange mode involves a transcript including Commit and KEMPart2 messages. The use of hash commitment constrains the attacker to only one guess to generate the correct Short Authentication String (SAS) (Section 8) in his attack, which means the SAS can be quite short. A 16-bit SAS, for example, provides the attacker only one chance out of 65536 of not being detected.¶
Without the KEMPart2 message, a MitM putting itself in the role of responder could acquire pvi and quickly perform a bunch of trial encapsulations or modify the retained secrets ids until he finds a SAS mathing the one generated on the other connection. The KEMPart2 message forces the responder to wait for it to be able to derive the SAS even with the ability to select the shared secret exchanged via the KEM itself.¶
Without the hash commitment feature, a MitM putting itself in the role of initiator could acquire the pvr and quickly perform a bunch of trial SAS computation using random nonces (ni) and/or retained secret ids until he finds two matching SAS.¶
To raise the cost of this birthday attack, the SAS would have to be much longer. The Short Authentication String would have to become a Long Authentication String, which would be unacceptable to the user. KEMPart2 nonce and a hash commitment precludes this attack by forcing the MiTM to choose his own nonce before learning the other endpoint contribution to the final secret.¶
Upon receipt of the Commit message, the responder uses the public key pvi to generate the shared secret, KEMResult and to encapsulate it in a public value pvr.¶
KEMResult, pvr = KEMencaps(pvi)¶
Upon receipt of the KEMPart2 message, the responder computes its own value for the hash commitment using the received KEMPart2 message and its own Hello message and compares the result with the hvi received in the Commit message. If they are different, a MiTM attack is taking place and the user is alerted and the protocol exchange terminated.¶
Upon receipt of the KEMPart1 message, the initiator computes the same KEMResult using the decapsulation function on the responder's public value (pvr) and its own private key (svi)¶
KEMResult = KEMdecaps(pvr, svi)¶
The initiator then sends a KEMPart2 message containing the initiator's random nonce (ni) and the set of calculated shared secret IDs as defined in Section 4.3.1.¶
KEMResult size is defined by the algorithm used. See Section 5.2.5 for details.¶
All ZRTP packets messages use the message format defined in Figure 3 and Figure 4. All word lengths referenced in this specification are 32 bits, or 4 octets. All integer fields are carried in network byte order, that is, most-significant byte (octet) first, commonly known as big-endian.¶
0 1 2 3 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |0 0 0 1 0 0 0 0| Not Used: 0 | Sequence Number | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Magic Cookie 'ZRTP' (0x5a525450) | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Source Identifier | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | | | ZRTP Message (length depends on Message Type) | | . . . | | | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | CRC (1 word) | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
0 1 2 3 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |0 0 0 1 0 0 0 1| Not Used: 0 | Sequence Number | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Magic Cookie 'ZRTP' (0x5a525450) | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Source Identifier | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | message Id | message total length | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | offset | fragment length | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | | | ZRTP Message fragment(length as indicated) | | . . . | | | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | CRC (1 word) | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
[RFC7983] section 7 reserves for the ZRTP packet format the values 16 to 19 on the first byte to clearly distinguish ZRTP packets from STUN, DTLS, TURN or RTP/RTCP packets. Values 16 and 17 are used to distinguish fragmented and non-fragmented messages. The 8 unused bits are set to zero and MUST be ignored when received. Previous version of ZRTP non supporting the message fragmentation will simply discard the fragmented message as invalid.¶
The Sequence Number is a count that is incremented for each ZRTP packet sent. The count is initialized to a random value. This is useful in estimating ZRTP packet loss and also detecting when ZRTP packets arrive out of sequence.¶
The ZRTP Magic Cookie is a 32-bit string that uniquely identifies a ZRTP packet and has the value 0x5a525450.¶
Source Identifier is the SSRC number of the RTP stream to which this ZRTP packet relates. For cases of forking or forwarding, RTP, and hence ZRTP, may arrive at the same port from several different sources -- each of these sources will have a different SSRC and may initiate an independent ZRTP protocol session. SSRC collisions would be disruptive to ZRTP. SSRC collision handling procedures are described in Section 4.1.¶
When the packet carries a message fragment, the header also includes:¶
message Id: a unique Id for this message, is attached to the message and is not incremented at each retransmission like the sequence number. It is initialised to a random value and is incremented for each new message generated.¶
message total length: size, in 32-bit words of the total message.¶
offset: offset of this fragment, in 32-bit words.¶
fragment length: size of this fragment, in 32-bit words.¶
The messages susceptibles to be fragmented are Commit, KEMPart1, Confirm1 and Confirm2 messages. There is then no reason to store fragments for several messages. A simple buffer storing the message currently in reception is enough, if a fragment with message Id superior to the current one is received, the current buffer content must be discarded and the new message collection started. Fragments may overlap if the MTU is modified during the ZRTP handshake.¶
The ZRTP messages are defined in Section 5.2 and are of variable length.¶
Hash Type Block | Meaning |
---|---|
"S256" | SHA-256 Hash defined in [NIST-FIPS180-4] |
"S384" | SHA-384 Hash defined in [NIST-FIPS180-4] |
"S512" | SHA-512 Hash defined in [NIST-FIPS180-4] |
"N256" | SHA3-256 Hash defined in [NIST-FIPS202] |
"N384" | SHA3-384 Hash defined in [NIST-FIPS202] |
"N512" | SHA3-512 Hash defined in [NIST-FIPS202] |
Key Agreement Type Block | Short Type Block | Meaning |
---|---|---|
"DH3k" | - | DH mode with p=3072 bit prime per [RFC3526], Section 4. |
"DH2k" | - | DH mode with p=2048 bit prime per [RFC3526], Section 3. |
"EC25" | - | Elliptic Curve DH, P-256 per [RFC5114], Section 2.6 |
"EC38" | - | Elliptic Curve DH, P-384 per [RFC5114], Section 2.7 |
"X255" | "X1" | ECDH X25519 per [RFC7748] |
"X414" | "X2" | ECDH 41417 per [Ber14] |
"X448" | "X3" | ECDH X448 per [RFC7748] |
Key Agreement Type Block | Short Type Block | Meaning |
---|---|---|
"KYB1" | "K1" | Kyber512 |
"KYB2" | "K2" | Kyber768 |
"KYB3" | "K3" | Kyber1024 |
"BIK1" | "B1" | Bike-L1 |
"BIK2" | "B2" | Bike-L3 |
"BIK3" | "B3" | Bike-L5 |
"HQC1" | "H1" | HQC-128 |
"HQC2" | "H2" | HQC-192 |
"HQC3" | "H3" | HQC-256 |
"NTR1" | "N1" | NTRU-HPS 2048-509 |
"NTR2" | "N2" | NTRU-HPS 2048-677 |
"NTR3" | "N3" | NTRU-HPS 4096-821 |
"SAB1" | "A1" | LightSaber |
"SAB2" | "A2" | Saber |
"SAB3" | "A3" | FireSaber |
Key Agreement Type Block | Meaning |
---|---|
"Prsh" | Preshared Non-DH mode |
"Mult" | Multistream Non-DH mode |
The Hybrid KEM, constructed as decribed in Section 6, can combine several KEMs. It is recommended to use one ECDH algorithm(X25519, X41417 or X448) used in KEM form as described in Section 6.1 and one or more of the PQ KEM from Table 3. The 4 characters char describing an hybrid KEM key agreement type block is built using the "Short Type Block" from Table 3 and Table 4. The ECDH-based KEM is always mentionned first.¶
For an hybrid scheme combining one ECDH and one PQ KEM, the key agreement type block concatenates the 2 short type blocks. Examples:¶
For an hybrid scheme combining one ECDH and two PQ KEM, the key agreement type block uses the short type blocks first letter and one number for the algorithm variation applied to the three algorithms involved. This limit the three parties hybrid to some combinations. Examples:¶
0 1 2 3 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |0 1 0 1 0 0 0 0 0 1 0 1 1 0 1 0| length | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Message Type Block="Hello " (2 words) | | | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | version="1.10" (1 word) | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | | | Client Identifier (4 words) | | | | | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | | | Hash image H3 (8 words) | | . . . | | | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | | | ZID (3 words) | | | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |0|S|M|P| unused (zeros)| hc | cc | ac | kc | sc | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | hash algorithms (0 to 7 values) | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | cipher algorithms (0 to 7 values) | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | auth tag types (0 to 7 values) | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Key Agreement Types (0 to 7 values) | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | SAS Types (0 to 7 values) | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | MAC (2 words) | | | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
0 1 2 3 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |0 1 0 1 0 0 0 0 0 1 0 1 1 0 1 0| length=29 words | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Message Type Block="Commit " (2 words) | | | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | | | Hash image H2 (8 words) | | . . . | | | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | | | ZID (3 words) | | | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | hash algorithm | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | cipher algorithm | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | auth tag type | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Key Agreement Type | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | SAS Type | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | | | hvi (8 words) | | . . . | | | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | MAC (2 words) | | | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
0 1 2 3 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |0 1 0 1 0 0 0 0 0 1 0 1 1 0 1 0| length=depends on KA type | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Message Type Block="Commit " (2 words) | | | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | | | Hash image H2 (8 words) | | . . . | | | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | | | ZID (3 words) | | | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | hash algorithm | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | cipher algorithm | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | auth tag type | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Key Agreement Type | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | SAS Type | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | | | hvi (8 words) | | . . . | | | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | | | pvi (length depends on KA Type) | | . . . | | | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | MAC (2 words) | | | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
0 1 2 3 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |0 1 0 1 0 0 0 0 0 1 0 1 1 0 1 0| length=depends on KA Type | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Message Type Block="DHPart1 " (2 words) | | | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | | | Hash image H1 (8 words) | | . . . | | | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | rs1IDr (2 words) | | | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | rs2IDr (2 words) | | | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | auxsecretIDr (2 words) | | | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | pbxsecretIDr (2 words) | | | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | | | pvr (length depends on KA Type) | | . . . | | | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | MAC (2 words) | | | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
0 1 2 3 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |0 1 0 1 0 0 0 0 0 1 0 1 1 0 1 0| length=depends on KA Type | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Message Type Block="DHPart2 " (2 words) | | | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | | | Hash image H1 (8 words) | | . . . | | | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | rs1IDi (2 words) | | | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | rs2IDi (2 words) | | | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | auxsecretIDi (2 words) | | | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | pbxsecretIDi (2 words) | | | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | | | pvi (length depends on KA Type) | | . . . | | | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | MAC (2 words) | | | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
0 1 2 3 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |0 1 0 1 0 0 0 0 0 1 0 1 1 0 1 0| length=depends on KA Type | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Message Type Block="KEMPart1" (2 words) | | | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | | | Hash image H1 (8 words) | | . . . | | | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | rs1IDi (2 words) | | | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | rs2IDi (2 words) | | | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | auxsecretIDi (2 words) | | | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | pbxsecretIDi (2 words) | | | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | | | pvr (length depends on KA Type) | | . . . | | | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | MAC (2 words) | | | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
0 1 2 3 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |0 1 0 1 0 0 0 0 0 1 0 1 1 0 1 0| length=25 words | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Message Type Block="KEMPart2" (2 words) | | | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | | | Hash image H1 (8 words) | | . . . | | | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | rs1IDi (2 words) | | | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | rs2IDi (2 words) | | | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | auxsecretIDi (2 words) | | | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | pbxsecretIDi (2 words) | | | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | | | ni (4 words) | | . . . | | | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | MAC (2 words) | | | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
PQC KEM algorithm being quite recent, it is recommended to combine them with well-known, classical key exchange algorithms to obtain an hybrid KEM. We defined a method to hybridize key exchange schemes by providing an interface identical to a "simple" KEM:¶
Generate a fresh set of key pair:¶
publicKey, secretKey = KEMgenKey()¶
Generate a sharedSecret and encapsulates it in cipherText using the given publicKey:¶
sharedSecret, cipherText = KEMencaps( publicKey )¶
Use the given secretKey to compute the sharedSecret encapsulated in cipherText:¶
sharedSecret = KEMdecaps( cipherText, secretKey )¶
This makes the handling of Hybrid KEM by ZRTP transparent and will allow the switch to PQC KEM only once the confidence in this kind algorithm reaches an acceptable level.¶
We first define an ECDH-KEM based and then a way to combine two KEM algorithms.¶
Based on Section 4.1 of [RFC9180], we define a scheme to provide a KEM interface based on ECDH algorithms.¶
ECDH interface is the following:¶
Generate a fresh set of key pair:¶
publicKey, secretKey = ECDHgenKey()¶
Compute the shared secret given self secret key and peer public key¶
sharedSecret = ECDHcomputeShared( selfSecret, peerPublic )¶
Derive the public key given the secret one¶
publicKey = ECDHderivePublicKey( secretKey )¶
The ECDH-based KEM relies upon HKDF as defined in [RFC5869] based on the negotiated hash algorithm:¶
kfd ( ikm, context, outputSize ): ikm = "ZRTP" || ECDHId || "aea_prk" || ikm salt = "" info = outputSize || "ZRTP" || ECDHId || "shared_secret" || context return HKDF( ikm, salt, info, outputSize ) KEMgenKey(): return ECDHgenKey() KEMencaps( publicKey ): skE, pkE = ECDHgenKey() ss = ECDHcomputeShared( skE, publicKey ) return kdf( ss, pkE || publicKey, sizeof(ss) ), pkE KEMdecaps( cipherText, secretKey ): ss = ECDHcomputeShared( secretKey, cipherText ) publicKey = ECDHderivePublicKey( secretKey ) return kdf( ss, cipherText || publicKey, sizeof(ss) )¶
The implicit value ECDHId defined as follow:¶
Section 3.3 in [Bin18] describes a way of combining several KEMs into one. We apply this to build an hybrid KEM from two or more KEMs using HMAC-SHA as dual Pseudo Random Function and extractor.¶
PublicKey, secretKey and cipherText sizes are implicitly known for each component KEM, so the function "split" can separate the concatenated entities. The following pseudo code combines n KEMs together, each component is noted KEM[i].¶
Generate a fresh set of key pair:¶
publicKey, secretKey = KEMgenKey(): for i in [1..n] pk[i], sk[i] = KEM[i].genKey() return pk[1] || .. || pk[n], sk[1] || .. || sk[n]¶
Generate a sharedSecret and encapsulate it in cipherText using the given publicKey:¶
sharedSecret, cipherText = KEMencaps( publicKey ): pk[1], .. , pk[n] = split( publicKey ) for i in [1..n] ss[i], ct[i] = KEM[i].encaps( pk[i] ) cipherText = ct[1] || .. || ct[n] k[1] = HMAC( "", ss[1] ) for in in [2..n] k[i] = HMAC( k[i-1], ss[i] ) sharedSecret = HMAC( k[n], cipherText) return sharedSecret, cipherText¶
Use the given secretKey to compute the sharedSecret encapsulated in cipherText:¶
sharedSecret = KEMdecaps( cipherText, secretKey ): sk[1], .. , sk[n] = split( secretKey ) ct[1], .. , ct[n] = split( cipherText ) for i in [1..n] ss[i] = KEM[i].decaps( ct[i], sk[i] ) k[1] = HMAC( "", ss1 ) for in in [2..n] k[i] = HMAC( k[i-1], ss[i] ) sharedSecret = HMAC( k[n], cipherText ) return sharedSecret¶
The HMAC function is based on the negotiated hash algorithm.¶
In most applications, it is desirable to avoid the added complexity of a PKI-backed digital signature, which is why ZRTP is designed not to require it. Nonetheless, in some applications, it may be hard to arrange for two human users to verbally compare the SAS. Or, an application may already be using an existing PKI and wants to use it to augment ZRTP.¶
To handle these cases, ZRTP allows for an OPTIONAL signature feature, which allows the SAS to be checked without human participation. The SAS MAY be signed and the signature sent inside the Confirm1, Confirm2 (Figure 10), or SASrelay (Figure 16) messages. The signature type (Section Section 5.2.7), length of the signature, and the key used to create the signature (or a link to it) are all sent along with the signature. The signature is calculated across the entire SAS hash result (sashash), from which the sasvalue was derived. The signatures exchanged in the encrypted Confirm1, Confirm2, or SASrelay messages MAY be used to authenticate the ZRTP exchange. A signature may be sent only in the initial media stream in a DH or ECDH ZRTP exchange, not in Multistream mode.¶
The initiator computes its signature as follows:¶
sigi = sign(Initiator's private key, "Initiator" || Initiator's public key || sashash)¶
The responder computes its signature as follows:¶
sigr = sign(Responder's private key, "Responder" || Responder's public key || sashash)¶
Although the signature is sent, the material that is signed, the sashash, is not sent with it in the Confirm message, since both parties have already independently calculated the sashash. That is not the case for the SASrelay message, which must relay the sashash. To avoid unnecessary signature calculations, a signature SHOULD NOT be sent if the other ZRTP endpoint did not set the (S) flag in the Hello message (Section Section 5.3).¶
Note that the choice of hash algorithm used in the digital signature is independent of the hash used in the sashash. The sashash is determined by the negotiated Hash Type (Section Section 5.2.2), while the hash used by the digital signature is separately defined by the digital signature algorithm. For example, the sashash may be based on SHA-256, while the digital signature might use SHA-384, if an ECDSA P-384 key is used.¶
If the sashash (which is always truncated to 256 bits) is shorter than the signature hash, the security is not weakened because the hash commitment precludes the attacker from searching for sashash collisions.¶
ECDSA algorithms may be used with either OpenPGP-formatted keys, or X.509v3 certificates. If the ZRTP key exchange is ECDH, and the SAS is signed, then the signature SHOULD be ECDSA, and SHOULD use the same size curve as the ECDH exchange if an ECDSA key of that size is available.¶
If a ZRTP endpoint supports incoming signatures (evidenced by setting the (S) flag in the Hello message), it SHOULD be able to parse signatures from the other endpoint in OpenPGP format and MUST be able to parse them in X.509v3 format. If the incoming signature is in an unsupported format, or the trust model does not lead to a trusted introducer or a trusted certificate authority (CA), another authentication method may be used if available, such as the SAS compare, or a cached shared secret from a previous session. If none of these methods are available, it is up to the ZRTP user agent and the user to decide whether to proceed with the call, after the user is informed.¶
ECDSA [NIST-FIPS186-5] has a feature that allows most of the signature calculation to be done in advance of the session, reducing latency during call setup. This is useful for low-power mobile handsets.¶
ECDSA is preferred because it has compact keys as well as compact signatures. However, if the signature along with its public key certificate are insufficiently compact, the Confirm message may become too long for the maximum transmission unit (MTU) size, and fragmentation is applied to ZRTP messages (see Section Section 5.1). This avoids using UDP fragmentation. Indeed, if UDP fragmentation is applied, then some firewalls and NATs may discard fragmented UDP packets, which would cause the ZRTP exchange to fail. Such an issue is now mitigated thanks to ZRTP messages fragmentation.¶
From a packet-size perspective, ECDSA produces equally compact signatures for a given signature strength.¶
All signatures generated MUST use only NIST-approved hash algorithms, and MUST avoid using SHA1. This applies to both OpenPGP and X.509v3 signatures. NIST-approved hash algorithms are found in [NIST-FIPS186-5]. All ECDSA curves used throughout this spec are over prime fields, drawn from Section 4.2 of [NIST-SP800-186].¶
version 00.¶