Secure channels over TCP/IP

This library was born out of a need to set up a secure channel over a TCP/IP network without the overhead of TLS. It uses NaCl for security, and follows the guidelines for secure channels outlined in Cryptography Engineering.

A secure channel has the following properties:

  1. A bi-directional channel has separate keys for each direction.
  2. The channel has send and receive counters to prevent replayed messages; these message counters will be reset whenever the keys are rotated.
  3. A regressed message counter is considered a decryption failure.
  4. The channel transmits discrete messages, and doesn’t operate as a stream.
  5. New keys are generated for each channel.
  6. An eavesdropper can still perform traffic analysis to note when and how often the two sides communicate, and will be able to observe the size of the messages.

There are three different types of keys that are used in this system; users of this system need only worry about one of them. These three key types are:

Key exchange high-level overview

For this discussion, the client is the peer that initiates the secure channel, and server is the other peer. They are so-named because the corresponding functions are called “dial” and “listen”. It is assumed both sides have set up a TCP connection, e.g. using connect(2) and accept(2).

  1. Both sides generate their key exchange pair. If a peer has an identity key, it will sign its keypair. Otherwise, an empty signature is used; this is the tuple k<sub>pub,1</sub>||k<sub>pub,2</sub>||signature.
  2. The client sends its key exchange tuple to the server.
  3. The server receives the tuple, and verifies the signature as appropriate.
  4. The server now sends its tuple.
  5. The client receives this tuple, and verifies the signature as appropriate.
  6. Both sides can now compute their shared keys. The client computes its send key as ECDH(kpriv,1,kpeer,1), and its receive key as ECDH(kpriv,2,kpeer,2). The server necessarily reverses the order: its send key is computed as ECDH(kpriv,2,kpeer,2), and its receive key as ECDH(kpriv,1,kpeer,1).
  7. The secure channel is established and both sides can exchange messages.
  8. If at some point, one side determines that a key rotation is needed, the same basic steps are followed without the signatures. Key rotations are signaled via a key exchange message.

Message security

Once the channel is established, all traffic will be authenticated and encrypted. Messages are wrapped in an envelope before encryption that pairs the message with a format version, sequence number, and message type. The message type is used to provide additional messages for managing the secure channel: the normal message type is used for all messages sent from one side to the other. A key exchange message triggers a key rotation, and a shutdown message signals the other side that the secure channel is being closed.