Note: This proposal has been retracted by the author.
WARNING: This JEP has been retracted by the author(s). Implementation of the protocol described herein is not recommended. Developers desiring similar functionality should implement the protocol that supersedes this one (if any).
Type: Standards Track
Last Updated: 2004-07-26
JIG: Standards JIG
Approving Body: Jabber Council
Superseded By: None
Short Name: esession
This Jabber Enhancement Proposal is copyright 1999 - 2004 by the Jabber Software Foundation (JSF) and is in full conformance with the JSF's Intellectual Property Rights Policy <http://www.jabber.org/jsf/ipr-policy.php>. This material may be distributed only subject to the terms and conditions set forth in the Open Publication License, v1.0 or later (the latest version is presently available at <http://www.opencontent.org/openpub/>).
The preferred venue for discussion of this document is the Standards-JIG discussion list: <http://mail.jabber.org/mailman/listinfo/standards-jig>.
Given that this JEP normatively references IETF technologies, discussion on the JSF-IETF list may also be appropriate (see <http://mail.jabber.org/mailman/listinfo/jsf-ietf> for details).
The Extensible Messaging and Presence Protocol (XMPP) is defined in the XMPP Core and XMPP IM specifications contributed by the Jabber Software Foundation to the Internet Standards Process, which is managed by the Internet Engineering Task Force in accordance with RFC 2026. Any protocols defined in this JEP have been developed outside the Internet Standards Process and are to be understood as extensions to XMPP rather than as an evolution, development, or modification of XMPP itself.
The keywords "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 RFC 2119.
This JEP describes a lightweight protocol which allows two Jabber endpoints to create a secure tunnel between them, called an "ESession". Once the tunnel is established, all packets between the endpoints will be compressed, encrypted, and transmitted in a "wrapper" protocol element. Steps are taken to ensure that packets exchanged are in the order they were transmitted, were not tampered with, and cannot be replayed at a later time.
Traditionally, creating an end-to-end encrypted session between two Jabber endpoints has required the use of a PKI system such as PGP or GPG (see, for example, Current Jabber OpenPGP Usage ). Integrating with PGP/GPG is problematic due to a lack of solid SDKs. Typical integration with this system requires spawning the PGP/GPG client as a child process and passing data back and forth over some mixture of IPC (such as shared memory or redirected stin/stdout). Additionally, there are efficiency issues with using PKI-based encryption and signatures for every message. Finally, the way in which the PGP/GPG integration is currently used is susceptible to replay attacks. Given these issues, a protocol is needed which:
There exist other Internet protocols which exhibit these characteristics and that are based on standard cryptographic techniques. One of these is SSH (Secure Shell). The transport protocol used in SSH is flexible, relatively simple to implement and, most importantly, proven. For these reasons, SSH was chosen as the conceptual model for this end-to-end encryption proposal. This proposal builds on the key-exchange, replay protection, and cipher processing models that are outlined in the SSH transport protocol.
This JEP is built on a broad foundation of well-researched cryptographic techniques (by authors who have far more experience in the crypto sciences than the current author). While this JEP provides all the necessary information to implement the protocol described herein, it is strongly recommended that developers also spend some time perusing the following documents, in order to achieve a more perfect understanding of the theories behind this protocol.
In addition, this proposal depends on the following Jabber Enhancement Proposals for syntax within XML streams:
This JEP introduces a few characters to help the reader follow the necessary exchanges:
Note that while Alice and Bob are introduced as "end-users", they are simply meant to be an example of Jabber entities. Any directly addressable Jabber entity may participate in an ESession.
Alice (alice@host/res) wants to establish an encrypted session with Bob (bob@host/res). Before she can do so, she MUST determine that he supports the ESession protocol. This SHOULD be done using the disco protocol to ensure he supports the "http://jabber.org/protocol/esession" namespace. Once this determination has been made, she can begin the process of establishing an ESession.
The establishment of an ESession is based on the SSH transport mechanism for establishing a secure session over an insecure transport (refer to "SSH Transport Layer Protocol" for more information). Like SSH, ESession uses a Diffie-Hellman (DH) key exchange algorithm with SHA-1 as the hashing algorithm. The first packet is the initial part of the DH exchange, so Alice must perform the following steps to prepare:
Select a Modular Exponential (MODP) Diffie-Hellman group (these are defined in RFC 3526). Each MODP group defines a series of constants, including a prime (which we will refer to as "DH_PRIME") and a generator (which we will refer to as "DH_GEN"). Additionally, a third parameter ("DH_GROUPORDER") is derived from DH_PRIME and DH_GEN. The value of DH_GROUPORDER is (DH_PRIME - 1) / 2.
Generate a random number "x" (where 1 < x < DH_GROUPORDER). Implementors MUST use a cryptographically strong, pseudo-random number generator.
Calculate "e" = DH_GEN ^ (x mod DH_PRIME)
Alice then sends "e" to Bob as a part of the initial exchange request to start an ESession. Alice includes an identifier of the MODP group that she used, so that Bob will be able to work off the same DH parameters. Finally, she specifies the cipher, key, and message authentication code (MAC) algorithms that she is willing to use, in the order of preference.
<iq from='alice' to='bob' type='set' id='es1'> <esession xmlns='http://jabber.org/protocol/esession'> <start> <features xmlns='http://jabber.org/protocol/feature-neg'> <x xmlns='jabber:x:data'> <field type='hidden' var='FORM_TYPE'> <value>http://jabber.org/protocol/esession</value> </field> <field type='list-single' var='cipher-algo'> <option><value>3des-cbc</value></option> <option><value>blowfish-cbc</value></option> <option><value>twofish128-cbc</value></option> <option><value>aes128-cbc</value></option> </field> <field type='list-single' var='key-algo'> <option><value>esession-dss</value></option> <option><value>esession-rsa</value></option> </field> <field type='list-single' var='mac-algo'> <option><value>hmac-sha1</value></option> <option><value>hmac-sha1-96</value></option> </field> </x> </features> <e modp='MODP-5'> ** value of "e", encoded as a hexadecimal string ** </e> </start> </esession> </iq>
When Bob receives the request for the ESession, he must examine the available algorithms and the selected MODP group. If none of these parameters meets his requirements for security or Bob is unwilling to negotiate an ESession, he MUST return an IQ type='error'. However, if Bob is willing to start an ESession with Alice, he MUST select one algorithm each from the list of cipher, key, and MAC algorithms that Alice provided, and perform the following computations (using the MODP parameters provided by Alice):
Verify that (1 < e < DH_PRIME - 1)
Generate a random number "y" (where 0 < y < DH_GROUPORDER)
Calculate "f" = DH_GEN ^ (y mod DH_GROUPORDER)
Verify that (1 < f < DH_PRIME - 1)
Calculate "K" = e ^ (y mod DH_PRIME). K represents the base key material used to derive the actual keys for encryption and integrity checking
Compute a session identifier (SID) by computing the SHA-1 hash of the following values :
|Bob's public key (base64 encoded)||string|
|Value of "e"||mpint|
|Value of "f"||mpint|
|Value of "K"||mpint|
|Name of the selected cipher-algo||string|
|Name of the selected key-algo||string|
|Name of the selected mac-algo||string|
Note that "e", "f" and "K" are hashed as raw multiple-precision integers, encoded according to the "mpint" type defined in the "SSH Protocol Architecture" specification.
Compute signature ("SIG") of the session identifier. To complete this step, Bob must select a key algorithm from the list Alice provided and use that to create a signed message digest of the SID. Alice will use this message digest, in conjunction with Bob's public key, to verify that the value of "f" which she receives from Bob was actually generated by Bob, and was not tampered with.
Bob now sends "f", "SIG" and his public key to Alice, along with his choices for the required algorithms.
<iq from='bob' to='alice' type='result' id='es1'> <esession xmlns='http://jabber.org/protocol/esession'> <starting> <features xmlns='http://jabber.org/protocol/feature-neg'> <x xmlns='jabber:x:data'> <field var='cipher-algo'><value>blowfish-cbc</value></field> <field var='key-algo'><value>esession-dss</value></field> <field var='mac-algo'><value>hmac-sha1</value></field> </x> </features> <f> ** value of "f", encoded as a hexadecimal string ** </f> <sig> ** value of SIG, Base64 encoded ** </sig> <public-key type='dsa'> ** Base64 encoded DSA public key ** </public-key> </starting> </esession> </iq>
On receipt of the IQ-result, Alice now needs to verify the "f" value provided by Bob. She performs the following computations:
Verify that (1 < f < DH_PRIME-1)
Calculate "K" where K = f ^ (x mod DH_PRIME).
Compute SID (session id) exactly as Bob did above in Step 9.
Verify the signed message digest ("SIG") that Bob provided, using his public key and SID.
At this point, Alice can be certain that the "f" value in the IQ-result was actually generated by Bob, and in turn, can trust that she has the same value for "K" that Bob does. This entire trust system is based on Alice trusting that the public key presented by Bob is actually Bob's key. Depending on the public key algorithm selected, determining this trust can be done in a variety of ways. For instance, if PGP/GPG is in use Alice may verify that Bob's key is signed by another key she knows to be good. Or if they are using an X.509-based algorithm, she may check that Bob's key has been signed by a trusted Certificate Authority (CA).
With the Diffie-Helman negotiation complete and verified, Alice and Bob can generate two sets of key data, one for each direction of the ESession. For data that Alice will send to Bob (Alice -> Bob), the keys are calculated as:
IV (cipher vector) K-I1 = SHA-1(K, "A", SID)
Encryption Key K-E1 = SHA-1(K, "C", SID)
Integrity Key K-M1 = SHA-1(K, "E", SID)
For data that Bob will send to Alice (Bob -> Alice) the keys are calculated as:
IV (cipher vector) K-I2 = SHA-1(K, "B", SID)
Encryption Key K-E2 = SHA-1(K, "D", SID)
Integrity Key K-M2 = SHA-1(K, "F", SID)
As described in the "SSH Transport Layer Protocol" specification (Section 5.2), key data MUST be taken from the beginning of the hash output. 192 bits (24 bytes) SHOULD be used for algorithms with variable-length keys. For other algorithms, as many bytes as are needed are taken from the beginning of the hash value. If the key length in longer than the output of the hash, the key is extended by computing a hash of the concatenation of K and H and the entire key so far, and appending the resulting bytes (as many as the hash generates) to the key. This process is repeated until enough key material is available; the key is taken from the beginning of this value . In other words:
K-E1_1 = SHA-1(K, X, SID) (X is e.g. "A") K-E1_2 = SHA-1(K, K1) K-E1_3 = SHA-1(K, K1, K2) ... K-E1 = K-E1_1 || K-E1_2 || K-E1_3 || ...
Note that for each key generated, the following inputs should be passed into the SHA-1 hash function, using the formats specified below:
|The value of "K", as calculated above||mpint|
|Literal value of "A", "B", etc.||character (single-byte)|
|Value of "SID" (an output of another SHA-1 digest)||raw SHA-1 digest|
With these keys computed and algorithms agreed upon, ESession negotiation is now complete. From this point forward, Alice and Bob MUST only exchange encrypted forms of directed <message/> and <iq/> stanzas. Presence stanzas SHOULD NOT be encrypted, since they are typically relayed by the server, which does not have the key.
Each side will now start a counter ("C") which will be incremented with each packet sent and received. This counter is used to prevent replay attacks by ensuring that the MAC for a given packet never repeats, even if the content of the packet is identical.
When Alice wants to send Bob a <message/> (such as the one in Example 3) she will now take the following steps:
Construct the packet she wishes to send, and serialize this packet ("m").
<message from='alice' to='bob' type='chat'> <body>Hello, Bob!</body> </message>
Compress the serialization using the ZLIB compression format defined in RFC 1950 . This is a required step due to the large amount of repeated data inherent in XML. Typically, the compression context will be initialized after key exchange and is passed from one packet to the next, with only a partial flush being performed at the end of the packet.
m_compressed = zlib-compress(m)
Random bytes of padding are now appended to the compressed serialization, with the following constraints:
m_padded = m_compressed + padding
The resulting data from Step 3 is now processed through the selected MAC algorithm ("mac-algo"), along with the MAC key ("K-M1") and the current value of the packet counter ("C").
m_mac = mac-algo(K-M1, C, m_padded)
Finally, the data from Step 3 will be encrypted with the selected algorithm ("cipher-algo"), using the encryption key.
m_final = cipher-algo-encrypt(K-E1, m_padded)
Alice will now wrap m_mac and m_final in a <message/> packet and transmit it directly to Bob's address (fully-qualified):
<message from='alice' to='bob' xmlns:enc='http://jabber.org/protocol/esession#data'> <enc:data> ** base64 encoded m_final ** </enc:data> <enc:mac> ** base64 encoded m_mac ** </enc:mac> </message>
When Bob recieves the packet from Alice, he will extract the m_final and m_mac from the message and perform the following steps:
Decrypt m_final using the selected cipher and K-M1
r_padded = cipher-algo-decrypt(K-E1, m_final)
Calculate the MAC for the decrypted data
r_mac = mac-algo(K-M1, C, r_padded)
Compare r_mac and m_mac; they MUST match. If they do not match, the message has been tampered with and SHOULD be bounced with a Bad Request error. Additionally, Bob MUST invalidate the ESession (since if a packet was dropped or delivered out of order, it will be impossible to recover the contents, as ZLIB stream would be in an inconsistent state).
assert(r_mac == m_mac)
n = last-byte-of(r_padded)
r_compressed = left(r_padded, len(r_padded) - n)
Decompress r_padded via ZLIB
r = zlib-decompress(r_padded)
Bob will now take r and feed it into an XML parser to transform the raw bytes into a useable, parsed XML form.
ESession supports two public key algorithms initially:
This JEP requires no interaction with the Internet Assigned Numbers Authority (IANA) .
Upon approval of this JEP, the Jabber Registrar  shall register the following namespaces:
The Jabber Registrar shall reserve the following fields within the scope of Data Forms used for ESession negotation:
<form_type> <name>http://jabber.org/protocol/esession</name> <jep>JEP-0116</jep> <desc>ESession negotiation forms</desc> <field var='cipher-algo' type='list-single' label='Cipher algorithm options'/> <field var='key-algo' type='list-single' label='Public key algorithm options'/> <field var='mac-algo' type='list-single' label='Message authentication code algorithm options'/> </form_type>
1. JEP-0027: Current Jabber OpenPGP Usage <http://www.jabber.org/jeps/jep-0027.html>.
2. RFC 2412: The OAKLEY Key Determination Protocol <http://www.ietf.org/rfc/rfc2412.txt>.
3. RFC 3526: More Modular Exponential (MODP) Diffie-Hellman Groups <http://www.ietf.org/rfc/rfc3526.txt>.
4. SSH Transport Layer Protocol <http://www.ietf.org/internet-drafts/draft-ietf-secsh-transport-17.txt>. Work in progress.
5. SSH Protocol Architecture <http://www.ietf.org/internet-drafts/draft-ietf-secsh-architecture-15.txt>. Work in progress.
6. JEP-0004: Data Forms <http://www.jabber.org/jeps/jep-0004.html>.
7. JEP-0020: Feature Negotiation <http://www.jabber.org/jeps/jep-0020.html>.
8. JEP-0030: Service Discovery <http://www.jabber.org/jeps/jep-0030.html>.
9. JEP-0068: Field Data Standardization for Data Forms <http://www.jabber.org/jeps/jep-0068.html>.
10. The SID must NEVER be transmitted between Alice and Bob; they should both be able to derive the same value.
11. As noted in "SSH Transport Layer Protocol", this process will lose entropy if the amount of entropy in K is larger than the internal state size of SHA-1.
12. RFC 1950: ZLIB Compressed Data Format Specification version 3.3 <http://www.ietf.org/rfc/rfc1950.txt>.
13. This helps protect against attacks on the last cipher block, since it will contain only random data
14. The Internet Assigned Numbers Authority (IANA) is the central coordinator for the assignment of unique parameter values for Internet protocols, such as port numbers and URI schemes. For further information, see <http://www.iana.org/>.
15. The Jabber Registrar maintains a list of reserved Jabber protocol namespaces as well as registries of parameters used in the context of protocols approved by the Jabber Software Foundation. For further information, see <http://www.jabber.org/registrar/>.