引言 
   有个项目中用到了Socket ssl通信,在此记录一下.

证书

Socket ssl需要用到证书用来校验身份,而作为调试,我们只需用测试证书即可.

有个工具可以很方便地制作测试证书,下载地址为http://supersocket.codeplex.com/releases/view/59311

首先, 输入Common Name,密码和保存路径后,我们可以得到包含私钥的证书server.pfx.

然后,安装证书到电脑中,在IE选项中导出一份证书作为client.cer.

客户端

使用客户端的电脑需要安装client.cer到<受信任的根证书颁发机构>,且要把证书放在程序目录中,具体代码如下

 class Program
{
private static SslStream _sslStream; static void Main(string[] args)
{ try
{
TcpClient client = new TcpClient("127.0.0.1", );
Console.WriteLine("Client connected.");
_sslStream = new SslStream(
client.GetStream(),
false,
new RemoteCertificateValidationCallback(ValidateServerCertificate),
null
); X509CertificateCollection certs = new X509CertificateCollection();
X509Certificate cert = X509Certificate.CreateFromCertFile(System.Environment.CurrentDirectory + @"\" + "client.cer");
certs.Add(cert);
//验证证书
try
{
_sslStream.AuthenticateAsClient("test", 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();
Console.ReadLine();
return;
} //开始读取消息
Task.Factory.StartNew(() =>
{
ReadMessage(_sslStream);
}); Console.WriteLine("按Q退出程序");
string message = "";
message = Console.ReadLine() + "<EOF>";
while (message != "Q")
{
byte[] bytes = Encoding.UTF8.GetBytes(message);
_sslStream.Write(bytes);
_sslStream.Flush();
Console.WriteLine("send:" + message);
message = Console.ReadLine() + "<EOF>";
} client.Close();
}
catch (Exception ex)
{ Console.WriteLine(ex);
Console.ReadLine();
}
} public static void ReadMessage(SslStream sslStream)
{
byte[] buffer = new byte[];
StringBuilder messageData = new StringBuilder();
int bytes = -;
do
{
bytes = sslStream.Read(buffer, , buffer.Length);
Decoder decoder = Encoding.UTF8.GetDecoder();
char[] chars = new char[decoder.GetCharCount(buffer, , bytes)];
decoder.GetChars(buffer, , bytes, chars, );
messageData.Append(chars);
if (messageData.ToString().IndexOf("<EOF>", StringComparison.Ordinal) != -)
{
break;
}
} while (bytes != ); string message = messageData.ToString().Replace("<EOF>", "");
Console.WriteLine("recevied:" + message);
ReadMessage(sslStream);
} private static bool ValidateServerCertificate(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslpolicyerrors)
{
if (sslpolicyerrors == SslPolicyErrors.None)
return true;
Console.WriteLine("Certificate error: {0}", sslpolicyerrors);
return false;
}
}

服务端

服务端电脑要安装server.pfx证书,且要把证书放在程序目录中,具体代码如下

  class Program
{
static void Main(string[] args)
{
TcpListener listener = new TcpListener(IPAddress.Any, );
listener.Start(); Console.WriteLine("Waiting for a client to connect...");
TcpClient client = listener.AcceptTcpClient(); _sslStream = new SslStream(client.GetStream(), true); try
{
serverCertificate = new X509Certificate(Environment.CurrentDirectory + @"\" + "server.pfx", "");
_sslStream.AuthenticateAsServer(serverCertificate, false, SslProtocols.Tls, true);
}
catch (Exception ex)
{
Console.WriteLine(ex);
Console.ReadLine();
return;
} while (true)
{
string receivedMessage = ReadMessage(_sslStream);
Console.WriteLine("received:" + receivedMessage);
byte[] message = Encoding.UTF8.GetBytes("Success.<EOF>");
_sslStream.Write(message);
_sslStream.Flush();
}
} static X509Certificate serverCertificate = null;
private static SslStream _sslStream; static string ReadMessage(SslStream sslStream)
{
byte[] buffer = new byte[];
StringBuilder messageData = new StringBuilder();
int bytes = -;
do
{
bytes = sslStream.Read(buffer, , buffer.Length);
Decoder decoder = Encoding.UTF8.GetDecoder();
char[] chars = new char[decoder.GetCharCount(buffer, , bytes)];
decoder.GetChars(buffer, , bytes, chars, );
messageData.Append(chars);
if (messageData.ToString().IndexOf("<EOF>") != -)
{
break;
}
} while (bytes != ); return messageData.ToString();
} static void ProcessClient(TcpClient client)
{ SslStream sslStream = new SslStream(
client.GetStream(), true); try
{
sslStream.AuthenticateAsServer(serverCertificate, true, SslProtocols.Tls, true); Console.WriteLine("Waiting for client message...");
string messageData = ReadMessage(sslStream);
Console.WriteLine("Received: {0}", messageData); byte[] message = Encoding.UTF8.GetBytes("已收到信息.<EOF>");
sslStream.Write(message);
sslStream.Flush();
}
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();
}
} }

注意事项

  1.服务端验证方法AuthenticateAsServer的参数clientCertificateRequired如果为true,那在客户端也要安装server.pfx.

2.客户端验证方法AuthenticateAsClient的参数targetHost对应证书中Common Name,也就是受颁发者.

参考资料

   https://msdn.microsoft.com/zh-cn/library/system.net.security.sslstream(v=vs.110).aspx

【C#】Socket中的ssl通信的更多相关文章

  1. Tomcat6和Tomcat7配置SSL通信的比较

    <Tomcat6和Tomcat7配置SSL通信的比较> 作者:chszs,转载需注明.博客主页: http://blog.csdn.net/chszs 在项目开发过程中,尝尝会遇到Tomc ...

  2. SSL、TLS协议格式、HTTPS通信过程、RDP SSL通信过程

    相关学习资料 http://www.360doc.com/content/10/0602/08/1466362_30787868.shtml http://www.gxu.edu.cn/college ...

  3. SSL 通信原理及Tomcat SSL 配置

    SSL 通信原理及Tomcat SSL 双向配置 目录1 参考资料 .................................................................. ...

  4. Java 下 SSL 通信原理及实例

    有关SSL的原理和介绍在网上已经有不少,对于Java下使用keytool生成证书,配置SSL通信的教程也非常多.但如果我们不能够亲自动手做一个SSL Sever和SSL Client,可能就永远也不能 ...

  5. SSL 通信原理及Tomcat SSL 双向配置

    SSL 通信原理及Tomcat SSL 双向配置 目录1 参考资料 .................................................................. ...

  6. SSL、TLS协议格式、HTTPS通信过程、RDP SSL通信过程(缺heartbeat)

    SSL.TLS协议格式.HTTPS通信过程.RDP SSL通信过程   相关学习资料 http://www.360doc.com/content/10/0602/08/1466362_30787868 ...

  7. 转 关于Https协议中的ssl加密解密流程

    关于Https协议中的ssl加密解密流程 2016年09月28日 09:51:15 阅读数:14809 转载自:http://www.cnblogs.com/P_Chou/archive/2010/1 ...

  8. 【转】证书的应用之一 —— TCP&SSL通信实例及协议分析(下)

    原文链接 前面两部分分别讲解了如何在.net程序中使用SSL实现安全通信以及SSL的通信过程,并通过抓包工具具体分析了ssl的握手过程,本文通过一个demo来模拟ssl协议,在TCP之上实现自己的安全 ...

  9. C#的Socket实现UDP协议通信

    今天稍花化了一点时间,利用C#的Socket验证了UDP的通信,为接下来特地利用UDP做个分布式的通信仿真系统打下基础.众所周知,UDP 就是用户数据报协议,在互联网参考模型的第四层——传输层.与TC ...

随机推荐

  1. pandas数据分析第二天

    一:汇总和计算描述统计 pandas对象拥有一组常用的数据和统计方法,用于从Series中提取单个值(sum,mean)或者从DataFrame的行或者列中提取一个Series对应的Numpy数组方法 ...

  2. Android主页导航:fragment+viewpager

    简单实现Fragment+ViewPager实现主页导航控制,效果如下: 一.activity_main.xml布局文件: <?xml version="1.0" encod ...

  3. jquery请求数据

    $(document).ready(function() { $.ajax({ url: "http://123.207.88.84:8080/zdm/AppApi/Search/Categ ...

  4. beego——事务处理和命令模式

    1.事务处理 ORM 可以简单的进行事务操作. o := NewOrm() err := o.Begin() // 事务处理过程 ... ... // 此过程中的所有使用 o Ormer 对象的查询都 ...

  5. pycharm修改配置

    恢复pycharm的初始设置

  6. Github 的其他用法

    一.概述 Github 除了作为代码托管库外,有趣的程序员们还利用它解锁了有趣的新姿势. 二.新姿势 2.1 Github Pages 可以为项目建立静态主页(即gh-pages分支), 也可以建立命 ...

  7. 设计模式(三) cglib代理

    1.1.cglib代理,也可也叫子类代理 Cglib代理,也叫做子类代理.我们知道,JDK的动态代理机制只能代理实现了接口的类,而不能实现接口的类就不能使用JDK的动态代理.cglib是针对类来实现代 ...

  8. 【笔记】IntelliJ IDEA配置Hibernate

    参考:imooc:http://www.imooc.com/video/7706 1.创建Hibernate的配置文件. 将依赖包导入项目.http://blog.csdn.net/a15337525 ...

  9. HCNP学习笔记之ICMP协议与ping原理以及用Python实现ping

    一.ICMP协议分析 ICMP:Internet控制报文协议.由于IP协议并不是一个可靠的协议,它不保证数据被成功送达,那么,如何才能保证数据的可靠送达呢? 这里就需要使用到一个重要的协议模块ICMP ...

  10. python 利用PIL库进行更改图片大小的操作

    python 是可以利用PIL库进行更改图片大小的操作的,当然一般情况下是不需要的,但是在一些特殊的利用场合,是需要改变图片的灰度或是大小等的操作的,其实用python更改图片的大小还是蛮简单的,只需 ...