SSL approach for private software - ssl

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.

Related

Which client certificate auth validations are done by NGINX for auth-tls-verify-client = optional_no_ca

We have a K8S service leveraging NGINX and in some flows would like to accept client certificate authentication.
Service has a dynamic list of public trusted client certificates (PEM format), and the root CAs aren't known.
In NGINX, it seems like the best setting to use would be:
nginx.ingress.kubernetes.io/auth-tls-verify-client: optional_no_ca
While sending the full certificate ($ssl_client_escaped_cert) to the upstream service to compare the entire public cert.
The question is whether NGINX will still perform the client cert validations during SSL handshake (and only skips CA checks), to verify the request is indeed sent by the one and only owner of the cert and its private key.
It will still check in the TLS handshake that the public key in the certificate can be used to verify the signature in CertificateVerify, i.e. that the client actually owns the private key to the sent certificate.
It will not check that the certificate itself is issued by a trusted CA etc - such verification are expected to be done elsewhere.

Mutual Authentication TLS

What is the use of mutual authentication in TLS without restricting the client cert?
Here is my understanding about client/mutual auth using TLS.
The idea is that both the server the client authenticate/verifies each other certs so,
1- The client verifies the server cert based on its CA trust store
2- The server verifies the client cert based on its *CA trust store*
Now the key point to me is the second one, the server has to trust the client certificate by either saving it in the server trust store, or save the CA/ICA of the client cert, which should be private to the client, not via public CA, private CA to that client that the server wishes to trust.
Now [rfc5246][1] says the following
If the client has sent a certificate with signing ability, a digitally-signed
CertificateVerify message is sent to explicitly verify possession of
the private key in the certificate.
This won't achieve any authentication correct? for example, if I have a server that trusts any certificate signed by the trusted CAs around the world, then why bother at all with client authentication at all?
[1]: https://www.rfc-editor.org/rfc/rfc5246
When the server gets the client cert (as part of the TLS protocol), the server does all the normal cert checks, including chaining up to a trusted root. For the server to trust a client cert issued by Foo CA, the server needs to have the Foo CA root already installed at the server.
The corner stone of X.509 certs is root CA certs. A host should only trust certs issued by the CAs it trusts. So when an admin installs FooCA's roots, the admin is stating "I trust the certs issued by Foo and I trust that Foo did appropriate checks that the cert is valid and assigned to the correct entity."
The server does not need to store the client's cert, there's no reason to. When the cert comes in as part of TLS, the server simply checks it. No persistence needed, and if anything fails, and that includes not having the Foo CA root cert installed, then the connection fails.
The server DOES authenticate the client. A certificate binds a public key (in the cert) to an entity; for example CN=frodo#theshire.com. When the client connects and the server asks for the client cert, the server will check that the name in the cert (frodo#theshire.com) matches the name of the user, but it will also get the client to encrypt some data using the private key associated with the public key in the cert, and if the server successfully decrypts the data, then the client (frodo#theshire.com) really is who they claim to be. Or, in the worst case, an imposter who got access to Frodo's private key :)
Does that help?

SSL Certificates and browser to web-server connectivity

I am sure this is embedded in the details of the SSL certificate/HTTPS specs but I am not entirely grokking this subject.
If a modern browser connects to a HTTPS site, the body of the HTTP request is encrypted. Is the SSL certificate essentially the "public" key used to communicate back and forth between the client and server?
Couldn't a hacker get the public key from the public site, say "https://www.google.com" and monitor client/server traffic and decrypt the data?
Also, do clients need to verify the "issuer" of a certificate. For example, self sign certificates clients don't need to verify but for certificates provided from a trusted issuer, what happens during the certificate verification process?
The server's certificate contains a public key which in fact is visible to everybody. This key in turn is used during the handshake between the server and client in order to create a unique session key that will be used to encrypt any further messages:
http://en.wikipedia.org/wiki/Secure_Sockets_Layer#TLS_handshake_in_detail
Couldn't a hacker get the public key from the public site, say
"https://www.google.com" and monitor client/server traffic and decrypt
the data?
The hacker won't know the session key. He will be listening to (senseless) encrypted stuff.
Also, do clients need to verify the "issuer" of a certificate. For
example, self sign certificates clients don't need to verify but for
certificates provided from a trusted issuer, what happens during the
certificate verification process?
Like you said, the issuer of the certificate is verified against a pre-defined list of trusted authorities. Any certificate up in the chain will be verified too, including the trusted issuer, expiration dates. Additionally each certificate contains URLs that point to Certificate Revocation Lists (CRL Distribution Points), the client will attempt to download the list from such URL and ensure the certificate at hand has not been revoked.

Is it possible to prevent man-in-the-middle attack when using self-signed certificates?

I'm not sure is similar question has been asked before (I couldn't find any), but is it possible to protect Client/Server from Man-In-The-Middle attack?
I'm writing a Client application to communicate with Server. Communication will be SSLv3 based.
I am OK with server's self-signed certificates, but worried about someone else generating same self-signed certificate in the same server name and pretend to be it. My Client application uses OpenSSL library. [Client and Server are thrift based, if it makes any difference]. Can I avoid such attack at the same time maintaining support for self-signed certificates?
Yes.
In short, a self signed certificate is more insecure than a CA certificate only when the client does not know the certificate in advance and therefore has no way to validate that the server is who it says it is.
If you add the self signed certificate to the client and don't accept any other certificate, you're actually as secure (or, one could argue, even more so) than having a certificate authority signed certificate.
The important parts to keep SSL secure with or without a certificate authority are;
The server private key (and in the case of a CA, the private keys of all its roots) is kept secret.
The client knows the server certificate (or its CA root).
You can hard-code the server's certificate and compare it against what you receive.
Or better yet, create a CA certificate and server certificate, signed by the CA. Have the CA trusted on the client (again by hardcoding it in your application) and validate received server certificate using the CA certificate.
If you can protect your private keys well enough, a middleman will not be able to masquerade as you, assuming the user actually looks at the certificate. The problem with self-signed is that if you want the user to add the exception to their browser, or just ignore the warning, then you are exposed to man-in-the-middle attack, because anyone else may create their own certificate.
Of course, "protecting your private keys well enough" is not trivial at all. When you pay for a "Verisign" certificate, you're not paying for their software creating the certificate - you're paying for the security forces they have guarding the building in which the private keys are stored.
That's easy! NOOOO !!! Not anymore than you could prevent a man-in-the-middle attack from certificate issued-by a well-know authority. >:)

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.)