Skip to content

Latest commit

 

History

History
2107 lines (1595 loc) · 64.9 KB

spec-elligator.md

File metadata and controls

2107 lines (1595 loc) · 64.9 KB

N

Sender and recipient have the following DH key pairs (private half in lower case, public half in upper case):

  • (ie, IE) Initiator's ephemeral key.
  • (rs, RS) Responder's static key.

Those key pairs are used to derive the following shared secrets:

  • es = DH(ie, RS) = DH(rs, IE)

Those shared secrets are hashed to derive the following keys (zero is a string of zero bytes):

  • H0 = "Monokex N" (ASCII, 32 bytes, zero padded)
  • H1 = KDF(H0, RS)
  • H2 = KDF(H1, prelude) if there is a prelude, H1 otherwise
  • H3 = KDF(H2, IE)
  • H4 = KDF(H3, es)
  • H5, K1 = ENC(H4, Zero)
  • H6, T1 = KDF(H5, ENC(K1, p1))

The messages contain the following (||denotes concatenation):

  • msg1 = IE || ENC(K1, p1) || T1

Note that RS is shared in advance.

The handshake proceeds as follows:

  • Initiator sends msg1 to the Responder.
  • Responder verifies msg1, and aborts if it fails.
  • The protocol is complete. The session key is H6.

K

Sender and recipient have the following DH key pairs (private half in lower case, public half in upper case):

  • (is, IS) Initiator's static key.
  • (ie, IE) Initiator's ephemeral key.
  • (rs, RS) Responder's static key.

Those key pairs are used to derive the following shared secrets:

  • es = DH(ie, RS) = DH(rs, IE)
  • ss = DH(is, RS) = DH(rs, IS)

Those shared secrets are hashed to derive the following keys (zero is a string of zero bytes):

  • H0 = "Monokex K" (ASCII, 32 bytes, zero padded)
  • H1 = KDF(H0, IS)
  • H2 = KDF(H1, RS)
  • H3 = KDF(H2, prelude) if there is a prelude, H2 otherwise
  • H4 = KDF(H3, IE)
  • H5 = KDF(H4, es)
  • H6 = KDF(H5, ss)
  • H7, K1 = ENC(H6, Zero)
  • H8, T1 = KDF(H7, ENC(K1, p1))

The messages contain the following (||denotes concatenation):

  • msg1 = IE || ENC(K1, p1) || T1

Note that IS and RS are shared in advance.

The handshake proceeds as follows:

  • Initiator sends msg1 to the Responder.
  • Responder verifies msg1, and aborts if it fails.
  • The protocol is complete. The session key is H8.

X

Sender and recipient have the following DH key pairs (private half in lower case, public half in upper case):

  • (is, IS) Initiator's static key.
  • (ie, IE) Initiator's ephemeral key.
  • (rs, RS) Responder's static key.

Those key pairs are used to derive the following shared secrets:

  • es = DH(ie, RS) = DH(rs, IE)
  • ss = DH(is, RS) = DH(rs, IS)

Those shared secrets are hashed to derive the following keys (zero is a string of zero bytes):

  • H0 = "Monokex X" (ASCII, 32 bytes, zero padded)
  • H1 = KDF(H0, RS)
  • H2 = KDF(H1, prelude) if there is a prelude, H1 otherwise
  • H3 = KDF(H2, IE)
  • H4 = KDF(H3, es)
  • H5, K1 = ENC(H4, Zero)
  • H6, T1 = KDF(H5, ENC(K1, IS))
  • H7 = KDF(H6, ss)
  • H8, K2 = ENC(H7, Zero)
  • H9, T2 = KDF(H8, ENC(K2, p1))

The messages contain the following (||denotes concatenation):

  • msg1 = IE || ENC(K1, IS) || T1 || ENC(K2, p1) || T2

Note that RS is shared in advance.

The handshake proceeds as follows:

  • Initiator sends msg1 to the Responder.
  • Responder verifies msg1, and aborts if it fails.
  • Responder checks Initiator's static key, and aborts if it fails.
  • The protocol is complete. The session key is H9.

NN

Sender and recipient have the following DH key pairs (private half in lower case, public half in upper case):

  • (ie, IE) Initiator's ephemeral key.
  • (re, RE) Responder's ephemeral key.

Those key pairs are used to derive the following shared secrets:

  • ee = DH(ie, RE) = DH(re, IE)

Those shared secrets are hashed to derive the following keys (zero is a string of zero bytes):

  • H0 = "Monokex NN" (ASCII, 32 bytes, zero padded)
  • H1 = KDF(H0, prelude) if there is a prelude, H0 otherwise
  • H2 = KDF(H1, IE)
  • H3 = KDF(H2, p1)
  • H4 = KDF(H3, RE)
  • H5 = KDF(H4, ee)
  • H6, K1 = ENC(H5, Zero)
  • H7, T1 = KDF(H6, ENC(K1, p2))

The messages contain the following (||denotes concatenation):

  • msg1 = IE || p1
  • msg2 = RE || ENC(K1, p2) || T1

To avoid network amplification attacks: the network packet containing msg1 should be as big as the network packet containing msg2 (and its payload). Pad msg1 with zeroes as necessary

The handshake proceeds as follows:

  • Initiator sends msg1 to the Responder.
  • Responder receives msg1.
  • Responder sends msg2 to the Initiator.
  • Initiator verifies msg2, and aborts if it fails.
  • The protocol is complete. The session key is H7.

NK

Sender and recipient have the following DH key pairs (private half in lower case, public half in upper case):

  • (ie, IE) Initiator's ephemeral key.
  • (rs, RS) Responder's static key.
  • (re, RE) Responder's ephemeral key.

Those key pairs are used to derive the following shared secrets:

  • es = DH(ie, RS) = DH(rs, IE)
  • ee = DH(ie, RE) = DH(re, IE)

Those shared secrets are hashed to derive the following keys (zero is a string of zero bytes):

  • H0 = "Monokex NK" (ASCII, 32 bytes, zero padded)
  • H1 = KDF(H0, RS)
  • H2 = KDF(H1, prelude) if there is a prelude, H1 otherwise
  • H3 = KDF(H2, IE)
  • H4 = KDF(H3, es)
  • H5, K1 = ENC(H4, Zero)
  • H6, T1 = KDF(H5, ENC(K1, p1))
  • H7, T2 = KDF(H6, RE)
  • H8 = KDF(H7, ee)
  • H9, K2 = ENC(H8, Zero)
  • H10, T3 = KDF(H9, ENC(K2, p2))

The messages contain the following (||denotes concatenation):

  • msg1 = IE || ENC(K1, p1) || T1
  • msg2 = RE || ENC(K2, p2) || T2

Note that RS is shared in advance.

To avoid network amplification attacks: the network packet containing msg1 should be as big as the network packet containing msg2 (and its payload). Pad msg1 with zeroes as necessary

The handshake proceeds as follows:

  • Initiator sends msg1 to the Responder.
  • Responder verifies msg1, and aborts if it fails.
  • Responder sends msg2 to the Initiator.
  • Initiator verifies msg2, and aborts if it fails.
  • The protocol is complete. The session key is H10.

NX

Sender and recipient have the following DH key pairs (private half in lower case, public half in upper case):

  • (ie, IE) Initiator's ephemeral key.
  • (rs, RS) Responder's static key.
  • (re, RE) Responder's ephemeral key.

Those key pairs are used to derive the following shared secrets:

  • ee = DH(ie, RE) = DH(re, IE)
  • es = DH(ie, RS) = DH(rs, IE)

Those shared secrets are hashed to derive the following keys (zero is a string of zero bytes):

  • H0 = "Monokex NX" (ASCII, 32 bytes, zero padded)
  • H1 = KDF(H0, prelude) if there is a prelude, H0 otherwise
  • H2 = KDF(H1, IE)
  • H3 = KDF(H2, p1)
  • H4 = KDF(H3, RE)
  • H5 = KDF(H4, ee)
  • H6, K1 = ENC(H5, Zero)
  • H7, T1 = KDF(H6, ENC(K1, RS))
  • H8 = KDF(H7, es)
  • H9, K2 = ENC(H8, Zero)
  • H10, T2 = KDF(H9, ENC(K2, p2))

The messages contain the following (||denotes concatenation):

  • msg1 = IE || p1
  • msg2 = RE || ENC(K1, RS) || T1 || ENC(K2, p2) || T2

To avoid network amplification attacks: the network packet containing msg1 should be as big as the network packet containing msg2 (and its payload). Pad msg1 with zeroes as necessary

The handshake proceeds as follows:

  • Initiator sends msg1 to the Responder.
  • Responder receives msg1.
  • Responder sends msg2 to the Initiator.
  • Initiator verifies msg2, and aborts if it fails.
  • Initiator checks Responder's static key, and aborts if it fails.
  • The protocol is complete. The session key is H10.

KN

Sender and recipient have the following DH key pairs (private half in lower case, public half in upper case):

  • (is, IS) Initiator's static key.
  • (ie, IE) Initiator's ephemeral key.
  • (re, RE) Responder's ephemeral key.

Those key pairs are used to derive the following shared secrets:

  • ee = DH(ie, RE) = DH(re, IE)
  • se = DH(is, RE) = DH(re, IS)

Those shared secrets are hashed to derive the following keys (zero is a string of zero bytes):

  • H0 = "Monokex KN" (ASCII, 32 bytes, zero padded)
  • H1 = KDF(H0, IS)
  • H2 = KDF(H1, prelude) if there is a prelude, H1 otherwise
  • H3 = KDF(H2, IE)
  • H4 = KDF(H3, p1)
  • H5 = KDF(H4, RE)
  • H6 = KDF(H5, ee)
  • H7 = KDF(H6, se)
  • H8, K1 = ENC(H7, Zero)
  • H9, T1 = KDF(H8, ENC(K1, p2))

The messages contain the following (||denotes concatenation):

  • msg1 = IE || p1
  • msg2 = RE || ENC(K1, p2) || T1

Note that IS is shared in advance.

To avoid network amplification attacks: the network packet containing msg1 should be as big as the network packet containing msg2 (and its payload). Pad msg1 with zeroes as necessary

The handshake proceeds as follows:

  • Initiator sends msg1 to the Responder.
  • Responder receives msg1.
  • Responder sends msg2 to the Initiator.
  • Initiator verifies msg2, and aborts if it fails.
  • The protocol is complete. The session key is H9.

KK

Sender and recipient have the following DH key pairs (private half in lower case, public half in upper case):

  • (is, IS) Initiator's static key.
  • (ie, IE) Initiator's ephemeral key.
  • (rs, RS) Responder's static key.
  • (re, RE) Responder's ephemeral key.

Those key pairs are used to derive the following shared secrets:

  • es = DH(ie, RS) = DH(rs, IE)
  • ss = DH(is, RS) = DH(rs, IS)
  • ee = DH(ie, RE) = DH(re, IE)
  • se = DH(is, RE) = DH(re, IS)

Those shared secrets are hashed to derive the following keys (zero is a string of zero bytes):

  • H0 = "Monokex KK" (ASCII, 32 bytes, zero padded)
  • H1 = KDF(H0 , IS)
  • H2 = KDF(H1 , RS)
  • H3 = KDF(H2 , prelude) if there is a prelude, H2 otherwise
  • H4 = KDF(H3 , IE)
  • H5 = KDF(H4 , es)
  • H6 = KDF(H5 , ss)
  • H7, K1 = ENC(H6 , Zero)
  • H8, T1 = KDF(H7 , ENC(K1, p1))
  • H9, T2 = KDF(H8 , RE)
  • H10 = KDF(H9 , ee)
  • H11 = KDF(H10, se)
  • H12, K2 = ENC(H11, Zero)
  • H13, T3 = KDF(H12, ENC(K2, p2))

The messages contain the following (||denotes concatenation):

  • msg1 = IE || ENC(K1, p1) || T1
  • msg2 = RE || ENC(K2, p2) || T2

Note that IS and RS are shared in advance.

To avoid network amplification attacks: the network packet containing msg1 should be as big as the network packet containing msg2 (and its payload). Pad msg1 with zeroes as necessary

The handshake proceeds as follows:

  • Initiator sends msg1 to the Responder.
  • Responder verifies msg1, and aborts if it fails.
  • Responder sends msg2 to the Initiator.
  • Initiator verifies msg2, and aborts if it fails.
  • The protocol is complete. The session key is H13.

KX

Sender and recipient have the following DH key pairs (private half in lower case, public half in upper case):

  • (is, IS) Initiator's static key.
  • (ie, IE) Initiator's ephemeral key.
  • (rs, RS) Responder's static key.
  • (re, RE) Responder's ephemeral key.

Those key pairs are used to derive the following shared secrets:

  • ee = DH(ie, RE) = DH(re, IE)
  • se = DH(is, RE) = DH(re, IS)
  • es = DH(ie, RS) = DH(rs, IE)

Those shared secrets are hashed to derive the following keys (zero is a string of zero bytes):

  • H0 = "Monokex KX" (ASCII, 32 bytes, zero padded)
  • H1 = KDF(H0 , IS)
  • H2 = KDF(H1 , prelude) if there is a prelude, H1 otherwise
  • H3 = KDF(H2 , IE)
  • H4 = KDF(H3 , p1)
  • H5 = KDF(H4 , RE)
  • H6 = KDF(H5 , ee)
  • H7 = KDF(H6 , se)
  • H8, K1 = ENC(H7 , Zero)
  • H9, T1 = KDF(H8 , ENC(K1, RS))
  • H10 = KDF(H9 , es)
  • H11, K2 = ENC(H10, Zero)
  • H12, T2 = KDF(H11, ENC(K2, p2))

The messages contain the following (||denotes concatenation):

  • msg1 = IE || p1
  • msg2 = RE || ENC(K1, RS) || T1 || ENC(K2, p2) || T2

Note that IS is shared in advance.

To avoid network amplification attacks: the network packet containing msg1 should be as big as the network packet containing msg2 (and its payload). Pad msg1 with zeroes as necessary

The handshake proceeds as follows:

  • Initiator sends msg1 to the Responder.
  • Responder receives msg1.
  • Responder sends msg2 to the Initiator.
  • Initiator verifies msg2, and aborts if it fails.
  • Initiator checks Responder's static key, and aborts if it fails.
  • The protocol is complete. The session key is H12.

XN

Sender and recipient have the following DH key pairs (private half in lower case, public half in upper case):

  • (is, IS) Initiator's static key.
  • (ie, IE) Initiator's ephemeral key.
  • (re, RE) Responder's ephemeral key.

Those key pairs are used to derive the following shared secrets:

  • ee = DH(ie, RE) = DH(re, IE)
  • se = DH(is, RE) = DH(re, IS)

Those shared secrets are hashed to derive the following keys (zero is a string of zero bytes):

  • H0 = "Monokex XN" (ASCII, 32 bytes, zero padded)
  • H1 = KDF(H0 , prelude) if there is a prelude, H0 otherwise
  • H2 = KDF(H1 , IE)
  • H3 = KDF(H2 , p1)
  • H4 = KDF(H3 , RE)
  • H5 = KDF(H4 , ee)
  • H6, K1 = ENC(H5 , Zero)
  • H7, T1 = KDF(H6 , ENC(K1, p2))
  • H8, K2 = ENC(H7 , Zero)
  • H9, T2 = KDF(H8 , ENC(K2, IS))
  • H10 = KDF(H9 , se)
  • H11, K3 = ENC(H10, Zero)
  • H12, T3 = KDF(H11, ENC(K3, p3))

The messages contain the following (||denotes concatenation):

  • msg1 = IE || p1
  • msg2 = RE || ENC(K1, p2) || T1
  • msg3 = ENC(K2, IS) || T2 || ENC(K3, p3) || T3

To avoid network amplification attacks: the network packet containing msg1 should be as big as the network packet containing msg2 (and its payload). Pad msg1 with zeroes as necessary

The handshake proceeds as follows:

  • Initiator sends msg1 to the Responder.
  • Responder receives msg1.
  • Responder sends msg2 to the Initiator.
  • Initiator verifies msg2, and aborts if it fails.
  • Initiator sends msg3 to the Responder.
  • Responder verifies msg3, and aborts if it fails.
  • Responder checks Initiator's static key, and aborts if it fails.
  • The protocol is complete. The session key is H12.

XK

Sender and recipient have the following DH key pairs (private half in lower case, public half in upper case):

  • (is, IS) Initiator's static key.
  • (ie, IE) Initiator's ephemeral key.
  • (rs, RS) Responder's static key.
  • (re, RE) Responder's ephemeral key.

Those key pairs are used to derive the following shared secrets:

  • es = DH(ie, RS) = DH(rs, IE)
  • ee = DH(ie, RE) = DH(re, IE)
  • se = DH(is, RE) = DH(re, IS)

Those shared secrets are hashed to derive the following keys (zero is a string of zero bytes):

  • H0 = "Monokex XK" (ASCII, 32 bytes, zero padded)
  • H1 = KDF(H0 , RS)
  • H2 = KDF(H1 , prelude) if there is a prelude, H1 otherwise
  • H3 = KDF(H2 , IE)
  • H4 = KDF(H3 , es)
  • H5, K1 = ENC(H4 , Zero)
  • H6, T1 = KDF(H5 , ENC(K1, p1))
  • H7, T2 = KDF(H6 , RE)
  • H8 = KDF(H7 , ee)
  • H9, K2 = ENC(H8 , Zero)
  • H10, T3 = KDF(H9 , ENC(K2, p2))
  • H11, K3 = ENC(H10, Zero)
  • H12, T4 = KDF(H11, ENC(K3, IS))
  • H13 = KDF(H12, se)
  • H14, K4 = ENC(H13, Zero)
  • H15, T5 = KDF(H14, ENC(K4, p3))

The messages contain the following (||denotes concatenation):

  • msg1 = IE || ENC(K1, p1) || T1
  • msg2 = RE || ENC(K2, p2) || T2
  • msg3 = ENC(K3, IS) || T3 || ENC(K4, p3) || T4

Note that RS is shared in advance.

To avoid network amplification attacks: the network packet containing msg1 should be as big as the network packet containing msg2 (and its payload). Pad msg1 with zeroes as necessary

The handshake proceeds as follows:

  • Initiator sends msg1 to the Responder.
  • Responder verifies msg1, and aborts if it fails.
  • Responder sends msg2 to the Initiator.
  • Initiator verifies msg2, and aborts if it fails.
  • Initiator sends msg3 to the Responder.
  • Responder verifies msg3, and aborts if it fails.
  • Responder checks Initiator's static key, and aborts if it fails.
  • The protocol is complete. The session key is H15.

XX

Sender and recipient have the following DH key pairs (private half in lower case, public half in upper case):

  • (is, IS) Initiator's static key.
  • (ie, IE) Initiator's ephemeral key.
  • (rs, RS) Responder's static key.
  • (re, RE) Responder's ephemeral key.

Those key pairs are used to derive the following shared secrets:

  • ee = DH(ie, RE) = DH(re, IE)
  • es = DH(ie, RS) = DH(rs, IE)
  • se = DH(is, RE) = DH(re, IS)

Those shared secrets are hashed to derive the following keys (zero is a string of zero bytes):

  • H0 = "Monokex XX" (ASCII, 32 bytes, zero padded)
  • H1 = KDF(H0 , prelude) if there is a prelude, H0 otherwise
  • H2 = KDF(H1 , IE)
  • H3 = KDF(H2 , p1)
  • H4 = KDF(H3 , RE)
  • H5 = KDF(H4 , ee)
  • H6, K1 = ENC(H5 , Zero)
  • H7, T1 = KDF(H6 , ENC(K1, RS))
  • H8 = KDF(H7 , es)
  • H9, K2 = ENC(H8 , Zero)
  • H10, T2 = KDF(H9 , ENC(K2, p2))
  • H11, K3 = ENC(H10, Zero)
  • H12, T3 = KDF(H11, ENC(K3, IS))
  • H13 = KDF(H12, se)
  • H14, K4 = ENC(H13, Zero)
  • H15, T4 = KDF(H14, ENC(K4, p3))

The messages contain the following (||denotes concatenation):

  • msg1 = IE || p1
  • msg2 = RE || ENC(K1, RS) || T1 || ENC(K2, p2) || T2
  • msg3 = ENC(K3, IS) || T3 || ENC(K4, p3) || T4

To avoid network amplification attacks: the network packet containing msg1 should be as big as the network packet containing msg2 (and its payload). Pad msg1 with zeroes as necessary

The handshake proceeds as follows:

  • Initiator sends msg1 to the Responder.
  • Responder receives msg1.
  • Responder sends msg2 to the Initiator.
  • Initiator verifies msg2, and aborts if it fails.
  • Initiator checks Responder's static key, and aborts if it fails.
  • Initiator sends msg3 to the Responder.
  • Responder verifies msg3, and aborts if it fails.
  • Responder checks Initiator's static key, and aborts if it fails.
  • The protocol is complete. The session key is H15.

IN

Sender and recipient have the following DH key pairs (private half in lower case, public half in upper case):

  • (is, IS) Initiator's static key.
  • (ie, IE) Initiator's ephemeral key.
  • (re, RE) Responder's ephemeral key.

Those key pairs are used to derive the following shared secrets:

  • ee = DH(ie, RE) = DH(re, IE)
  • se = DH(is, RE) = DH(re, IS)

Those shared secrets are hashed to derive the following keys (zero is a string of zero bytes):

  • H0 = "Monokex IN" (ASCII, 32 bytes, zero padded)
  • H1 = KDF(H0, prelude) if there is a prelude, H0 otherwise
  • H2 = KDF(H1, IE)
  • H3 = KDF(H2, IS)
  • H4 = KDF(H3, p1)
  • H5 = KDF(H4, RE)
  • H6 = KDF(H5, ee)
  • H7 = KDF(H6, se)
  • H8, K1 = ENC(H7, Zero)
  • H9, T1 = KDF(H8, ENC(K1, p2))

The messages contain the following (||denotes concatenation):

  • msg1 = IE || IS || p1
  • msg2 = RE || ENC(K1, p2) || T1

To avoid network amplification attacks: the network packet containing msg1 should be as big as the network packet containing msg2 (and its payload). Pad msg1 with zeroes as necessary

The handshake proceeds as follows:

  • Initiator sends msg1 to the Responder.
  • Responder receives msg1.
  • Responder checks Initiator's static key, and aborts if it fails.
  • Responder sends msg2 to the Initiator.
  • Initiator verifies msg2, and aborts if it fails.
  • The protocol is complete. The session key is H9.

IK

Sender and recipient have the following DH key pairs (private half in lower case, public half in upper case):

  • (is, IS) Initiator's static key.
  • (ie, IE) Initiator's ephemeral key.
  • (rs, RS) Responder's static key.
  • (re, RE) Responder's ephemeral key.

Those key pairs are used to derive the following shared secrets:

  • es = DH(ie, RS) = DH(rs, IE)
  • ss = DH(is, RS) = DH(rs, IS)
  • ee = DH(ie, RE) = DH(re, IE)
  • se = DH(is, RE) = DH(re, IS)

Those shared secrets are hashed to derive the following keys (zero is a string of zero bytes):

  • H0 = "Monokex IK" (ASCII, 32 bytes, zero padded)
  • H1 = KDF(H0 , RS)
  • H2 = KDF(H1 , prelude) if there is a prelude, H1 otherwise
  • H3 = KDF(H2 , IE)
  • H4 = KDF(H3 , es)
  • H5, K1 = ENC(H4 , Zero)
  • H6, T1 = KDF(H5 , ENC(K1, IS))
  • H7 = KDF(H6 , ss)
  • H8, K2 = ENC(H7 , Zero)
  • H9, T2 = KDF(H8 , ENC(K2, p1))
  • H10, T3 = KDF(H9 , RE)
  • H11 = KDF(H10, ee)
  • H12 = KDF(H11, se)
  • H13, K3 = ENC(H12, Zero)
  • H14, T4 = KDF(H13, ENC(K3, p2))

The messages contain the following (||denotes concatenation):

  • msg1 = IE || ENC(K1, IS) || T1 || ENC(K2, p1) || T2
  • msg2 = RE || ENC(K3, p2) || T3

Note that RS is shared in advance.

To avoid network amplification attacks: the network packet containing msg1 should be as big as the network packet containing msg2 (and its payload). Pad msg1 with zeroes as necessary

The handshake proceeds as follows:

  • Initiator sends msg1 to the Responder.
  • Responder verifies msg1, and aborts if it fails.
  • Responder checks Initiator's static key, and aborts if it fails.
  • Responder sends msg2 to the Initiator.
  • Initiator verifies msg2, and aborts if it fails.
  • The protocol is complete. The session key is H14.

IX

Sender and recipient have the following DH key pairs (private half in lower case, public half in upper case):

  • (is, IS) Initiator's static key.
  • (ie, IE) Initiator's ephemeral key.
  • (rs, RS) Responder's static key.
  • (re, RE) Responder's ephemeral key.

Those key pairs are used to derive the following shared secrets:

  • ee = DH(ie, RE) = DH(re, IE)
  • se = DH(is, RE) = DH(re, IS)
  • es = DH(ie, RS) = DH(rs, IE)

Those shared secrets are hashed to derive the following keys (zero is a string of zero bytes):

  • H0 = "Monokex IX" (ASCII, 32 bytes, zero padded)
  • H1 = KDF(H0 , prelude) if there is a prelude, H0 otherwise
  • H2 = KDF(H1 , IE)
  • H3 = KDF(H2 , IS)
  • H4 = KDF(H3 , p1)
  • H5 = KDF(H4 , RE)
  • H6 = KDF(H5 , ee)
  • H7 = KDF(H6 , se)
  • H8, K1 = ENC(H7 , Zero)
  • H9, T1 = KDF(H8 , ENC(K1, RS))
  • H10 = KDF(H9 , es)
  • H11, K2 = ENC(H10, Zero)
  • H12, T2 = KDF(H11, ENC(K2, p2))

The messages contain the following (||denotes concatenation):

  • msg1 = IE || IS || p1
  • msg2 = RE || ENC(K1, RS) || T1 || ENC(K2, p2) || T2

To avoid network amplification attacks: the network packet containing msg1 should be as big as the network packet containing msg2 (and its payload). Pad msg1 with zeroes as necessary

The handshake proceeds as follows:

  • Initiator sends msg1 to the Responder.
  • Responder receives msg1.
  • Responder checks Initiator's static key, and aborts if it fails.
  • Responder sends msg2 to the Initiator.
  • Initiator verifies msg2, and aborts if it fails.
  • Initiator checks Responder's static key, and aborts if it fails.
  • The protocol is complete. The session key is H12.

NK1

Sender and recipient have the following DH key pairs (private half in lower case, public half in upper case):

  • (ie, IE) Initiator's ephemeral key.
  • (rs, RS) Responder's static key.
  • (re, RE) Responder's ephemeral key.

Those key pairs are used to derive the following shared secrets:

  • ee = DH(ie, RE) = DH(re, IE)
  • es = DH(ie, RS) = DH(rs, IE)

Those shared secrets are hashed to derive the following keys (zero is a string of zero bytes):

  • H0 = "Monokex NK1" (ASCII, 32 bytes, zero padded)
  • H1 = KDF(H0, RS)
  • H2 = KDF(H1, prelude) if there is a prelude, H1 otherwise
  • H3 = KDF(H2, IE)
  • H4 = KDF(H3, p1)
  • H5 = KDF(H4, RE)
  • H6 = KDF(H5, ee)
  • H7 = KDF(H6, es)
  • H8, K1 = ENC(H7, Zero)
  • H9, T1 = KDF(H8, ENC(K1, p2))

The messages contain the following (||denotes concatenation):

  • msg1 = IE || p1
  • msg2 = RE || ENC(K1, p2) || T1

Note that RS is shared in advance.

To avoid network amplification attacks: the network packet containing msg1 should be as big as the network packet containing msg2 (and its payload). Pad msg1 with zeroes as necessary

The handshake proceeds as follows:

  • Initiator sends msg1 to the Responder.
  • Responder receives msg1.
  • Responder sends msg2 to the Initiator.
  • Initiator verifies msg2, and aborts if it fails.
  • The protocol is complete. The session key is H9.

NX1

Sender and recipient have the following DH key pairs (private half in lower case, public half in upper case):

  • (ie, IE) Initiator's ephemeral key.
  • (rs, RS) Responder's static key.
  • (re, RE) Responder's ephemeral key.

Those key pairs are used to derive the following shared secrets:

  • ee = DH(ie, RE) = DH(re, IE)
  • es = DH(ie, RS) = DH(rs, IE)

Those shared secrets are hashed to derive the following keys (zero is a string of zero bytes):

  • H0 = "Monokex NX1" (ASCII, 32 bytes, zero padded)
  • H1 = KDF(H0 , prelude) if there is a prelude, H0 otherwise
  • H2 = KDF(H1 , IE)
  • H3 = KDF(H2 , p1)
  • H4 = KDF(H3 , RE)
  • H5 = KDF(H4 , ee)
  • H6, K1 = ENC(H5 , Zero)
  • H7, T1 = KDF(H6 , ENC(K1, RS))
  • H8, K2 = ENC(H7 , Zero)
  • H9, T2 = KDF(H8 , ENC(K2, p2))
  • H10 = KDF(H9 , es)
  • H11, K3 = ENC(H10, Zero)
  • H12, T3 = KDF(H11, ENC(K3, p3))

The messages contain the following (||denotes concatenation):

  • msg1 = IE || p1
  • msg2 = RE || ENC(K1, RS) || T1 || ENC(K2, p2) || T2
  • msg3 = ENC(K3, p3) || T3

To avoid network amplification attacks: the network packet containing msg1 should be as big as the network packet containing msg2 (and its payload). Pad msg1 with zeroes as necessary

The handshake proceeds as follows:

  • Initiator sends msg1 to the Responder.
  • Responder receives msg1.
  • Responder sends msg2 to the Initiator.
  • Initiator verifies msg2, and aborts if it fails.
  • Initiator checks Responder's static key, and aborts if it fails.
  • Initiator sends msg3 to the Responder.
  • Responder verifies msg3, and aborts if it fails.
  • The protocol is complete. The session key is H12.

K1N

Sender and recipient have the following DH key pairs (private half in lower case, public half in upper case):

  • (is, IS) Initiator's static key.
  • (ie, IE) Initiator's ephemeral key.
  • (re, RE) Responder's ephemeral key.

Those key pairs are used to derive the following shared secrets:

  • ee = DH(ie, RE) = DH(re, IE)
  • se = DH(is, RE) = DH(re, IS)

Those shared secrets are hashed to derive the following keys (zero is a string of zero bytes):

  • H0 = "Monokex K1N" (ASCII, 32 bytes, zero padded)
  • H1 = KDF(H0 , IS)
  • H2 = KDF(H1 , prelude) if there is a prelude, H1 otherwise
  • H3 = KDF(H2 , IE)
  • H4 = KDF(H3 , p1)
  • H5 = KDF(H4 , RE)
  • H6 = KDF(H5 , ee)
  • H7, K1 = ENC(H6 , Zero)
  • H8, T1 = KDF(H7 , ENC(K1, p2))
  • H9 = KDF(H8 , se)
  • H10, K2 = ENC(H9 , Zero)
  • H11, T2 = KDF(H10, ENC(K2, p3))

The messages contain the following (||denotes concatenation):

  • msg1 = IE || p1
  • msg2 = RE || ENC(K1, p2) || T1
  • msg3 = ENC(K2, p3) || T2

Note that IS is shared in advance.

To avoid network amplification attacks: the network packet containing msg1 should be as big as the network packet containing msg2 (and its payload). Pad msg1 with zeroes as necessary

The handshake proceeds as follows:

  • Initiator sends msg1 to the Responder.
  • Responder receives msg1.
  • Responder sends msg2 to the Initiator.
  • Initiator verifies msg2, and aborts if it fails.
  • Initiator sends msg3 to the Responder.
  • Responder verifies msg3, and aborts if it fails.
  • The protocol is complete. The session key is H11.

K1K

Sender and recipient have the following DH key pairs (private half in lower case, public half in upper case):

  • (is, IS) Initiator's static key.
  • (ie, IE) Initiator's ephemeral key.
  • (rs, RS) Responder's static key.
  • (re, RE) Responder's ephemeral key.

Those key pairs are used to derive the following shared secrets:

  • es = DH(ie, RS) = DH(rs, IE)
  • ee = DH(ie, RE) = DH(re, IE)
  • se = DH(is, RE) = DH(re, IS)

Those shared secrets are hashed to derive the following keys (zero is a string of zero bytes):

  • H0 = "Monokex K1K" (ASCII, 32 bytes, zero padded)
  • H1 = KDF(H0 , IS)
  • H2 = KDF(H1 , RS)
  • H3 = KDF(H2 , prelude) if there is a prelude, H2 otherwise
  • H4 = KDF(H3 , IE)
  • H5 = KDF(H4 , es)
  • H6, K1 = ENC(H5 , Zero)
  • H7, T1 = KDF(H6 , ENC(K1, p1))
  • H8, T2 = KDF(H7 , RE)
  • H9 = KDF(H8 , ee)
  • H10, K2 = ENC(H9 , Zero)
  • H11, T3 = KDF(H10, ENC(K2, p2))
  • H12 = KDF(H11, se)
  • H13, K3 = ENC(H12, Zero)
  • H14, T4 = KDF(H13, ENC(K3, p3))

The messages contain the following (||denotes concatenation):

  • msg1 = IE || ENC(K1, p1) || T1
  • msg2 = RE || ENC(K2, p2) || T2
  • msg3 = ENC(K3, p3) || T3

Note that IS and RS are shared in advance.

To avoid network amplification attacks: the network packet containing msg1 should be as big as the network packet containing msg2 (and its payload). Pad msg1 with zeroes as necessary

The handshake proceeds as follows:

  • Initiator sends msg1 to the Responder.
  • Responder verifies msg1, and aborts if it fails.
  • Responder sends msg2 to the Initiator.
  • Initiator verifies msg2, and aborts if it fails.
  • Initiator sends msg3 to the Responder.
  • Responder verifies msg3, and aborts if it fails.
  • The protocol is complete. The session key is H14.

KK1

Sender and recipient have the following DH key pairs (private half in lower case, public half in upper case):

  • (is, IS) Initiator's static key.
  • (ie, IE) Initiator's ephemeral key.
  • (rs, RS) Responder's static key.
  • (re, RE) Responder's ephemeral key.

Those key pairs are used to derive the following shared secrets:

  • ee = DH(ie, RE) = DH(re, IE)
  • se = DH(is, RE) = DH(re, IS)
  • es = DH(ie, RS) = DH(rs, IE)

Those shared secrets are hashed to derive the following keys (zero is a string of zero bytes):

  • H0 = "Monokex KK1" (ASCII, 32 bytes, zero padded)
  • H1 = KDF(H0 , IS)
  • H2 = KDF(H1 , RS)
  • H3 = KDF(H2 , prelude) if there is a prelude, H2 otherwise
  • H4 = KDF(H3 , IE)
  • H5 = KDF(H4 , p1)
  • H6 = KDF(H5 , RE)
  • H7 = KDF(H6 , ee)
  • H8 = KDF(H7 , se)
  • H9 = KDF(H8 , es)
  • H10, K1 = ENC(H9 , Zero)
  • H11, T1 = KDF(H10, ENC(K1, p2))

The messages contain the following (||denotes concatenation):

  • msg1 = IE || p1
  • msg2 = RE || ENC(K1, p2) || T1

Note that IS and RS are shared in advance.

To avoid network amplification attacks: the network packet containing msg1 should be as big as the network packet containing msg2 (and its payload). Pad msg1 with zeroes as necessary

The handshake proceeds as follows:

  • Initiator sends msg1 to the Responder.
  • Responder receives msg1.
  • Responder sends msg2 to the Initiator.
  • Initiator verifies msg2, and aborts if it fails.
  • The protocol is complete. The session key is H11.

K1K1

Sender and recipient have the following DH key pairs (private half in lower case, public half in upper case):

  • (is, IS) Initiator's static key.
  • (ie, IE) Initiator's ephemeral key.
  • (rs, RS) Responder's static key.
  • (re, RE) Responder's ephemeral key.

Those key pairs are used to derive the following shared secrets:

  • ee = DH(ie, RE) = DH(re, IE)
  • es = DH(ie, RS) = DH(rs, IE)
  • se = DH(is, RE) = DH(re, IS)

Those shared secrets are hashed to derive the following keys (zero is a string of zero bytes):

  • H0 = "Monokex K1K1" (ASCII, 32 bytes, zero padded)
  • H1 = KDF(H0 , IS)
  • H2 = KDF(H1 , RS)
  • H3 = KDF(H2 , prelude) if there is a prelude, H2 otherwise
  • H4 = KDF(H3 , IE)
  • H5 = KDF(H4 , p1)
  • H6 = KDF(H5 , RE)
  • H7 = KDF(H6 , ee)
  • H8 = KDF(H7 , es)
  • H9, K1 = ENC(H8 , Zero)
  • H10, T1 = KDF(H9 , ENC(K1, p2))
  • H11 = KDF(H10, se)
  • H12, K2 = ENC(H11, Zero)
  • H13, T2 = KDF(H12, ENC(K2, p3))

The messages contain the following (||denotes concatenation):

  • msg1 = IE || p1
  • msg2 = RE || ENC(K1, p2) || T1
  • msg3 = ENC(K2, p3) || T2

Note that IS and RS are shared in advance.

To avoid network amplification attacks: the network packet containing msg1 should be as big as the network packet containing msg2 (and its payload). Pad msg1 with zeroes as necessary

The handshake proceeds as follows:

  • Initiator sends msg1 to the Responder.
  • Responder receives msg1.
  • Responder sends msg2 to the Initiator.
  • Initiator verifies msg2, and aborts if it fails.
  • Initiator sends msg3 to the Responder.
  • Responder verifies msg3, and aborts if it fails.
  • The protocol is complete. The session key is H13.

K1X

Sender and recipient have the following DH key pairs (private half in lower case, public half in upper case):

  • (is, IS) Initiator's static key.
  • (ie, IE) Initiator's ephemeral key.
  • (rs, RS) Responder's static key.
  • (re, RE) Responder's ephemeral key.

Those key pairs are used to derive the following shared secrets:

  • ee = DH(ie, RE) = DH(re, IE)
  • es = DH(ie, RS) = DH(rs, IE)
  • se = DH(is, RE) = DH(re, IS)

Those shared secrets are hashed to derive the following keys (zero is a string of zero bytes):

  • H0 = "Monokex K1X" (ASCII, 32 bytes, zero padded)
  • H1 = KDF(H0 , IS)
  • H2 = KDF(H1 , prelude) if there is a prelude, H1 otherwise
  • H3 = KDF(H2 , IE)
  • H4 = KDF(H3 , p1)
  • H5 = KDF(H4 , RE)
  • H6 = KDF(H5 , ee)
  • H7, K1 = ENC(H6 , Zero)
  • H8, T1 = KDF(H7 , ENC(K1, RS))
  • H9 = KDF(H8 , es)
  • H10, K2 = ENC(H9 , Zero)
  • H11, T2 = KDF(H10, ENC(K2, p2))
  • H12 = KDF(H11, se)
  • H13, K3 = ENC(H12, Zero)
  • H14, T3 = KDF(H13, ENC(K3, p3))

The messages contain the following (||denotes concatenation):

  • msg1 = IE || p1
  • msg2 = RE || ENC(K1, RS) || T1 || ENC(K2, p2) || T2
  • msg3 = ENC(K3, p3) || T3

Note that IS is shared in advance.

To avoid network amplification attacks: the network packet containing msg1 should be as big as the network packet containing msg2 (and its payload). Pad msg1 with zeroes as necessary

The handshake proceeds as follows:

  • Initiator sends msg1 to the Responder.
  • Responder receives msg1.
  • Responder sends msg2 to the Initiator.
  • Initiator verifies msg2, and aborts if it fails.
  • Initiator checks Responder's static key, and aborts if it fails.
  • Initiator sends msg3 to the Responder.
  • Responder verifies msg3, and aborts if it fails.
  • The protocol is complete. The session key is H14.

KX1

Sender and recipient have the following DH key pairs (private half in lower case, public half in upper case):

  • (is, IS) Initiator's static key.
  • (ie, IE) Initiator's ephemeral key.
  • (rs, RS) Responder's static key.
  • (re, RE) Responder's ephemeral key.

Those key pairs are used to derive the following shared secrets:

  • ee = DH(ie, RE) = DH(re, IE)
  • se = DH(is, RE) = DH(re, IS)
  • es = DH(ie, RS) = DH(rs, IE)

Those shared secrets are hashed to derive the following keys (zero is a string of zero bytes):

  • H0 = "Monokex KX1" (ASCII, 32 bytes, zero padded)
  • H1 = KDF(H0 , IS)
  • H2 = KDF(H1 , prelude) if there is a prelude, H1 otherwise
  • H3 = KDF(H2 , IE)
  • H4 = KDF(H3 , p1)
  • H5 = KDF(H4 , RE)
  • H6 = KDF(H5 , ee)
  • H7 = KDF(H6 , se)
  • H8, K1 = ENC(H7 , Zero)
  • H9, T1 = KDF(H8 , ENC(K1, RS))
  • H10, K2 = ENC(H9 , Zero)
  • H11, T2 = KDF(H10, ENC(K2, p2))
  • H12 = KDF(H11, es)
  • H13, K3 = ENC(H12, Zero)
  • H14, T3 = KDF(H13, ENC(K3, p3))

The messages contain the following (||denotes concatenation):

  • msg1 = IE || p1
  • msg2 = RE || ENC(K1, RS) || T1 || ENC(K2, p2) || T2
  • msg3 = ENC(K3, p3) || T3

Note that IS is shared in advance.

To avoid network amplification attacks: the network packet containing msg1 should be as big as the network packet containing msg2 (and its payload). Pad msg1 with zeroes as necessary

The handshake proceeds as follows:

  • Initiator sends msg1 to the Responder.
  • Responder receives msg1.
  • Responder sends msg2 to the Initiator.
  • Initiator verifies msg2, and aborts if it fails.
  • Initiator checks Responder's static key, and aborts if it fails.
  • Initiator sends msg3 to the Responder.
  • Responder verifies msg3, and aborts if it fails.
  • The protocol is complete. The session key is H14.

K1X1

Sender and recipient have the following DH key pairs (private half in lower case, public half in upper case):

  • (is, IS) Initiator's static key.
  • (ie, IE) Initiator's ephemeral key.
  • (rs, RS) Responder's static key.
  • (re, RE) Responder's ephemeral key.

Those key pairs are used to derive the following shared secrets:

  • ee = DH(ie, RE) = DH(re, IE)
  • se = DH(is, RE) = DH(re, IS)
  • es = DH(ie, RS) = DH(rs, IE)

Those shared secrets are hashed to derive the following keys (zero is a string of zero bytes):

  • H0 = "Monokex K1X1" (ASCII, 32 bytes, zero padded)
  • H1 = KDF(H0 , IS)
  • H2 = KDF(H1 , prelude) if there is a prelude, H1 otherwise
  • H3 = KDF(H2 , IE)
  • H4 = KDF(H3 , p1)
  • H5 = KDF(H4 , RE)
  • H6 = KDF(H5 , ee)
  • H7, K1 = ENC(H6 , Zero)
  • H8, T1 = KDF(H7 , ENC(K1, RS))
  • H9, K2 = ENC(H8 , Zero)
  • H10, T2 = KDF(H9 , ENC(K2, p2))
  • H11 = KDF(H10, se)
  • H12 = KDF(H11, es)
  • H13, K3 = ENC(H12, Zero)
  • H14, T3 = KDF(H13, ENC(K3, p3))

The messages contain the following (||denotes concatenation):

  • msg1 = IE || p1
  • msg2 = RE || ENC(K1, RS) || T1 || ENC(K2, p2) || T2
  • msg3 = ENC(K3, p3) || T3

Note that IS is shared in advance.

To avoid network amplification attacks: the network packet containing msg1 should be as big as the network packet containing msg2 (and its payload). Pad msg1 with zeroes as necessary

The handshake proceeds as follows:

  • Initiator sends msg1 to the Responder.
  • Responder receives msg1.
  • Responder sends msg2 to the Initiator.
  • Initiator verifies msg2, and aborts if it fails.
  • Initiator checks Responder's static key, and aborts if it fails.
  • Initiator sends msg3 to the Responder.
  • Responder verifies msg3, and aborts if it fails.
  • The protocol is complete. The session key is H14.

X1N

Sender and recipient have the following DH key pairs (private half in lower case, public half in upper case):

  • (is, IS) Initiator's static key.
  • (ie, IE) Initiator's ephemeral key.
  • (re, RE) Responder's ephemeral key.

Those key pairs are used to derive the following shared secrets:

  • ee = DH(ie, RE) = DH(re, IE)
  • se = DH(is, RE) = DH(re, IS)

Those shared secrets are hashed to derive the following keys (zero is a string of zero bytes):

  • H0 = "Monokex X1N" (ASCII, 32 bytes, zero padded)
  • H1 = KDF(H0 , prelude) if there is a prelude, H0 otherwise
  • H2 = KDF(H1 , IE)
  • H3 = KDF(H2 , p1)
  • H4 = KDF(H3 , RE)
  • H5 = KDF(H4 , ee)
  • H6, K1 = ENC(H5 , Zero)
  • H7, T1 = KDF(H6 , ENC(K1, p2))
  • H8, K2 = ENC(H7 , Zero)
  • H9, T2 = KDF(H8 , ENC(K2, IS))
  • H10, K3 = ENC(H9 , Zero)
  • H11, T3 = KDF(H10, ENC(K3, p3))
  • H12 = KDF(H11, se)
  • H13, K4 = ENC(H12, Zero)
  • H14, T4 = KDF(H13, ENC(K4, p4))

The messages contain the following (||denotes concatenation):

  • msg1 = IE || p1
  • msg2 = RE || ENC(K1, p2) || T1
  • msg3 = ENC(K2, IS) || T2 || ENC(K3, p3) || T3
  • msg4 = ENC(K4, p4) || T4

To avoid network amplification attacks: the network packet containing msg1 should be as big as the network packet containing msg2 (and its payload). Pad msg1 with zeroes as necessary

The handshake proceeds as follows:

  • Initiator sends msg1 to the Responder.
  • Responder receives msg1.
  • Responder sends msg2 to the Initiator.
  • Initiator verifies msg2, and aborts if it fails.
  • Initiator sends msg3 to the Responder.
  • Responder verifies msg3, and aborts if it fails.
  • Responder checks Initiator's static key, and aborts if it fails.
  • Responder sends msg4 to the Initiator.
  • Initiator verifies msg4, and aborts if it fails.
  • The protocol is complete. The session key is H14.

X1K

Sender and recipient have the following DH key pairs (private half in lower case, public half in upper case):

  • (is, IS) Initiator's static key.
  • (ie, IE) Initiator's ephemeral key.
  • (rs, RS) Responder's static key.
  • (re, RE) Responder's ephemeral key.

Those key pairs are used to derive the following shared secrets:

  • es = DH(ie, RS) = DH(rs, IE)
  • ee = DH(ie, RE) = DH(re, IE)
  • se = DH(is, RE) = DH(re, IS)

Those shared secrets are hashed to derive the following keys (zero is a string of zero bytes):

  • H0 = "Monokex X1K" (ASCII, 32 bytes, zero padded)
  • H1 = KDF(H0 , RS)
  • H2 = KDF(H1 , prelude) if there is a prelude, H1 otherwise
  • H3 = KDF(H2 , IE)
  • H4 = KDF(H3 , es)
  • H5, K1 = ENC(H4 , Zero)
  • H6, T1 = KDF(H5 , ENC(K1, p1))
  • H7, T2 = KDF(H6 , RE)
  • H8 = KDF(H7 , ee)
  • H9, K2 = ENC(H8 , Zero)
  • H10, T3 = KDF(H9 , ENC(K2, p2))
  • H11, K3 = ENC(H10, Zero)
  • H12, T4 = KDF(H11, ENC(K3, IS))
  • H13, K4 = ENC(H12, Zero)
  • H14, T5 = KDF(H13, ENC(K4, p3))
  • H15 = KDF(H14, se)
  • H16, K5 = ENC(H15, Zero)
  • H17, T6 = KDF(H16, ENC(K5, p4))

The messages contain the following (||denotes concatenation):

  • msg1 = IE || ENC(K1, p1) || T1
  • msg2 = RE || ENC(K2, p2) || T2
  • msg3 = ENC(K3, IS) || T3 || ENC(K4, p3) || T4
  • msg4 = ENC(K5, p4) || T5

Note that RS is shared in advance.

To avoid network amplification attacks: the network packet containing msg1 should be as big as the network packet containing msg2 (and its payload). Pad msg1 with zeroes as necessary

The handshake proceeds as follows:

  • Initiator sends msg1 to the Responder.
  • Responder verifies msg1, and aborts if it fails.
  • Responder sends msg2 to the Initiator.
  • Initiator verifies msg2, and aborts if it fails.
  • Initiator sends msg3 to the Responder.
  • Responder verifies msg3, and aborts if it fails.
  • Responder checks Initiator's static key, and aborts if it fails.
  • Responder sends msg4 to the Initiator.
  • Initiator verifies msg4, and aborts if it fails.
  • The protocol is complete. The session key is H17.

XK1

Sender and recipient have the following DH key pairs (private half in lower case, public half in upper case):

  • (is, IS) Initiator's static key.
  • (ie, IE) Initiator's ephemeral key.
  • (rs, RS) Responder's static key.
  • (re, RE) Responder's ephemeral key.

Those key pairs are used to derive the following shared secrets:

  • ee = DH(ie, RE) = DH(re, IE)
  • es = DH(ie, RS) = DH(rs, IE)
  • se = DH(is, RE) = DH(re, IS)

Those shared secrets are hashed to derive the following keys (zero is a string of zero bytes):

  • H0 = "Monokex XK1" (ASCII, 32 bytes, zero padded)
  • H1 = KDF(H0 , RS)
  • H2 = KDF(H1 , prelude) if there is a prelude, H1 otherwise
  • H3 = KDF(H2 , IE)
  • H4 = KDF(H3 , p1)
  • H5 = KDF(H4 , RE)
  • H6 = KDF(H5 , ee)
  • H7 = KDF(H6 , es)
  • H8, K1 = ENC(H7 , Zero)
  • H9, T1 = KDF(H8 , ENC(K1, p2))
  • H10, K2 = ENC(H9 , Zero)
  • H11, T2 = KDF(H10, ENC(K2, IS))
  • H12 = KDF(H11, se)
  • H13, K3 = ENC(H12, Zero)
  • H14, T3 = KDF(H13, ENC(K3, p3))

The messages contain the following (||denotes concatenation):

  • msg1 = IE || p1
  • msg2 = RE || ENC(K1, p2) || T1
  • msg3 = ENC(K2, IS) || T2 || ENC(K3, p3) || T3

Note that RS is shared in advance.

To avoid network amplification attacks: the network packet containing msg1 should be as big as the network packet containing msg2 (and its payload). Pad msg1 with zeroes as necessary

The handshake proceeds as follows:

  • Initiator sends msg1 to the Responder.
  • Responder receives msg1.
  • Responder sends msg2 to the Initiator.
  • Initiator verifies msg2, and aborts if it fails.
  • Initiator sends msg3 to the Responder.
  • Responder verifies msg3, and aborts if it fails.
  • Responder checks Initiator's static key, and aborts if it fails.
  • The protocol is complete. The session key is H14.

X1K1

Sender and recipient have the following DH key pairs (private half in lower case, public half in upper case):

  • (is, IS) Initiator's static key.
  • (ie, IE) Initiator's ephemeral key.
  • (rs, RS) Responder's static key.
  • (re, RE) Responder's ephemeral key.

Those key pairs are used to derive the following shared secrets:

  • ee = DH(ie, RE) = DH(re, IE)
  • es = DH(ie, RS) = DH(rs, IE)
  • se = DH(is, RE) = DH(re, IS)

Those shared secrets are hashed to derive the following keys (zero is a string of zero bytes):

  • H0 = "Monokex X1K1" (ASCII, 32 bytes, zero padded)
  • H1 = KDF(H0 , RS)
  • H2 = KDF(H1 , prelude) if there is a prelude, H1 otherwise
  • H3 = KDF(H2 , IE)
  • H4 = KDF(H3 , p1)
  • H5 = KDF(H4 , RE)
  • H6 = KDF(H5 , ee)
  • H7 = KDF(H6 , es)
  • H8, K1 = ENC(H7 , Zero)
  • H9, T1 = KDF(H8 , ENC(K1, p2))
  • H10, K2 = ENC(H9 , Zero)
  • H11, T2 = KDF(H10, ENC(K2, IS))
  • H12, K3 = ENC(H11, Zero)
  • H13, T3 = KDF(H12, ENC(K3, p3))
  • H14 = KDF(H13, se)
  • H15, K4 = ENC(H14, Zero)
  • H16, T4 = KDF(H15, ENC(K4, p4))

The messages contain the following (||denotes concatenation):

  • msg1 = IE || p1
  • msg2 = RE || ENC(K1, p2) || T1
  • msg3 = ENC(K2, IS) || T2 || ENC(K3, p3) || T3
  • msg4 = ENC(K4, p4) || T4

Note that RS is shared in advance.

To avoid network amplification attacks: the network packet containing msg1 should be as big as the network packet containing msg2 (and its payload). Pad msg1 with zeroes as necessary

The handshake proceeds as follows:

  • Initiator sends msg1 to the Responder.
  • Responder receives msg1.
  • Responder sends msg2 to the Initiator.
  • Initiator verifies msg2, and aborts if it fails.
  • Initiator sends msg3 to the Responder.
  • Responder verifies msg3, and aborts if it fails.
  • Responder checks Initiator's static key, and aborts if it fails.
  • Responder sends msg4 to the Initiator.
  • Initiator verifies msg4, and aborts if it fails.
  • The protocol is complete. The session key is H16.

X1X

Sender and recipient have the following DH key pairs (private half in lower case, public half in upper case):

  • (is, IS) Initiator's static key.
  • (ie, IE) Initiator's ephemeral key.
  • (rs, RS) Responder's static key.
  • (re, RE) Responder's ephemeral key.

Those key pairs are used to derive the following shared secrets:

  • ee = DH(ie, RE) = DH(re, IE)
  • es = DH(ie, RS) = DH(rs, IE)
  • se = DH(is, RE) = DH(re, IS)

Those shared secrets are hashed to derive the following keys (zero is a string of zero bytes):

  • H0 = "Monokex X1X" (ASCII, 32 bytes, zero padded)
  • H1 = KDF(H0 , prelude) if there is a prelude, H0 otherwise
  • H2 = KDF(H1 , IE)
  • H3 = KDF(H2 , p1)
  • H4 = KDF(H3 , RE)
  • H5 = KDF(H4 , ee)
  • H6, K1 = ENC(H5 , Zero)
  • H7, T1 = KDF(H6 , ENC(K1, RS))
  • H8 = KDF(H7 , es)
  • H9, K2 = ENC(H8 , Zero)
  • H10, T2 = KDF(H9 , ENC(K2, p2))
  • H11, K3 = ENC(H10, Zero)
  • H12, T3 = KDF(H11, ENC(K3, IS))
  • H13, K4 = ENC(H12, Zero)
  • H14, T4 = KDF(H13, ENC(K4, p3))
  • H15 = KDF(H14, se)
  • H16, K5 = ENC(H15, Zero)
  • H17, T5 = KDF(H16, ENC(K5, p4))

The messages contain the following (||denotes concatenation):

  • msg1 = IE || p1
  • msg2 = RE || ENC(K1, RS) || T1 || ENC(K2, p2) || T2
  • msg3 = ENC(K3, IS) || T3 || ENC(K4, p3) || T4
  • msg4 = ENC(K5, p4) || T5

To avoid network amplification attacks: the network packet containing msg1 should be as big as the network packet containing msg2 (and its payload). Pad msg1 with zeroes as necessary

The handshake proceeds as follows:

  • Initiator sends msg1 to the Responder.
  • Responder receives msg1.
  • Responder sends msg2 to the Initiator.
  • Initiator verifies msg2, and aborts if it fails.
  • Initiator checks Responder's static key, and aborts if it fails.
  • Initiator sends msg3 to the Responder.
  • Responder verifies msg3, and aborts if it fails.
  • Responder checks Initiator's static key, and aborts if it fails.
  • Responder sends msg4 to the Initiator.
  • Initiator verifies msg4, and aborts if it fails.
  • The protocol is complete. The session key is H17.

XX1

Sender and recipient have the following DH key pairs (private half in lower case, public half in upper case):

  • (is, IS) Initiator's static key.
  • (ie, IE) Initiator's ephemeral key.
  • (rs, RS) Responder's static key.
  • (re, RE) Responder's ephemeral key.

Those key pairs are used to derive the following shared secrets:

  • ee = DH(ie, RE) = DH(re, IE)
  • es = DH(ie, RS) = DH(rs, IE)
  • se = DH(is, RE) = DH(re, IS)

Those shared secrets are hashed to derive the following keys (zero is a string of zero bytes):

  • H0 = "Monokex XX1" (ASCII, 32 bytes, zero padded)
  • H1 = KDF(H0 , prelude) if there is a prelude, H0 otherwise
  • H2 = KDF(H1 , IE)
  • H3 = KDF(H2 , p1)
  • H4 = KDF(H3 , RE)
  • H5 = KDF(H4 , ee)
  • H6, K1 = ENC(H5 , Zero)
  • H7, T1 = KDF(H6 , ENC(K1, RS))
  • H8, K2 = ENC(H7 , Zero)
  • H9, T2 = KDF(H8 , ENC(K2, p2))
  • H10 = KDF(H9 , es)
  • H11, K3 = ENC(H10, Zero)
  • H12, T3 = KDF(H11, ENC(K3, IS))
  • H13 = KDF(H12, se)
  • H14, K4 = ENC(H13, Zero)
  • H15, T4 = KDF(H14, ENC(K4, p3))

The messages contain the following (||denotes concatenation):

  • msg1 = IE || p1
  • msg2 = RE || ENC(K1, RS) || T1 || ENC(K2, p2) || T2
  • msg3 = ENC(K3, IS) || T3 || ENC(K4, p3) || T4

To avoid network amplification attacks: the network packet containing msg1 should be as big as the network packet containing msg2 (and its payload). Pad msg1 with zeroes as necessary

The handshake proceeds as follows:

  • Initiator sends msg1 to the Responder.
  • Responder receives msg1.
  • Responder sends msg2 to the Initiator.
  • Initiator verifies msg2, and aborts if it fails.
  • Initiator checks Responder's static key, and aborts if it fails.
  • Initiator sends msg3 to the Responder.
  • Responder verifies msg3, and aborts if it fails.
  • Responder checks Initiator's static key, and aborts if it fails.
  • The protocol is complete. The session key is H15.

X1X1

Sender and recipient have the following DH key pairs (private half in lower case, public half in upper case):

  • (is, IS) Initiator's static key.
  • (ie, IE) Initiator's ephemeral key.
  • (rs, RS) Responder's static key.
  • (re, RE) Responder's ephemeral key.

Those key pairs are used to derive the following shared secrets:

  • ee = DH(ie, RE) = DH(re, IE)
  • es = DH(ie, RS) = DH(rs, IE)
  • se = DH(is, RE) = DH(re, IS)

Those shared secrets are hashed to derive the following keys (zero is a string of zero bytes):

  • H0 = "Monokex X1X1" (ASCII, 32 bytes, zero padded)
  • H1 = KDF(H0 , prelude) if there is a prelude, H0 otherwise
  • H2 = KDF(H1 , IE)
  • H3 = KDF(H2 , p1)
  • H4 = KDF(H3 , RE)
  • H5 = KDF(H4 , ee)
  • H6, K1 = ENC(H5 , Zero)
  • H7, T1 = KDF(H6 , ENC(K1, RS))
  • H8, K2 = ENC(H7 , Zero)
  • H9, T2 = KDF(H8 , ENC(K2, p2))
  • H10 = KDF(H9 , es)
  • H11, K3 = ENC(H10, Zero)
  • H12, T3 = KDF(H11, ENC(K3, IS))
  • H13, K4 = ENC(H12, Zero)
  • H14, T4 = KDF(H13, ENC(K4, p3))
  • H15 = KDF(H14, se)
  • H16, K5 = ENC(H15, Zero)
  • H17, T5 = KDF(H16, ENC(K5, p4))

The messages contain the following (||denotes concatenation):

  • msg1 = IE || p1
  • msg2 = RE || ENC(K1, RS) || T1 || ENC(K2, p2) || T2
  • msg3 = ENC(K3, IS) || T3 || ENC(K4, p3) || T4
  • msg4 = ENC(K5, p4) || T5

To avoid network amplification attacks: the network packet containing msg1 should be as big as the network packet containing msg2 (and its payload). Pad msg1 with zeroes as necessary

The handshake proceeds as follows:

  • Initiator sends msg1 to the Responder.
  • Responder receives msg1.
  • Responder sends msg2 to the Initiator.
  • Initiator verifies msg2, and aborts if it fails.
  • Initiator checks Responder's static key, and aborts if it fails.
  • Initiator sends msg3 to the Responder.
  • Responder verifies msg3, and aborts if it fails.
  • Responder checks Initiator's static key, and aborts if it fails.
  • Responder sends msg4 to the Initiator.
  • Initiator verifies msg4, and aborts if it fails.
  • The protocol is complete. The session key is H17.

I1N

Sender and recipient have the following DH key pairs (private half in lower case, public half in upper case):

  • (is, IS) Initiator's static key.
  • (ie, IE) Initiator's ephemeral key.
  • (re, RE) Responder's ephemeral key.

Those key pairs are used to derive the following shared secrets:

  • ee = DH(ie, RE) = DH(re, IE)
  • se = DH(is, RE) = DH(re, IS)

Those shared secrets are hashed to derive the following keys (zero is a string of zero bytes):

  • H0 = "Monokex I1N" (ASCII, 32 bytes, zero padded)
  • H1 = KDF(H0 , prelude) if there is a prelude, H0 otherwise
  • H2 = KDF(H1 , IE)
  • H3 = KDF(H2 , IS)
  • H4 = KDF(H3 , p1)
  • H5 = KDF(H4 , RE)
  • H6 = KDF(H5 , ee)
  • H7, K1 = ENC(H6 , Zero)
  • H8, T1 = KDF(H7 , ENC(K1, p2))
  • H9 = KDF(H8 , se)
  • H10, K2 = ENC(H9 , Zero)
  • H11, T2 = KDF(H10, ENC(K2, p3))

The messages contain the following (||denotes concatenation):

  • msg1 = IE || IS || p1
  • msg2 = RE || ENC(K1, p2) || T1
  • msg3 = ENC(K2, p3) || T2

To avoid network amplification attacks: the network packet containing msg1 should be as big as the network packet containing msg2 (and its payload). Pad msg1 with zeroes as necessary

The handshake proceeds as follows:

  • Initiator sends msg1 to the Responder.
  • Responder receives msg1.
  • Responder checks Initiator's static key, and aborts if it fails.
  • Responder sends msg2 to the Initiator.
  • Initiator verifies msg2, and aborts if it fails.
  • Initiator sends msg3 to the Responder.
  • Responder verifies msg3, and aborts if it fails.
  • The protocol is complete. The session key is H11.

I1K

Sender and recipient have the following DH key pairs (private half in lower case, public half in upper case):

  • (is, IS) Initiator's static key.
  • (ie, IE) Initiator's ephemeral key.
  • (rs, RS) Responder's static key.
  • (re, RE) Responder's ephemeral key.

Those key pairs are used to derive the following shared secrets:

  • es = DH(ie, RS) = DH(rs, IE)
  • ee = DH(ie, RE) = DH(re, IE)
  • se = DH(is, RE) = DH(re, IS)

Those shared secrets are hashed to derive the following keys (zero is a string of zero bytes):

  • H0 = "Monokex I1K" (ASCII, 32 bytes, zero padded)
  • H1 = KDF(H0 , RS)
  • H2 = KDF(H1 , prelude) if there is a prelude, H1 otherwise
  • H3 = KDF(H2 , IE)
  • H4 = KDF(H3 , es)
  • H5, K1 = ENC(H4 , Zero)
  • H6, T1 = KDF(H5 , ENC(K1, IS))
  • H7, K2 = ENC(H6 , Zero)
  • H8, T2 = KDF(H7 , ENC(K2, p1))
  • H9, T3 = KDF(H8 , RE)
  • H10 = KDF(H9 , ee)
  • H11, K3 = ENC(H10, Zero)
  • H12, T4 = KDF(H11, ENC(K3, p2))
  • H13 = KDF(H12, se)
  • H14, K4 = ENC(H13, Zero)
  • H15, T5 = KDF(H14, ENC(K4, p3))

The messages contain the following (||denotes concatenation):

  • msg1 = IE || ENC(K1, IS) || T1 || ENC(K2, p1) || T2
  • msg2 = RE || ENC(K3, p2) || T3
  • msg3 = ENC(K4, p3) || T4

Note that RS is shared in advance.

To avoid network amplification attacks: the network packet containing msg1 should be as big as the network packet containing msg2 (and its payload). Pad msg1 with zeroes as necessary

The handshake proceeds as follows:

  • Initiator sends msg1 to the Responder.
  • Responder verifies msg1, and aborts if it fails.
  • Responder checks Initiator's static key, and aborts if it fails.
  • Responder sends msg2 to the Initiator.
  • Initiator verifies msg2, and aborts if it fails.
  • Initiator sends msg3 to the Responder.
  • Responder verifies msg3, and aborts if it fails.
  • The protocol is complete. The session key is H15.

IK1

Sender and recipient have the following DH key pairs (private half in lower case, public half in upper case):

  • (is, IS) Initiator's static key.
  • (ie, IE) Initiator's ephemeral key.
  • (rs, RS) Responder's static key.
  • (re, RE) Responder's ephemeral key.

Those key pairs are used to derive the following shared secrets:

  • ee = DH(ie, RE) = DH(re, IE)
  • se = DH(is, RE) = DH(re, IS)
  • es = DH(ie, RS) = DH(rs, IE)

Those shared secrets are hashed to derive the following keys (zero is a string of zero bytes):

  • H0 = "Monokex IK1" (ASCII, 32 bytes, zero padded)
  • H1 = KDF(H0 , RS)
  • H2 = KDF(H1 , prelude) if there is a prelude, H1 otherwise
  • H3 = KDF(H2 , IE)
  • H4 = KDF(H3 , IS)
  • H5 = KDF(H4 , p1)
  • H6 = KDF(H5 , RE)
  • H7 = KDF(H6 , ee)
  • H8 = KDF(H7 , se)
  • H9 = KDF(H8 , es)
  • H10, K1 = ENC(H9 , Zero)
  • H11, T1 = KDF(H10, ENC(K1, p2))

The messages contain the following (||denotes concatenation):

  • msg1 = IE || IS || p1
  • msg2 = RE || ENC(K1, p2) || T1

Note that RS is shared in advance.

To avoid network amplification attacks: the network packet containing msg1 should be as big as the network packet containing msg2 (and its payload). Pad msg1 with zeroes as necessary

The handshake proceeds as follows:

  • Initiator sends msg1 to the Responder.
  • Responder receives msg1.
  • Responder checks Initiator's static key, and aborts if it fails.
  • Responder sends msg2 to the Initiator.
  • Initiator verifies msg2, and aborts if it fails.
  • The protocol is complete. The session key is H11.

I1K1

Sender and recipient have the following DH key pairs (private half in lower case, public half in upper case):

  • (is, IS) Initiator's static key.
  • (ie, IE) Initiator's ephemeral key.
  • (rs, RS) Responder's static key.
  • (re, RE) Responder's ephemeral key.

Those key pairs are used to derive the following shared secrets:

  • ee = DH(ie, RE) = DH(re, IE)
  • es = DH(ie, RS) = DH(rs, IE)
  • se = DH(is, RE) = DH(re, IS)

Those shared secrets are hashed to derive the following keys (zero is a string of zero bytes):

  • H0 = "Monokex I1K1" (ASCII, 32 bytes, zero padded)
  • H1 = KDF(H0 , RS)
  • H2 = KDF(H1 , prelude) if there is a prelude, H1 otherwise
  • H3 = KDF(H2 , IE)
  • H4 = KDF(H3 , IS)
  • H5 = KDF(H4 , p1)
  • H6 = KDF(H5 , RE)
  • H7 = KDF(H6 , ee)
  • H8 = KDF(H7 , es)
  • H9, K1 = ENC(H8 , Zero)
  • H10, T1 = KDF(H9 , ENC(K1, p2))
  • H11 = KDF(H10, se)
  • H12, K2 = ENC(H11, Zero)
  • H13, T2 = KDF(H12, ENC(K2, p3))

The messages contain the following (||denotes concatenation):

  • msg1 = IE || IS || p1
  • msg2 = RE || ENC(K1, p2) || T1
  • msg3 = ENC(K2, p3) || T2

Note that RS is shared in advance.

To avoid network amplification attacks: the network packet containing msg1 should be as big as the network packet containing msg2 (and its payload). Pad msg1 with zeroes as necessary

The handshake proceeds as follows:

  • Initiator sends msg1 to the Responder.
  • Responder receives msg1.
  • Responder checks Initiator's static key, and aborts if it fails.
  • Responder sends msg2 to the Initiator.
  • Initiator verifies msg2, and aborts if it fails.
  • Initiator sends msg3 to the Responder.
  • Responder verifies msg3, and aborts if it fails.
  • The protocol is complete. The session key is H13.

I1X

Sender and recipient have the following DH key pairs (private half in lower case, public half in upper case):

  • (is, IS) Initiator's static key.
  • (ie, IE) Initiator's ephemeral key.
  • (rs, RS) Responder's static key.
  • (re, RE) Responder's ephemeral key.

Those key pairs are used to derive the following shared secrets:

  • ee = DH(ie, RE) = DH(re, IE)
  • es = DH(ie, RS) = DH(rs, IE)
  • se = DH(is, RE) = DH(re, IS)

Those shared secrets are hashed to derive the following keys (zero is a string of zero bytes):

  • H0 = "Monokex I1X" (ASCII, 32 bytes, zero padded)
  • H1 = KDF(H0 , prelude) if there is a prelude, H0 otherwise
  • H2 = KDF(H1 , IE)
  • H3 = KDF(H2 , IS)
  • H4 = KDF(H3 , p1)
  • H5 = KDF(H4 , RE)
  • H6 = KDF(H5 , ee)
  • H7, K1 = ENC(H6 , Zero)
  • H8, T1 = KDF(H7 , ENC(K1, RS))
  • H9 = KDF(H8 , es)
  • H10, K2 = ENC(H9 , Zero)
  • H11, T2 = KDF(H10, ENC(K2, p2))
  • H12 = KDF(H11, se)
  • H13, K3 = ENC(H12, Zero)
  • H14, T3 = KDF(H13, ENC(K3, p3))

The messages contain the following (||denotes concatenation):

  • msg1 = IE || IS || p1
  • msg2 = RE || ENC(K1, RS) || T1 || ENC(K2, p2) || T2
  • msg3 = ENC(K3, p3) || T3

To avoid network amplification attacks: the network packet containing msg1 should be as big as the network packet containing msg2 (and its payload). Pad msg1 with zeroes as necessary

The handshake proceeds as follows:

  • Initiator sends msg1 to the Responder.
  • Responder receives msg1.
  • Responder checks Initiator's static key, and aborts if it fails.
  • Responder sends msg2 to the Initiator.
  • Initiator verifies msg2, and aborts if it fails.
  • Initiator checks Responder's static key, and aborts if it fails.
  • Initiator sends msg3 to the Responder.
  • Responder verifies msg3, and aborts if it fails.
  • The protocol is complete. The session key is H14.

IX1

Sender and recipient have the following DH key pairs (private half in lower case, public half in upper case):

  • (is, IS) Initiator's static key.
  • (ie, IE) Initiator's ephemeral key.
  • (rs, RS) Responder's static key.
  • (re, RE) Responder's ephemeral key.

Those key pairs are used to derive the following shared secrets:

  • ee = DH(ie, RE) = DH(re, IE)
  • se = DH(is, RE) = DH(re, IS)
  • es = DH(ie, RS) = DH(rs, IE)

Those shared secrets are hashed to derive the following keys (zero is a string of zero bytes):

  • H0 = "Monokex IX1" (ASCII, 32 bytes, zero padded)
  • H1 = KDF(H0 , prelude) if there is a prelude, H0 otherwise
  • H2 = KDF(H1 , IE)
  • H3 = KDF(H2 , IS)
  • H4 = KDF(H3 , p1)
  • H5 = KDF(H4 , RE)
  • H6 = KDF(H5 , ee)
  • H7 = KDF(H6 , se)
  • H8, K1 = ENC(H7 , Zero)
  • H9, T1 = KDF(H8 , ENC(K1, RS))
  • H10, K2 = ENC(H9 , Zero)
  • H11, T2 = KDF(H10, ENC(K2, p2))
  • H12 = KDF(H11, es)
  • H13, K3 = ENC(H12, Zero)
  • H14, T3 = KDF(H13, ENC(K3, p3))

The messages contain the following (||denotes concatenation):

  • msg1 = IE || IS || p1
  • msg2 = RE || ENC(K1, RS) || T1 || ENC(K2, p2) || T2
  • msg3 = ENC(K3, p3) || T3

To avoid network amplification attacks: the network packet containing msg1 should be as big as the network packet containing msg2 (and its payload). Pad msg1 with zeroes as necessary

The handshake proceeds as follows:

  • Initiator sends msg1 to the Responder.
  • Responder receives msg1.
  • Responder checks Initiator's static key, and aborts if it fails.
  • Responder sends msg2 to the Initiator.
  • Initiator verifies msg2, and aborts if it fails.
  • Initiator checks Responder's static key, and aborts if it fails.
  • Initiator sends msg3 to the Responder.
  • Responder verifies msg3, and aborts if it fails.
  • The protocol is complete. The session key is H14.

I1X1

Sender and recipient have the following DH key pairs (private half in lower case, public half in upper case):

  • (is, IS) Initiator's static key.
  • (ie, IE) Initiator's ephemeral key.
  • (rs, RS) Responder's static key.
  • (re, RE) Responder's ephemeral key.

Those key pairs are used to derive the following shared secrets:

  • ee = DH(ie, RE) = DH(re, IE)
  • se = DH(is, RE) = DH(re, IS)
  • es = DH(ie, RS) = DH(rs, IE)

Those shared secrets are hashed to derive the following keys (zero is a string of zero bytes):

  • H0 = "Monokex I1X1" (ASCII, 32 bytes, zero padded)
  • H1 = KDF(H0 , prelude) if there is a prelude, H0 otherwise
  • H2 = KDF(H1 , IE)
  • H3 = KDF(H2 , IS)
  • H4 = KDF(H3 , p1)
  • H5 = KDF(H4 , RE)
  • H6 = KDF(H5 , ee)
  • H7, K1 = ENC(H6 , Zero)
  • H8, T1 = KDF(H7 , ENC(K1, RS))
  • H9, K2 = ENC(H8 , Zero)
  • H10, T2 = KDF(H9 , ENC(K2, p2))
  • H11 = KDF(H10, se)
  • H12 = KDF(H11, es)
  • H13, K3 = ENC(H12, Zero)
  • H14, T3 = KDF(H13, ENC(K3, p3))

The messages contain the following (||denotes concatenation):

  • msg1 = IE || IS || p1
  • msg2 = RE || ENC(K1, RS) || T1 || ENC(K2, p2) || T2
  • msg3 = ENC(K3, p3) || T3

To avoid network amplification attacks: the network packet containing msg1 should be as big as the network packet containing msg2 (and its payload). Pad msg1 with zeroes as necessary

The handshake proceeds as follows:

  • Initiator sends msg1 to the Responder.
  • Responder receives msg1.
  • Responder checks Initiator's static key, and aborts if it fails.
  • Responder sends msg2 to the Initiator.
  • Initiator verifies msg2, and aborts if it fails.
  • Initiator checks Responder's static key, and aborts if it fails.
  • Initiator sends msg3 to the Responder.
  • Responder verifies msg3, and aborts if it fails.
  • The protocol is complete. The session key is H14.