c++ encrypt a text with a key received over packet? keyczar? - c++

I'm storing a client's password in his device and there are times when clients need to send their password to server.
When a client connects to me(server),
I give him a key that will be used for encryption.
I want a client to send a encrypted password by the key.
Server will decrypt the password with the key(which was stored) and
verify the password.
Even if it may not be perfect, it sounds more secure than using one static key stored in client and server.
Sounds simple enough and I was looking at c++ encryption library(crypto++), bleh looks too complicated.
Found there is a easy one to use. Keyczar.
But doesn't seem to offer the functionality that I need.
Keyczar seems to require to generate a file that will hold encryption key, and this file is generated by one of their tools, which will be too much hassle to do it on the fly.
If this can be done in c++ or keyczar(I may have missed what it can do)
please enlighten me how to.
Thank you.
Linux/Mac platform.

If you are sending the key to the user immediately before the user uses it to encrypt his or her password, you might as well be sending the password in the clear. (You're sending all the data required to reconstruct the cleartext password, anyway.)
A better method would use TLS to encrypt the entire conversation using a nonce-protected (to avoid replay attack) randomly generated session key.
If you really wanted to be fancy, you could use client-side x509 certificates to authenticate the client for you -- then you wouldn't need passwords on the server at all. (But you might still want to use the password to store the private key encrypted on the devices.)
If you like the idea but dislike TLS because x509 is supremely complicated, perhaps it would be easier to integrate ssh session management, using ssh keys. ssh keys are far easier to work with than x509 keys, but their simplicity means they aren't applicable everywhere.

if the key exchange is not secured, you'll gain absolutely nothing (except reduced replay attack); perhaps simply look into TLS/SSL for the purpose of securing the transport

Related

Algorithm for client validation?

Here is what I am trying to do.
I have a game and a server executable. The clients connect to the server to play.
The concern I currently have is that someone might use telnet or something to simulate a client.
Currently, the user only sends a simply hello string after they are connected and if it is correct I accept data from them.
I have tried to use certificates / ssl without success so I am trying to figure out an effective way to know if a game client is really a client.
Simply put, what would be an effective way to validate the client?
I am not concerned with a man in the middle attack since the users do not login nor provide passwords, just a session name.
I have thought of the possibility of the server sending a fixed length random string, then the client modifies this string with an algorithm, then sends it back.
I am wondering if there are better more clever ways than that.
I do actually have a certificate for my server, it is a pfx, if that helps.
Thanks
Its intrinsically difficult as a problem. Certainly there is no software you can write, that could run on a foriegn machine, that can proves its the program you wrote in an un-tampered form.
Still, there is some simple challenge response stuff you ca do to improve things.
Lets assume your client and your server share a secret (your writing it, so they can, though being software it wont be very secret.) Lets also assume you have ahandy crypt or hashing library (for things like a SHA-1 hash) Then:
Server send challenge, including a nonce (eg the time + random number).
Client sends a response, which includes a secure hash of (nonce + secret)
Server know the nonce and the secret, so they can check the hash received is correct, and thus can confirm the "client" also knows the secret.
This is a basic symmetric validation scheme.

creating and Signing Public/Private Key pair Programmatically

Please read the question first as the heading isn't very clear and I am not able to put my question in few words.
My scenario is as such:
I am creating a P2P application. A peer, during installation, generates Public and Private key pair and uploads the public key to my central server. When a peer A wants to communicate with peer B, it downloads the public key of B and normal encryption and data transfer takes place.
I need a little heads up for creating this public/private key pair programmatically. Again I need this public key of a peer to be signed by the central server's private key so as to know its authenticity.
Do I have to create a private CA sort of thing or any other way is possible ? If someone can help me understand this creating, signing, etc from programming perspective, that would be great. I am getting a lot of concept out there in google search but not much in coding. I am new to cryptography so any other idea to implement the same would be helpful.
Note: I cannot use any third party CA. And I am not using the certificates for authentication, but for encryption.
Thanks.
The reason you get many hits on the concept but not the programming is that it is hard to come up with a good protocol, and not that hard to actually program it. It is the right order to go with this too, this kind of protocol you cannot just program and document later.
It doesn't really matter much if you want to use the certificates/private key for signing or for encryption. The point is that the public key needs to be trusted. If you cannot trust the public key then you cannot guarantee that the encryption was performed for the right entity. This means that e.g. peer A was encrypting using a public key of M instead of B. This is almost always a problem, unless you are only interested in eavesdropping attacks.
As you seem to have a central server it seems logical to use a hierarchical trust model. For such a system PKI using X509 certificates and a central CA makes the most sense. You can use an OpenSSL based CA system or any other free CA solution such as EJBCA or some Windows server based solution.
When you have the CA running you are not there yet. You need a method for the peers to trust the root certificate of the CA. After that you need a method for the CA to trust the certificate requests send by the peers. Without more information it is hard to say what method would fit you best.
You should only worry about the programming when you've figured all this out (at the minimum).
classic PKI scenario ... you want a CA ...
all your peers need to know the public CA cert ahead of time ...
once a peer registers with the server, it should encrypt its own key so the server can be sure that the received key wasn't tampered with...
for data structure you should probably use X509
from the programmers point of view:
peer A wants to register with a new keypair ...
-> generate keypair
-> fill the identification details of a certificate, and attach the public key
(what you have now is usually called "certificate request")
-> encrypt the request symetrically (AES-CBC-256 with a random IV looks like a good choice)
-> encrypt the symertic key, and send that together with the encrypted request and the cleartext IV to the server (optionally, include a server provided nonce or addidional session data in the encrypted part)
on the server side:
decrypt, check the data, especially the identification information of the request
if that's ok, take the request (ID part + public key) and sign that with the CA key
report back to peer A and handover the signed certificate (since it does not include any secrets, that may be clear text or encrypted with the provided key for peer A)
once you need to make contact between the peers, you only need some contact information:
if peer X wants to contact peer A, all you have to hand out is the address how A can be contacted ... X then contacts A and asks for ID ("Hello? is this A? please give me your cert and here is my cert.") ... after certificates have been exchanged the signatures are verified ... if CA sigs are ok, both parties generate random numbers ("nonces"; number-once-used) and encrypt them with the public keys from the received and verified cert and hand them over to the other peer ... upon receiving the encrypted value is decrypted, and reencrypted with the other parties key, and send back ... upon receiving that decrypt the value with your own private key, and verify that it's the same number you sent ... authenticated connection is established and you can now proceed to handover symetric keys and start transfering encrypted data
if you think you can live without authenticating the other peer, you can directly start transfering encrypted data after you checked the CA sig on their cert ... but consider that in this case, an attacker can receive data that's not for him (he can't decrypt it, but he can pretend to be the other peer ...)

Client to Server Authentication in C++ using sockets

I'm implementing a login/authentication system for my little server-client program. I'm wondering how to go about this, and I was hoping to get some great tips/advice from Stack Overflow as always. This is how I imagine I'll do it.
Client connects to the server.
Server sends a 'token' to the Client (based on time probably and whatever)
Client returns the username and a sha1 encrypted password, along with the token.
Server receives them and authenticates the user to the credentials in the server-side database.
The token is now verified and the user is signed in with the token.
Is this at all a secure way of doing it? I figured the client also sends a serial key or some such to form a serial / token pair, so that another client cannot fake the same token (though the token is generated by the server-side).
Implementation details aren't required, as I am capable of doing the implementation.
My question would, rather, two questions:
What ways are there to achieve a login/authentication system with sockets
What ways are there to secure my client-to-server connection
EDIT: I forgot to ask, as this is a C++ question, are there any libraries that can assist in encryption/authentication?
Security is an issue for me, so I want to be sure I do it right.
Maybe some background information. It's a game server, a person logs in with his account and is taken to a 'Lobby', where he can pick a 'World Server' to play on. The world server is a separate process running (possibly) on a different machine in the same network.
For that reason, I want to have a concept of a session in this, the user logs in and a session is generated, the login server relays the session to the world server the user picks, so that world server knows that the user is actually logged in.
I reckon the client will have to confirm the session to the world server and all that, but I'll worry about that later.
Sincerely,
Jesse
You generally do not want to send the password over the link at all, not even with encryption. The usual method is a challenge-response protocol.
The client connects to the server, sending in the user-name (but not password)
The server responds by sending out unique random number
The client encrypts that random number using the hash of their password as the key
The client sends the encrypted random number to the server
The server encrypts the random number with the correct hash of the user's password
The server compares the two encrypted random numbers
This has a couple of advantages. First, it means the password never goes over the link in any form. Second, it's immune to a replay attack -- if an attacker records the conversation, they can't replay the client's replies later to log in, because the random number will have changed.
Securing the connection (i.e., encrypting the content) is a little simpler. Typically, one of the two (doesn't really matter much which) picks a random number, encrypts it with the other's public key, and sends it to the other. The other decrypts it, and they encrypt the rest of the session using that as a key for symmetric encryption.
Libraries: Beecrypt and OpenSSL are a couple of obvious ones. Unless you have a fairly specific reason to do otherwise, TLS is what you probably want to use (it does quite a bit more than what I've outlined above, including two-way authentication, so not only does the server know who the client is, but the client also knows who the server is, so it's reasonably verified that it's not connected to somebody else who might just collect his credit card number and run with it).
Edit:
To authenticate each packet without the overhead of encrypting everything, you could do something like this:
The server sends its public key with the challenge
The client generates a random number, encrypts it with the server's public key, and sends it back with its response
The number is the first number used for counter-mode encryption
The client includes one counter-mode result with each packet it sends
Counter mode means you just generate consecutive numbers, and encrypt each in turn, using the right key. In this case, the key would be the hash of the client's password. What this means is that each packet will contain a unique random number that both the client and the server can generate, but nobody else can. By using the counter-mode encryption, each packet will have a unique random number. By starting from a random number, each session will have a unique sequence of random numbers.
To minimize overhead, you could send just a part of the result with each packet -- e.g., if you use AES in counter mode, it'll generate 16 bytes of result for each number you encrypt. Include only (say) two bytes of that with each packet, so you only have to encrypt a number once every 8 packets. In theory, this cuts security -- an attacker could just try all 65536 possible values for a packet, but if you assume the connection has been compromised after (say) two bad attempts, the chances of an attacker getting the right value become pretty small (and, of course, you can pretty much pick the chances you're willing to live with by controlling the number of bad attempts you allow and the size of authentication you include in each packet).
If security is a big issue for you, don't roll your own. You want a secure socket library. Something like OpenSSL.

What is the correct way to use the Crypto Api for encryption and decryption between client and server?

After many headaches and people advising to stop, I finally managed to get my Server/Client App to work with this API and create the required keys, i.e. Session and Exchange.
When I send the public key to the client, it successfully imports the key and will also encrypt a message using that key, but when I pass it back to the server; it decrypts the message using the session key but the message is returned as garbage (hmm.. private key is needed!). Now this could be due to way I am passing the encrypted message back via rpc, but something tells me it is something else. Ideally what I need is a clear and plain explanation of what it is I should be doing with all these keys, because the information I am currently getting is quite confused.
Do I pass the exchange public key to the client so it can encrypt a message and return for decryption.
Or:
Should I actually be encrypting the clients session key with the servers public key and then return that? (This doesn't sound right to me, but I am all ears!!!)
Please leave out comments to move to another API, or copy pasties from MSDN (I have already read all that). I am working with the Crypto API and just need a clear explanation of what keys the server should pass to the client, and then what the client should do and pass back so I can finally move on...
Sounds like you are on the right track if you really are determined to stick with that API :)
There are two distinct families of encryption algorithms in cryptography. 1) Ones that use symmetric keys and 2) those that use asymmetric keys. Symmetric key algorithms (e.g. AES, DES...) are very fast and should be used as long as there's a safe way to make sure both client and server have the same key (i.e. session key) and no one else can gain access to that key. On the other hand, asymmetric key algorithms (e.g. RSA...), which are also known private/public key algorithms, are much more computationally expensive. They have one key which can only be used to encrypt data and a second key which can only be used to decrypt data. These algorithms, as you found out, are perfect for the initial handshake and session key exchange. The server creates public/private key pair and sends the client the public key. Anyone can intercept it, but when the client encodes the session key and sends that back, pbulic key is useless if an eavesdropper wants to find out the session key. Only the server can decode the message as it is the only entity that is holding the private key. So your initial problem was that when the message came back, instead of using the private key from the pair, you were using synchronous session key and thus were getting garbage.
Essentially you've just implemented the basic handshake that SSL does (and you could easily do with very few lines of code if using OpenSSL library).
Once the handshake is performed you now have a secure channel between the client and the server. The only problem you might have is, what if someone piggy backs on your server's IP address and starts pretending like they are the real server? Your client will think he is talking to the real server, it'll do the key exchange and will start sending secure information, but that information might all end up in malicious hands if an attacker's PC happens to be on the other end.
This is where SSL's use of certificates comes in. Certificates are another example of where public/private keys are used. A trusted authority uses private key to sign certificates hash code and anyone can verify that certificate is valid by using it's attach public key against certificates identity data. This way even if attacker takes over your server's IP address, it won't be able to spoof your server's certificate.

Client / Server Cryptography for passwords

I am building a client/server application in C++ and need each client to provide a password. Obviously I want this to be secure during transport so I have been looking into a way of encrypting the password; so that only the server application can decrypt it again.
The problem I am having is not necessarily getting the functions to work, but rather understanding what it is I need to do in order to relate that into code. I am trying to understand and have read MSDN (feels like it) but still I am only learning so really need some clear and accurate guidance on my implementation.
Does this sound right?
I aquire a context to the CSP on both server and client.
I generate a key on the server, or load one (whatever).
and then I
export a public key from the server and send it to the client, the client imports the key and then encrypts the password and returns it so that only the server can decrypt it again.
(Fails when I try).
OR, do I then
export a session key, or an exchange key pair ( single public) which is encrypted with the exchange key pair?
Oh I am so lost, I cannot even explain clearly.
Please help me to understand this...
It really depends on what sort of authentication solution you want to be based one. The options are varied.
You could, for example, rely on the underlying OS authentication. You wouldn't need to manage passwords at all. But this requires a somewhat tighter integration with the domain in which your application is running.
Another option is to use HTTPS and simple authentication. It basically uses SSL to encrypt communication and then sends a username/password pair. Pretty simple, and supported by all web servers. You could probably find C++ code quite easily that takes care of this for you (search StackOverflow for such a question) if you don't want to rely on an existing web server like IIS being installed.
If you do not need the encrypted Communication for other things like data transfer, you can use Challenge-Response for password verification. The Password does not need to be transferred over the network and there is no risk of a replay attack in wich a third party just resends some packets. On the downside, a man in the middle (MITM) attack is possible.
If you need protection from MITM or need an encrypted channel for other communication, you should use TLS with certificates or Public-Key-Encryption with two keypairs.
Do not do anything.
This is very important. Do not implement this yourself.
Repeat do not do anything you will get it wrong.
You should use what is already available. Simply open a connection to an SSL socket and the content of the stream will be automatically encrypted and de-crypted at the other end.
Your application should simply take a username/password tupple and validate if they are correct. Do not attempt to implement the cryptographic part.