Would it be ok to create an X509Certificate2 object in one thread and then use it in multiple threads for WCF calls?

I have the following situation. I need to upload a .pfx file to an X509Certificate2 object and use it for WCF calls:

 private IThatWcfService GetService() { var binding = new WebHttpBinding(); binding.Security.Mode = WebHttpSecurityMode.Transport; binding.Security.Transport.ClientCredentialType = HttpClientCredentialType.Certificate; // some more minor tweaking of the binding object here which makes reusing the // WebChannelFactory object below impossible var endpointAddress = new EndpointAddress( ThatServiceUriConstant ); var contract = ContractDescription.GetContract( typeof( IThatWcfService ) ); var endpoint = new ServiceEndpoint( contract, binding, endpointAddress ); var certificate = loadCertificate(); // news X509Certificate2() var factory = new WebChannelFactory<IThatWcfService >( endpoint ); factory.Credentials.ClientCertificate.Certificate = certificate; var service = factory.CreateChannel(); return service; } 

Now there is a problem with the error in Windows Server 2008, which causes the leak of two temporary files each time the .pfx file is loaded into the X509Certificate2 object. The error is fixed, but the fix is ​​not available (and will not be available) where the code is executing, so I have to work with this.

I already cached the X509Certificate2 object, so when the same thread calls GetService() several times, X509Certificate2 used. The problem is that GetService() needs to be called from two threads, so I need to take care of thread safety when using X509Certificate2 from different threads.

So, I would like to have the following design: I create an X509Certificate2 static object, and depending on which thread calls GetService() , it first creates and caches the X509Certificate2 object, and therefore the whole thread actually uses the same object when creating the object WebChannelFactory .

Is it possible to reuse the same X509Certificate2 object from multiple threads when calling WCF calls for the same service?

+4
source share
1 answer

From MSDN, this class is "not guaranteed to be thread safe."

From common sense, look at this class: there is a Handle property. This means that this class is just a wrapper for some lower level, perhaps a direct wrapper for CAPI services, and I actually do not think this is really unsafe.

I managed to find this one discussion: http://marc.info/?l=ms-cryptoapi&m=103430170033615 , pointing to some "discussions@microsoft.com", but it is controversial as a source of information.

Looking at X509Certificate and X509Cert2 with TypeDescriptor, it looks like it makes heavy use of lower levels, and even getters are not cached and polling all values ​​directly from CAPI. If you are only reading, the X509 object does not seem to do much harm, but, of course, since MSDN says that it is “not guaranteed to be thread safe,” I cannot guarantee it either.

Some important points:

  • The X509 object is just a manager wrapper in a CAPI context and processes
  • The X509 object does not seem to cache anything, but the CAPI can do this based on TRANSFER.
  • X509 obj does some error checking (even in getters) on the .Net side and throws exceptions if CAPI considers the request to be invalid.
  • CAPI is almost certainly thread safe in terms of READing certificates.
  • CAPI will almost certainly return errors when a certificate is deleted or something similar happens evil, but you do not control it, because the user can, for example, delete this certificate manually, and this makes me even more confident that CAPI is fully internally strengthened against multithreading.

However, I am sure that even if the x509 shell is damaged, the CAPI will not crash and will not damage the certificate database. I think the worst that could be the exception on the .Net side

You may also find this question interesting: Mitigating RsaCryptoServiceProvider security problems on a web server

Now lean back from this optimistic point of view.

You are talking about an error and a memory leak. Where was it? Was it in the .Net crypto class library or inside the CAPI? It was in CAPI, and if you cannot apply corrections on this machine, then you know, I would rather advise a little bit paranoid with this. If you open the same file with two X509 objects, and therefore two handles caused a leak, then I would really empirically ensure that reusing the same descriptor from many threads does not leak either. Errors like going into swarms and a “pen” are more fragile than a “file name”.

In addition, let me completely distract from the question;) - a known memory leak with known preconditions is usually not dangerous and can be circumvented in various ways.

Of course, if you created new X509 objects on the fly with every service request, you would run into memory problems, as each object would add a new leak. But a leak can easily be kept and closed to a constant value even without sharing objects. For example, you can pre-construct 10/100/1000 identical x509 objects, drop them into any thread safe collection and create a small manager class (a few lines of code, really) that will provide access to them upon acquisition / release. Thus, you will use the cost of memory 10/100/1000 times the leak, but it will be known and constant and will not grow further. Of course, this will mean that only 10/100/1000 simultaneous tasks related to certificates can be performed at a given time.

+5
source

Source: https://habr.com/ru/post/1480466/


All Articles