How to log System.Net

In your App.config add the following code:

<?xml version="1.0"?>
<configuration>
  <system.diagnostics>

    <trace autoflush="true"/>

    <switches>
      <add name="System.Net" value="Verbose" />
    </switches>

    <sources>
      
      <source name="System.Net">
        <listeners>
          <add name="SystemNetLogFile"/>
        </listeners>
      </source>
      
    </sources>

    <sharedListeners>
      <add name="SystemNetLogFile" type="System.Diagnostics.TextWriterTraceListener" initializeData="d:\system.net.log"/>
    </sharedListeners>

  </system.diagnostics>
</configuration>

That’s it!

The log looks like this:

System.Net Information: 0 : [8548] SecureChannel#238379
System.Net Information: 0 : [8548] Enumerating security
System.Net Information: 0 : [8548] Negotiate
System.Net Information: 0 : [8548] NegoExtender
System.Net Information: 0 : [8548] pku2u
System.Net Information: 0 : [8548] WDigest
System.Net Information: 0 : [8548] Kerberos
System.Net Information: 0 : [8548] NTLM
System.Net Information: 0 : [8548] Schannel
System.Net Information: 0 : [8548] Microsoft Unifie
System.Net Information: 0 : [8548] TSSSP
System.Net Information: 0 : [8548] CREDSSP
System.Net Information: 0 : [8548] SecureChannel#238379
System.Net Information: 0 : [8548] Current OS installat
System.Net Information: 0 : [8548] AcquireCredentialsHa
System.Net Error: 0 : [8548] AcquireCredentialsHandle()
System.Net Information: 0 : [8548] AcquireCredentialsHa
System.Net Error: 0 : [8548] AcquireCredentialsHandle()
System.Net Information: 0 : [8548] SecureChannel#214541
System.Net Information: 0 : [8548] SecureChannel#214541
System.Net Information: 0 : [8548] AcquireCredentialsHa
System.Net Information: 0 : [8548] InitializeSecurityCo
System.Net Information: 0 : [8548] InitializeSecurityCo
System.Net Information: 0 : [8548] InitializeSecurityCo
System.Net Information: 0 : [8548] InitializeSecurityCo
System.Net Information: 0 : [8548] InitializeSecurityCo
System.Net Information: 0 : [8548] InitializeSecurityCo
System.Net Information: 0 : [8548] InitializeSecurityCo
System.Net Information: 0 : [8548] InitializeSecurityCo
System.Net Information: 0 : [8548] InitializeSecurityCo
System.Net Information: 0 : [8548] InitializeSecurityCo
System.Net Information: 0 : [8548] InitializeSecurityCo
System.Net Information: 0 : [8548] InitializeSecurityCo
System.Net Information: 0 : [8548] Remote certificate:
V3

[Subject]
CN=mail.postecert.it, O=Postecom S.p.A., L=Roma, S=Ro
Simple Name: mail.postecert.it
DNS Name: mail.postecert.it

[Issuer]
CN=GlobalSign Organization Validation CA - SHA256 - G
Simple Name: GlobalSign Organization Validation CA -
DNS Name: GlobalSign Organization Validation CA - SHA

[Serial Number]
0A9141CFE287B47FF4273C12

[Not Before]
2016-11-02 08:01:04

[Not After]
2017-11-03 08:01:04

[Thumbprint]
F12F74096659D9CCAA4ACD3432C896AF39CA8B9E

[Signature Algorithm]
sha256RSA(1.2.840.113549.1.1.11)

[Public Key]
Algorithm: RSA
Length: 2048
Key Blob: 30 82 01 0a 02 82 01 01 00 bf a1 62 b7 64 1
System.Net Information: 0 : [8548] SecureChannel#214541
System.Net Information: 0 : [8548] ProcessAuthenticatio

Create code signing certificate

Management summary

  1. You generate certificate signing request on your machine (using certmgr or ActiveX component).
  2. Private/public key pair is generated along with the request (on your machine).
  3. You export certificate that represents the request from your certificate key store.
  4. You extract private key from the certificate that represents the request.
  5. You send the request (it contains public key only) to CA (or ActiveX does this automatically).
  6. CA sends your certificate back (crt file that is basically your public key, signed with CA’s keys).
  7. Finally you need to combine the private key and the crt to create a pfx, that contains both private key and the certificate.

Important points

  • Private key is generated along with the certificate request.
  • Private key is generated on your machine.
  • Private key is never sent to CA (Certificate Authority).
  • Certificate received from the CA (*.crt file) doesn’t contain your private key.
    • Generate CSR & private key – ActiveX

      Some vendors, like Comodo, use Active X component, that runs on your machine and creates certificate request along with private/public key pair generation on your machine:

      activex_01

      Private key can be found in the certmgr of the local account (not machine’s):

      activex_02

      Later on it must be exported as a pfx (e.g. “Request.pfx”).

      Generate CSR & private key – CertMgr

      In MMC (certmgr), expand Certificates (Local Computer) and then Personal.
      Right-click Certificates, and then go to the following menus: All Tasks > Advanced Operations > Create Custom Request:

      certmgr_00

      Click Next:

      certmgr_01

      Click Next:

      certmgr_02

      Click Next:

      certmgr_03

      Ensure the Request format is PKCS #10, and then click Next:

      certmgr_04

      Click the downward-facing arrow next to Details, and then click Properties.

      certmgr_06

      On the subject type, select the following values, enter the corresponding Value, and then click Add:

      • Common name – Your business or organization’s name
      • Organization – Your business or organization’s name
      • Locality – Your business or organization’s address
      • State – The state where your business or organization resides
      • Country – The country where your business or organization resides

      Go to the Private Key tab, click Key type, and then select Make private key exportable:
      Click OK, and then click Next:

      certmgr_07

      Browse for the location where you want to save the file, enter a File Name (“Request.csr”), and then click Finish.
      Your CSR is now stored in the file you saved it to on your local machine.

      certmgr_05

      Request file is regular text file:

      certmgr_15

      This process also creates a private key, which you will need to use later to create a PFX file to sign your code or driver.

      Export certificate that represents the request

      If you were using ActiveX to generate certificate request, certificate that represents the request (including private key) is stored in certmgr of the local account (not machine’s):

      activex_02

      Go to “Certificate Enrollment Requests”/ “Certificates” (Hit refresh if it is empty):

      certmgr_08

      Right-click the certificate and then go to the following menus: All Tasks > Export:

      certmgr_09

      Select export private key and hit Next:

      certmgr_10

      Ensure the Request format is PKCS #12, and then click Next:

      certmgr_11

      Specify password:

      certmgr_12

      Browse for the location where you want to save the file, enter a File Name (“Request.pfx”), and then click Finish.

      certmgr_13

      Click Finish:

      certmgr_14

      Certificate that represents your request is now stored in the file you saved on your local machine. It contains both private and public key.

      Extract private key

      First you’ll need to install OpenSSL.

      To extract private key from the request, issue following command:

      openssl pkcs12 -in Request.pfx -out Request_PrivateKey.pem -nocerts -nodes

      nocerts = private key only,
      nodes = no password

      Generate CSR & private key – OpenSSL

      You can use following command to create certificate request and key using OpenSSL:

      openssl req -new -newkey rsa:2048 -nodes -keyout Request_PrivateKey.key -out Request.csr

      You may need to convert to convert the key (BEGIN PRIVATE KEY) to PKCS#1 format (BEGIN RSA PRIVATE KEY):

      openssl rsa -outform pem -in Request_PrivateKey.key -out Request_PrivateKey.pem

      CA creates a certificate

      Now you should upload -or- copy&paste request file (“Request.csr”) to your CA, and in return, they should create the certificate for you:

      generated_00

      What you receive from your CA looks more or less like this:
      generated_01

      Most important file is the crt file which contains your certificate (it includes public key only).

      Combine private key with cert to create pfx

      To combine private key from the request and certificate from CA into one pfx certificate, issue following command:

      openssl pkcs12 -inkey Request_PrivateKey.pem -in 00…70.crt -export -out 00…70.pfx

      The pfx file you created contains both private key and the certificate and can be used to sign your code.

System.Security.Authentication.AuthenticationException

.NET uses SChannel.dll as underlying SSL/TLS implementation. SChannel is OS dependent and if incorrectly configured or configured to use only the latest TLS/SSL versions, may lead to problems with TLS/SSL negotiation.

Please note that protocols that were considered secure some time ago, like SSL 3.0, are no longer considered secure. New OS updates may disable some protocols or cipher versions. On Windows this is done via registry settings.

SSL version status

  • SSL 2.0 was deprecated (prohibited) in 2011 by RFC 6176.
  • SSL 3.0 was deprecated by RFC 7568 in June 2015.
    As of 2014 the 3.0 version of SSL is considered insecure as it is vulnerable to the POODLE attack that affects all block ciphers in SSL; and RC4, the only non-block cipher supported by SSL 3.0, is also feasibly broken as used in SSL 3.0.
  • The use of RC4 in TLS is prohibited by RFC 7465 published in February 2015.
  • The token supplied to the function is invalid

    Full exception looks like this:

    System.Security.Authentication.AuthenticationException :
    A call to SSPI failed, see inner exception.
    ----> System.ComponentModel.Win32Exception :
    The token supplied to the function is invalid

    Most likely your client tries to use TLS 1.2 but you are using old certificate on the server (e.g. signed using md5RSA algorithm).

    There are 2 options for you:

    1. Regenerate the certificate (especially if it’s self-signed).
    2. Use older TLS/SSL version (TLS 1.1, TLS 1.0, SSL 3.0). You can force Mail.dll or Ftp.dll to use it using following code:

      using (XXX client = new XXX())
      {
          client.SSLConfiguration.EnabledSslProtocols = SslProtocols.Tls11;
          //client.SSLConfiguration.EnabledSslProtocols = SslProtocols.Tls; // TLS 1.0
          //client.SSLConfiguration.EnabledSslProtocols = SslProtocols.Ssl3;
      
          client.ConnectSSL("host");
      
          client.Close();
      }
      
      

      Please contact your server administrator as TLS 1.1, TLS 1.0 and SSL 3.0 aren’t considered secure anymore.

    The client and server cannot communicate, because they do not possess a common algorithm

    Full exception looks like this:

    System.Security.Authentication.AuthenticationException :
    A call to SSPI failed, see inner exception.
    ----> System.ComponentModel.Win32Exception :
    The client and server cannot communicate, because they do not possess a common algorithm

    There are 2 possible scenarios:

    1. In most cases this means that the client is trying to use older SSL protocols like SSL 3.0, TLS 1.0 or TLS 1.1, but the remote server requires modern protocol – TLS 1.2.

      By default all our clients support TLS 1.2. Some older versions need to be told to use TLS 1.2, it is also a good practice to force TLS 1.2 only:

      using (XXX client = new XXX())
      {
          client.SSLConfiguration.EnabledSslProtocols = SslProtocols.Tls12;
      
          client.ConnectSSL("host");
      
          client.Close();
      }
      
    2. Second option is the server is not supporting TLS 1.2 – you’ll need to use older protocol (TLS 1.1, TLS 1.0, SSL 3.0):
      using (XXX client = new XXX())
      {
          client.SSLConfiguration.EnabledSslProtocols = SslProtocols.Tls11;
          // client.SSLConfiguration.EnabledSslProtocols = SslProtocols.Tls; // TLS 1.0
          // client.SSLConfiguration.EnabledSslProtocols = SslProtocols.Ssl3; 
      
          client.ConnectSSL("host");
      
          client.Close();
      }
      

      Please contact your server administrator as TLS 1.1, TLS 1.0 and SSL 3.0 aren’t considered secure anymore.

    The message received was unexpected or badly formatted

    Full exception looks like this:

    System.Security.Authentication.AuthenticationException :
    A call to SSPI failed, see inner exception.
    ----> System.ComponentModel.Win32Exception :
    The message received was unexpected or badly formatted

    This error generally means that something is incorrectly configured on your machine.

    What you should try:

    1. Try forcing the latest TLS version (TLS 1.2):
      using (XXX client = new XXX())
      {
          client.SSLConfiguration.EnabledSslProtocols = SslProtocols.Tls12;
      
          client.ConnectSSL("host");
      
          client.Close();
      }
      
    2. Use older TLS/SSL version (TLS 1.1, TLS 1.0, SSL 3.0). You can force Mail.dll or Ftp.dll to use it using following code:

      using (XXX client = new XXX())
      {
          client.SSLConfiguration.EnabledSslProtocols = SslProtocols.Tls11;
          //client.SSLConfiguration.EnabledSslProtocols = SslProtocols.Tls; // TLS 1.0
          //client.SSLConfiguration.EnabledSslProtocols = SslProtocols.Ssl3;
      
          client.ConnectSSL("host");
      
          client.Close();
      }
      
      

      Please contact your server administrator as TLS 1.1, TLS 1.0 and SSL 3.0 aren’t considered secure anymore.

    3. Finally you can download IISCrypto and review “Schannel” and “Cipher Suites” tabs.

      For example we have seen clients that have TLS 1.0 turned on, but have TLS_RSA_WITH_3DES_EDE_CBC_SHA cypher suite turned off. If server requires this cypher, you’ll get this error message.

      Selecting “Best Practices” and restarting, should solve the issue. You may need to select additional protocol suites depending on what your server requires

      Please note that using TLS 1.2 and forcing your server administrator to enable TLS 1.2 is the only correct and secure way to go.

    One or more of the parameters passed to the function was invalid

    Full exception looks like this:

    System.Security.Authentication.AuthenticationException:
    A call to SSPI failed, see inner exception.
    ----> System.ComponentModel.Win32Exception:
    One or more of the parameters passed to the function was invalid

    This error generally means that you are trying to use TLS/SSL protocol version that is not supported on your machine (most likely it was turned off, because it is no longer considered secure)

    What you should try:

    1. Try forcing the latest TLS version (TLS 1.2):
      using (XXX client = new XXX())
      {
          client.SSLConfiguration.EnabledSslProtocols = SslProtocols.Tls12;
      
          client.ConnectSSL("host");
      
          client.Close();
      }
      
    2. Use older TLS/SSL version (TLS 1.1, TLS 1.0, SSL 3.0). You can force Mail.dll or Ftp.dll to use it using following code:

      using (XXX client = new XXX())
      {
          client.SSLConfiguration.EnabledSslProtocols = SslProtocols.Tls11;
          //client.SSLConfiguration.EnabledSslProtocols = SslProtocols.Tls; // TLS 1.0
          //client.SSLConfiguration.EnabledSslProtocols = SslProtocols.Ssl3;
      
          client.ConnectSSL("host");
      
          client.Close();
      }
      
    3. Try to disable strong crypto using code:

            const string DisableCachingName = @"TestSwitch.LocalAppContext.DisableCaching";
            const string DontEnableSchUseStrongCryptoName = @"Switch.System.Net.DontEnableSchUseStrongCrypto";
            AppContext.SetSwitch(DisableCachingName, true);
            AppContext.SetSwitch(DontEnableSchUseStrongCryptoName, true);
      

      -or- by using app.config file:

      <configuration>
          <runtime>
              <AppContextSwitchOverrides value="Switch.System.Net.DontEnableSchUseStrongCrypto=true"/>
          </runtime>
      </configuration>
      

      ref: https://msdn.microsoft.com/en-us/library/mt298998(v=vs.110).aspx

    4. Finally you can download IISCrypto and review “Schannel” and “Cipher Suites” tabs.

      Selecting “Best Practices” restarting, should solve the issue. You may need to select additional protocol suites depending on what your server requires

      Please note that using TLS 1.2 and forcing your server administrator to enable TLS 1.2 is the only correct and secure way to go.

      Please contact your server administrator as TLS 1.1, TLS 1.0 and SSL 3.0 aren’t considered secure anymore.

    Using TLS 1.2 with .NET IMAP client

    In this article, you’ll find an extensive tutorial detailing the process of setting up the Mail.dll IMAP client to make use of the TLS 1.2 encryption protocol.

    This security enhancement guarantees the protection of incoming email messages through IMAP, shielding them from potential risks and unauthorized entry.

    Typically, clients and IMAP servers engage in a negotiation process to determine compatible SSL/TLS versions. Many systems no longer support SSL 3.0, TLS 1.0, or 1.1. Mail.dll IMAP component automatically uses the latest available TLS version.

    TLS 1.2 and 1.3 are the most secure versions of TLS protocols. You can force the connection to use it.

    All you need to do is to set Imap.SSLConfiguration.EnabledSslProtocols property to SslProtocols.Tls12 before issuing ConnectSSL or Connect and StartTLS sequence:

    // C#
    
    using (Imap imap = new Imap())
    {
        imap.SSLConfiguration.EnabledSslProtocols = SslProtocols.Tls12;
    
        imap.ConnectSSL("imap.example.com");
    
        imap.UseBestLogin("user","password");
    
        // ... 
    
        imap.Close();
    }
    
    ' VB.NET
    
    Using imap As New Imap()
    	imap.SSLConfiguration.EnabledSslProtocols = SslProtocols.Tls12
    
    	imap.ConnectSSL("imap.example.com")
    
    	imap.UseBestLogin("user@example.com", "password")
    
    	'...
    
    	imap.Close()
    End Using
    

    For explicit SSL/TLS, code is almost the same. You first connect to a default, non-secure IMAP port and secure the connection using Imap.StartTLS method:

    // C#
    
    using (Imap imap= new Imap())
    {
        imap.SSLConfiguration.EnabledSslProtocols = SslProtocols.Tls12;
    
        imap.Connect("imap.example.com");
        imap.StartTLS();
    
        imap.UseBestLogin("user@example.com","password");
    
        // ... 
    
        imap.Close();
    }
    
    ' VB.NET
    
    Using imap As New Imap()
    	imap.SSLConfiguration.EnabledSslProtocols = SslProtocols.Tls12
    
    	imap.Connect("imap.example.com")
    	imap.StartTLS()
    
    	imap.UseBestLogin("user@example.com", "password")
    
    	'...
    
    	imap.Close()
    End Using
    

    Older .NET framework versions

    To use TLS 1.2 in IMAP client at least .NET Framework 4.5+ must be installed on your machine and your application should target .NET 4.5+.

    It is possible to use TLS 1.2 in applications targeting earlier .NET framework versions, but 4.5 must be installed on the machine. After you have .NET 4.5 installed, your 2.0 – 4.0 apps will use the 4.5 System.dll and you can enable TLS 1.2 using this code:

    // C#
    
    imap.SSLConfiguration.EnabledSslProtocols = 
        (SecurityProtocolType)3072;
    

    Using FTP TLS 1.2 with FTP

    By default most systems allow SSL 3.0, TLS 1.0, 1.2 and 1.2 to be used.

    TLS 1.2 is the most secure version of SSL/TLS protocols. It is easy to force the connection to use it. All you need to do is to set Ftp.SSLConfiguration.EnabledSslProtocols property to SslProtocols.Tls12:

    // C#
    
    using (Ftp ftp = new Ftp())
    {
        ftp.SSLConfiguration.EnabledSslProtocols = SslProtocols.Tls12;
    
        ftp.ConnectSSL("ftps.example.com");
    
        ftp.Login("user","password");
    
        ftp.ChangeFolder("uploads");
        ftp.Upload("report.txt", @"c:\report.txt");
    
    
        ftp.Close();
    }
    
    ' VB.NET
    
    Using ftp As New Ftp()
    	ftp.SSLConfiguration.EnabledSslProtocols = SslProtocols.Tls12
    
    	ftp.ConnectSSL("ftps.example.com")
    
    	ftp.Login("user", "password")
    
    	ftp.ChangeFolder("uploads")
    	ftp.Upload("report.txt", "c:\report.txt")
    
    
    	ftp.Close()
    End Using
    

    For explicit SSL/TLS, code is almost the same. You first connect to non-secure port (21) and secure the connection using Ftp.AuthTLS command:

    // C#
    
    using (Ftp ftp = new Ftp())
    {
        ftp.SSLConfiguration.EnabledSslProtocols = SslProtocols.Tls12;
    
        ftp.Connect("ftp.example.com");
        ftp.AuthTLS();
    
        ftp.Login("user","password");
    
        ftp.ChangeFolder("uploads");
        ftp.Upload("report.txt", @"c:\report.txt");
    
        ftp.Close();
    }
    
    ' VB.NET
    
    Using ftp As New Ftp()
    	ftp.SSLConfiguration.EnabledSslProtocols = SslProtocols.Tls12
    
    	ftp.Connect("ftp.example.com")
    	ftp.AuthTLS()
    
    	ftp.Login("user", "password")
    
    	ftp.ChangeFolder("uploads")
    	ftp.Upload("report.txt", "c:\report.txt")
    
    	ftp.Close()
    End Using
    

    To use TLS 1.2 .NET Framework 4.5+ must be installed on your machine and you application should target .NET 4.5+.

    It is possible to use TLS 1.2 in applications targeting .NET lower than 4.5, but 4.5 must be installed on the machine. After you have .NET 4.5 installed, your 2.0-4.0 apps will use the 4.5 System.dll and you can enable TLS 1.2 using this code:

        ftp.SSLConfiguration.EnabledSslProtocols = (System.Security.Authentication.SslProtocols)3072;