Keystore with multiple keys for MTLS client authentication - ssl

I have a keystore with multiple keys where I use one of them for MTLS client authentication. The root CA used to sign this certificate is present in server truststore. But my client sends empty certificate always. This is my client side code
SSLContext sslContext = SSLContextBuilder.create().setKeyManagerFactoryAlgorithm("PKIX")
.loadKeyMaterial(keyStore,password).build();
httpClientBuilder.setSSLContext(sslContext);
Can someone please tell me why my client sends empty certificate when the root CA (issuer) is present in the server truststore? As I understand, the client should send the first certificate that meets the server requirements.

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?

Does TLS client ever require a certificate installation?

In a TLS communication I always thought the server would send the public certificate to the client during the handshake process.
However, I received a request from a provider asking us to manually install a certificate in order to initiate a TLS communication with one of their STunnel server.
I'm a bit confuse by this request. Is there's a situation where TLS server would not be able to send the certificate to the client and therefore required a manuel certificate installation?
There are two cases where a certificate installation is needed on the client side:
The server is using a certificate not issued by a public CA, i.e. self-signed or issued by a private CA. In this case the client must import the certificate or CA up front and install it as trusted.
The server is requiring client authentication based on certificates, i.e. not only the server authenticates to the client with a certificate but also the client to the server (instead or additionally to typical passwords). In this case the client has to get a client certificate and matching key and import so that it can be used for authentication.
It is unclear which of these cases is the one you are dealing with.

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

WCF trust client certificates only from one root ca

When securing WCF services with server and client certificates there is an easy way to ensure the identity of the service provider certificate (server certificate), by comparing the public key or finger print of the sender certificate with an expected value.
On http://msdn.microsoft.com/en-us/library/ff648360.aspx this is explained in step 8. You can config your app.config file in the endpoint section with an identity element where you can pass in the expected encoded finger print value of the server certificate. A comparison between received service certificate and expected value ensures I am talking to the server I expect.
But now I consider the servers point of view. The server can have several RootCA certificates in its certificate store. If the client certificate send from the requester was issued (and signed) by one of these RootCA my service will trust this client certificate. How can I ensure that my service will only trust certificates issued by one determined RootCA? And how can I configure the one trusted RootCA?
(I think this could be some kind of an equivalent way of certificate pinning for client certificates issued by on RootCA)
The only way to achieve this would be to roll your own custom x509 certificate validator. Then for each incoming request you can simply check to make sure the client certificate was issued by your root CA. It's actually quite easy to do. You can find the steps to implement this here:
How to: Create a Service that Employs a Custom Certificate Validator