What is the difference between X509Certificate2 and X509Certificate in .NET?

.NetSslCertificateX509certificate

.Net Problem Overview


What is the difference between the two?

.Net Solutions


Solution 1 - .Net

The x509Certificate was introduced in .NET v1.0/1.1 and was (comparatively) limited in its functionality. It can be used to get information about an existing certificate (valid dates, issuer, etc.). It had simple methods/operations (i.e. reading a cert from disk).

The x509Certificate2 is a subclass of x509Certificate with additional functionality.

  • It represents an actual X509 certificate.
  • It was new in the .NET Framework v2.0.
  • This class gives you access to all the V2 and V3 properties (authority key identifier and key usage).
  • It supports loading a certificate from a certificate store.

Solution 2 - .Net

For completeness' sake, here is a copy of the relevant section of the site linked to in @dommer's answer, since the site may no longer be up and only in Google's cache for who-knows-how long:

> Version 1.1 of the framework had very little other than the > X509Certificate class to allow you to manipulate certificates. In > fact, the v1.1 X509Certificate class gave only basic support: it only > gave access to the X509 version 1 fields (like the valid from and > valid to dates, subject and public key) but not version 2 fields (like > the authority key identifier) nor version 3 fields (like the key > usage). There was no support to load a certificate from a certificate > store, nor does it have the facilities to access certificate > revocation lists or certificate trust lists. Microsoft improved on > this with the Web Services Enhancement (WSE) toolkit extending the > certificate class and providing classes to access certificate stores. > These classes can now be found in the .NET 3.0/2.0 framework library. > > The first big change is a new class called X509Certificate2 which > derives from X509Certificate. The methods to access the X509 > certificate fields have been deprecated and now the class has > properties to access those fields. In addition, if the certificate has > an associated private key then the class gives access to this key. > There are methods that allow you to provide a password if the private > key is protected by one. The password is passed through a SecureString > parameter which is a special type that makes sure that when the object > is no longer being used the memory it occupied will be written over so > that the password cannot be read by another process on the machine. > Secure strings and other forms of protected data will be covered in a > later section. > > Since X509Certificate2 derives from X509Certificate it means that you > can call the static methods CreateFromeCertFile and > CreateFromSignedFile through the X509Certificate2 class. However, > these methods return an X509Certificate object and you cannot down > cast this to a X509Certificate2 object. The X509Certificate class has > been improved in version 3.0/2.0: it provides properties to access > some of the X509 fields; it provides Import and Export methods to > initialize an object from a byte array or generate a byte array from > the certificate and it has constructors that will create an object > from a file (ASN.1 DER) and from a byte array. Interestingly, the > X509Certificate2 class has a constructor that can create an > X509Certificate2 object from an X509Certificate object. Note that > although an X509Certificate object can only show the X509v1 fields it > can be created from an X509v3 certificate and so if you create an > X509Certificate2 object from an X509Certificate object you will be > able to access the X509v3 fields.

Solution 3 - .Net

To convert an X.509 cert from "X509Certificate" to "X509Certificate2", try something like this:

X509Certificate  X509  = sslStream.RemoteCertificate;
X509Certificate2 X5092 = new X509Certificate2(X509);

Solution 4 - .Net

For those that would like to read the certificate and use this to authenticate one would simply create a X509Certificate2 and pass the X509Certificate in it's constructor.

For a signed assembly (the exe) the code would be code like this, and I omit error validation for simplicity.

Module m = Assembly.GetEntryAssembly().GetModules()[0];
using (var cert = m.GetSignerCertificate())
using (var cert2 = new X509Certificate2(cert))
{
   var _clientHandler = new HttpClientHandler();
   _clientHandler.ClientCertificates.Add(cert2);
   _clientHandler.ClientCertificateOptions = ClientCertificateOption.Manual;
   var myModel = new Dictionary<string, string>
   {
       { "property1","value" },
       { "property2","value" },
   };
   using (var content = new FormUrlEncodedContent(myModel))
   using (var _client = new HttpClient(_clientHandler))
   using (HttpResponseMessage response = _client.PostAsync($"{url}/{controler}/{action}", content).Result)
   {
       response.EnsureSuccessStatusCode();
       string jsonString = response.Content.ReadAsStringAsync().Result;
       var json = new Newtonsoft.Json.JsonSerializer();
       var myClass = JsonConvert.DeserializeObject<MyClass>(json);
    }
}

Obviously you're class isn't called MyClass but some business object that you'd expect from the web service.

You can send a class to your action by sending the property & value you require filled. You can now ensure that the request you received is from a valid mobile or windows client by reading the request certificate like so:

public class MyController : ApiController
{
    public IHttpActionResult Get()
    {           
       X509Certificate2 clientCertInRequest = Request.HttpContext.Connection.ClientCertificate;
       if (!clientCertInRequest.Verify() || !AllowedCerialNumbers(clientCertInRequest.SerialNumber))
       {
            Response.StatusCode = 404;
            return null;
       }
       //your code
   }

}

What is left is to set your webserver to accept client certificates... You can read all about properties that come from the new format and you have secured your public web service, something most fail to do as just being authorized isn't good enough anymore (if it ever was)

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionKyleView Question on Stackoverflow
Solution 1 - .Netp.campbellView Answer on Stackoverflow
Solution 2 - .NetSoManyGoblinsView Answer on Stackoverflow
Solution 3 - .NetftexpertsView Answer on Stackoverflow
Solution 4 - .NetWalter VerhoevenView Answer on Stackoverflow