SslStream Class
Provides a stream used for client-server communication that uses the Secure Socket Layer (SSL) security protocol to authenticate the server and optionally the client.
System.MarshalByRefObject
System.IO.Stream
System.Net.Security.AuthenticatedStream
System.Net.Security.SslStream
Assembly: System (in System.dll)
The SslStream type exposes the following members.
| Name | Description | |
|---|---|---|
![]() | SslStream(Stream) | Initializes a new instance of the SslStream class using the specified Stream. |
![]() | SslStream(Stream, Boolean) | Initializes a new instance of the SslStream class using the specified Stream and stream closure behavior. |
![]() | SslStream(Stream, Boolean, RemoteCertificateValidationCallback) | Initializes a new instance of the SslStream class using the specified Stream, stream closure behavior and certificate validation delegate. |
![]() | SslStream(Stream, Boolean, RemoteCertificateValidationCallback, LocalCertificateSelectionCallback) | Initializes a new instance of the SslStream class using the specified Stream, stream closure behavior, certificate validation delegate and certificate selection delegate. |
![]() | SslStream(Stream, Boolean, RemoteCertificateValidationCallback, LocalCertificateSelectionCallback, EncryptionPolicy) | Initializes a new instance of the SslStream class using the specified Stream |
| Name | Description | |
|---|---|---|
![]() | CanRead | Gets a Boolean value that indicates whether the underlying stream is readable. (Overrides Stream.CanRead.) |
![]() | CanSeek | Gets a Boolean value that indicates whether the underlying stream is seekable. (Overrides Stream.CanSeek.) |
![]() | CanTimeout | Gets a Boolean value that indicates whether the underlying stream supports time-outs. (Overrides Stream.CanTimeout.) |
![]() | CanWrite | Gets a Boolean value that indicates whether the underlying stream is writable. (Overrides Stream.CanWrite.) |
![]() | CheckCertRevocationStatus | Gets a Boolean value that indicates whether the certificate revocation list is checked during the certificate validation process. |
![]() | CipherAlgorithm | Gets a value that identifies the bulk encryption algorithm used by this SslStream. |
![]() | CipherStrength | Gets a value that identifies the strength of the cipher algorithm used by this SslStream. |
![]() | HashAlgorithm | Gets the algorithm used for generating message authentication codes (MACs). |
![]() | HashStrength | Gets a value that identifies the strength of the hash algorithm used by this instance. |
![]() | InnerStream | Gets the stream used by this AuthenticatedStream for sending and receiving data. (Inherited from AuthenticatedStream.) |
![]() | IsAuthenticated | Gets a Boolean value that indicates whether authentication was successful. (Overrides AuthenticatedStream.IsAuthenticated.) |
![]() | IsEncrypted | Gets a Boolean value that indicates whether this SslStream uses data encryption. (Overrides AuthenticatedStream.IsEncrypted.) |
![]() | IsMutuallyAuthenticated | Gets a Boolean value that indicates whether both server and client have been authenticated. (Overrides AuthenticatedStream.IsMutuallyAuthenticated.) |
![]() | IsServer | Gets a Boolean value that indicates whether the local side of the connection used by this SslStream was authenticated as the server. (Overrides AuthenticatedStream.IsServer.) |
![]() | IsSigned | Gets a Boolean value that indicates whether the data sent using this stream is signed. (Overrides AuthenticatedStream.IsSigned.) |
![]() | KeyExchangeAlgorithm | Gets the key exchange algorithm used by this SslStream. |
![]() | KeyExchangeStrength | Gets a value that identifies the strength of the key exchange algorithm used by this instance. |
![]() | LeaveInnerStreamOpen | Gets whether the stream used by this AuthenticatedStream for sending and receiving data has been left open. (Inherited from AuthenticatedStream.) |
![]() | Length | Gets the length of the underlying stream. (Overrides Stream.Length.) |
![]() | LocalCertificate | Gets the certificate used to authenticate the local endpoint. |
![]() | Position | Gets or sets the current position in the underlying stream. (Overrides Stream.Position.) |
![]() | ReadTimeout | Gets or sets the amount of time a read operation blocks waiting for data. (Overrides Stream.ReadTimeout.) |
![]() | RemoteCertificate | Gets the certificate used to authenticate the remote endpoint. |
![]() | SslProtocol | Gets a value that indicates the security protocol used to authenticate this connection. |
![]() | TransportContext | Gets the TransportContext used for authentication using extended protection. |
![]() | WriteTimeout | Gets or sets the amount of time a write operation blocks waiting for data. (Overrides Stream.WriteTimeout.) |
| Name | Description | |
|---|---|---|
![]() | AuthenticateAsClient(String) | Called by clients to authenticate the server and optionally the client in a client-server connection. |
![]() | AuthenticateAsClient(String, X509CertificateCollection, SslProtocols, Boolean) | Called by clients to authenticate the server and optionally the client in a client-server connection. The authentication process uses the specified certificate collection and SSL protocol. |
![]() | AuthenticateAsServer(X509Certificate) | Called by servers to authenticate the server and optionally the client in a client-server connection using the specified certificate. |
![]() | AuthenticateAsServer(X509Certificate, Boolean, SslProtocols, Boolean) | Called by servers to begin an asynchronous operation to authenticate the server and optionally the client using the specified certificates, requirements and security protocol. |
![]() | BeginAuthenticateAsClient(String, AsyncCallback, Object) | Called by clients to begin an asynchronous operation to authenticate the server and optionally the client. |
![]() | BeginAuthenticateAsClient(String, X509CertificateCollection, SslProtocols, Boolean, AsyncCallback, Object) | Called by clients to begin an asynchronous operation to authenticate the server and optionally the client using the specified certificates and security protocol. |
![]() | BeginAuthenticateAsServer(X509Certificate, AsyncCallback, Object) | Called by servers to begin an asynchronous operation to authenticate the client and optionally the server in a client-server connection. |
![]() | BeginAuthenticateAsServer(X509Certificate, Boolean, SslProtocols, Boolean, AsyncCallback, Object) | Called by servers to begin an asynchronous operation to authenticate the server and optionally the client using the specified certificates, requirements and security protocol. |
![]() | BeginRead | Begins an asynchronous read operation that reads data from the stream and stores it in the specified array. (Overrides Stream.BeginRead(Byte(), Int32, Int32, AsyncCallback, Object).) |
![]() | BeginWrite | Begins an asynchronous write operation that writes Bytes from the specified buffer to the stream. (Overrides Stream.BeginWrite(Byte(), Int32, Int32, AsyncCallback, Object).) |
![]() | Close | Closes the current stream and releases any resources (such as sockets and file handles) associated with the current stream. (Inherited from Stream.) |
![]() | CopyTo(Stream) | Reads the bytes from the current stream and writes them to the destination stream. (Inherited from Stream.) |
![]() | CopyTo(Stream, Int32) | Reads all the bytes from the current stream and writes them to a destination stream, using a specified buffer size. (Inherited from Stream.) |
![]() | CreateObjRef | Creates an object that contains all the relevant information required to generate a proxy used to communicate with a remote object. (Inherited from MarshalByRefObject.) |
![]() | CreateWaitHandle | Obsolete. Allocates a WaitHandle object. (Inherited from Stream.) |
![]() | Dispose | Releases all resources used by the Stream. (Inherited from Stream.) |
![]() | Dispose(Boolean) | Releases the unmanaged resources used by the SslStream and optionally releases the managed resources. (Overrides AuthenticatedStream.Dispose(Boolean).) |
![]() | EndAuthenticateAsClient | Ends a pending asynchronous server authentication operation started with a previous call to BeginAuthenticateAsServer. |
![]() | EndAuthenticateAsServer | Ends a pending asynchronous client authentication operation started with a previous call to BeginAuthenticateAsClient. |
![]() | EndRead | Ends an asynchronous read operation started with a previous call to BeginRead. (Overrides Stream.EndRead(IAsyncResult).) |
![]() | EndWrite | Ends an asynchronous write operation started with a previous call to BeginWrite. (Overrides Stream.EndWrite(IAsyncResult).) |
![]() | Equals(Object) | Determines whether the specified Object is equal to the current Object. (Inherited from Object.) |
![]() | Finalize | Allows an object to try to free resources and perform other cleanup operations before it is reclaimed by garbage collection. (Inherited from Object.) |
![]() | Flush | Causes any buffered data to be written to the underlying device. (Overrides Stream.Flush.) |
![]() | GetHashCode | Serves as a hash function for a particular type. (Inherited from Object.) |
![]() | GetLifetimeService | Retrieves the current lifetime service object that controls the lifetime policy for this instance. (Inherited from MarshalByRefObject.) |
![]() | GetType | Gets the Type of the current instance. (Inherited from Object.) |
![]() | InitializeLifetimeService | Obtains a lifetime service object to control the lifetime policy for this instance. (Inherited from MarshalByRefObject.) |
![]() | MemberwiseClone | Creates a shallow copy of the current Object. (Inherited from Object.) |
![]() | MemberwiseClone(Boolean) | Creates a shallow copy of the current MarshalByRefObject object. (Inherited from MarshalByRefObject.) |
![]() | ObjectInvariant | Infrastructure. Provides support for a Contract. (Inherited from Stream.) |
![]() | Read | Reads data from this stream and stores it in the specified array. (Overrides Stream.Read(Byte(), Int32, Int32).) |
![]() | ReadByte | Reads a byte from the stream and advances the position within the stream by one byte, or returns -1 if at the end of the stream. (Inherited from Stream.) |
![]() | Seek | Infrastructure. Throws a NotSupportedException. (Overrides Stream.Seek(Int64, SeekOrigin).) |
![]() | SetLength | Sets the length of the underlying stream. (Overrides Stream.SetLength(Int64).) |
![]() | ToString | Returns a string that represents the current object. (Inherited from Object.) |
![]() | Write(Byte()) | Writes the specified data to this stream. |
![]() | Write(Byte(), Int32, Int32) | Write the specified number of Bytes to the underlying stream using the specified buffer and offset. (Overrides Stream.Write(Byte(), Int32, Int32).) |
![]() | WriteByte | Writes a byte to the current position in the stream and advances the position within the stream by one byte. (Inherited from Stream.) |
SSL protocols help to provide confidentiality and integrity checking for messages transmitted using an SslStream. An SSL connection, such as that provided by SslStream, should be used when communicating sensitive information between a client and a server. Using an SslStream helps to prevent anyone from reading and tampering with information while it is in transit on the network.
An SslStream instance transmits data using a stream that you supply when creating the SslStream. When you supply this underlying stream, you have the option to specify whether closing the SslStream also closes the underlying stream. Typically, the SslStream class is used with the TcpClient and TcpListener classes. The GetStream method provides a NetworkStream suitable for use with the SslStream class.
After creating an SslStream, the server and optionally, the client must be authenticated. The server must provide an X509 certificate that establishes proof of its identity and can request that the client also do so. Authentication must be performed before transmitting information using an SslStream. Clients initiate authentication using the synchronous AuthenticateAsClient methods, which block until the authentication completes, or the asynchronous BeginAuthenticateAsClient methods, which do not block waiting for the authentication to complete. Servers initiate authentication using the synchronous AuthenticateAsServer or asynchronous BeginAuthenticateAsServer methods. Both client and server must initiate the authentication.
The authentication is handled by the Security Support Provider (SSPI) channel provider. The client is given an opportunity to control validation of the server's certificate by specifying a RemoteCertificateValidationCallback delegate when creating an SslStream. The server can also control validation by supplying a RemoteCertificateValidationCallback delegate. The method referenced by the delegate includes the remote party's certificate and any errors SSPI encountered while validating the certificate. Note that if the server specifies a delegate, the delegate's method is invoked regardless of whether the server requested client authentication. If the server did not request client authentication, the server's delegate method receives a null certificate and an empty array of certificate errors.
If the server requires client authentication, the client must specify one or more certificates for authentication. If the client has more than one certificate, the client can provide a LocalCertificateSelectionCallback delegate to select the correct certificate for the server. The client's certificates must be located in the current user's "My" certificate store. Client authentication via certificates is not supported for the Ssl2 (SSL version 2) protocol.
If the authentication fails, you receive a AuthenticationException, and the SslStream is no longer useable. You should close this object and remove all references to it so that it can be collected by the garbage collector.
When the authentication process, also known as the SSL handshake, succeeds, the identity of the server (and optionally, the client) is established and the SslStream can be used by the client and server to exchange messages. Before sending or receiving information, the client and server should check the security services and levels provided by the SslStream to determine whether the protocol, algorithms, and strengths selected meet their requirements for integrity and confidentiality. If the current settings are not sufficient, the stream should be closed. You can check the security services provided by the SslStream using the IsEncrypted and IsSigned properties. The following table shows the elements that report the cryptographic settings used for authentication, encryption and data signing.
Element | Members |
|---|---|
The security protocol used to authenticate the server and, optionally, the client. | The SslProtocol property and the associated SslProtocols enumeration. |
The key exchange algorithm. | The KeyExchangeAlgorithm property and the associated ExchangeAlgorithmType enumeration. |
The message integrity algorithm. | The HashAlgorithm property and the associated HashAlgorithmType enumeration. |
The message confidentiality algorithm. | The CipherAlgorithm property and the associated CipherAlgorithmType enumeration. |
The strengths of the selected algorithms. | The KeyExchangeStrength, HashStrength, and CipherStrength properties. |
After a successful authentication, you can send data using the synchronous Write or asynchronous BeginWrite methods. You can receive data using the synchronous Read or asynchronous BeginRead methods.
If you specified to the SslStream that the underlying stream should be left open, you are responsible for closing that stream when you are done using it.
Note |
|---|
If the application that creates the SslStream object runs with the credentials of a Normal user, the application will not be able to access certificates installed in the local machine store unless permission has been explicitly given to the user to do so. |
SslStream assumes that a timeout along with any other IOException when one is thrown from the inner stream will be treated as fatal by its caller. Reusing a SslStream instance after a timeout will return garbage. An application should Close the SslStream and throw an exception in these cases.
The following code example demonstrates creating an TcpListener that uses the SslStream class to communicate with clients.
Imports System Imports System.Collections Imports System.Net Imports System.Net.Sockets Imports System.Net.Security Imports System.Security.Authentication Imports System.Text Imports System.Security.Cryptography.X509Certificates Imports System.IO Namespace Examples.System.Net Public NotInheritable Class SslTcpServer Private Shared serverCertificate As X509Certificate = Nothing ' The certificate parameter specifies the name of the file ' containing the machine certificate. Public Shared Sub RunServer(ByVal certificate As String) serverCertificate = X509Certificate.CreateFromCertFile(certificate) ' Create a TCP/IP (IPv4) socket and listen for incoming connections. Dim listener As New TcpListener(IPAddress.Any, 8080) listener.Start() Do Console.WriteLine("Waiting for a client to connect...") ' Application blocks while waiting for an incoming connection. ' Type CNTL-C to terminate the server. Dim client As TcpClient = listener.AcceptTcpClient() ProcessClient(client) Loop End Sub Private Shared Sub ProcessClient(ByVal client As TcpClient) ' A client has connected. Create the ' SslStream using the client's network stream. Dim sslStream As New SslStream(client.GetStream(), False) ' Authenticate the server but don't require the client to authenticate. Try sslStream.AuthenticateAsServer(serverCertificate, False, SslProtocols.Tls, True) ' Display the properties and settings for the authenticated stream. DisplaySecurityLevel(sslStream) DisplaySecurityServices(sslStream) DisplayCertificateInformation(sslStream) DisplayStreamProperties(sslStream) ' Set timeouts for the read and write to 5 seconds. sslStream.ReadTimeout = 5000 sslStream.WriteTimeout = 5000 ' Read a message from the client. Console.WriteLine("Waiting for client message...") Dim messageData As String = ReadMessage(sslStream) Console.WriteLine("Received: {0}", messageData) ' Write a message to the client. Dim message() As Byte = Encoding.UTF8.GetBytes("Hello from the server.<EOF>") Console.WriteLine("Sending hello message.") sslStream.Write(message) Catch e As AuthenticationException Console.WriteLine("Exception: {0}", e.Message) If e.InnerException IsNot Nothing Then Console.WriteLine("Inner exception: {0}", e.InnerException.Message) End If Console.WriteLine ("Authentication failed - closing the connection.") sslStream.Close() client.Close() Return Finally ' The client stream will be closed with the sslStream ' because we specified this behavior when creating ' the sslStream. sslStream.Close() client.Close() End Try End Sub Private Shared Function ReadMessage(ByVal sslStream As SslStream) As String ' Read the message sent by the client. ' The client signals the end of the message using the ' "<EOF>" marker. Dim buffer(2047) As Byte Dim messageData As New StringBuilder() Dim bytes As Integer = -1 Do ' Read the client's test message. bytes = sslStream.Read(buffer, 0, buffer.Length) ' Use Decoder class to convert from bytes to UTF8 ' in case a character spans two buffers. Dim decoder As Decoder = Encoding.UTF8.GetDecoder() Dim chars(decoder.GetCharCount(buffer,0,bytes) - 1) As Char decoder.GetChars(buffer, 0, bytes, chars,0) messageData.Append (chars) ' Check for EOF or an empty message. If messageData.ToString().IndexOf("<EOF>") <> -1 Then Exit Do End If Loop While bytes <>0 Return messageData.ToString() End Function Private Shared Sub DisplaySecurityLevel(ByVal stream As SslStream) Console.WriteLine("Cipher: {0} strength {1}", stream.CipherAlgorithm, stream.CipherStrength) Console.WriteLine("Hash: {0} strength {1}", stream.HashAlgorithm, stream.HashStrength) Console.WriteLine("Key exchange: {0} strength {1}", stream.KeyExchangeAlgorithm, stream.KeyExchangeStrength) Console.WriteLine("Protocol: {0}", stream.SslProtocol) End Sub Private Shared Sub DisplaySecurityServices(ByVal stream As SslStream) Console.WriteLine("Is authenticated: {0} as server? {1}", stream.IsAuthenticated, stream.IsServer) Console.WriteLine("IsSigned: {0}", stream.IsSigned) Console.WriteLine("Is Encrypted: {0}", stream.IsEncrypted) End Sub Private Shared Sub DisplayStreamProperties(ByVal stream As SslStream) Console.WriteLine("Can read: {0}, write {1}", stream.CanRead, stream.CanWrite) Console.WriteLine("Can timeout: {0}", stream.CanTimeout) End Sub Private Shared Sub DisplayCertificateInformation(ByVal stream As SslStream) Console.WriteLine("Certificate revocation list checked: {0}", stream.CheckCertRevocationStatus) Dim localCertificate As X509Certificate = stream.LocalCertificate If stream.LocalCertificate IsNot Nothing Then Console.WriteLine("Local cert was issued to {0} and is valid from {1} until {2}.", localCertificate.Subject, localCertificate.GetEffectiveDateString(), localCertificate.GetExpirationDateString()) Else Console.WriteLine("Local certificate is null.") End If ' Display the properties of the client's certificate. Dim remoteCertificate As X509Certificate = stream.RemoteCertificate If stream.RemoteCertificate IsNot Nothing Then Console.WriteLine("Remote cert was issued to {0} and is valid from {1} until {2}.", remoteCertificate.Subject, remoteCertificate.GetEffectiveDateString(), remoteCertificate.GetExpirationDateString()) Else Console.WriteLine("Remote certificate is null.") End If End Sub Private Shared Sub DisplayUsage() Console.WriteLine("To start the server specify:") Console.WriteLine("serverSync certificateFile.cer") Environment.Exit(1) End Sub Public Shared Function Main(ByVal args() As String) As Integer Dim certificate As String = Nothing If args Is Nothing OrElse args.Length < 1 Then DisplayUsage() End If certificate = args(0) SslTcpServer.RunServer(certificate) Return 0 End Function End Class End Namespace
The following code example demonstrates creating a TcpClient that uses the SslStream class to communicate with a server.
Imports System Imports System.Collections Imports System.Net Imports System.Net.Security Imports System.Net.Sockets Imports System.Security.Authentication Imports System.Text Imports System.Security.Cryptography.X509Certificates Imports System.IO Namespace Examples.System.Net Public Class SslTcpClient Private Shared certificateErrors As New Hashtable() ' The following method is invoked by the RemoteCertificateValidationDelegate. Public Shared Function ValidateServerCertificate(ByVal sender As Object, ByVal certificate As X509Certificate, ByVal chain As X509Chain, ByVal sslPolicyErrors As SslPolicyErrors) As Boolean If sslPolicyErrors = SslPolicyErrors.None Then Return True End If Console.WriteLine("Certificate error: {0}", sslPolicyErrors) ' Do not allow this client to communicate with unauthenticated servers. Return False End Function Public Shared Sub RunClient(ByVal machineName As String, ByVal serverName As String) ' Create a TCP/IP client socket. ' machineName is the host running the server application. Dim client As New TcpClient(machineName,443) Console.WriteLine("Client connected.") ' Create an SSL stream that will close the client's stream. Dim sslStream As New SslStream(client.GetStream(), False, New RemoteCertificateValidationCallback (AddressOf ValidateServerCertificate), Nothing) ' The server name must match the name on the server certificate. Try sslStream.AuthenticateAsClient(serverName) Catch e As AuthenticationException Console.WriteLine("Exception: {0}", e.Message) If e.InnerException IsNot Nothing Then Console.WriteLine("Inner exception: {0}", e.InnerException.Message) End If Console.WriteLine ("Authentication failed - closing the connection.") client.Close() Return End Try ' Encode a test message into a byte array. ' Signal the end of the message using the "<EOF>". Dim messsage() As Byte = Encoding.UTF8.GetBytes("Hello from the client.<EOF>") ' Send hello message to the server. sslStream.Write(messsage) sslStream.Flush() ' Read message from the server. Dim serverMessage As String = ReadMessage(sslStream) Console.WriteLine("Server says: {0}", serverMessage) ' Close the client connection. client.Close() Console.WriteLine("Client closed.") End Sub Private Shared Function ReadMessage(ByVal sslStream As SslStream) As String ' Read the message sent by the server. ' The end of the message is signaled using the ' "<EOF>" marker. Dim buffer(2047) As Byte Dim messageData As New StringBuilder() Dim bytes As Integer = -1 Do bytes = sslStream.Read(buffer, 0, buffer.Length) ' Use Decoder class to convert from bytes to UTF8 ' in case a character spans two buffers. Dim decoder As Decoder = Encoding.UTF8.GetDecoder() Dim chars(decoder.GetCharCount(buffer,0,bytes) - 1) As Char decoder.GetChars(buffer, 0, bytes, chars,0) messageData.Append (chars) ' Check for EOF. If messageData.ToString().IndexOf("<EOF>") <> -1 Then Exit Do End If Loop While bytes <> 0 Return messageData.ToString() End Function Private Shared Sub DisplayUsage() Console.WriteLine("To start the client specify:") Console.WriteLine("clientSync machineName [serverName]") Environment.Exit(1) End Sub Public Shared Function Main(ByVal args() As String) As Integer Dim serverCertificateName As String = Nothing Dim machineName As String = Nothing If args Is Nothing OrElse args.Length <1 Then DisplayUsage() End If ' User can specify the machine name and server name. ' Server name must match the name on the server's certificate. machineName = args(0) If args.Length <2 Then serverCertificateName = machineName Else serverCertificateName = args(1) End If SslTcpClient.RunClient(machineName, serverCertificateName) Return 0 End Function End Class End Namespace
Windows 7, Windows Vista SP1 or later, Windows XP SP3, Windows XP SP2 x64 Edition, Windows Server 2008 (Server Core not supported), Windows Server 2008 R2 (Server Core supported with SP1 or later), Windows Server 2003 SP2
The .NET Framework does not support all versions of every platform. For a list of the supported versions, see .NET Framework System Requirements.
