【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 ...
随机推荐
- PHP获取客户端的IP
function getClientIP(){ global $ip; if (getenv("HTTP_CLIENT_IP")) $ip = geten ...
- python删除目录下七天前创建的文件
#coding=utf-8 import os import time import datetime def deleteOutdateFiles(path): """ ...
- tkprof工具详解二
TKPROF是一个可执行文件,自带在Oracle Server软件中,无需额外的安装. 该工具文件可以用来解析ORACLE的SQL TRACE(10046) 以便生成更可读的内容. 实际上tkp ...
- Hadoop家族学习路线图-张丹老师
前言 使用Hadoop已经有一段时间了,从开始的迷茫,到各种的尝试,到现在组合应用….慢慢地涉及到数据处理的事情,已经离不开hadoop了.Hadoop在大数据领域的成功,更引发了它本身的加速发展.现 ...
- java反射基础知识(二)
1. 了解 Java 中的反射 1.1 什么是 Java 的反射 Java 反射是可以让我们在运行时获取类的函数.属性.父类.接口等 Class 内部信息的机制.通过反射还可以让我们在运行期实例化对象 ...
- 第一课Linux系统安装知识(2)
接着上节课单击Finish按钮之后,虚拟机将会启动进入安装界面. 根据提示按回车选择图形界面安装. 这里选择Skip跳过媒介检查. 选择安装语言为简体中文,键盘鼠标默认项即可. 这里安装类型选择是定制 ...
- 微信小程序之日期与时间插件
页面 <picker mode="time" value="{{time}}" start="{{minTime}}" end=&qu ...
- Kattis - honey【DP】
Kattis - honey[DP] 题意 有一只蜜蜂,在它的蜂房当中,蜂房是正六边形的,然后它要出去,但是它只能走N步,第N步的时候要回到起点,给出N, 求方案总数 思路 用DP 因为N == 14 ...
- Codeforces Round #397 by Kaspersky Lab and Barcelona Bootcamp (Div. 1 + Div. 2 combined) A - Neverending competitions
地址:http://codeforces.com/contest/765/problem/A 题目: A. Neverending competitions time limit per test 2 ...
- Java伪代码示例
学习并转载自https://www.cnblogs.com/z245894546/p/7535261.html import.java.大道至简.*; import.java.愚公移山.*; publ ...