【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 ...
随机推荐
- 【我的Android进阶之旅】解决bug:You need to use a Theme.AppCompat theme (or descendant) with this activity.
前言 今天用Android Studio 生成Activity的时候,默认继承AppCompatActivity ,而在AndroidManifest.xml我对该Activity设置了一个主题,然后 ...
- CentOS7.1 KVM虚拟化之linux虚拟机安装(2)
一.上传ISO文件到/data/iso下 这里使用CentOS-5.5-i386-bin-DVD.iso 二.安装CentOS5.5 CentOS7.1 安装KVM虚拟机默认磁盘格式为qcow2(推荐 ...
- Motion camera 真人动作捕捉器
视频1 http://v.youku.com/v_show/id_XNzk4MDA2MTg4.html 视频2 http://v.youku.com/v_show/id_XNzk4MDA5OTIw.h ...
- Linux vim 操作技巧
·Linux设计的重要原则是信息存储在基于文本的文件中 文本文件:无格式文件,作用类似于win的注册表(etc下的配置文件,.conf或者无扩展名)可扩展标记语言(XML),文本标记定义数据结构(et ...
- Django日志
Django日志 简单的Django日志 在settings里配置,会在屏幕输出日志 LOGGING = { 'version': 1, 'disable_existing_loggers': Fal ...
- day9 文件的读取
文件操作 一.打开文件 f = open('歌词.txt','w',encoding='utf-8') # f:文件操作符 文件句柄 文件操作对象 open打开文件是依赖了操作系统提供的途径 操作系统 ...
- LeetCode:翻转二叉树【226】
LeetCode:翻转二叉树[226] 题目描述 翻转一棵二叉树. 示例: 输入: 4 / \ 2 7 / \ / \ 1 3 6 9 输出: 4 / \ 7 2 / \ / \ 9 6 3 1 题目 ...
- springmvc自定义视图
自定义视图 可以整合jfreechart.excel @RequestMapping("/testView") public String testView(){ System.o ...
- SSO 单点登录的实现原理
单点登录SSO(Single Sign On)说得简单点就是在一个多系统共存的环境下,用户在一处登录后,就不用在其他系统中登录,也就是用户的一次登录能得到其他所有系统的信任.单点登录在大型网站里使用得 ...
- javascript Date对象 之 获取时间
javascript Date对象 --> 获取时间: 测试代码: <!DOCTYPE html> <html lang="en"> <head ...