C# Socket SSL通讯笔记

一、x.509证书

 

1.制作证书

先进入到vs2005的命令行状态,即:
开始-->程序-->Microsoft Visual Studio 2005-->Visual Studio Tools-->Visual Studio 2005 命令提示

键入:

makecert -r -pe -n  " CN=MyServer "  -ss My -sky exchange

解释一下:makecert.exe是一个专门用来制作证书的小工具,上面一行的意思就是制作一个CN=MyServer的服务器证书,默认存储在CurrentUser"My这个位置,同时这个证书标识为可导出。(详细的

MakeCert参数可参见http://msdn.microsoft.com/zh-cn/bfsktky3(vs.80).aspx)

再输入:

makecert -r -pe -n  " CN=MyClient "  -ss My -sky exchange

生成客户端证书,证书生成好以后,可以在IE里查看到,IE-->工具-->Internet选项-->内容-->证书

记得要把证书导入到受信任的那栏,不然是访问不到的, 然后在IE-->工具-->Internet选项-->内容-->证书里导出一个CER,面通知过程中选不要是私钥, 这样给客户端使用

socket服务器的建立代码如下,注意所引用的命名空间:

 

代码
using  System;
using  System.ServiceModel;
using  System.Net;
using  System.Net.Sockets;
using  System.Net.Security;
using  System.Text;
using  System.Security.Authentication;
using  System.Security.Cryptography.X509Certificates;
using  System.IdentityModel.Tokens;
using  System.IdentityModel.Selectors;

namespace  ConsoleApp
{
    
public   class  Program
    {
        
static  X509Certificate serverCertificate  =   null ;

        
public   static   void  RunServer()
        {
            
// serverCertificate = X509Certificate.CreateFromSignedFile(@"C:\Program Files\Microsoft Visual Studio 8\SDK\v2.0\samool.pvk");
            TcpListener listener  =   new  TcpListener(IPAddress.Parse( " 192.168.20.139 " ),  901 );
            listener.Start();
            
while  ( true )
            {
                
try
                {
                    Console.WriteLine(
" Waiting for a client to connect... " );
                    TcpClient client 
=  listener.AcceptTcpClient();
                    ProcessClient(client);
                }
                
catch
                {
 
                }
            }
        }

        
static   void  ProcessClient(TcpClient client)
        {
            SslStream sslStream 
=   new  SslStream(client.GetStream(),  false );
            
try
            {
                sslStream.AuthenticateAsServer(serverCertificate, 
false , SslProtocols.Tls,  true );
                DisplaySecurityLevel(sslStream);
                DisplaySecurityServices(sslStream);
                DisplayCertificateInformation(sslStream);
                DisplayStreamProperties(sslStream);

                sslStream.ReadTimeout 
=   5000 ;
                sslStream.WriteTimeout 
=   5000 ;
                Console.WriteLine(
" Waiting for client message... " );
                
string  messageData  =  ReadMessage(sslStream);
                Console.WriteLine(
" Received: {0} " , messageData);
                
byte [] message  =  Encoding.UTF8.GetBytes( " Hello from the server. " );
                Console.WriteLine(
" Sending hello message. " );
                sslStream.Write(message);
            }
            
catch  (AuthenticationException e)
            {
                Console.WriteLine(
" Exception: {0} " , e.Message);
                
if  (e.InnerException  !=   null )
                {
                    Console.WriteLine(
" Inner exception: {0} " , e.InnerException.Message);
                }
                Console.WriteLine(
" Authentication failed - closing the connection. " );
                sslStream.Close();
                client.Close();
                
return ;
            }
            
finally
            {
                sslStream.Close();
                client.Close();
            }
        }

        
static   string  ReadMessage(SslStream sslStream)
        {
            
byte [] buffer  =   new   byte [ 2048 ];
            StringBuilder messageData 
=   new  StringBuilder();
            
int  bytes  =   - 1 ;
            
do
            {
                bytes 
=  sslStream.Read(buffer,  0 , buffer.Length);
                Decoder decoder 
=  Encoding.UTF8.GetDecoder();
                
char [] chars  =   new   char [decoder.GetCharCount(buffer,  0 , bytes)];
                decoder.GetChars(buffer, 
0 , bytes, chars,  0 );
                messageData.Append(chars);
                
if  (messageData.ToString().IndexOf( "" !=   - 1 )
                {
                    
break ;
                }
            }
            
while  (bytes  !=   0 );

            
return  messageData.ToString();
        }

        
static   void  DisplaySecurityLevel(SslStream stream)
        {
            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);
        }

        
static   void  DisplaySecurityServices(SslStream stream)
        {
            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);
        }

        
static   void  DisplayStreamProperties(SslStream stream)
        {
            Console.WriteLine(
" Can read: {0}, write {1} " , stream.CanRead, stream.CanWrite);
            Console.WriteLine(
" Can timeout: {0} " , stream.CanTimeout);
        }

        
static   void  DisplayCertificateInformation(SslStream stream)
        {
            Console.WriteLine(
" Certificate revocation list checked: {0} " , stream.CheckCertRevocationStatus);

            X509Certificate localCertificate 
=  stream.LocalCertificate;
            
if  (stream.LocalCertificate  !=   null )
            {
                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. " );
            }
            X509Certificate remoteCertificate 
=  stream.RemoteCertificate;
            
if  (stream.RemoteCertificate  !=   null )
            {
                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. " );
            }
        }

        
private   static   void  DisplayUsage()
        {
            Console.WriteLine(
" To start the server specify: " );
            Console.WriteLine(
" serverSync certificateFile.cer " );
            
// Environment.Exit(1);
        }

        
public   static   void  Main( string [] args)
        {
            
// string certificate = null;
            
// if (args == null || args.Length < 1)
            
// {
            
//     DisplayUsage();
            
// }
            
// certificate = args[0];
             try
            {
                X509Store store 
=   new  X509Store(StoreName.My);
                store.Open(OpenFlags.ReadWrite);

                
//  检索证书 
                X509Certificate2Collection certs  =  store.Certificates.Find(X509FindType.FindBySubjectName,  " MyServer " false );  //  vaildOnly = true时搜索无结果。
                 if  (certs.Count  ==   0 return ;

                serverCertificate 
=  certs[ 0 ];
                RunServer();
                store.Close(); 
//  关闭存储区。
            }
            
catch  (Exception ex)
            {
                Console.WriteLine(ex.Message);
            }
            Console.ReadLine();
            
// return 0;



            
// try
            
// {
            
//     Console.WriteLine("服务端输出:" + ServiceSecurityContext.Current.PrimaryIdentity.AuthenticationType);
            
//     Console.WriteLine(ServiceSecurityContext.Current.PrimaryIdentity.Name);
            
//     Console.WriteLine("服务端时间:" + DateTime.Now.ToString());
            
// }
            
// catch (Exception ex)
            
// {
            
//     Console.WriteLine(ex.Message);
            
// }
            
// Console.ReadLine();

        }
    }


}

 

 

Sokect客户端代码如下:

 

代码
using  System;
using  System.Security;
using  System.Net;
using  System.Net.Sockets;
using  System.Net.Security;
using  System.Text;
using  System.Security.Authentication;
using  System.Security.Cryptography.X509Certificates;

namespace  ConsoleAppClient
{
    
using  System;
    
using  System.Collections;
    
using  System.Net;
    
using  System.Net.Security;
    
using  System.Net.Sockets;
    
using  System.Security.Authentication;
    
using  System.Text;
    
using  System.Security.Cryptography.X509Certificates;
    
using  System.IO;

    
namespace  Examples.System.Net
    {
        
public   class  SslTcpClient
        {
            
private   static  Hashtable certificateErrors  =   new  Hashtable();
            
//  The following method is invoked by the RemoteCertificateValidationDelegate.
             public   static   bool  ValidateServerCertificate(
                  
object  sender,
                  X509Certificate certificate,
                  X509Chain chain,
                  SslPolicyErrors sslPolicyErrors)
            {
                
if  (sslPolicyErrors  ==  SslPolicyErrors.None)
                    
return   true ;

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

                
//  Do not allow this client to communicate with unauthenticated servers.
                 return   false ;
            }

            
public   static   void  RunClient( string  machineName)
            {
                
//  Create a TCP/IP client socket.
                
//  machineName is the host running the server application.
                TcpClient client  =   new  TcpClient(machineName,  901 );
                Console.WriteLine(
" Client connected. " );
                
//  Create an SSL stream that will close the client's stream.
                SslStream sslStream  =   new  SslStream(client.GetStream(),  false new  RemoteCertificateValidationCallback(ValidateServerCertificate),  null );
                
//  The server name must match the name on the server certificate.

                
// X509Store store = new X509Store(StoreName.My);
                
// store.Open(OpenFlags.ReadWrite);

                
/// / 检索证书 
                 // X509Certificate2Collection certs = store.Certificates.Find(X509FindType.FindBySubjectName, "MyServer", false);  //  vaildOnly = true时搜索无结果。

                X509CertificateCollection certs 
=   new  X509CertificateCollection();
                X509Certificate cert 
=  X509Certificate.CreateFromCertFile( @" D:\cashcer.cer " );
                certs.Add(cert);
                
try
                {
                    sslStream.AuthenticateAsClient(
" MyServer " , certs, SslProtocols.Tls,  false );
                }
                
catch  (AuthenticationException e)
                {
                    Console.WriteLine(
" Exception: {0} " , e.Message);
                    
if  (e.InnerException  !=   null )
                    {
                        Console.WriteLine(
" Inner exception: {0} " , e.InnerException.Message);
                    }
                    Console.WriteLine(
" Authentication failed - closing the connection. " );
                    client.Close();
                    
return ;
                }
                
//  Encode a test message into a byte array.
                
//  Signal the end of the message using the "<EOF>".
                 byte [] messsage  =  Encoding.UTF8.GetBytes( " Hello from the client.<EOF> " );
                
//  Send hello message to the server. 
                sslStream.Write(messsage);
                sslStream.Flush();
                
//  Read message from the server.
                 string  serverMessage  =  ReadMessage(sslStream);
                Console.WriteLine(
" Server says: {0} " , serverMessage);
                
//  Close the client connection.
                client.Close();
                Console.WriteLine(
" Client closed. " );
            }

            
static   string  ReadMessage(SslStream sslStream)
            {
                
//  Read the  message sent by the server.
                
//  The end of the message is signaled using the
                
//  "<EOF>" marker.
                 byte [] buffer  =   new   byte [ 2048 ];
                StringBuilder messageData 
=   new  StringBuilder();
                
int  bytes  =   - 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.
                    Decoder decoder  =  Encoding.UTF8.GetDecoder();
                    
char [] chars  =   new   char [decoder.GetCharCount(buffer,  0 , bytes)];
                    decoder.GetChars(buffer, 
0 , bytes, chars,  0 );
                    messageData.Append(chars);
                    
//  Check for EOF.
                     if  (messageData.ToString().IndexOf( " <EOF> " !=   - 1 )
                    {
                        
break ;
                    }
                } 
while  (bytes  !=   0 );

                
return  messageData.ToString();
            }

            
private   static   void  DisplayUsage()
            {
                Console.WriteLine(
" To start the client specify: " );
                Console.WriteLine(
" clientSync machineName [serverName] " );
                Environment.Exit(
1 );
            }

            
public   static   void  Main( string [] args)
            {
                
string  machineName  =   null
                machineName 
=   " 192.168.20.139 " ;

                
try
                {                  
                    RunClient(machineName);
                }
                
catch  (Exception ex)
                {
                    Console.WriteLine(ex.Message);
                }
                Console.ReadLine();
            }
        }
    }

}

 

运行就可以了。

 

注意的是证书的取得, 客户端有个向服务器验证证书的方法:

 

代码
  public   static   bool  ValidateServerCertificate(
                  
object  sender,
                  X509Certificate certificate,
                  X509Chain chain,
                  SslPolicyErrors sslPolicyErrors)
            {
                
if  (sslPolicyErrors  ==  SslPolicyErrors.None)
                    
return   true ;

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

                
//  Do not allow this client to communicate with unauthenticated servers.
                 return   false ;
            }

 

 

如果上面返回的SslPolicyErrors枚举值不是None你就应该检查你的证书是否正确, 是否添加到信任里面。

 

你可能感兴趣的:(socket)