Recipe 17.16. Securing Stream DataProblemYou want to use the TCP server in Recipe 16.1 to communicate with the TCP client in Recipe 16.2. However, you need the communication to be secure. SolutionReplace the NetworkStream class with the more secure SslStream class on both the client and the server. The code for the more secure TCP client, TCPClient_SSL, is shown in Example 17-19 (changes are highlighted). Example 17-19. TCPClient_SSL class
The new code for the more secure TCP server, TCPServer_SSL, is shown in Example 17-20 (changes are highlighted). Example 17-20. TCPServer_SSL class
DiscussionFor more information about the inner workings of the TCP server and client and how to run these applications, see Recipes 16.1 and 16.2. In this recipe, you will cover only the changes needed to convert the TCP server and client to use the SslStream object for secure communication. The SslStream object uses the SSL protocol to provide a secure encrypted channel on which to send data. However, encryption is just one of the security features built into the SslStream object. Another feature of SslStream is that it prevents malicious or even accidental modification to the data. Even though the data is encrypted, it may become modified during transit. To determine if this has occurred, the data is signed with a hash before it is sent. When it is received, the data is rehashed and the two hashes are compared. If both hashes are equivalent, the message arrived intact; if the hashes are not equivalent, then something modified the data during transit. The SslStream object also has the ability to use client and/or server certificates to authenticate the client and/or the server. These certificates are used to prove the identity of the issuer. For example, if a client attaches to a server using SSL, the server must provide a certificate to the client that is used to prove that the server is who it says it is. The SslStream object also allows the client to pass a certificate to the server if the client also needs to prove who it is to the server. To allow the TCP server and client to communicate successfully, you need to set up an X.509 certificate that will be used to authenticate the TCP server. To do this, you set up a test certificate using the makecert.exe utility. This utility can be found in the <drive>:\Program Files\Microsoft Visual Studio 8\SDK\v2.0\Bin directory. The syntax for creating a simple certificate is as follows: makecert -r -pe -n "CN=MyTestCert2" -e 01/01/2036 -sr localMachine c:\MyAppTestCert.cer The options are defined as follows:
The final argument to the makecert.exe utility is the output filename, in this case c:\MyAppTestCert.cer. This will create the certificate in the c:\MyAppTestCert.cer file on the hard drive. The next step involves opening Windows Explorer and right-clicking on the c:\MyAppTestCert.cer file. This will display a pop-up menu with the Install Certificate menu item. Click this menu item and a wizard will be started to allow you to import this .cer file into the certificate store. The first dialog box of the wizard is shown in Figure 17-2. Click the Next button to go to the next step in the wizard. Figure 17-2. The first step of the Certificate Import WizardThe next step in the wizard allows you to choose the certificate store in which you want to install your certificate. This dialog is shown in Figure 17-3. Keep the defaults and click the Next button. The final step in the wizard is shown in Figure 17-4. On this dialog, click the Finish button. Figure 17-3. Specifying a certificate store in the Certificate Import WizardFigure 17-4. The last step of the Certificate Import WizardAfter you click the Finish button, the message box shown in Figure 17-5 is displayed, warning you to verify the certificate that you wish to install. Click the Yes button to install the certificate. Figure 17-5. The security warningFinally, the message box in Figure 17-6 is displayed, indicating that the import was successful. Figure 17-6. The import successful messageAt this point you can run the TCP server and client and they should communicate successfully. To use the SslStream in the TCP server project, you need to create a new SslStream object to wrap the TcpClient object: SslStream sslStream = new SslStream(newClient.GetStream()); Before you can use this new stream object, you must authenticate the server using the following line of code: sslStream.AuthenticateAsServer(GetServerCert("MyTestCert2"), false, SslProtocols.Default, true); The GetServerCert method finds the server certificate used to authenticate the server. Notice the name passed in to this method; it is the same as the publisher's certificate name switch used with the makecert.exe utility (see the n switch). This certificate is returned from the GetServerCert method as an X509Certificate object. The next argument to the AuthenticateAsServer method is false, indicating that a client certificate is not required. The SslProtocols.Default argument indicates that the authentication mechanism (SSL 2.0, SSL 3.0, TLS 1.0, or PCT 1.0) is chosen based on what is available to the client and server. The final argument indicates that the certificate will be checked to see whether it has been revoked. To use the SslStream in the TCP client project, you create a new SslStream object, a bit differently from how it was created in the TCP server project: SslStream sslStream = new SslStream(_client.GetStream(), false, new RemoteCertificateValidationCallback(CertificateValidationCallback)); This constructor accepts a stream from the _client field, a false indicating that the stream associated with the _client field will be closed when the Close method of the SslStream object is called, and a delegate that validates the server certificate. The CertificateValidationCallback method is called whenever a server certificate needs to be validated. The server certificate is checked and any errors are passed into this delegate method to allow you to handle them as you wish. The AuthenticateAsClient method is called next to authenticate the server: sslStream.AuthenticateAsClient("MyTestCert2"); As you can see, with a little extra work, you can replace the current stream type you are using with the SslStream to gain the benefits of the SSL protocol. See AlsoSee the "SslStream Class" topic in the MSDN documentation. |