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.
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.
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:
The client generates a random Diffie-Hellman secret x and the corresponding public value A.
The client sends A to the server.
The server generates a random Diffie-Hellman secret y and the corresponding public value B.
The server computes the Diffie-Hellman shared secret.
The server signs a string consisting of the public values A and B with the server’s private DSA key.
The server sends B and the signature to the client.
The client computes the shared secret.
The client validates the signature, failing if it isn’t valid.
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, ...