Self-Signed Certificates with SSL
Today I was playing around with an SslStream implementation in C#, and was able to create a client/server connection over TCP. Also to verify it, I used wireshark to ensure that the data was in fact encrypted, but I have a couple of questions.
First, I should explain the process I went through.
- Create a TCP client with an SslStream layer inside. The TCP client connects to the server and DOES NOT try to authenticate the servers identify (just returns true when validating the server certificate). Once connected, just send a simple message to the server
- Create a TCP server with an SslStream layer inside. The server uses an X509 certificate that I generated with powershell (see this post from MSDN if interested)
- Install the certificate on my server computer's Personal Certificates (which requires me entering the password for the private key that was generated). The server listens, connects to the incoming connection, and prints out the decrypted data on screen.
Now, my question is basically this. What I've set up above, is this essentially a secure connection (e.g. both server and client have the symmetric key and encrypt/decrypt at will), but both are unable to verify "who" is on either end? For example, the client can't be sure of the server's identity, and the server can't be sure of the client's identity. Is this the case?
I want to use this scheme in a IOT project to control a garage door with a smartphone app.
So, my question is leading to another question: if I have my smartphone app (client) establish the SSL connection with my server, and then enter a password in my smartphone app which my server can verify (I guess I could use SHA-2 to hash the password on both ends, but is there any point since the channel is secure?), wouldn't this be able to verify the client from the server's perspective? Am I missing anything here?
For example, the client can't be sure of the server's identity, and the server can't be sure of the client's identity. Is this the case?
Correct. But validating the server certificates only addresses the first point: that the client is not sure about the servers identity, i.e. that the client might actually be connected to some man in the middle attacker instead who is able to sniff and modify the traffic.
Client identity is typically addressed inside the application protocol (i.e. login with username and password) but can also be addressed inside TLS with client certificates.
... then enter a password in my smartphone app which my server can verify ... wouldn't this be able to verify the client from the server's perspective?
Yes, this identifies the client against the server. But as long as the server certificate is not checked it might still be that a man in the middle attacker can intercept the connection and just claim to be the server against the client and claim to be the client against the server - then forward, analyse and potentially modify the data between real client and real server. And the attacker could also sniff the password this way and use it later again to impersonate the real client, without the real client being involved at all. In case of the garage door this would mean that the attacker could control the door even if the owner of the garage is not present.
Using a client certificate would protect against this attack even if the server is not authenticated by the client with a certificate - as long as the server checks that the client certificate is the expected one.