TLS/SSL core

TLS/SSL is a cryptographic communication protocol providing a way of securing protocols such as FTP, HTTP, SMTP, IMAP, POP3 or Telnet.

TLS and SSL are different versions of the same protocol. TLS 1.0 is a name for what was supposed to be SSL 3.1. When we use the terms "SSL" or "TLS", we generally mean "TLS or SSL".

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 HTTPS:

  • By default, the server certificate is validated against Windows certificate infrastructure.
  • If you cannot rely on the certificate can be validated against your Windows certificate infrastructure, you can write your own certificate validation.
  • The certificate validation can be simply skipped by setting the SslAcceptAllCertificates property:

    CSharp

    // create client instance (Rebex.Net.WebClient or Rebex.Net.HttpRequestCreator)
    // ...
    
    // skip certificate validation (don't do this in production environment!)
    client.Settings.SslAcceptAllCertificates = true;
    

    VisualBasic

    ' create client instance (Rebex.Net.WebClient or Rebex.Net.HttpRequestCreator)
    ' ...
    
    ' skip certificate validation (don't do this in production environment!)
    client.Settings.SslAcceptAllCertificates = True
    
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

CSharp

// create client instance (Rebex.Net.WebClient or Rebex.Net.HttpRequestCreator)
// ...

// register custom validation event handler
client.ValidatingCertificate += client_ValidatingCertificate;

VisualBasic

' create client instance (Rebex.Net.WebClient or Rebex.Net.HttpRequestCreator)
' ...

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

Implement the custom validation within the event handler

CSharp

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();
    }
}

VisualBasic

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. Set 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:

CSharp

// set a certificate request handler
client.Settings.SslClientCertificateRequestHandler = CertificateRequestHandler.StoreSearch;

VisualBasic

' set a certificate request handler
client.Settings.SslClientCertificateRequestHandler = CertificateRequestHandler.StoreSearch

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

CSharp

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

// set a certificate request handler
client.Settings.SslClientCertificateRequestHandler = CertificateRequestHandler.CreateRequestHandler(certificate);

VisualBasic

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

' set a certificate request handler
client.Settings.SslClientCertificateRequestHandler = CertificateRequestHandler.CreateRequestHandler(certificate)

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

CSharp

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);
    }
}

VisualBasic

Private Class MyCertRequestHandler
    Implements ICertificateRequestHandler
    ' This method is called during TLS/SSL negotiation
    ' when the server requests client certificate authentication
    Public Function Request(socket As TlsSocket, issuers As DistinguishedName()) _
                        As CertificateChain _
                        Implements ICertificateRequestHandler.Request
        ' provide a certificate loaded from a .pfx/.p12 file
        Return CertificateChain.LoadPfx(clientCertPath, clientCertPassword)
    End Function
End Class

Don't forget to register the handle:

CSharp

// set a certificate request handler
client.Settings.SslClientCertificateRequestHandler = new MyCertRequestHandler();

VisualBasic

' set a certificate request handler
client.Settings.SslClientCertificateRequestHandler = New MyCertRequestHandler()

Overriding SSL server name #

Server certificate's common name should specify the server hostname - this ensures that the server presents a certificate that actually belongs to it. If the names are mismatched, you can still work around it.

Security settings and algorithms #

When connecting with Rebex HTTPS, you can choose from a number of security algorithms and standards.

TLS/SSL cipher suites

The Settings.SslAllowedSuites property (on the client object) makes it possible to specify a combination of following algorithms:

Cipher ID Certificate Key Algorithm Key Exchange Algorithm Encryption Algorithm Key Size (bit) MAC Alg.
RSA_WITH_AES_128_CBC_SHA256 * RSA RSA AES in CBC mode 128 SHA-256
RSA_WITH_AES_256_CBC_SHA256 * AES in CBC mode 256 SHA-256
RSA_EXPORT_WITH_RC4_40_MD5 ! RC4 40 MD5
RSA_WITH_RC4_128_MD5 RC4 128 MD5
RSA_WITH_RC4_128_SHA RC4 128 SHA-1
RSA_EXPORT_WITH_RC2_CBC_40_MD5 ! RC2 in CBC mode 40 MD5
RSA_EXPORT_WITH_DES40_CBC_SHA ! DES in CBC mode 40 SHA-1
RSA_WITH_DES_CBC_SHA DES in CBC mode 56 SHA-1
RSA_WITH_3DES_EDE_CBC_SHA * TripleDES in CBC mode 168 SHA-1
RSA_EXPORT1024_WITH_DES_CBC_SHA ! DES in CBC mode 56 SHA-1
RSA_EXPORT1024_WITH_RC4_56_SHA ! RC4 56 SHA-1
RSA_WITH_AES_128_CBC_SHA * AES in CBC mode 128 SHA-1
RSA_WITH_AES_256_CBC_SHA * AES in CBC mode 256 SHA-1
ECDHE_RSA_WITH_AES_128_CBC_SHA256 * RSA Elliptic Curve Diffie-Hellman AES in CBC mode 128 SHA-256
ECDHE_RSA_WITH_AES_256_CBC_SHA384 * AES in CBC mode 256 SHA-384
ECDHE_RSA_WITH_AES_128_CBC_SHA * AES in CBC mode 128 SHA-1
ECDHE_RSA_WITH_AES_256_CBC_SHA * AES in CBC mode 256 SHA-1
ECDHE_RSA_WITH_3DES_EDE_CBC_SHA * TripleDES in CBC mode 168 SHA-1
ECDHE_RSA_WITH_RC4_128_SHA RC4 128 SHA-1
ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 * Elliptic Curve DSA Elliptic Curve Diffie-Hellman AES in CBC mode 128 SHA-256
ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 * AES in CBC mode 256 SHA-384
ECDHE_ECDSA_WITH_AES_128_CBC_SHA * AES in CBC mode 128 SHA-1
ECDHE_ECDSA_WITH_AES_256_CBC_SHA * AES in CBC mode 256 SHA-1
ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA * TripleDES in CBC mode 168 SHA-1
ECDHE_ECDSA_WITH_RC4_128_SHA RC4 128 SHA-1
DHE_RSA_WITH_AES_128_CBC_SHA256 * RSA Diffie-Hellman AES in CBC mode 128 SHA-256
DHE_RSA_WITH_AES_256_CBC_SHA256 * AES in CBC mode 256 SHA-256
DHE_RSA_EXPORT_WITH_DES40_CBC_SHA ! DES in CBC mode 40 SHA-1
DHE_RSA_WITH_DES_CBC_SHA DES in CBC mode 56 SHA-1
DHE_RSA_WITH_3DES_EDE_CBC_SHA * TripleDES in CBC mode 168 SHA-1
DHE_RSA_WITH_AES_128_CBC_SHA * AES in CBC mode 128 SHA-1
DHE_RSA_WITH_AES_256_CBC_SHA * AES in CBC mode 256 SHA-1
DHE_DSS_WITH_AES_128_CBC_SHA256 * DSS Diffie-Hellman AES in CBC mode 128 SHA-256
DHE_DSS_WITH_AES_256_CBC_SHA256 * AES in CBC mode 256 SHA-256
DHE_DSS_EXPORT_WITH_DES40_CBC_SHA ! DES in CBC mode 40 SHA-1
DHE_DSS_WITH_DES_CBC_SHA DES in CBC mode 56 SHA-1
DHE_DSS_WITH_3DES_EDE_CBC_SHA * TripleDES in CBC mode 168 SHA-1
DHE_DSS_WITH_AES_128_CBC_SHA * AES in CBC mode 128 SHA-1
DHE_DSS_WITH_AES_256_CBC_SHA * AES in CBC mode 256 SHA-1
DHE_DSS_EXPORT1024_WITH_DES_CBC_SHA ! DES in CBC mode 56 SHA-1
DHE_DSS_EXPORT1024_WITH_RC4_56_SHA ! RC4 56 SHA-1
DHE_DSS_WITH_RC4_128_SHA RC4 128 SHA-1
DH_anon_WITH_AES_256_CBC_SHA256 no certificate Diffie-Hellman AES in CBC mode 256 SHA-256
DH_anon_WITH_AES_128_CBC_SHA256 AES in CBC mode 128 SHA-256
DH_anon_WITH_AES_256_CBC_SHA AES in CBC mode 256 SHA-1
DH_anon_WITH_AES_128_CBC_SHA AES in CBC mode 128 SHA-1
DH_anon_WITH_RC4_128_MD5 RC4 128 MD5
DH_anon_WITH_3DES_EDE_CBC_SHA TripleDES in CBC mode 168 SHA-1
DH_anon_WITH_DES_CBC_SHA DES in CBC mode 56 SHA-1
DH_anon_EXPORT_WITH_RC4_40_MD5 ! RC4 40 MD5
DH_anon_EXPORT_WITH_DES40_CBC_SHA ! DES in CBC mode 40 SHA-1

* These cipher suites are currently considered secure.

! These cipher suites are considered vulnerable.

Please note that on some platforms, cipher suites based on Elliptic Curve Diffie Hellman are only available with external plugins.
Note: Vulnerable cipher suites are switched off by default. To enable them, set Settings.SslAllowVulnerableSuites to true. However, this is strongly discouraged.
Tip: When using TlsSocket as a stand-alone object to implement server-side TLS/SSL, use TlsParameters.SetPreferredSuites(...) method to specify the preferred cipher suite order.

TLS/SSL extensions

Rebex HTTPS supports Server Name Identification (SNI) extension and Renegotiation Indication extension.

TLS/SSL elliptic curves

The Settings.SslAllowedCurves property (on client object) makes it possible to specify a set of enabled elliptic curves used by ECDHE_RSA ciphers above. Supported elliptic curves:

Curve ID Curve Name
NistP256* NIST P-256 curve
NistP384* NIST P-384 curve
NistP521* NIST P-521 curve
BrainpoolP256R1** Brainpool P-256 R1 curve
BrainpoolP384R1** Brainpool P-384 R1 curve
BrainpoolP512R1** Brainpool P-512 R1 curve
Curve25519*** Curve 25519

* These curves require a plugin on non-Windows and legacy Windows platforms.

** These curves require a plugin on non-Windows platforms and on Windows earlier than Windows 10 / Windows Server 2016.

*** These curves require a plugin.

TLS/SSL protocol versions

Use Settings.SslAllowedVersions property (on client object) to enable or disable specific versions of the TLS/SSL protocol. Supported versions:

  • TLS 1.2
  • TLS 1.1
  • TLS 1.0
  • SSL 3.0
Note: SSL 3.0 is no longer considered secure and it's disabled by default. To enable it:
  • C#: client.Settings.SslAllowedVersions |= TlsVersion.SSL30;
  • VB.NET: client.Settings.SslAllowedVersions = client.Settings.SslAllowedVersions Or TlsVersion.SSL30
Note: TLS and SSL are different versions of the same protocol. TLS 1.0 is a name for a protocol that was originally supposed to become SSL 3.1.