Key Exchange

Jhydro comes with three variants of key exchanges. The N variant, the KK variant, and the XX variant. For more information on their use in libhydrogen, see the wiki. All variants exchange a pair of symmetric keys, so that client A can send encrypted messages to client B, and B can send encrypted messages to A.

Usage Examples

N variant

(use jhydro)

(def {:public-key pk :secret-key sk} (kx/keygen))
(def packet @"")
(def psk (random/buf kx/psk-bytes))
(def {:tx client-tx :rx client-rx} (kx/n1 packet psk pk))
(def {:tx server-tx :rx server-rx} (kx/n2 packet psk pk sk))
# (test "client tx = server rx" (util/= client-tx server-rx))
# (test "client rx = server tx" (util/= client-rx server-tx))

KK variant

(use jhydro)

(def {:public-key pk1 :secret-key sk1} (kx/keygen))
(def {:public-key pk2 :secret-key sk2} (kx/keygen))
(def packet1 @"")
(def packet2 @"")
(def a-state (kx/kk1 packet1 pk2 pk1 sk1))
(def {:tx b-tx :rx b-rx} (kx/kk2 packet2 packet1 pk1 pk2 sk2))
(def {:tx a-tx :rx a-rx} (kx/kk3 a-state packet2 pk1 sk1))
# (test "a tx = b rx" (util/= a-tx b-rx))
# (test "a rx = b tx" (util/= a-rx b-tx))

XX variant

(use jhydro)

(def {:public-key pk1 :secret-key sk1} (kx/keygen))
(def {:public-key pk2 :secret-key sk2} (kx/keygen))
(def packet1 @"")
(def packet2 @"")
(def packet3 @"")
(def psk (random/buf kx/psk-bytes))
(def a-state (kx/xx1 packet1 psk))
(def b-state (kx/xx2 packet2 packet1 psk pk2 sk2))
(def {:tx b-tx :rx b-rx} (kx/xx3 a-state packet3 packet2 psk pk1 sk1))
(def {:tx a-tx :rx a-rx} (kx/xx4 b-state packet3 psk))
# (test "a tx = b rx" (util/= a-tx b-rx))
# (test "a rx = b tx" (util/= a-rx b-tx))

Index

kx/keygen kx/kk-packet-1-bytes kx/kk-packet-2-bytes kx/kk1 kx/kk2 kx/kk3 kx/n-packet-1-bytes kx/n1 kx/n2 kx/psk-bytes kx/public-key-bytes kx/secret-key-bytes kx/session-key-bytes kx/xx-packet-1-bytes kx/xx-packet-2-bytes kx/xx-packet-3-bytes kx/xx1 kx/xx2 kx/xx3 kx/xx4

Reference

kx/keygencfunction
(kx/keygen)

Generate a keypair for use key exchanges. Contains both a public key and a secret key. Returns a struct with two entries, and :secret-key and a :public-key.

Number of bytes in the first packet sent in the KK variant key exchange.

Number of bytes in the second packet sent in the KK variant key exchange.

kx/kk1cfunction
(kx/kk1 packet-1 static-pk pk sk)

Generate the first packet for the KK variant key exchange. Returns a jhydro/ks-state abstract which contains some useful state for the key exchange. static-pk is the peer's public key, and pk and sk are the client's public and secret keys. Modifies the buffer packet-1 by appending new data.

kx/kk2cfunction
(kx/kk2 packet-2 packet-1 static-pk pk sk)

Generate the second packet and a session keypair in the KK variant key exchange. packet-2 is a buffer to put the new packet in. packet-1 is the packet received from the peer. static-pk is the other peer's public key, and pk and sk are the local client's public and secret keys. Returns a session keypair, which is a struct of two entries, :rx and :tx.

kx/kk3cfunction
(kx/kk3 state packet-2 pk sk)

Generate a session key on the initiating peer in the KK variant key exchange. state is the jhydro/kx-state from step 1, packet-2 is the packet from step 2, and pk and sk are the local client's public and secret keys. Returns a session keypair, which is a struct of two entries, :rx and :tx.

Number of bytes in the first packet sent in the N variant key exchange.

kx/n1cfunction
(kx/n1 packet-buf psk peer-pk)

Create a session key and generate a packet on the client as the first step in the N variant key exchange. Also take a pre-shared key, and the peer's public key. Returns a session key as a struct of two entries, :tx and :rx, which are the transmit and receive keys for communicating with the peer.

kx/n2cfunction
(kx/n2 packet1 psk pk sk)

Create a session key as the second step in the N variant key exchange on the server. packet1 is what kx/n1 put into a buffer (packet-buf), psk is a pre-shared key, pk is the server's public key, and sk is the server's secret key. Returns a session keypair that is a mirror of what is on the client, but :tx and :rx are swapped.

kx/psk-bytesnumber 32

Number of bytes in a pre-shared key for key exchange.

Number of bytes in a public key intended for key exchange.

Number of bytes in a secret key intended for key exchange.

Number of bytes in a session key (tx or rx key). These keys are used to encrypt and decrypt messages between two peers.

Number of bytes in the first packet sent in the XX variant key exchange.

Number of bytes in the second packet sent in the XX variant key exchange.

Number of bytes in the third packet sent in the XX variant key exchange.

kx/xx1cfunction
(kx/xx1 packet-1 psk)

First step in XX variant key exchange. Takes in a packet buffer and pre-shared key, and generates the first packet. Also returns a jhydro/kx-state for use in future steps.

kx/xx2cfunction
(kx/xx2 packet-2 packet-1 psk pk sk)

Second step in XX variant key exchange. Takes a buffer for writing packet number 2 too, packet 1, a pre-shared key, and the local public key and secret key. Writes the second packet to packet-2, and returns a jhydro/kx-state.

kx/xx3cfunction
(kx/xx3 state packet-3 packet-2 psk pk sk &opt peer-pk)

Third step in XX variant key exchange. Takes the state returned from kx/xx1, a buffer packet-3 to write the final packet into, the packet packet-2 send from the other peer, a pre-shared key psk, and the public and secret keys of the local machine. Optionally takes a buffer to write the remote peer's public key into, so you can reject connections if they do not match the expected public key. Returns a session keypair, which is a struct with two entries, :rx and :tx.

kx/xx4cfunction
(kx/xx4 state packet-3 psk &opt peer-pk)

Fourth and final step in the XX key exchange variant. Takes the state returned from kx/xx2, the packet received from kx/xx3, and a pre-shared key psk. Optionally takes a buffer peer-pk, which will have the remote peer's public key written appended to it. Returns a session keypair, which contains :tx and :rx entires.