I am trying to understand how Certificate Pinning works with Self Signed Certificates. My idea is that a Server with a Self Signed certificate will accept the connections only from the clients that have got the Server Certificate (Certificate Pinning).

I have generated the Server's private key & certificate files using the below command

 Server: openssl req -x509 -days 365 -newkey -sha512 rsa:4096 -keyout keyfile.key -out certfile.cert

And then I'm trying to accept a connection with this command

Server: openssl s_server -accept 5000 -key keyfile.key -cert certfile.cert
Client:openssl s_client -connect localhost:5000

The connection succeeds but looks like the Server is sending out its certificate during the Handshake which is not what I'm expecting so I have tried the below command

Server: openssl s_server -accept 50020 -key keyfile.key -cert certfile.cert -Verify 0
Client: openssl s_client -connect localhost:50020

Now the client is unable to connect and the server is giving this error:

 140736924775432:error:140890C7:SSL routines:ssl3_get_client_certificate:peer did not return a certificate:s3_srvr.c:3269:

I am not sure how to specify the Server certificate file from the Client side. I have copied the Server Certificate (certfile.cert) to the client and tried with the below command but this requires a private key as well.

Client: openssl s_client -connect localhost:50020 -cert certfile.cert

Am I getting confused with Server & Client certificates and is there a way for the Client to specify the Server certificate?

1 Answer 1


I think you've misunderstood how TLS and certificate pinning works. The client will not specify which certificate the server will return (apart from using SNI extension to set the expected hostname) but the server will return exactly the certificate which should be used by the client to identify the server. The client will check in your scenario of pinning with a self-signed certificate if the sent certificate matches the expected certificate.

Sending this certificate within a full handshake (i.e. not resumed) is not optional when certificate based authentication is used, i.e. there is no way to make the server not sending the certificate (but still proof the possession of the matching private key) because the client already knows it. For more details take a look at How does SSL/TLS work.

  • Thank you Steffen, things are more clear now. I guess I need to pin the Server certificate on the Client side and the Client certificate on the Server side if I need mutual authentication.
    – AndroidDev
    Dec 8, 2016 at 9:20
  • So, when cert pinning is the case (regardless the certificate received is self-signed or not), we compare the pinned one with what the server sends in addition to regular CA validation. Is that correct?
    – zgulser
    Apr 30, 2020 at 9:57
  • 1
    @zgulser: this depends on the specific implementation and use case. Some pin only against the certificate and thus expect it also when expired or self-signed. Some have pinning in addition to the normal validation. Some do not pin against the certificate itself but expect instead a specific CA which should have issued the certificate and then proceed with the normal certificate validation. Apr 30, 2020 at 11:23
  • ok. so, it can be either one of them or mix of both.
    – zgulser
    Apr 30, 2020 at 11:53

You must log in to answer this question.

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