【C#】Socket中的ssl通信
引言
有个项目中用到了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通信的更多相关文章
- Tomcat6和Tomcat7配置SSL通信的比较
<Tomcat6和Tomcat7配置SSL通信的比较> 作者:chszs,转载需注明.博客主页: http://blog.csdn.net/chszs 在项目开发过程中,尝尝会遇到Tomc ...
- SSL、TLS协议格式、HTTPS通信过程、RDP SSL通信过程
相关学习资料 http://www.360doc.com/content/10/0602/08/1466362_30787868.shtml http://www.gxu.edu.cn/college ...
- SSL 通信原理及Tomcat SSL 配置
SSL 通信原理及Tomcat SSL 双向配置 目录1 参考资料 .................................................................. ...
- Java 下 SSL 通信原理及实例
有关SSL的原理和介绍在网上已经有不少,对于Java下使用keytool生成证书,配置SSL通信的教程也非常多.但如果我们不能够亲自动手做一个SSL Sever和SSL Client,可能就永远也不能 ...
- SSL 通信原理及Tomcat SSL 双向配置
SSL 通信原理及Tomcat SSL 双向配置 目录1 参考资料 .................................................................. ...
- SSL、TLS协议格式、HTTPS通信过程、RDP SSL通信过程(缺heartbeat)
SSL.TLS协议格式.HTTPS通信过程.RDP SSL通信过程 相关学习资料 http://www.360doc.com/content/10/0602/08/1466362_30787868 ...
- 转 关于Https协议中的ssl加密解密流程
关于Https协议中的ssl加密解密流程 2016年09月28日 09:51:15 阅读数:14809 转载自:http://www.cnblogs.com/P_Chou/archive/2010/1 ...
- 【转】证书的应用之一 —— TCP&SSL通信实例及协议分析(下)
原文链接 前面两部分分别讲解了如何在.net程序中使用SSL实现安全通信以及SSL的通信过程,并通过抓包工具具体分析了ssl的握手过程,本文通过一个demo来模拟ssl协议,在TCP之上实现自己的安全 ...
- C#的Socket实现UDP协议通信
今天稍花化了一点时间,利用C#的Socket验证了UDP的通信,为接下来特地利用UDP做个分布式的通信仿真系统打下基础.众所周知,UDP 就是用户数据报协议,在互联网参考模型的第四层——传输层.与TC ...
随机推荐
- pandas数据分析第二天
一:汇总和计算描述统计 pandas对象拥有一组常用的数据和统计方法,用于从Series中提取单个值(sum,mean)或者从DataFrame的行或者列中提取一个Series对应的Numpy数组方法 ...
- Android主页导航:fragment+viewpager
简单实现Fragment+ViewPager实现主页导航控制,效果如下: 一.activity_main.xml布局文件: <?xml version="1.0" encod ...
- jquery请求数据
$(document).ready(function() { $.ajax({ url: "http://123.207.88.84:8080/zdm/AppApi/Search/Categ ...
- beego——事务处理和命令模式
1.事务处理 ORM 可以简单的进行事务操作. o := NewOrm() err := o.Begin() // 事务处理过程 ... ... // 此过程中的所有使用 o Ormer 对象的查询都 ...
- pycharm修改配置
恢复pycharm的初始设置
- Github 的其他用法
一.概述 Github 除了作为代码托管库外,有趣的程序员们还利用它解锁了有趣的新姿势. 二.新姿势 2.1 Github Pages 可以为项目建立静态主页(即gh-pages分支), 也可以建立命 ...
- 设计模式(三) cglib代理
1.1.cglib代理,也可也叫子类代理 Cglib代理,也叫做子类代理.我们知道,JDK的动态代理机制只能代理实现了接口的类,而不能实现接口的类就不能使用JDK的动态代理.cglib是针对类来实现代 ...
- 【笔记】IntelliJ IDEA配置Hibernate
参考:imooc:http://www.imooc.com/video/7706 1.创建Hibernate的配置文件. 将依赖包导入项目.http://blog.csdn.net/a15337525 ...
- HCNP学习笔记之ICMP协议与ping原理以及用Python实现ping
一.ICMP协议分析 ICMP:Internet控制报文协议.由于IP协议并不是一个可靠的协议,它不保证数据被成功送达,那么,如何才能保证数据的可靠送达呢? 这里就需要使用到一个重要的协议模块ICMP ...
- python 利用PIL库进行更改图片大小的操作
python 是可以利用PIL库进行更改图片大小的操作的,当然一般情况下是不需要的,但是在一些特殊的利用场合,是需要改变图片的灰度或是大小等的操作的,其实用python更改图片的大小还是蛮简单的,只需 ...