What is the correct way to implement SSL? - ssl

I have a flask application(client) from where I need to send some data to a server(another flask application as of now) and get some corresponding data. I need to use REST because the server can be anything later(the current flask app is a dummy server for testing). I need to have SSL connection between client and server. I see that SSL works in several steps:
Client requests for an encrypted connection.
Server responds with an SSL Certificate which will have a public key.
Client verifies the SSL Certificate
Client creates a private key
Client encrypts the private key with the public key and sends it to the server.
Server decrypts it and gets the private key.
Thus an encrypted connection is established between client and server. Further exchange of data between client and server happens by encrypting the data with the private key.
This is what I am trying to achieve. Please correct me if I got the SSL concept wrong.
I have seen below implementation and works perfectly for me.
Client side uses requests.get() with verify=<path to server SSL certificate>. I have generated SSL certificate for server using openssl as follows.
openssl req -x509 -newkey rsa:4096 -nodes -out cert.pem -keyout key.pem -days 365
But I don't think all the above 7 steps are being covered here. What is the actual way of implementing SSL? Any help would be appreciated.

Client requests for an encrypted connection.
Correct.
Server responds with an SSL Certificate which will have a public key.
Correct.
Client verifies the SSL Certificate
Correct.
Client creates a private key
Incorrect. It is already far too late for this to occur.
Client encrypts the private key with the public key and sends it to the server.
Incorrect. There is no such step. See RFC 2246 and successors.
Server decrypts it and gets the private key.
Incorrect, ditto.
Thus an encrypted connection is established between client and server.
Incorrect, ditto.
Further exchange of data between client and server happens by encrypting the data with the private key.
Incorrect, ditto. TLS works by (1) establishing trust via the server certificate and PKI; (2) optionally establishing trust via the client certificate; and (3) establishing a symmetric session key via a process of key negotiation, in which the actual session key is never transmitted.
This is what I am trying to achieve.
No it isn't. You are trying to establish a TLS connection. What it does is really very little concern of yours.
Please correct me if I got the SSL concept wrong.
You got it totally wrong.
I have generated SSL certificate for server using openssl as follows.
No you haven't. You have created a Certificate Signing Request (CSR). This is useless until you get it signed by a Certificate Authority (CA). It isn't an SSL certificate.
In the above method of implementation, client verifies the server's certificate for every rest call but I dont want to do this. I want to create an encrypted connection between client and server and then the further exchange of data should be encrypted. So, I think the initial creation of enrypted connection between client and server is missing. Also, the private key generation from client side is missing. I want to implement SSL and I think TLS is different from SSL. Correct me if I am wrong.
You are wrong. TLS supports session resumption, which allows for abbreviated handshakes, which eliminates the certificate exchange steps. The 'private key generation from client side' step is missing because it doesn't necessarily exist. You're guessing.

Related

Client Private Key is set as part of client certificate authentication

I'm looking at this example, and I can see that as part of client authentication the user should pass the --key holding the private key used for certificate signing request to the curl command, I'm not sure why this is needed if it's for encryption shouldn't the public key of the server to be used?
Having the certificate itself doesn't prove anything. Certificate is never secret, can be shared freely and as such multiple parties could be in a possession of a valid client certificate.
As part of the TLS handshake with mutual authentication, client sends CertificateVerify message to prove it also has the private key matching the certificate it sent in Certificate message before. With TLS server already having client's certificate (and thus its public key), it can verify the signature.

SSL/TLS handshake between Websphere MQ Server and Client

I'm debugging SSL errors between Websphere MQ Server and Client using T.Rob's suggestions and need help understanding the SSL handshake (SSL connect to MQ using .net mq client SSLV3?).
My WMQ 7.5 client application is C code and uses a keystore (.kdb). Utilizing a CHLTAB provided by the WebSphere admin. The WMQ server is running Java and the channel is defined with mutual authentication.
The article states that in the SSL/TLS handshake, the server always sends its public certificate in response to a connections request. The client then must validate that certificate by first checking the signature and validity date, then looking in its trust store for the thing that signed the certificate.
Here's my confusion: Since my keystore on the client side has only the application personal cert, how does the client validate the public certificate sent by the server? I have provided the Common Name of my application cert to the WebSphere server admin but nothing more than that.
Thanks in advance for the clarification!
The bit about "my keystore on the client side has only the application personal cert" is troubling. That won't work. The client KDB must have the server's public key. If the MQ server has SSLCAUTH(OPTIONAL) the the server's public cert is all that's required in the KDB for the connection to succeed.
The first part of the TLS handshake is where the client validates the server's certificate. The use of public/private key pairs is how the authenticity of the thing on the other side is assured. In order for that to happen the server must have its own personal certificate and the client must have the public key of the root of the signer chain. In the case of self-signed certificates the public portion of the personal cert must be trusted by the client. In the case of CA-signed certs the CA Root must be trusted by the client. Whichever one it is, the client must trust something used to sign the server's personal cert or that cert can't be validated.
The TLS handshake is symmetrical so the second part works exactly the same as the first but the roles are reversed. Therefore, in cases where mutual authentication is enabled the client must have its own personal cert (because that contains the private key) and the server must trust whatever signed the client's matching public key. If the client cert is self-signed the QMgr has to trust it. If the client's cert is CA-signed, the QMgr must trust the signer. Either way, the QMgr has to have a cert to validate the client in its KDB.
Following this logic, for anonymous client connections the required parts are the personal certificate in the QMgr's keystore (because it contains the QMgr's private key), and the matching trusted certificate in the client's KDB or for Java the Trust Store. Neither of these is optional.
If the client is to be authenticated you still need the same two certs as for anonymous clients because that part of the handshake has to complete before the client is authenticated. In addition, now you also need the client to have its own personal certificate (because it contains the client's private key) and the QMgr now needs to trust whatever signed the client's certificate - the client cert if self-signed or the signer root if CA-signed.
As a side note, There is also some confusion in the post because it says that "My WMQ 7.5 client application is C code and the WMQ server is running Java." There is nothing in the queue manager that uses Java on the server side. There are Java components installed to do things like manage JNDI objects and run the sample code. In modern MQ versions Java runs the Web Console. But there are no Java components in the QMgr itself and no Java components in the path of the incoming channel connection request. That's all habdled by the QMgr's listener, agent, and other internal processes. So I'm not at all sure what is being referred to there other than that the notion of Java running on the MQ server side and participating in the TLS handshake might be a source of some of the confusion mentioned in the post. ;-)

SSL approach for private software

What is the proper way of using SSL certificates for private applications? By private I mean that I am the only user, and software is running on my computers.
I want to have a encrypted communication between two of my programs. I want to send passwords between them, so I need to be sure that remote program is not fake/hacked.
As far as I understand I don't need to get paid SSL certificate from the CA, if there is no third party involved.
Is the following correct?
Server has a private key and self-signed SSL certificate.
Client has a copy of server's self-signed certificate (it needs to be well protected).
During the handshake server sends the certificate to client.
client checks if the certificates are the same.
client can start encrypted transmission.
Is there other way?
Server has a private key and self-signed SSL certificate.
Yes
Client has a copy of server's self-signed certificate (it needs to be well protected).
The client has either a copy of the certificate or the certificates public key or the fingerprint of these. Since the certificate is public these information do not need to be protected. Only the private key of the server (residing only in the server side) needs to be protected because using this key one could prove ownership of the certificate.
During the handshake server sends the certificate to client.
Yes.
client checks if the certificates are the same.
Kind of. It might check the certificate or the public key or the fingerprints.
client can start encrypted transmission.
Yes.
I would recommend that you read the OWASP article about certificate and public key pinning. It also contains sample code for various environments.
Client has a copy of server's self-signed certificate (it needs to be well protected).
Clients do not have copy of the server certificate. They get it in SSL handshake
client checks if the certificates are the same.
NO! Clients will have the public certificate of the Certificate Authorities who would have signed the server certificate. They will validate the server cert with the CA cert including things like certificate expiry, CRLs. Not compare for 'sameness'
In your case you are using the self-signed certificates. The clients should be made to ignore the self signed certificate and proceed with SSL handshake.
I would recommend you read through SSL handshake sequence again.

OpenSSL and s_client - why is a private key required from the client?

I need to setup a 2 way SSL communication channel between a .NET/WCF application and a third party web server. Right now I am trying get a successful handshake with the host in order to validate that all the elements are setup correctly (client certificate, server certificate authority, network communication...). I'm using the openSSL command line tool to try and validate this, using the s_client command.
Here is what is stopping me, and what I don't understand:
whatever I do, openSSL is expecting to find a private key for the
client certificate
the client certificate was given to me by the third party, but it
does not contain any private key
if I just generate my own private key file using openSSL, I'm getting
a key values mismatch error
Keep in mind that I have just started getting my hands into SSL so I have a very basic understanding of the whole protocol. From what I've been reading, it seems that both server and client need their private key in a 2 way SSL setting. However, I can't figure out how to get a working private key on my client (working with the client certificate that was given to me).
I would very much appreciate if somebody could shed some light on client certificate private keys, as this is giving me a major headache.
Certificates on their own are only public pieces of information. What links a public key certificate to the name it contains is the fact that whoever has legitimate control over that name (e.g. your name or your server's name) also has the private key for it.
Certificates are used to prove the identity of the remote party by challenging the remote party to perform an operation that can only be done with the corresponding private key: signing something (which can be verified with the public key) or deciphering something that was encrypted with the public key. (Both can happen in the SSL/TLS handshake, depending on the cipher suite.)
During the SSL/TLS handshake, the server sends its certificate (in clear) and proves to the client that it has the corresponding private key using an authenticated key exchange.
In your case, you also want to use client-certificate authentication. It's not enough to send the client certificate during the handshake: the client must also prove it has the private key. Otherwise, anyone who receives that certificate could clone it. The point of using certificates is to prevent any cloning, in such a way that you never have to show your own secret (the private key).
More specifically, the client has to sign the handshake messages in the Certificate Verify message of the TLS handshake so that the server can verify it against the public key sent in the client certificate. Without this step, no client-certificate authentication would be taking place.
the client certificate was given to me by the third party, but it does
not contain any private key
Giving you your certificate without its private key seems a bit pointless, unless you're expected to have generated a certificate request on your side beforehand (in which case you would have the private key).
Indeed, rather than being given a certificate and its private key, it's better practice for you to generate your key-pair, create a certificate request (CSR), and have your CA issue a certificate from that CSR (but without them ever knowing your private key). In this case, you would be expected to have kept your private key, and you would be able to use it with the cert you would have received.
This is an interesting question. I was puzzled by TLS related errors while configuring LDAPS, my learnings here.
The names, "public key" and "private key" sound like it's an one-way operations, but it works both ways, anything encrypted by one key and be decrypted by another key - just that one key is made public
Info = openly available data, with unknown integrity - it could be tampered by 3rd party
Signature = Info encrypted by a private key, accompanies Info
Verifying signature = use public key to decrypt the signature and get Info back thus proving "whoever created the signature knows the private key", or, the Info is untouched after it's signed
That is, unless the private key is stolen
Certificate = Info + Signature + public key + private key
Info = the meat
Signature = to verify integrity of Info
public key = to verify other certificates, see Certificate Chain
private key = not included in certificate itself but should be kept by certificate owner, could be used to sign other certificates
Certificate Authority (CA) = Anyone who holds a public / private key pair and creates certificates
CA identity is indicated in Info on a certificate
Certificate Chain = Use public key on mother-certificate to verify the signature on a child-certificate, to ensure child-certificate was created and signed by mother CA
And mother created and signed by grandma, so forth
Root CA = Root CA is the CA you trust unconditionally
Because their certificates (Root Certificates) are pre-loaded in your browser or OS as a source of trust
Also because their certificates are self-signed, its Signature is created using its own private key, verified by its own public key
This could be confusing, but think it as the origin of certificate-based encryption - only when people found out that relying on a few Root CA's to create and sign countless certificates are insecure (private keys might get stolen) and impossible (rapidly increasing demands of certificates), they came up with the idea of certificate chains
Root CA's only create and sign certificates for some Intermediate CA's so private keys are not used too often and is safer
Intermediate CA's can create and sign millions of certificates and get their certificate revoked when a private key is known to be leaked
This is the reason you don't often see the Root Key Ceremony, which signifies the importance of the private key for a Root Certificate: the less the private key is used, the less it could be exposed
Self-Signed Root Certificate = virtually the same as a Root Certificate - just no one but the creator would trust
TLS Handshake = server sends certificate, client validate is against the certificate chain, when verified, exchange a "password" securely
The "password" is then used to encrypt actual data transfer using symmetric encryption
Asymmetric encryption is not used for actual data due to its need for intense computation powers
Client Certificate Authentication = in addition to previous process which authenticates the server, the server demands a valid certificate to be provided by the client, also a signature of previous handshake messages
The signature is created using the private key of the certificate and can be verified by the public key on the certificate
This proves the ownership of the certificate
This is used usually for restricting access to known individual clients
Using certificates means no man-in-the-middle or replay attack could happen
This is often seen in finance or IoT
This is also utilized by LDAPS, which caused mystic error messages when I had a valid certificate in my local keystore but it was not accompanied by its private key
...So, in terms of openssl, when you use -cert you indicate Client Certificate Authentication, with which you will need -key to specify the corresponding private key.
However, for many Web scenarios, even if the certificate for a server is signed by a homemade CA, one only need to add the homemade CA to truststore or keychain then server certificate can be validated. This is done by using -CAfile.
Bottom-line.. If you're sending client certificates, then you would need the client certificates' private key to encrypt the pre-master secret

SSL and public key security

I'm consuming a web service from an Android device using HTTP(s) with SSL. A self-signed (untrusted) certificate is used for client authentication.
I have a general understanding of how public/private keys are used for SSL. From my understanding I can clearly see how a certificate can be used to set up a secure connection and transmit data securely. However I do not understand how they are used for client authentication since the certificate contains the public key and is not kept a secret.
I have a few questions:
Where can I read about how SSL and certificates can be used for client authentication?
Even if the certificate was not made public...by visiting the HTTPS URL in a browser I can view and save the certificate. I can then package up the certificate in a key store and use it from an application.
In this post Jeremy Huiskamp writes
client auth will automatically be performed when the server requests
it
...so client authentication as well as encryption of data can be performed with certificates?
Edited to answer the first part of my question: The client keystore should contain not only the server's public key but also the client's private key. The server must then be able to decrypt using the client's public key? Does this mean the keystore should have two certificates?
First, a quick point about the terminology in public key cryptography:
you sign and decrypt/decipher using a private key,
you verify (a signature) and encrypt/encipher using a public key.
(You don't really "decrypt" using a public key.)
Using SSL/TLS with or without client-authentication, the server presents a certificate (*) for which it has the private key. The server sends its certificate during the SSL/TLS handshake (at the beginning of the connection) and is able to decipher what the client sends using its private key (which it keeps private). The private key and certificates are stored in the server's keystore (or equivalent if it's not implemented in Java).
As part of this, the client uses its truststore, which is a form a keystore that contains trusted certificates, to verify the server certificate. The server certificate could be trusted by being explicitly in the truststore or, in most cases, trusted by linking in to a trusted CA certificate in the truststore (PKI).
The terminology between keystore and truststore in Java can be a bit confusing, you can find more details in this answer.
Regarding your question, the client's truststore doesn't contain the server's public key, but either its certificate or a CA certificate with which it should be verifiable. (It's not just about having the public key, but knowing whose it is, using the other pieces of information in the certificate.)
When you use client-certificate authentication in addition to this, there is a truststore (or equivalent) on the server side and a keystore on the client side too, since the roles are reversed for this purpose.
In the SSL/TLS handshake that uses client-authentication, the server requests a certificate from the client, who sends it (if available).
At the end of this handshake, the client sends a CertificateVerify message, which signs all the messages exchanged so far between the client and the server (so it's something known to both) using the client certificate private key. The server is then able to verify this signature against the public key within the client certificate it has obtained as part of this exchange. This proves to the server that whoever is on the client side has the private key corresponding to the public key in the certificate it has sent.
The next step for the server is to verify whether to trust this certificate, i.e. whether to trust the binding between identity and public key as presented and "sealed" within the certificate.
This is usually done using a PKI, whereby you check the certificate against a known CA, or if your deployment environment is sufficiently small, against a fixed set of trusted certificates. (There can be alternative methods of verification, but their usability will really depend on the circumstances where you want to deploy this system.)
Therefore, for your second question:
The client keystore should contain at least the client's certificate and its private key.
The client truststore should contain the server certificate or a CA certificate with which the server certificate can be verified.
Since both keystore and truststore are a keystore (in the storage format sense, usually a file) used for a different purpose, it's often possible to use the same keystore to serve both the purpose of keystore and truststore.
(*) There are cipher suites that don't rely on certificates, but that's unusual and off topic for this question.
A certificate just binds an identity to a public key. This binding is not secret, so there is no need to keep the certificate secret. If I have John Smith's certificate, I can prove that John Smith owns the secret key corresponding to a particular public key. But since I don't know that secret key, the certificate is of no use to me.
When authentication occurs by certificate, one step is always to have whoever presents the certificate prove they know the secret key corresponding to the public key in the certificate. If you cannot pass that step, the authentication fails.
The server's keystore should have the server's certificate. The client's keystore should have the client's certificate. The client will present its certificate to the server, so the server will learn the client's public key that way. (And vice-versa.)