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?


  • Secure from what? The fact that something is encrypted does not mean it is secure.
    – nethero
    Apr 11, 2021 at 20:42
  • OP, wrt, "I guess I could use SHA-2 to hash the password on both ends, but is there any point since the channel is secure?" - hashing the password on the server side prevents the password from being leaked in the event that the server is compromised (see security.stackexchange.com/questions/211/…). Hashing the password on the client side accomplishes very little (see security.stackexchange.com/questions/8596/…). The password is encrypted in transit by virtue of the TLS connection.
    – mti2935
    Apr 11, 2021 at 23:03
  • So basically it's so the password isn't stored in plain-text on the server? But you would actually send the password raw in transit (over a secure channel)? I never understood this, but this makes sense imo
    – michael b
    Apr 12, 2021 at 0:30
  • @MichaelBurt Yes, that's correct. Standard practice is to salt and hash the password on the server side, using many rounds of a slow hashing function and store the result. This way, the server can verify that the password provided by the user is correct, but if an attacker gets a hold of the salted+hashed password, it will be difficult for him to reverse this to get the user's underlying password. See security.stackexchange.com/questions/211/… for more info on this.
    – mti2935
    Apr 12, 2021 at 12:53

3 Answers 3


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.

  • I'm not really sure how to deliberately generate a client certificate within the SSL framework. I guess if I figure out how to do that, I just store that .cer file in Trusted Root Certificate Authorities on my server so my server application can validate it. This question might be really dumb, but how can my client validate my server's self-signed certificate? Also, a follow-up, but related, how would someone establish a man-in-the-middle attack? Wouldn't they need my server's private key to do so?
    – michael b
    Apr 10, 2021 at 22:39
  • @MichaelBurt: As long as the client does not check the servers certificate properly the MITM attacker don't need to use the original server certificate and thus don't need the private key - the attacker can simply create its own certificate. A self-signed certificate can be validated in various ways, for example treated like yet another trusted CA and just put in the CA store or it can be checked if the certificate or public key inside matches a specific fingerprint (this is called pinning). The same can be done for the client certificate on the server side. Apr 11, 2021 at 6:48
  • @MichaelBurt your client can validate server certificate against his truststore, you can explicitly trust any given self-signed certificate. If you want to generate a client certificate you need to create csr configuration file and specify client EKU so you can then use it for generating the CSR.
    – nethero
    Apr 11, 2021 at 8:47

Password-based authentication (as you describe in the last paragraph of your question) is perhaps the most common way for a client to authenticate with a server in https. Another method is to use client certificates.

With regard to the client authenticating the server, you write:

The TCP client connects to the server and DOES NOT try to authenticate the servers identify (just returns true when validating the server certificate).

Without the client authenticating the server's identity - this opens the door to a Man-In-The-Middle (MITM) attack. An attacker that is able to position himself between the client and the server can present his own certificate to the client. If the client does not authenticate that the certificate is the true and correct certificate for the server, and the client trusts the certificate of the MITM, then the MITM can intercept and/or alter all communication between the client and the server. This is why it is essential that the client authenticates the server's certificate. Normally on the web, this is done through PKI, where trusted CA's authenticate servers certificates, then sign the certificates to indicate their 'stamp of approval'. Another way of authenticating a server certificate is to use 'certificate pinning', where the server's certificate is stored by the client, and the client checks that the certificate presented by the server matches the one that the client has stored. Certificate pinning is common with IOT clients.

  • Thanks a lot for the term "certificate pinning". Hadn't heard of it before, but this is exactly what I'm looking for. Going to start googling now. I had no idea how SSL would work outside of CA authentication, but this makes sense. Thanks
    – michael b
    Apr 10, 2021 at 22:48
  • Sorry for beating this to death- but could I just check the public key of the server from my client to ensure that it really is my server? Is that adequate?
    – michael b
    Apr 10, 2021 at 23:12
  • Yes! This is known as HTTP Public Key Pinning (HPKP). See developer.mozilla.org/en-US/docs/Web/HTTP/Public_Key_Pinning. Note that many articles about certificate pinning and HPKP nowadays will say that these standards are now deprecated - and this is true in the context of web browsers. But, certificate pinning and HPKP are common in IoT systems.
    – mti2935
    Apr 11, 2021 at 0:28
  • You may want to look into the so-called "tofu" security model (Trust on First Use) — this is the primary security model that OpenSSH uses. Apr 11, 2021 at 0:55
  • Awesome, thanks so much for the help folks! It's been fun playing around with this a bit. Today I got my proof of concept IOT app working with SSL, with a self-signed certificate on my server using public key pinning on my smartphone app.
    – michael b
    Apr 11, 2021 at 5:06

Let me start by saying that SHA-256 is not an encryption algorithm, it is a hash so you can't:

I guess I could use SHA-2 to encrypt the password on both ends, but is there any point since the channel is secure?

Sha-256 is a hash algorithm that on its own does not provide any security as hashes are deterministic in nature, in other words, if you know the plain text you'll know the hash and you can map known hashes to known plain texts (rainbow tables). There is no sense to talk about security if you don't present a threat model. The question as such is too general to be answered. As suggested in the comments, you may use certificate pinning to distribute your self-signed certificate in an out-of-band fashion, but that does not provide much flexibility and limited security.

What you need to understand is that a self-signed certificate on its own (without pinning) provides no security besides the cryptographic aspect of it, there is no authentication. You should avoid use of them in commercial applications. Certificate issued from a trusted CA (be it private or public) is a better option and pinning them provides much more security and flexibility to your application. If you pin the self-signed cert, there is no revocation available, no CRL or OCSP. In order to invalidate your certificate you'll need to change it on the server and push it to the application this can lead to long outages.

  • I will add here that I understand what a hashing algorithm is. The comment you replied to is more of a question of, "do I need to hash a password if it's already over a secure channel"?. I had questions regarding self-signed certificates that others have answered. Fundamentally I wanted to create a secure channel between myself (running a client on a smartphone app) and my server at home. Using certificate pinning (as I recently have learned), I'm able to verify the identify of the server, and through a username/password scheme I will be able to verify the identify of my client from my server.
    – michael b
    Apr 11, 2021 at 18:10
  • Also, what do you mean "a self-signed certificate provides no security besides the cryptographic aspect of it"? There's no way this is true, as the key-exchange + RSA encryption provides a secure channel that prevents eavesdropping. Even if you didn't authenticate who was on the other end, the channel would still be secure (just subject to MITM attacks).
    – michael b
    Apr 11, 2021 at 18:14
  • @MichaelBurt Please read it one more time. It provides no security besides the cryptographic aspect of it. In other words it gives you only encryption and no authentication which is a crucial element of SSL communication. Is MITM only attack you're concerned with? Cause without pinning I can redirect you to any server with selfsigned cert and your app will hapily take it. You can't revoke self-signed cert so if someone obtains the key from your server he'll be able to impersonate it and the list goes on.
    – nethero
    Apr 11, 2021 at 20:36
  • @MichaelBurt and your need for pinning really comes from the fact that you're using a self signed certificate more than a strong security practice. So there is nothing wrong with my answer, please go and change the "encrypt" to "hash" in your question.
    – nethero
    Apr 11, 2021 at 20:40
  • 1
    A secure system needs to provide three things: secrecy, integrity, and authenticity. If any one of these fails, the whole system fails (see moxie.org/2011/04/11/ssl-and-the-future-of-authenticity.html for some interesting reading on this subject). WIth https on the web, authenticity is usually handled by PKI, using trusted CA's to issue and sign certificates. However, self-signed certificates are fine, as long as there is some out-of-band method of authenticating these certificates. OP's idea to pre-share the server certificate, and pin the cert on the client side is sound,
    – mti2935
    Apr 11, 2021 at 22:15

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .