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

57,573

Solution 1

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

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

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

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)

Share:
57,573

Related videos on Youtube

Kyle
Author by

Kyle

Self employed developer of SQLPro Studio for macOS, iOS and Windows.

Updated on July 08, 2022

Comments

  • Kyle
    Kyle almost 2 years

    What is the difference between the two?

  • Bruno
    Bruno over 12 years
    X509Certificate2 also has a member for the private key, which isn't part of the certificate itself but is convenient to have associated with the class representing the X.509 certificate.