How to implement secure socket communication in c++ application using winsock? - c++

I am trying to implement secure communication between a server and client in c++. The limitation is that both the client and server must run on windows and have to be in c++. This is for a research project I am working on at my university.
So far I have found that SChannel is the best option, but the documentation is extremely confusing and I can not find any guides/tutorials on how to use it. I have already looked at this link https://learn.microsoft.com/en-us/windows/desktop/secauthn/creating-a-secure-connection-using-schannel but still do not understand how to get it working. Could someone guide me through this if this is the best way?
I also looked into use SSLStream using the CLR to have .net run inside of a c++ application. However I can not use this because the client application is threaded and threads can't be used with CLR.
I already have a dummy client and server set up with communication between the two, I am just trying to secure and encrypt that communication.
Any help is greatly appreciated!

Whichever SSL library you choose to use there are a few things you need to know as a beginner in this field:
The server and client implementations will end up looking quite different in places.
Your server is absolutely going to need a certificate with a private key. During development you clearly don't want to get one from Verisign or something so you need to create a self-signed certificate. You can do this with openssl or other tools.
The certificate consists of a private part and a public part. The public part needs to go to the client, and will be used to validate the connection. When you are using something like SChannel the certificates (private and public) will need to be installed in the certificate stores of the server and client respectively.
SChannel does not send or receive data for you. So the core of your implementation is going to be: when the network has data: read ciphertext from socket and write to SChannel. Read clear text from SChannel (if any) and pass to application. When the application has data to send, get clear text from Application and pass to SChannel. Get the resulting ciphertext buffers from SChannel and write to the socket.
buffers from the internet may be partial, and negotiations and re-negotiations means there's no 1:1 mapping of passing data into SChannel and getting data out.
You therefore can't get away with a naive implementation that calls SChannel once to pass data in, and once again to get un/encrypted data. There will potentially be nothing available, or a whole lot of packets to send between the client and the server, before you'll get any application bytes. i.e. You will need some kind of state machine to keeptrack of this.
Obviously, don't write both the client and server at the same time: Start with your client against an https server.
That's the general outline of the process - the things that confused me when I first encountered SSL and why none of the samples were nearly as simple as I had hoped them to be.

Related

Simple payload encryption in C++

I have different applications that must communicate among themselves. They can use both UDP and TCP and there can be more than one link between two specific applications. My idea is to encrypt the communications using AES, storing the password somewhere in the computer (encrypted). The password that will be used is of course the same for all the applications and will be changed once in a while. The language I'm using is C++ and I was thinking to use libcrypto++ but I'm open to suggestions.
I know about OpenSSL, TLS etc but what I'd like to do is a really simple encryption of the payload of my custom application protocols. Is there any particular problem that I should pay attention to when implementing this, like message boundaries etc?
Another question is: is it possible to only get the shared key from a central server via SSL or other, and then use this for the above encryption? this will be done from the application at startup and the password could be stored in RAM.

C++ client/server application with single messages and broadcast

I am trying to write a simple client-server application where a client can send or broadcast a message to one or all clients in the network. The server stores all IP addresses that are connected to it, and broadcasts a new IP if a new client connects itself.
I'm not quite sure how to implement the sending of a single message to another client. Would I just have to send a TCP message to the server and put the desired recipient as data in the TCP layer which is then extracted by the server so it knows where to send it?
I also want to add encryption to the messages which would then no longer allow the server to read the data, so I'm not sure how to solve that!?
I am using c++ and Qt5 for the implementation
I'm not quite sure how to implement the sending of a single message to
another client. Would I just have to send a TCP message to the server
and put the desired recipient as data in the TCP layer which is then
extracted by the server so it knows where to send it?
In an ideal world, the clients could talk to each other directly, since they could find out the IP addresses of the other clients from the server (either via its broadcast or by requesting a list of IP addresses from the server). If all of your clients are running on the same LAN, that can work well.
Assuming you want your system to run on the general Internet, however, that won't work so well, since many/most clients will be behind various firewalls and so they won't accept incoming TCP connections. (There are some ways around that, but they require a very advanced understanding of how TCP works, and even then they only work in certain situations, so I don't recommend attempting them in a first project)
Therefore, for a reliable client->client messaging mechanism, your best bet is indeed to have the sending client send the message to the server, along with some short header that tells the server which other client(s) the message ought to be forwarded to. My own client/server messaging system works along these lines, and I've found it to work well.
I also want to add encryption to the messages which would then no
longer allow the server to read the data, so I'm not sure how to solve
that!?
Don't worry about adding encryption until you've got the basic non-encrypted functionality working first, since encryption will make things much more difficult to debug. That said, it's perfectly possible to pass encrypted/opaque data to the server, as long as the aforementioned header data (which tells the server where to forward the message to) is not encrypted (since the server will need to be able to read the header to know what to do with the encrypted data). The trickier part will be when the receiving client gets the forwarded data from the server -- how will the receiving client know how to decrypt it? You'll need some external mechanism for clients to share keys (either symmetric keys or public/private keypairs), since if you sent the encryption keys themselves through the server, there wouldn't be much point in encrypting anything (since the server could retain a copy of any keys it forwarded, and use them to decrypt, if it wanted to)

Sniffing HTTPS traffic from client program

this might be a dumb question...
I wrote a C++ client program that communicates with a web service over HTTPS with the help of the cURL library.
I am wondering if the person using the client can see clearly the traffic originating from his computer using some sniffing program?
Or would he see encrypted data?
Thanks!
Using a utility like netcat to sniff data on the wire, the user would only see encrypted data. The only way to see the raw data is to log it inside the app, before it's passed to cURL, OR to find it in the machine's active RAM (much more difficult since it's likely to be fragmented).
Not if your app checks for valid certificates.
If your users have the ability to use a proxy server with your app, they could use fiddler's decrypt https sessions function to do this, but it results in an invalid certificate which could be made to stop it from working when detected.
He would see the encrypted data. Sniffers only see the packets, so if HTTPS is working as it should, the packets should be encrypted, and that's all the program could see.
If you would like to try it yourself, learn about ettercap-ng.
I doubt that an average user would be able to do that...
BUT there are ways to do this like:
replacing the cURL library with a proxy (if you link dynamically)
running your program under a debugger and placing breakpoints on the cURL functions
replacing the cURL program with a proxy (if you use it as a commandline utility)
digging deep and diessecting the memory at runtime
From my POV it is improbable (since you need some skill + knowledge + some control over the client environment to pull that off) but possible...
The SSL/TLS protocol is typically implemented at the application layer, so the data is encrypted before it is sent.
If the user has access to the certificate key(s) used to encrypt/decrypt the data, then he/she can plug them into WireShark and it can then decode sniffed HTTPS packets off the wire.

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.

Advice on web services without HTTP

My company is planning on implementing a remote programming tool to configure embedded devices in the field. I assumed that these devices would have an HTTP client on them, and planned to implement some REST services for them to access. Unfortunately, I found out that they have a TCP stack but no HTTP client. One of my co-workers suggested that we try to send “soap packets” over port 80 without an HTTP client. The devices also don’t have any SOAP client. Is this possible? Would there be implications if there was a web server running on the network the devices are connected to? I’d appreciate any advice or best practices on how to implement something like this.
If your servers are serving simple files, the embedded devices really only need to send an HTTP GET request (possibly with a little extra data identifying the device, so the server can know which firmware version to send).
From there, it's pretty much a simple matter of reading the raw data coming in on the embedded device's socket -- you might need to only disregard the HTTP header on the response, or you could possibly configure your server to not send it for those requests.
you don't really need an HTTP client per-se. HTTP is a very simple text-based protocol that you can implement yourself if you need to.
That said, you probably won't need to implement it yourself. If they have a TCP stack and a standard sockets library, you can probably find a simple C library (such as this one) that wraps up HTTP or SOAP functionality for you. You could then just build that library into your application.
Basic HTTP is not a particularly difficult protocol to implement by hand. It's a text and line based protocol, save for the payload, and the servers work quite well with "primitive, ham fisted" clients, which is all a simple client needs to be.
If you can use just a subset, likely, then simply write it and be done.
You can implement a trivial http client over sockets (here is an example of how to do it in ruby: http://www.tutorialspoint.com/ruby/ruby_socket_programming.htm )
It probably depends what technology you have available on your embedded devices - if you can easily consume JSON or XML then a webservice approach using the above may work for you.