Skip to main content
GameDev.net gamedev.net
🔒 Locked

encryption

Started by fenghus Feb 16, 2007 at 6:09 AM 15 replies 3.2k views
Original Post
fenghus
fenghus
Hello everyone, I'm in the process of adding encryption to my network library and just wanted to run this by you all to ensure it's a valid way of doing it. * Client sends its RSA public key in plain text to the server * Server encrypts its own public key using the client public key and sends it to the client * Client decrypts the message and uses the server public key to encrypt a random symmetric key * Server decrypts the message and now both client and server has the symmetric key (Note; there's a unique public/private key pair per connection) The symmetric key will then be used to encrypt all communication using Tiny Encryption or something like it. How does this sound; will it provide reasonable protection against snoopers and man-in-the-middle? Thanks
fenghus
fenghus
Would you care to elaborate? As far as I can tell the man-in-the-middle won't be able to get the symmetric key (since he can't decrypt the first server message) and thus won't be able to read any messages or send valid messages?
A clarification; when in step two i wrote about the server public key I didn't mean the key is publicly known; only that its the first part of the asymmetric key. A different keypair will be generated for every connection.
Bob Janova
Bob Janova
It sounds quite sane to me. I agree with you, if you're using a decent public key system (like RSA) I don't see how a man in the middle is going to decrypt the server message and therefore get the symmetric key.
cobru
cobru
from the allmighty wikipedia:
In cryptography, a man-in-the-middle attack (MITM) is an attack in which an attacker is able to read, insert and modify at will, messages between two parties without either party knowing that the link between them has been compromised.

* Client sends its RSA public key in plain text to the server
* man-in-the-middle (MITM) interceps the request and saves the client's key locally and sends his OWN public key to the server.
* Server encrypts its own public key using the client public key and sends it to the client
* MITM gets server public key from the server, saves it and sends its own public key to the client
* Client decrypts the message and uses the server public key to encrypt a random symmetric key
* MITM gets the message from the client, decrypts it and saves the random key, then it sends its own symmetric key (crypted with server's public key) to the server
* Server decrypts the message and now both client and server has the symmetric key
* Actually, now the server has the symmetric key between the man-in-the-middle and server and the man-in-the-middle has the symmetric key used by the client. Neither client nor server know about man-in-the-middle, which can do whatever he wants with the messages.

It would provide enough protection agains packet sniffing (which is supposed to be able to just look at packets), but against full man-in-the-middle attack (where the man in the middle can alter packets, spoof them and so on) it's useless...

My guess is that dSniff does something similar to what I describe above to sniff ssh connections, but it's just a guess.


Q: How many programmers does it take to write a nice piece of software?A: MORE.
overflowed_
overflowed_
One small problem for the MITM with using the model describe in the Wikipedia article. The certificates (public keys) the MITM sends to the client wouldn't be signed by any CA, or if they were, wouldn't have the right information in them (assuming the CA is properly verifying identity before issuing signed certificates).

With fenghus' model (note there's no public key sent from the server to the client) the communication is even less reliable, because the server never establishes its identity, and it would be nigh impossible to give each client a unique, digitally signed, secure, key, making the MITM attack completely invisible to either side.

>Client sends RSA public key
*MITM intercepts key, sends its own in place
>Server receives MITM's public key, sends symmetric encryption key to MITM
*MITM sends its own random symmetric encryption to client
>Client uses Symmetric key from MITM
*MITM begins watching encrypted connection

You'd be much safer using a CA signed certificate for the server, rather than the client. From the MITM standpoint it's the same, but with a signed cert the client will atleast be able to see that the cert it's receiving isn't the right one.
-----BEGIN GEEK CODE BLOCK-----Version: 3.12GCS/M/S d->+(++) s+: a19? C++++ UL++ P+++ L+ !E W+++ N+ o++ K? w!O M-- V? !PS PE Y+ PGP t++ 5+++ X R tv+> b+(++)>+++ DI+++>+++++ D++G e>++++ h! r y?------END GEEK CODE BLOCK------
fenghus
fenghus
Ack! That's right! I knew it was a good idea to run it by the network forum (thanks!) :-)

So; it's impossible to resist a full man-in-the-middle attack without a prior (safe) contact between client and server - because a MITM can always mimic the server towards the client and mimic the client towards the server if the protocol is known... if I understand correctly.

Signed certificates seems difficult to implement in the library and may not be useful for some developers. Is there any other way to solve the problem? Is including the server public key in the client a good way to go?
Sneftel
Sneftel
Quote:
Original post by fenghus
So; it's impossible to resist a full man-in-the-middle attack without a prior (safe) contact between client and server - because a MITM can always mimic the server towards the client and mimic the client towards the server if the protocol is known... if I understand correctly.
Correct.
Quote:
Signed certificates seems difficult to implement in the library and may not be useful for some developers. Is there any other way to solve the problem? Is including the server public key in the client a good way to go?

Even though it can't protect against MITM, this sort of encryption can be useful for protecting against observation. In terms of including the server public key in the client, this can be very useful at times.
hplus0603
hplus0603
Quote:
So; it's impossible to resist a full man-in-the-middle attack without a prior (safe) contact between client and server


Correct. This is the basic weakness of all Diffie-Hellman style key exchanges (such as the one you initially proposed).

You need either a trusted path for a certificate, or a trusted third party that can verify a given certificate -- this is what Verisign, Thawte and others do for SSL. To avoid compromise of the trusted authority using the same attack, you have to pre-populate the root certificate on the machine.

Putting a known public key into the client is a fine way of providing a trusted path between client and server. Assuming you include the public key with the installation, then the key exchange you suggested above will work against a MITM.
enum Bool { True, False, FileNotFound };
fenghus
fenghus
Then that is what i'll do. Thanks to everyone for the help!
starfleetrp
starfleetrp
If your server requires the user to log on why not do it this way:

Server sends the Client and ID (this way the next MD5 always changes and can not be spoofed, without knowing log in info - sure this can be intercepted but what good would it do)
Client MD5's ID + username + password
Server checks the MD5 with the one it created, if it passed
Server sends an encryption Key to use for future use, encrypted with clients username + password + ID (always changing every new connection)

Now both sides would have the encryption key and the only way to receive it would be by knowing the Username + password?
I am also curious if this would be practical since I just thought of it now
hplus0603
hplus0603
You could still do a man-in-the-middle attack on that, I think (your description was not cohesive enough that I could do a full analysis on it).

For authentication strategies that work, you might want to check out my article on game authentication.
enum Bool { True, False, FileNotFound };
starfleetrp
starfleetrp
I will try and clarify what I meant (I hope it is better this time).
Each time the user logs in a new encryption key is to be used.

1. The client connects to the server
2. The server sends the client an ID number (this can be intercepted by a MITM attack)
3. The client enters his log-in info and it is sent to the server in the form of a username + MD5[ID + MD5[password] ]
4. The server verifies that the MD5[ID + MD5[password] ] is correct by verifying the ID and the user information in the database is correct
5. The server generates an encryption key to send to the client
6. The server sends the key encrypted with a MD5[username + MD5[password]] (Note: this MD5 is different than the one sent to the server containing the username and password because it does not contain the ID, hence the MITM does not know the encryption key)
7. The client de-crypts the message and extracts the new encryption key that will be used for further secure communication.

This whole thing would be useless if the MITM knew the users password since this whole sceme is based on the password being completely hidden.

I guess for an added layer of protection the ID number could be encrypted with a key that is stored in the software.
hplus0603
hplus0603
Yes, that is similar to the "server knows password" mechanism described in my overview.

In this case, there is a shared secret between the server and the client in the user's password, rather than a public key. Thus, it is slightly weaker, because it relies on non-compromise of two places (server + client), although in practice, if the client is compromised, you're screwed no matter what you try :-)
enum Bool { True, False, FileNotFound };
fenghus
fenghus
If anyone is interested, I ended up including the server public key in the client, and upon connecting the client sends a random 128 bit key, encrypted using the public key, to the server. The client and server then uses that key to encrypt all messages using XTEA.
It's all available in the repository at http://code.google.com/p/lidgren-library-network/ <- shameless plug!
Ozymandias43
Ozymandias43
Why is the server sending its public key to the client? Why not generate a single strong key for the server, then ship the client with the server's public key? That way, nobody can man-in-the-middle you, since only the real server can communicate with its own private key.
Ozymandias43
Ozymandias43
ah, shoot, this is what I get for not reading all the way down to the end of the thread!

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.