We have multiple programs hitting one WCF Service. When a client sends a message they get to define both a client certificate and a service certificate. To do signing and encryption. As far as I know a service can set both at start up. But i'm finding difficulty on how a service would check certificates on a per request basis.
If program A uses a certificate and program B uses a different certificate. Is there a way to tell WCF how to look up those certs without using the windows certificate store? I know how to load a X509Certificate2 from a file but can't seem to find what piece needs to be overridden to tell it to use a specific cert based on what is coming in. Everything I have done so far looks for that clients cert in the cert store. Business rules would rather we placed them somewhere else that we are encrypting. I would like program A's request to use one file and program B's request to use another that I can specify.
In order to do client authentication, you actually need a certificate + a private key, i.e., not just a certificate.
You need a .PFX file that contains both a certificate and its corresponding private key. PFX are password protected.
Here is a sample code:
Client client = new Client();
var cert = new X509Certificate2(File.ReadAllBytes("c:\\certificate_with_key.pfx"), "pfx_password");
client.ClientCredentials.ClientCertificate.Certificate = cert;
Related
In my project, I need to check and validate client certificate for each users' request and then give them access to calling my APIs. My users are machines (other API or library). They append a certificate(s) to their request and send it to my hosted API.
I implement a custom authentication handler and retrieve client certificates successfully. Right now, I compare client certificate with a list of valid certifications in my appsetting.json (Thumbprint, Issuer and Serial number).
If all of these three properties are same as the client-certification, I return return Task.FromResult(AuthenticateResult.Success(ticket)); otherwise I return
return Task.FromResult(AuthenticateResult.Fail("certificate is not valid"));
everything works fine but I do not feel good about how I validated client certificate. I would like to know if there is elegant way for validating client certificate rather than my solution in ASP.NET CORE.
Issuer and Serial number are controllable by an attacker, so they are not suitable for validation purposes.
Thumbprint is a SHA1 of multiple properties of the certificate, including issuer, serial number, public key. That's probably OK, for now, and can't be changed by .NET because it's a Windows feature, but thumbprints are meant for reference, not security.
A better approach would be to compare the certificate Signature and hash, and put a minimum quality on the hash of SHA256 or higher. cert.SignatureAlgorithm.Value; will give you the algorithm as an OID, you can then new up an System.Security.Cryptography.Oid with that and get use the FriendlyName property to get the algorithm in text, but getting the actual signature isn't supported, you have to restore to 3rd parties like BouncyCastle. So that's probably out, because it seems silly to take a dependency for that.
Really this boils down to how you register the client certificates. What I would do is ask for the certificates (or have a registration process somewhere, like, say nuget has for signing certificates), put them into the X509Certificate2 class then create a SHA256 hash of the RawData property and add that to your allow list. Then do the same for incoming client certificates and compare the SHA256 of the rawdata from the inbound certificate against your allowed list. Of course now you have to cope with certificate expiration ...
We use a multi-domain SSL certificate. Each time we add more client URLs, we obtain a new version of the certificate (with the newly added domains) and complete the request on a specific machine that the certificate request was originally created on. The single machine that the CSR was generated was formatted recently. Are there other method(s) that we could complete the certificate requests without that machine being available? Are there better ways of doing this by not being dependent on any single machine?
Please note that by creating a new CSR on another machine, we will need to ask all our clients to validate this new SSL and that is something we would not want to do.
Update 1
We got the certificate and the private key from another machine that was using it and imported them to our server. Whenever we try to "Request Certificate with New Key" in certmgr, we get "Enrollment Error - The request contains no certificate template information". How do we resolve this?
I am tring to figure out how a secure connection between client and server is established. I tried the SSL example provided by boost::asio library. My question is about the certifacte used by client and server. To be specific, I generated a private key(mykey.pem). Then I used this private key to generate a self-signed certificate(mycert.pem) and I used these files as follow:
Server side:
1)context_.use_certificate_chain_file("mycert.pem", error);
context_.use_private_key_file("mykey.pem", boost::asio::ssl::context::pem, error);
context_.use_tmp_dh_file("dHParam.pem",error);
Client side:
2)ctx.load_verify_file("mycert.pem",error);
With this code the handshake is done perfectly. My question is that how come both the server and client use the same certificate ("mycert.pem") in commands 1 and 2? With this approach a client can pretend to be a server easily.right? Do you think that I missed something here?
The certificate is public information.
It's the private key that allows the entity to prove its identity. The client is guaranteed by the SSL/TLS handshake that only the party with the private key matching the public key in the server certificate can be at the other end with the suitable master secret, so as to be able to decipher the communication. The problem it addresses is whether or not the remote party is indeed the one to which the certificate was issued. (This is similar to checking that the picture on the photo ID matches the person in front of you.)
Configuration of the certificate (and not the private key) on the client side is there to tell it which certificates you are willing to trust. The problem it addresses is whether or not to trust what the certificate say (in particular what it says about the identity of the server). This is normally done using a PKI, so as to build trust via 3rd parties (the CAs). (This is similar to checking that the photo ID itself is genuine, and that you can trust what it says.)
What you've done by trusting this specific server certificate is bypass the use of CAs to make an exception and indicate you were willing to trust this particular certificate to be genuine. (This is fine for a handful of certificates, but using a CA allows your trust structure to be more manageable and add other features, such as the ability to revoke certificates.)
Currently I am having a problem connecting to the server due to the following issue:
When I tried to connect to the server, it returned an error: MQRC_SSL_INITIALIZATION_ERROR
Upon closer analysis via WireShark, I found that the Client is attempting to connect to the server using SSL v2, while the server can only accept SSL V3, thus rejecting the connection.
I checked through the document, but am not able to find any information on
what SSL version the .Net client supports.
I would like to check whether the SSL version is controlled from the .Net MQ
client, and if so, how can we configure to make it connect via SSL v3?
Thanks.
I'm not sure I agree with your conclusion since WMQ has supported SSL V3.0 and TLS V1.0 since at least V6.0 and possibly earlier. This is more likely a mismatch of configurations between the client and server. The procedure I recommend to resolve SSL/TLS issues is as follows:
My method for debugging SSL connections on WMQ is to progress through the following sequence making sure each step works before advancing to the next:
Get the channel running without SSL. This validates that the channel names are spelled correctly, that a network route exists between the endpoints, that the QMgr's listener is running and that the client points to the right port. You'd be surprised how many times someone mis-keys a port or channel name.
Get the channel running with the SVRCONN definition set to SSLCAUTH(OPTIONAL). This performs an anonymous SSL connection similar to what your browser does. The QMgr presents a certificate to the client but the client is not obligated to send one back. This validates that the QMgr can find its certificate and that the client can find its trust store and properly validates the QMgr's cert. (Note: the QMgr will always request the client cert and the client will always send it if one is present. To perform this test, use a copy of the client's keystore that has the signer cert(s) but not the application's personal cert. Copy the keystore and delete the personal cert from the copy. Do NOT delete the original!)
Set the SVRCONN channel to SSLCAUTH(REQUIRED). This now requires the client to find its keystore (in the last step it required only its trust store) and to be able to find its certificate. It also requires the QMgr to be able to validate the client's cert.
Set up SSLPEER or CHLAUTH mapping rules to narrow the population of validated certificates that will be accepted on the channel.
The difference between steps #2 and #3 helps to isolate the problem by testing the SSL credential exchange in only one direction at a time. This allows you to identify whether the problem exists in the personal cert or the public cert and on which side of the channel. Nearly all problems are sorted out in these two steps.
UPDATE
Notes to respond to questions. There are two types of certificate used with SSL/TLS. The personal certificate contains the private key and is the one that doesn't get passed around. The public certificate is the one that contains the public key and can be given out freely. The private key is held in a keystore. The public keys (usually these are the CA's root and intermediate certs) are stored in a trust store. In some cases, these are separate files. For example, in Java and JMS the JSSE provider looks in the environment for variables that point to the keystore and to the trust store. It is possible in Java and JMS that the keystore and trust store variables point to the same file.
In the case of WebSphere MQ servers and clients other than Java, the keystore and trust store are combined into a single location. Often referred to as a kdb file, it is actually a CMS key database comprised of several files of which one is the KDB. In this case "keystore" is actually shorthand for a combined keystore and trust store. For the .Net client, set the keystore location and other SSL properties in the MQEnviornment.
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. If the thing that signed the certificate is an intermediate signer cert (it has itself been signed by something) then the search continues up the signer cert chain until the root cert is reached. Assuming that the server is authenticated, the same procedure is applied in reverse by having the client present a cert and the server validating it.
When the process fails in Step #2 we can debug using knowledge of the process above. The QMgr must first find its cert in its keystore and present it to the client. If the QMgr cannot find its cert, the result is errors in the AMQERR01.LOG file stating this. Always look on the QMgr side first when things die in Step #2!
If the QMgr does find its cert then the next step is that client must be able to find its trust store and then within that trust store must find the necessary signer cert chain. If this fails, there should be errors on the client side to indicate that. For example, a common error when setting the client environment is to specify the entire file name, including the .kdb extension. When this happens the QMgr looks for [keystorename].kdb.kdb which doesn't exist. Another common error is that the personal certificate exists in the keystore but with the wrong label. Non-Java WMQ clients look for the certificate by label name constructed from the literal string ibmwebspheremq followed by the user ID in lower case. For example, if my user ID is TRob then my certificate label would be ibmwebspheremqtrob. Note that this is the certificate's label in the keystore and NOT the certificates Common Name or other field in the Distinguished Name.
Depending on the type of client in use, these may be in the Windows error log, local MQ error logs or other location. If you can't find client-side errors, WMQ tracing is also an option.
Firstly, Thanks to all those patient techies trying to help unknown people.
Secondly, I have a wcf service which should be consumed by only several clients (10) known to our company. This wcf service has the x509certificate "CN=ABCD". Now it expects to receive a certificate in turn from clients to consume this service. So here are the design questions
Should I create one certificate
"CN=ABCD" , then right click on it
and export as pfx files and
distribute them to Clients?
Some say to validate in code and
some say to validate in config which
is better?
How should I know which client is
calling as the certificate has same
name for all if my company
distributes it?
what is the difference between .cer
file and .pfx file?
When passing the certificate to
clients, will I be giving both .cer
and .pfx files?
How should I be revocing only one
client if it expires?
My comapny already has a certificate
like *.fdfd.org . Can I use this as
my X509Certificate instead of
generating one?
Many questions! But due to lot frustration, I wanted to have the opinion of developers out there because I couldn't get the right info.
NO You must have separate certificate for the service and you should have one certificate for each client. Once you share private key of your service your security has gone.
You can either install public keys of client certificates to Machine\Trusted people (client with any trusted certificate will have access to your service) or you can use custom certificate validator (only message security - according to your previous question you probably use message security) to validate really only those 10 certificates.
This is only possible if you create separate certificate for each client. It is also possible to combine certificate with supporting user name and password but it requires very advanced WCF configuration and still sharing single certificate among multiple clients is a bad decision.
Certificate is just container for some information - keys for asymmetric encryption. .cer contains only public key which can be freely distributed - you will probably have to distribute .cer file of your service's certificate among clients. .pfx contains both public and private key and must be secured as much as possible. Once .pfx file is compromised the certificate is not secured any more and must be replaced. Because of that you must keep your service's .pfx (installed in certificate credential store) and each client must keep his .pfx.
If you create certificate for clients you will pass at least .pfx to them. Obviously once you send such certificate by unsecured email you seriously hurt the security.
If one client expires you will remove its certificate from trusted certificates. If you have your own certification authority (which you should have if you want to create certificates for clients)
If your service sits on fdfd.org you can probably use it but only for the service.