The Server - npmccallum/deo GitHub Wiki

Previous implementations of the server relied on two parallel X.509 stacks: one for TLS and one for decryption. This proved to be both heavy weight and conceptually difficult to deploy. A simpler algorithm is possible that provides an experience similar to SSH.

The Algorithm

The algorithm is a simple variant of a Diffie-Hellman exchange invented by Nathaniel McCallum and Robert Relyea. The server provides a public key. The client generates a public key and completes its half of the Diffie-Hellman creating a shared encryption key. The client uses this shared encryption key to provision the encrypted data and then discards its own private key (but retains its own public key).

In order to decrypt the data, the client generates an ephemeral key used to protect the key exchange. The client sends the server's public key and the client's public key (encrypted in the ephemeral key) to the server. The server adds its own private key to the encrypted client's public key and returns it to the client. The resulting key can be manipulated by the client in order to regain the original encryption key.

Encryption

Client Server
b = gB
a = gA
k = gAB = bA

Decryption

Client Server
x = a + gX
y = gAB + gXB = xB
k = gAB = y - bX

Protocol

ASN.1

DeoMessage ::= CHOICE {
  error   [0] DeoError,
  exc-req [1] DeoMessageExchangeRequest,
  exc-rep [2] DeoMessageExchangeReply,
  adv-req [3] DeoMessageAdvertiseRequest,
  adv-rep [4] DeoMessageAdvertiseReply,
  ...
}

DeoError ::= ENUMERATED {
  internal            (1),
  invalid-request     (2),
  unsupported-group   (3),
  unsupported-sigtype (4),
  notfound-key        (5),
  ...
}

DeoMessageExchangeRequest ::= SEQUENCE {
  group  [0] OBJECT IDENTIFIER,
  b      [1] BIT STRING,
  x      [2] BIT STRING,
  ...
}

DeoMessageExchangeReply ::= SEQUENCE {
  y      [0] BIT STRING,
  ...
}

DeoMessageAdvertiseRequest ::= SEQUENCE {
  type   [0] OBJECT IDENTIFIER,
  key    [1] DeoKey OPTIONAL,
  groups [2] SET OF OBJECT IDENTIFIER OPTIONAL,
  ...
}

DeoMessageAdvertiseReply ::= SEQUENCE {
  body   [0] DeoMessageAdvertiseReplyBody,
  r      [1] INTEGER,
  s      [2] INTEGER,
  key    [3] DeoKey OPTIONAL,
  ...
}

DeoMessageAdvertiseReplyBody ::= SEQUENCE {
  keys   [0] SET OF DeoKey,
  ...
}

DeoKey ::= SEQUENCE {
  group  [0] OBJECT IDENTIFIER,
  key    [1] BIT STRING,
  use    [2] DeoUse,
  ...
}

DeoUse ::= ENUMERATED {
  signature (1),
  exchange  (2),
  ...
}

Commands

The server supports two commands as specified in the above ASN.1 section:

  1. Exchange: In this command the client sends the value of the server's public key that the client used along with the client's x value. The server performs its operation and returns the y value. From this, the client can calculate the previously used key.

  2. Advertise: This command allows the server to advertise its keys to the client. The client sends the type of signature requested along with either a requested key or the client's supported groups. The server returns all of its keys signed by either the requested key or by a key from one of the specified groups. In the latter case, the selected key is provided in the response. This workflow permits a Trust On First Use mode as well as secure rotation once a trusted key exists.

Additional Considerations

Authentication

The server never sees any identifying information except for the IP address (which may possibly be spoofed). A simple authentication mode is possible where SPAKE is layered over top of the x (or a) and y values. In this case, clients which do not possess the password would be unable to calculate the key.

Push Vs. Pull

Two modes of operation will exist for the server side:

  1. Pull: In this mode the server will run as a daemon listening on UDP port 5700. All requests would be client initiated.

  2. Push: In this mode the server will not actively run as a daemon. Rather, a single command would connect to a client listening on TCP 5700. Once connected to the client, the client speaks first and executes the same protocol as the pull model.