Is this a proper key-exchange implementation? I've been trying to implement Diffie Hellman key exchange so far from my own understandings (I know I could just stick with SSL/TLS, but I want to understand it in depth more), so I created this basic server&lt;->client key exchange:

Generator and modulus are constants, thus same all the time
Generator is 3
Modulus is a 2048bit prime number

Step 1:
  1. Client connects to a server, asks for key exchange
  2. Server generates random 2048bit exponent
  3. Server rises generator to this exponent
  4. Server does modulo on result with 2048bit modulus
  5. Server sends result of modulo operation unencrypted to client

Step 2:
  1. Client receives result from server unencrypted in form of hex number
  2. Client generates random 2048bit exponent
  3. Client rises generator to this exponent
  5. Client sends this number to server unencrypted back
  6. Client rises server's number to client's exponent and does modulo op.
  7. Client remembers result as secret key (2048bit)
  8. Server receives this number, and rises it to it's own exponent and does modulo op.
  9. Server remembers result as secret key (2048bit)

Step3:
  1. Both client and server do SHA256 on secret key and get 256bit integer
  2. This 256bit key is used as private key for further AES/CBC/PKCS5 communication


So my questions are:


Can exponent be random number just like it is now or it should be a prime too?
Is using dynamic modulus and generator better idea?
Is there anything to improve this key exchange or are there any flaws?
Is using SHA256 a proper way to generate 256bit key for AES/CBC?


Edit: purpose of this key exchange is for JSON messaging between server and client and end-to-end encryption in VoIP between clients (it's all for self-educational purpose, I know I could stick with WebRTC/DTLS or any already existing protocol!)
Can exponent be random number just like it is now or it should be a prime too?


There is no particular advantage to be gained in selecting only prime exponents.


  Is using dynamic modulus and generator better idea?


Whether it makes sense to use dynamic modulii is currently under debate.  There are known algorithms that make attacking multiple discrete log problems under the same modulus not that much more expensive than attacking one; hence some people claim that you should vary the modulus (not to give TLAs a single target to attack).  Other people state that if you use a sufficiently large modulus (and 2048 bits would appear to be sufficiently large), this isn't a concern (and in addition, generating random modulii adds complexity, and that in itself is a security concern).

As for generators, we know the answer is "no, it doesn't help". It's provable that one particular base is not (much) weaker than a random based (of the same order); that is, if you can solve either the DLog or the computational Diffie-Hellman problem with one base, you can leverage that to solve the corresponding problem in any base (of the same order).  It's far more important to select a generator that you know has a large prime order (with possibly a small cofactor).


  Is there anything to improve this key exchange or are there any flaws?


Of course there are flaws.

You state that the modulus is "prime"; that's not sufficient for Diffie-Hellman; instead, you need to know the that it contains a subgroup that's a large prime factor (that is, $p-1$ has a large prime factor $q$).

You use the generator "3".  Small generators can be strong (in fact, "2" is a popular choice), however you should make sure that "3" has a large prime order (that is, it generates a subgroup whose size is a large prime).  One obvious way is to select a prime $p=2q + 1$ for prime $q$; and with $p \equiv 11 \pmod{12}$; if both requirements are true, then "3" will generate a group of size $q$.

You use a 2048 bit exponent; that's considerably more expensive than you need; you do the above checks (make sure that the subgroup that $g$ generates is large and prime), then a 256 bit exponent is quite sufficient (and 8 times faster).

You don't do any authentication; this means that someone in the middle that can modify messages can insert themselves into the conversation, and listen in.

You have the server perform the first modular exponentiation, and before any client verification; this opens up an obvious Denial-of-Service attack.


  Is using SHA256 a proper way to generate 256bit key for AES/CBC?


And how are you generating the key for the MAC (you are using a MAC with AES/CBC, aren't you???)