Rebex TLS

TLS library for modern and legacy platforms

Download 30-day free trial Buy from $699
More .NET libraries

Back to feature list...

X.509 certificates

Certificates are used in TLS/SSL to validate a server in order to make sure you are connecting to the right one. Certificates can be used for client authentication as well. For more information, read our Introduction to Public Key Certificates.

Validating and examining server certificate 

When connecting securely, you should ensure you are really connected to the desired server. TLS/SSL provides it with a security certificate of the server. On the client side you should just verify that the server certificate of the current connection really comes from the server you want to connect to. There are following ways, how to do it using the Rebex TLS:

  • By default, the server certificate is validated against Windows certificate infrastructure.
  • If you cannot rely on the built-in certificate verifier, you can write your own certificate validation.
  • The certificate validation can be simply skipped by setting the SslAcceptAllCertificates property:
    // create an instance of TlsClientSocket
    // ...
    
    // skip certificate validation (don't do this in production environment!)
    socket.Parameters.CertificateVerifier = CertificateVerifier.AcceptAll;
    
    ' create an instance of TlsClientSocket
    ' ...
    
    ' skip certificate validation (don't do this in production environment!)
    socket.Parameters.CertificateVerifier = CertificateVerifier.AcceptAll
    
Tip: For more detailed information read the Introduction to Public Key Certificates article.

Built-in certificate verifier 

When calling the Connect method and no custom validation is configured, the server certificate is validated using Windows CryptoAPI.

See what to do when a server certificate is not trusted.

Legacy Windows CE platforms don't natively support certificates signed using algorithms based on SHA-2 hashes. As a workaround for this major OS limitation, we introduced a built-in certificate validator in the 2016 R3 release.

Custom certificate validation 

If you cannot relay on the certificate can be trusted by the Windows certificate infrastructure, you can implement your own validation:

Register an event handler before calling the Connect method

// create an instance of TlsClientSocket
// ...

// register custom validation event handler
socket.ValidatingCertificate += client_ValidatingCertificate;
' create an instance of TlsClientSocket
' ...

' register custom validation event handler
AddHandler socket.ValidatingCertificate, AddressOf client_ValidatingCertificate

Implement the custom validation within the event handler

public void client_ValidatingCertificate(object sender, SslCertificateValidationEventArgs e)
{
    // first try to use the default validation (against the Windows certificate store)
    ValidationResult res = e.CertificateChain.Validate(e.ServerName, 0);
    if (res.Valid)
    {
        e.Accept();
        return;
    }

    // get server certificate of the current connection
    Certificate cert = e.CertificateChain[0];

    // check the certificate is already known
    if (trustedThumbprints.Contains(cert.Thumbprint))
    {
        e.Accept();
        return;
    }

    // the certificate is not know yet - show it to user
    Console.WriteLine("Do you trust to the following certificate?");
    Console.WriteLine(" Common name: {0}", cert.GetCommonName());
    Console.WriteLine(" Thumbprint:  {0}", cert.Thumbprint);
    Console.WriteLine(" Expires on:  {0:d}", cert.GetExpirationDate());

    // ask user for the answer
    // ...

    // accept or reject the certificate
    if (userAnswer)
    {
        e.Accept();

        // OPTIONALY store the current certificate as trusted
        trustedThumbprints.Add(cert.Thumbprint);
    }
    else
    {
        e.Reject();
    }
}
Public Sub client_ValidatingCertificate(sender As Object, e As SslCertificateValidationEventArgs)
    ' first try to use the default validation (against the Windows certificate store)
    Dim res As ValidationResult = e.CertificateChain.Validate(e.ServerName, 0)
    If res.Valid Then
        e.Accept()
        Return
    End If

    ' get server certificate of the current connection
    Dim cert As Certificate = e.CertificateChain(0)

    ' check the certificate is already known
    If trustedThumbprints.Contains(cert.Thumbprint) Then
        e.Accept()
        Return
    End If

    ' the certificate is not know yet - show it to user
    Console.WriteLine("Do you trust to the following certificate?")
    Console.WriteLine(" Common name: {0}", cert.GetCommonName())
    Console.WriteLine(" Thumbprint:  {0}", cert.Thumbprint)
    Console.WriteLine(" Expires on:  {0:d}", cert.GetExpirationDate())

    ' ask user for the answer
    ' ...

    ' accept or reject the certificate
    If userAnswer Then
        e.Accept()

        ' OPTIONALY store the current certificate as trusted
        trustedThumbprints.Add(cert.Thumbprint)
    Else
        e.Reject()
    End If
End Sub

Client certificate authentication 

Client certificates are an optional way to authenticate the client to the server. This is only possible when connecting/authenticating to a TLS/SSL-capable HTTP server.

A certificate with an associated private key is needed for client authentication. Assign the Settings.SslClientCertificateRequestHandler property to an implementation of certificate request handler that is called when the HTTP server asks for client certificate.

a) Use the built-in StoreSearch handler, that searches the user's certificate store for a first suitable certificate:

// set a certificate request handler
socket.Parameters.CertificateRequestHandler = CertificateRequestHandler.StoreSearch;

b) Use the built-in PFX-based certificate request handler:

// load a certificate chain from a .P12 or .PFX file
CertificateChain certificate = CertificateChain.LoadPfx("mycert.p12", "password");

// set a certificate request handler
socket.Parameters.CertificateRequestHandler = CertificateRequestHandler.CreateRequestHandler(certificate);

c) Write a custom handler, for example to load the certificate from a .pfx/.p12 file:

private class MyCertRequestHandler : ICertificateRequestHandler
{
    // This method is called during TLS/SSL negotiation
    // when the server requests client certificate authentication
    public CertificateChain Request(TlsSocket socket, DistinguishedName[] issuers)
    {
        // provide a certificate loaded from a .pfx/.p12 file
        return CertificateChain.LoadPfx(clientCertPath, clientCertPassword);
    }
}

Don't forget to register the handler:

// set a certificate request handler
socket.Parameters.CertificateRequestHandler = new MyCertRequestHandler();

Loading certificates 

A certificate can be loaded from:

  • PKCS #12 (.p7b) and PFX (.pfx) files. These usually contain a private key.
  • DER files (.der/.cer), either binary or Base64-encoded. Private key can be loaded from an external key file.
// load a certificate with private key from a PFX file
var cert1 = Certificate.LoadPfx(pfxPath, pfxPassword);

// load a certificate without a private key from a DER file
var cert2 = Certificate.LoadDer(derPath);

// load a certificate from a DER file and a private key from a key file
var cert3 = Certificate.LoadDerWithKey(derPath, keyPath, keyPassword);

Saving certificates 

A certificate can be saved either to a PKCS #12 or PFX file or to a DER file.
A certificate's private key (if exportable) can be saved either as a part of PFX file or separately using PKCS #8, PuTTY or OpenSSH format.

// save a certificate with private key to a PFX file
cert.Save(@"c:\MyData\cert.pfx", CertificateFormat.Pfx, "password");

// save a certificate to a DER file
cert.Save(@"c:\MyData\cert.der", CertificateFormat.Der);

// save certificate's private key to a base-64 encoded PKCS #8 file
cert.SavePrivateKey(@"c:\MyData\cert.key", "password", PrivateKeyFormat.OpenSsh, true);

Stand-alone certificate validation 

To jcheck whether a certificate is valid and trusted by Windows certificate infrastructure, use Certificate.Validate method.

// validate a certificate
var res1 = cert.Validate();
if (!res1.Valid)
    Console.Write("Validation failed: {0} (error {1}).", res1.Status, res1.NativeErrorCode);

// validate a server certificate for 'serverName',
// skip revocation check and don't care if it's expired or not valid yet
var res2 = cert.Validate(serverName,
    ValidationOptions.SkipRevocationCheck |
    ValidationOptions.IgnoreTimeNotValid);
if (!res2.Valid)
    Console.Write("Validation failed: {0} (error {1}).", res2.Status, res2.NativeErrorCode);
Legacy Windows CE platforms don't natively support certificates signed using algorithms based on SHA-2 hashes. As a workaround for this major OS limitation, we provide a built-in certificate validator.

Windows certificate store management 

Microsoft Windows provides a system-wide storage for X.509 certificates and private keys. The storage is used by applications such as Internet Explorer, Google Chrome, Microsoft Outlook or Windows Live Mail.

Windows certificate store can be managed using Rebex TLS CertificateStore class:

Manage personal certificate store

// load a certificate from file
var cert = Certificate.LoadPfx(certPath, certPassword, KeySetOptions.Exportable);

// add the certificate to the "Personal Certificates" store
var store = new CertificateStore(CertificateStoreName.My);
store.Add(cert);

// find all not-expired certificates from issuer named "TestCA"
var dn = new DistinguishedName("CN=TestCA, O=Rebex, C=CZ");
var found = store.FindCertificates(dn, CertificateFindOptions.IsTimeValid);
Console.WriteLine("{0} certificates found.", found.Length);

// remove the certificate from store
store.Remove(cert);

Add a certificate to trusted root certification authorities store

// load a certificate from file
var cert = Certificate.LoadDer(certPath);

// add the certificate to the "Trusted Root Certificates" store
var store = new CertificateStore(CertificateStoreName.Root);
store.Add(cert);
Tip: To manage Windows certificate store, you can use Internet Explorer (Tools / Internet options / Certificates) or the "Certificates" MMC snap-in.

Back to feature list...