Xceed .NET Libraries Documentation
How To Handle a PKCS #7 Formatted Client Certificate
Welcome to Xceed .NET, .NET Standard and Xamarin Libraries! > Task-Based Help > FTP capabilities > Making Secure Connections > How To Handle a PKCS #7 Formatted Client Certificate

Here is an example on how to handle a PKCS #7 formatted client certificate when making an SSL connection.

static void ClientCertificateExample()
{
  try
  {
    // Load the certificate file into a byte array
    byte[] certificateBytes = File.ReadAllBytes( @"D:\Xceed\PKCS7Certificates.p7b" );

    // Create an object that can decode the certificate data
    System.Security.Cryptography.Pkcs.SignedCms cms = new System.Security.Cryptography.Pkcs.SignedCms();
    
    // Decode the certificates
    cms.Decode( certificateBytes );

    FtpClient ftp = new FtpClient();
    //ftp.TraceWriter = Console.Out;

    string host = "localhost";
    int port = 990;

    // Pick an authentication method
    AuthenticationMethod authenticationMethod = AuthenticationMethod.Ssl;

    // Pick verification flags. If unsure, pick 'None'.
    VerificationFlags verificationFlags = VerificationFlags.None;

    // The client certificate to submit to the server
    Certificate clientCertificate = null;

    // Subscribe to the CertificateReceived event
    ftp.CertificateReceived += new CertificateReceivedEventHandler( OnCertificateReceived );

    /* A PKCS #7 file can contain more than one certificate. The certificates are in the collection
     * specified in the cms.Certificates property.
     * 
     * If you know which certificate the FTP server is waiting for, simply supply it to
     * the Connect() method. If you do not know which is the correct one, you can try to connect
     * using each one in turn until the server accepts one. */
     
    // Go through each certificate in the collection
    foreach( System.Security.Cryptography.X509Certificates.X509Certificate2 x509certificate in cms.Certificates )
    {
      // Create a client certificate out of the current x509 certificate
      clientCertificate = new Certificate( x509certificate );

      try
      {
        // Connect implicitly to the server using encryption.
        // This form always enables encryption for the data channel (for file transfers)
        ftp.Connect( host, port, authenticationMethod, verificationFlags, clientCertificate );
      }
      catch( FtpSslException )
      {
        // An FtpSslException exception will be thrown if the client certificate is rejected
      }

      // If we connected successfully to the server
      if( ftp.Connected )
      {
        // No need to try again
        break;
      }
    }

    try
    {
      // Login. The exchanged information will be encrypted
      ftp.Login( "username", "password" );

      /* Perform your file transfers */
    }
    finally
    {
      // Make sure we always disconnect
      ftp.Disconnect();

      ftp.CertificateReceived -= new CertificateReceivedEventHandler( OnCertificateReceived );
    }
  }
  catch( Exception exception )
  {
    // Output some information about it
    Console.WriteLine( "-->{0}: {1}\n{2}", exception.GetType().Name, exception.Message, exception.StackTrace );

    // Fetch the inner exception
    exception = exception.InnerException;

    // While there is an exception
    while( exception != null )
    {
      // Output some information about it
      Console.WriteLine( "-->Inner exception: {0}: {1}\n{2}", exception.GetType().Name, exception.Message, exception.StackTrace );

      // Fetch the inner exception
      exception = exception.InnerException;
    }
  }
}

static void OnCertificateReceived( object sender, CertificateReceivedEventArgs e )
{
  // Always accept the certificate
  e.Action = VerificationAction.Accept;
}
    Private Shared Sub ClientCertificateExample()
      Try
        ' Load the certificate file into a byte array
        Dim certificateBytes() As Byte = File.ReadAllBytes("D:\Xceed\PKCS7Certificates.p7b")

        ' Create an object that can decode the certificate data
        Dim cms As New System.Security.Cryptography.Pkcs.SignedCms()

        ' Decode the certificates
        cms.Decode(certificateBytes)

        Dim ftp As New FtpClient()
        'ftp.TraceWriter = Console.Out;

        Dim host As String = "localhost"
        Dim port As Integer = 990

        ' Pick an authentication method
        Dim authenticationMethod As AuthenticationMethod = AuthenticationMethod.Ssl

        ' Pick verification flags. If unsure, pick 'None'.
        Dim verificationFlags As VerificationFlags = VerificationFlags.None

        ' The client certificate to submit to the server
        Dim clientCertificate As Certificate = Nothing

        ' Subscribe to the CertificateReceived event
        AddHandler ftp.CertificateReceived, AddressOf OnCertificateReceived

'         A PKCS #7 file can contain more than one certificate. The certificates are in the collection
'         * specified in the cms.Certificates property.
'         * 
'         * If you know which certificate the FTP server is waiting for, simply supply it to
'         * the Connect() method. If you do not know which is the correct one, you can try to connect
'         * using each one in turn until the server accepts one. 

        ' Go through each certificate in the collection
        For Each x509certificate As System.Security.Cryptography.X509Certificates.X509Certificate2 In cms.Certificates
          ' Create a client certificate out of the current x509 certificate
          clientCertificate = New Certificate(x509certificate)

          Try
            ' Connect implicitly to the server using encryption.
            ' This form always enables encryption for the data channel (for file transfers)
            ftp.Connect(host, port, authenticationMethod, verificationFlags, clientCertificate)
          Catch e1 As FtpSslException
            ' An FtpSslException exception will be thrown if the client certificate is rejected
          End Try

          ' If we connected successfully to the server
          If ftp.Connected Then
            ' No need to try again
            Exit For
          End If
        Next x509certificate

        Try
          ' Login. The exchanged information will be encrypted
          ftp.Login("username", "password")

          ' Perform your file transfers 
        Finally
          ' Make sure we always disconnect
          ftp.Disconnect()

          RemoveHandler ftp.CertificateReceived, AddressOf OnCertificateReceived
        End Try
      Catch exception As Exception
        ' Output some information about it
        Console.WriteLine("-->{0}: {1}" & Constants.vbLf & "{2}", exception.GetType().Name, exception.Message, exception.StackTrace)

        ' Fetch the inner exception
        exception = exception.InnerException

        ' While there is an exception
        Do While exception IsNot Nothing
          ' Output some information about it
          Console.WriteLine("-->Inner exception: {0}: {1}" & Constants.vbLf & "{2}", exception.GetType().Name, exception.Message, exception.StackTrace)

          ' Fetch the inner exception
          exception = exception.InnerException
        Loop
      End Try
    End Sub

    Private Shared Sub OnCertificateReceived(ByVal sender As Object, ByVal e As CertificateReceivedEventArgs)
      ' Always accept the certificate
      e.Action = VerificationAction.Accept
    End Sub
See Also