SslStream.Negotiate Method

This method performs the SSL/TLS handshake for an SslStream. It negotiates the SSL/TLS protocol version, cipher suite, and other security parameters between the client and server. This is a crucial step in establishing a secure communication channel.

Syntax

public void Negotiate(
    int millisecondsTimeout
)

Parameters

Name Description
millisecondsTimeout The time-out value, in milliseconds, for the Negotiate operation. A value of 0 specifies an infinite time-out.

Remarks

The Negotiate method initiates the SSL/TLS handshake process. This process involves exchanging security parameters and establishing an encrypted session. The method blocks until the handshake is complete or the specified time-out is reached.

It is important to set an appropriate time-out value to prevent the application from hanging indefinitely if the handshake fails or takes too long.

This method can throw exceptions if the handshake fails due to reasons such as:

Note: For client applications, you typically call SslStream.AuthenticateAsClient, and for server applications, you call SslStream.AuthenticateAsServer. The Negotiate method is a lower-level operation and is often called internally by the authentication methods.

Example

C# Example
using System;
using System.Net.Security;
using System.Net.Sockets;
using System.Security.Cryptography.X509Certificates;
using System.Threading.Tasks;

public class SslExample
{
    public static async Task PerformSslNegotiation(TcpClient tcpClient, string targetHost)
    {
        SslStream sslStream = null;
        try
        {
            sslStream = new SslStream(
                tcpClient.GetStream(),
                false,
                new RemoteCertificateValidationCallback(ValidateServerCertificate),
                null
            );

            // Set a time-out of 30 seconds for the negotiation
            int timeoutMilliseconds = 30000;

            Console.WriteLine($"Starting SSL/TLS negotiation with timeout: {timeoutMilliseconds}ms...");
            await Task.Run(() => sslStream.Negotiate(timeoutMilliseconds)); // Blocking call, run in task for responsiveness
            Console.WriteLine("SSL/TLS negotiation successful.");

            // Now you can use sslStream for encrypted communication
            // For example: await sslStream.WriteAsync(data);
            //             await sslStream.ReadAsync(buffer);

        }
        catch (Exception ex)
        {
            Console.WriteLine($"SSL/TLS negotiation failed: {ex.Message}");
        }
        finally
        {
            // Clean up resources
            sslStream?.Dispose();
            tcpClient.Close();
        }
    }

    // Callback to validate the server certificate (for client-side)
    public static bool ValidateServerCertificate(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors)
    {
        if (sslPolicyErrors == SslPolicyErrors.None)
        {
            return true; // Certificate is valid
        }

        Console.WriteLine($"Certificate error: {sslPolicyErrors}");

        // For development/testing, you might accept invalid certificates,
        // but this is NOT recommended for production.
        // return true;

        return false; // Reject the certificate
    }

    // Example usage (would be part of a larger client/server application)
    public static async Task Main(string[] args)
    {
        // This is a placeholder. In a real scenario, you'd establish a TcpClient connection first.
        // For demonstration, we'll simulate an error scenario.
        Console.WriteLine("Simulating SSL negotiation (no actual connection established in this snippet).");
        // TcpClient client = new TcpClient();
        // try {
        //     await client.ConnectAsync("example.com", 443);
        //     await PerformSslNegotiation(client, "example.com");
        // } catch (Exception e) {
        //     Console.WriteLine($"Error connecting or negotiating: {e.Message}");
        // }
    }
}

Requirements

Assembly Package
System.Net.Primitives.dll Microsoft.NETCore.App (if using .NET Core/5+)
System.dll Microsoft.NETFramework.ReferenceAssemblies.net4x (if using .NET Framework)

See Also