证书的应用之一 —— TCPSSL通信实例及协议分析(上)

SSL(Security Socket Layer)是TLS(Transport Layer Security)的前身,是一种加解密协议,它提供了再网络上的安全传输,它介于网络通信协议的传输层与应用层之间。

为实现TCP层之上的ssl通信,需要用到数字证书。本文通过具体例子来说明如何使用数字证书来实现网络上的安全传输。需要用到.net提供的SslStream, TcpListener, TcpClient, X509Certificate2,X509Store,X509Certification2Collection等类。终于开始涉及到代码了。

一.服务器端

1.指定证书

常用的有两种方式:从文件获取和从certificate store中获取

a.从文件

ContractedBlock.gifExpandedBlockStart.gif从文件读取证书
1 OpenFileDialog dialog = new OpenFileDialog();
2 dialog.Filter = "Cert files(*.pfx;*.p7b;*.cer)|*.pfx;*.p7b;*.cer|All files(*.*)|*.*";
3 DialogResult dr = dialog.ShowDialog();
4 if (dr == DialogResult.OK)
5 {
6 Console.WriteLine("Input the password for the cert:");
7 StringBuilder stringBuilder = new StringBuilder();
8 while (true)
9 {
10 ConsoleKeyInfo passInfo = Console.ReadKey(true);
11 if (passInfo.Key == ConsoleKey.Enter)
12 {
13 break;
14 }
15 stringBuilder.Append(passInfo.KeyChar);
16 }
17 return new X509Certificate2(dialog.FileName, stringBuilder.ToString(), X509KeyStorageFlags.Exportable);
18 }
19 else
20 {
21 return null;
22 }

注意X509Certificate2构造函数第三个参数,如果想把调用Export方法将cert对象到处,此处必须使用Exportable标记,否则在导出时会抛出异常。

pfx格式的证书包含有private key,因此需要密码的保护,构造函数的第二个参数就是密码。

选取的证书必须包含有private key,否则在SSL的server端使用时会抛出AuthenticationException。

怎么得到pfx文件:使用MMC->File->Add/Remove Sanp-in->Add->Certificates->Add->My user account/Computer account->Finish 查看存储在本机当前用户和所有用户的证书,选择用导出的证书,

右键->All Tasks...->Export...注意要勾选[Yes, export the private key],如果该Radio button被禁用,说明该证书的private key不能被导出,可能是在导入该证书时没有选择标记private key为可导出,如下图所示:

2010062017132692.png

b.从certificate store

 

ContractedBlock.gifExpandedBlockStart.gif从store读取证书
1 X509Store store = new X509Store(StoreName.My, StoreLocation.LocalMachine);
2 store.Open(OpenFlags.ReadOnly);
3 X509Certificate2Collection collection = X509Certificate2UI.SelectFromCollection(store.Certificates,
4 "Select Certificate",
5 "Please select a certificate from the following list",
6 X509SelectionFlag.SingleSelection);

注意:

Server端指定的cert必须含有privatekey,且Enhanced key usage必须含有Server Authentication (1.3.6.1.5.5.7.3.1)

2010062017400679.png

没有private key

NotSupportedException: The server modeSSL must use a certificate with the associated private key.

证书purpose不对:

server端:AuthenticationException: A call to SSPIfailed, see inner exception.

client端:IOException: Unable to read data from the transport connection: Anexisting connection was forcibly closed by the remote host..

2.开始TCP监听

 

ContractedBlock.gifExpandedBlockStart.gifTCP监听
1 TcpListener listener = new TcpListener(IPAddress.Any, 8080);
2 listener.Start();
3 while (true)
4 {
5 Console.WriteLine("Waiting for a client to connect...");
6 TcpClient client = listener.AcceptTcpClient();
7 ......
8 }

 

3.指定服务器证书

 

ContractedBlock.gifExpandedBlockStart.gif指定服务器证书
1 // A client has connected. Create the
2 // SslStream using the client's network stream.
3   SslStream sslStream = new SslStream(client.GetStream(), false);
4 // Authenticate the server but don't require the client to authenticate.
5   try
6 {
7 sslStream.AuthenticateAsServer(cert, false, SslProtocols.Default, false);
8
9 // Set timeouts for the read and write to 5 seconds.
10   sslStream.ReadTimeout = 5000;
11 sslStream.WriteTimeout = 5000;
12 ......
13 }

 

4.发送数据

 

1 byte[] message = Encoding.UTF8.GetBytes("Hello from the server.<EOF>");
2 sslStream.Write(message);
3 sslStream.Flush();

 

5.接收数据

 

ContractedBlock.gifExpandedBlockStart.gif接收数据
1 byte[] buffer = new byte[2048];
2 StringBuilder messageData = new StringBuilder();
3 int bytes = -1;
4 do
5 {
6 // Read the client's message.
7   bytes = sslStream.Read(buffer, 0, buffer.Length);
8 messageData.Append(Encoding.UTF8.GetString(buffer, 0, bytes));
9 // Check for EOF or an empty message.
10   if (messageData.ToString().IndexOf("<EOF>") != -1)
11 {
12 break;
13 }
14 } while (bytes != 0);
15
16 return messageData.ToString();

 

注意:Write后需要调用Flush将数据立刻发送,Read需要多次调用,确定读不到数据位置,因为TCP连接时Stream方式的,在网络中传输可能会分包到达,一次无法全部读取,还需要消息边界。

6.结束

 

1 sslStream.Close();
2 client.Close();

 

二.客户端

1.与服务器端建立TCP连接

 

1 TcpClient client = new TcpClient(machineName, 8080);

2.与服务端建立SSL握手

 

ContractedBlock.gifExpandedBlockStart.gif客户端与服务端建立SSL握手
1 SslStream sslStream = new SslStream(
2 client.GetStream(),
3 false,
4 new RemoteCertificateValidationCallback(ValidateServerCertificate),
5 null
6 );
7 try
8 {
9 // The server name must match the name on the server certificate.
10   X509Certificate2 cert = GetCert();
11 X509Certificate2Collection collection = new X509Certificate2Collection();
12 if(cert != null)
13 {
14 collection.Add(cert);
15 }
16 sslStream.AuthenticateAsClient(serverName, collection, SslProtocols.Default, false);
17 }
18 catch (AuthenticationException e)
19 {
20 Console.WriteLine("Exception: {0}", e.Message);
21 if (e.InnerException != null)
22 {
23 Console.WriteLine("Inner exception: {0}", e.InnerException.Message);
24 }
25 Console.WriteLine("Authentication failed - closing the connection.");
26 client.Close();
27 return;
28 }

 

如果服务端在调用AuthenticateAsServer方法时指定不需要客户端的证书,则客户端在调用AuthenticateAsClient时可以不指定证书,

如果serverAuthenticateAsServer是指定client需要cert,而client在调用AuthenticateAsClient时没有指定cert或者cert没有private key时:

server端:AuthenticationExceptionThe remote certificate is invalid according to the validationprocedure.

client端:IOException: Unable to read data from the transportconnection: An established connection was aborted by the software in your hostmachine.

 

ClientAuthenticateAsClient方法指定的名字需要与server端使用cert的名字一致,否则在RemoteCertificateValidationCallback事件中SslPolicyErrors会是RemoteCertificateNameMismatch

3.发送接收数据,关闭连接,与服务器端方法相同


使用Wireshark Network Analyzer工具进行抓包分析,发现在建立TCP连接后,首先进行SSL握手,之后传输的数据都是被加密的,如下图所示:

2010062017430124.png


对SSL的握手和加密传输的详细过程,将在下节分析。

下载Demo

转载于:https://www.cnblogs.com/piyeyong/archive/2010/06/20/1761458.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/462959.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

ClickedOnce部署方法

1.ClickedOnce部署时有些DLL和配置文件无法自动部署到系统当中&#xff0c;只能用Manifest Manager Tool 修改manifest 文件 /Files/Tonyyang/Software/ManifestManagerUtility.rar 2.部署文件结构 3.部署方法 首先用VS自带的ClickedOnce发布应用程序&#xff08;博客园有&…

树莓派安装MySQL数据库与卸载

出处&#xff1a; 1、http://www.cnblogs.com/liyangLife/p/4500115.html 2、https://blog.csdn.net/huayucong/article/details/49736427 3、https://www.imooc.com/article/23132?block_idtuijian_wz 4、http://www.runoob.com/mysql/mysql-install.html&#xff08;Debian系…

Visual Studio.net 2010 Windows Service 开发,安装与调试

本示例完成一个每隔一分钟向C:\log.txt文件写入一条记录为例&#xff0c;讲述一个Windows Service 程序的开发,安装与调试 原程序&#xff0c;加文档示例下载 /Files/zycblog/SourceCode.rar 目录索引 1 开发工具 2 开发过程 3 安装 4 开发调试 5 注意事项 6 参考资料…

ArcGis dbf读写——挂接Excel到属性表 C#

ArcMap提供了挂接Excel表格信息到属性表的功能&#xff0c;但是当数据量较大到以万计甚至十万计的时候这个功能就歇菜了&#xff0c;当然&#xff0c;你可以考虑分段挂接。这个挂接功能只是做了一个表关联&#xff0c;属性记录每个字段的信息需要通过“字段计算器”计算过来。 …

VisualStudioAddIn2017.vsix的下载安装和使用

本加载项是用于Visual Studio的&#xff0c;下载以后按照如下步骤进行安装&#xff1a; 完全退出Visual Studio把下载了的文件解压缩&#xff0c;会产生一个VisualStudioAddIn2017.vsix文件双击该文件&#xff0c;按照提示安装重启Visual Studio安装完成后的使用方法&#xff0…

Presto基本概念

Presto基本概念 Presto是Facebook开源的MPP SQL引擎&#xff0c;旨在填补Hive在速度和灵活性&#xff08;对接多种数据源&#xff09;上的不足。相似的SQL on Hadoop竞品还有Impala和Spark SQL等。这里我们介绍下Presto的基本概念&#xff0c;为后续的笔记做基础。 Operator …

2019春第六周编程总结

这个作业属于哪个课程C语言程序设计Ⅱ这个作业要求在哪里https://edu.cnblogs.com/campus/zswxy/MS/homework/2829我在这个课程的目标是利用指针知识解决相关实际问题在具体哪方面帮我实现目标设计密码开锁、交换变量解决问题以及电码加密参考文献C语言基础、http://www.w3scho…

Exchange企业实战技巧(26)在Outlook中打开多个邮箱

工作中&#xff0c;有时要需要让某个用户在outlook中同时打开多个exchange邮箱&#xff0c;对于outlook2010来说&#xff0c;是支持多个Exchange邮箱用户账户的并存&#xff0c;而outlook2007则不支持。那该功能有没其他实现方法呢&#xff1f;答案是有的。 如果你的Exchange是…

Emulator Error: Could not load OpenGLES emulati...

为什么80%的码农都做不了架构师&#xff1f;>>> 模拟器提示警告&#xff1a;Emulator Error: Could not load OpenGLES emulation library: Could not load DLL! 亲测可用&#xff1a; 从SDK\tools\lib目录下将一下四个dll文件复制到SDK\tools&#xff0c;重启模…

关于.net的垃圾回收和大对象处理_标记

CLR垃圾回收器根据所占空间大小划分对象。大对象和小对象的处理方式有很大区别。比如内存碎片整理 —— 在内存中移动大对象的成本是昂贵的&#xff0c;让我们研究一下垃圾回收器是如何处理大对象的&#xff0c;大对象对程序性能有哪些潜在的影响。 大对象堆和垃圾回收 在.Net …

三篇文章了解 TiDB 技术内幕——说存储

此文转载了 申砾 PingCAP 的文章&#xff1a;https://mp.weixin.qq.com/s?__bizMzI3NDIxNTQyOQ&mid2247484822&idx1&sn5434362800d8dcc0ca69d2f3f3260173&chksmeb1622fcdc61abea428f74b26a24bc589d524dd3b666d9b124809300f488d00b33a315a87792&scene21#we…

复制数组方法总结

为什么80%的码农都做不了架构师&#xff1f;>>> 在java中&#xff0c;对数组复制有多种 1.通过循环来复制 比如用for循环 int a[]{1,2,3}; int b[]new int[a.length]; for(int i0;i<a.length;i){ b[i]a[i]; } 2.直接复制 int a[]{1,2,3}; int b[]a…

JS/Cs相互调用

js调用cs中函数的方法 在前台js代码里写上<%method();%>举例:cs文件中写的有public void method(){....执行某些操作.}这个函数,然后在前台页面的js里面调用.<script type"text/javascript"><%method();%></script>在cs中调用js函数法一:C…

PostgreSQL体系架构

PostgreSQL 使用客户机/服务器&#xff08;C/S&#xff09;的模式提供服务&#xff0c;一个PostgreSQL会话由下列相关的进程&#xff08;程序&#xff09;组成&#xff1a; (1)一个服务器端进程。该进程管理数据库文件&#xff0c;接受客户端与数据库的连接&#xff0c;且代表…

IPC之九:使用UNIX Domain Socket进行进程间通信的实例

socket 编程是一种用于网络通信的编程方式&#xff0c;在 socket 的协议族中除了常用的 AF_INET、AF_RAW、AF_NETLINK等以外&#xff0c;还有一个专门用于 IPC 的协议族 AF_UNIX&#xff0c;IPC 是 Linux 编程中一个重要的概念&#xff0c;常用的 IPC 方式有管道、消息队列、共…

CH 5102Mobile Service题解

题目&#xff1b; 用动态规划很容易将完成任务量作为dp的阶段&#xff0c;通过指派服务员&#xff0c;从当前i-1个任务转移到i个任务&#xff1b; 我们可以用一个四维数组f[i][x][y][z]来表示在完成当前任务i时&#xff0c;三个机器人分别在x&#xff0c;y&#xff0c;z的位置&…

Postgres主进程文件—postmaster.pid

postmaster内容 使用cat -n 命令可以查看postmaster.pid文件内容&#xff1a; ) 根据每一行进行解释&#xff0c;并给出对应的源代码说明 13795: 代表Postgres主进程的PID/usr/local/pgsql/data: 代表数据目录 1529235109&#xff1a; 代表postmaster文件的创建时间。 54…

Mysql 中 delete 与 left join 的问题

今天在一个程序后台删除一个东西的时候&#xff0c;却出现了这个问题&#xff1a; 在Google搜索了大约1小时候&#xff0c;终于找到了原因&#xff0c;解决起来非常简单&#xff1a; 增加一个T.*就搞定了。 故障分析&#xff1a;因为Insert、Update、Delete三个参数&#xff0c…

web架构设计经验分享

2019独角兽企业重金招聘Python工程师标准>>> 本人作为一位web工程师&#xff0c;着眼最多之处莫过于 性能与架构&#xff0c;本次幸得参与sd2.0大会&#xff0c;得以与同行广泛交流,于此二方面&#xff0c;有些心得&#xff0c;不敢独享&#xff0c;与众博友分享&am…

面向对象与软件工程—团队作业1

一、队伍介绍 队伍名称&#xff1a;逍遥此身君子意 队伍编号&#xff1a;1523933 参赛区域&#xff1a;西北赛区 参赛类别&#xff1a;小程序 指导老师&#xff1a;崔亚超 二、队伍成员信息 姓名&#xff1a;凌龙&#xff08;队长&#xff09; 学号&#xff1a;1700802085 班级…