8.18 Using Diffie-Hellman and DSA Together

8.18.1 Problem

You want to use Diffie-Hellman for key exchange, and you need some secure way to authenticate the key agreement to protect against a man-in-the-middle attack.

8.18.2 Solution

Use the station-to-station protocol for two-way authentication. A simple modification provides one-way authentication. For example, the server may not care to authenticate the client using public key cryptography.

8.18.3 Discussion

Remember, authentication requires a trusted third party or a secure channel for exchange of public DSA keys. If you'd prefer a password-based protocol that can achieve all the same properties you would get from Diffie-Hellman and DSA, see the discussion of PAX in Recipe 8.15.

Given a client initiating a connection with a server, the station-to-station protocol is as follows:

  1. The client generates a random Diffie-Hellman secret x and the corresponding public value A.

  2. The client sends A to the server.

  3. The server generates a random Diffie-Hellman secret y and the corresponding public value B.

  4. The server computes the Diffie-Hellman shared secret.

  5. The server signs a string consisting of the public values A and B with the server's private DSA key.

  6. The server sends B and the signature to the client.

  7. The client computes the shared secret.

  8. The client validates the signature, failing if it isn't valid.

  9. The client signs A concatenated with B using its private DSA key, and it encrypts the result using the shared secret (the secret can be postprocessed first, as long as both sides do the same processing).

  10. The client sends the encrypted signature to the server.

  11. The server decrypts the signature and validates it.

The station-to-station protocol works only if your Diffie-Hellman keys are always one-time values. If you need a protocol that doesn't expose the private values of each party, use Recipe 8.16. That basic protocol can be adapted from RSA to Diffie-Hellman with DSA if you so desire.

Unless you allow for anonymous connection establishment, the client needs to identify itself as part of this protocol. The client can send its public key (or a digital certificate containing the public key) at Step 2. The server should already have a record of the client based on its public key, or else it should fail. Alternatively, you can drop the client validation steps (9-11) and use a traditional login mechanism after the encrypted link is established.

In many circumstances, the client won't have the server's public key in advance. In such a case, the server will often send a copy of its public key (or a digital certificate containing the public key) at Step 6. In this case, the client can't assume that the public signing key is valid; there's nothing to distinguish it from an attacker's public key! Therefore, the key needs to be validated using a trusted third party before the client trusts that the party on the other end is really the intended server. (We discuss this problem in Recipe 7.1 and Recipe 10.1.)

8.18.4 See Also

Recipe 7.1, Recipe 8.15, Recipe 8.16, Recipe 10.1