使用C#实现SSLSocket加密通讯
SSL Socket通讯是对socket的扩展,增加Socket通讯的数据安全性,SSL认证分为单向和双向认证。单向认证只认证服务器端的合法性而不认证客户端的合法性。双向认证是同时认证服务端和客户端。下面我分别说说使用C#实现单向认证和双向认证的过程,并用代码实现。
一、 单向认证
第1步:准备一个数字证书,可以使用如下脚本生成
先进入到vs2005的命令行状态,即:
开始–>程序–>Microsoft Visual Studio 2005–>Visual Studio Tools–>Visual Studio 2005 命令提示
键入: makecert -r -pe -n “CN=TestServer” -ss Root -sky exchange
说明:上面的指令将在创建一个受信任的根证书,
第2步创建服务器端程序,代码如下:
using System;
using System.ServiceModel;
using System.Net;
using System.Net.Sockets;
using System.Net.Security;
using System.Text;
using System.Security.Authentication;
using System.Security.Cryptography.X509Certificates;
using System.IdentityModel.Tokens;
using System.IdentityModel.Selectors;
namespace ConsoleApp
{
public class Program
{
static X509Certificate serverCertificate = null;
public static void RunServer(){TcpListener listener = new TcpListener(IPAddress.Parse("192.168.1.25"), 901);listener.Start();while (true){try{Console.WriteLine("Waiting for a client to connect...");TcpClient client = listener.AcceptTcpClient();ProcessClient(client);}catch{}}}
static void ProcessClient(TcpClient client)
{SslStream sslStream = new SslStream(client.GetStream(), false);try{sslStream.AuthenticateAsServer(serverCertificate, false, SslProtocols.Tls, true);DisplaySecurityLevel(sslStream);DisplaySecurityServices(sslStream);DisplayCertificateInformation(sslStream);DisplayStreamProperties(sslStream);sslStream.ReadTimeout = 5000;sslStream.WriteTimeout = 5000;byte[] message = Encoding.UTF8.GetBytes("Hello from the server.");Console.WriteLine("Sending hello message.");sslStream.Write(message);Console.WriteLine("Waiting for client message...");while (true){string messageData = ReadMessage(sslStream);Console.WriteLine("Received: {0}", messageData);if (messageData.ToUpper() == "EXIT")break;} }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();}
}static string ReadMessage(SslStream sslStream)
{byte[] buffer = new byte[2048];StringBuilder messageData = new StringBuilder();int bytes = -1;do{bytes = sslStream.Read(buffer, 0, buffer.Length);Decoder decoder = Encoding.UTF8.GetDecoder();char[] chars = new char[decoder.GetCharCount(buffer, 0, bytes)];decoder.GetChars(buffer, 0, bytes, chars, 0);messageData.Append(chars);if (messageData.ToString().IndexOf("") != -1){break;}}while (bytes != 0);return messageData.ToString();
}static void DisplaySecurityLevel(SslStream stream)
{Console.WriteLine("Cipher: {0} strength {1}", stream.CipherAlgorithm, stream.CipherStrength);Console.WriteLine("Hash: {0} strength {1}", stream.HashAlgorithm, stream.HashStrength);Console.WriteLine("Key exchange: {0} strength {1}", stream.KeyExchangeAlgorithm, stream.KeyExchangeStrength);Console.WriteLine("Protocol: {0}", stream.SslProtocol);
}static void DisplaySecurityServices(SslStream stream)
{Console.WriteLine("Is authenticated: {0} as server? {1}", stream.IsAuthenticated, stream.IsServer);Console.WriteLine("IsSigned: {0}", stream.IsSigned);Console.WriteLine("Is Encrypted: {0}", stream.IsEncrypted);
}static void DisplayStreamProperties(SslStream stream)
{Console.WriteLine("Can read: {0}, write {1}", stream.CanRead, stream.CanWrite);Console.WriteLine("Can timeout: {0}", stream.CanTimeout);
}static void DisplayCertificateInformation(SslStream stream)
{Console.WriteLine("Certificate revocation list checked: {0}", stream.CheckCertRevocationStatus);X509Certificate localCertificate = stream.LocalCertificate;if (stream.LocalCertificate != null){Console.WriteLine("Local cert was issued to {0} and is valid from {1} until {2}.",localCertificate.Subject,localCertificate.GetEffectiveDateString(),localCertificate.GetExpirationDateString());}else{Console.WriteLine("Local certificate is null.");}X509Certificate remoteCertificate = stream.RemoteCertificate;if (stream.RemoteCertificate != null){Console.WriteLine("Remote cert was issued to {0} and is valid from {1} until {2}.",remoteCertificate.Subject,remoteCertificate.GetEffectiveDateString(),remoteCertificate.GetExpirationDateString());}else{Console.WriteLine("Remote certificate is null.");}
}private static void DisplayUsage()
{Console.WriteLine("To start the server specify:");Console.WriteLine("serverSync certificateFile.cer");
}public static void Main(string[] args)
{try{X509Store store = new X509Store(StoreName.Root);store.Open(OpenFlags.ReadWrite);// 检索证书 X509Certificate2Collection certs = store.Certificates.Find(X509FindType.FindBySubjectName, "TestServer", false); // vaildOnly = true时搜索无结果。if (certs.Count == 0) return;serverCertificate = certs[0];RunServer();store.Close(); // 关闭存储区。}catch (Exception ex){Console.WriteLine(ex.Message);}Console.ReadLine();
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
- 93
- 94
- 95
- 96
- 97
- 98
- 99
- 100
- 101
- 102
- 103
- 104
- 105
- 106
- 107
- 108
- 109
- 110
- 111
- 112
- 113
- 114
- 115
- 116
- 117
- 118
- 119
- 120
- 121
- 122
- 123
- 124
- 125
- 126
- 127
- 128
- 129
- 130
- 131
- 132
- 133
- 134
- 135
- 136
- 137
- 138
- 139
- 140
- 141
- 142
- 143
- 144
- 145
- 146
- 147
- 148
- 149
- 150
- 151
- 152
- 153
- 154
- 155
- 156
- 157
- 158
- 159
- 160
- 161
- 162
}
第3步,创建客户端代码
namespace ConsoleAppClient
{
using System;
using System.Collections;
using System.Net.Security;
using System.Net.Sockets;
using System.Security.Authentication;
using System.Text;
using System.Security.Cryptography.X509Certificates;
namespace Examples.System.Net
{public class SslTcpClient{private static Hashtable certificateErrors = new Hashtable();// The following method is invoked by the RemoteCertificateValidationDelegate.public static bool ValidateServerCertificate(object sender,X509Certificate certificate,X509Chain chain,SslPolicyErrors sslPolicyErrors){if (sslPolicyErrors == SslPolicyErrors.None)return true;Console.WriteLine("Certificate error: {0}", sslPolicyErrors);// Do not allow this client to communicate with unauthenticated servers.return false;}
public static void RunClient(string machineName){// Create a TCP/IP client socket.// machineName is the host running the server application.TcpClient client = new TcpClient(machineName, 901);Console.WriteLine("Client connected.");// Create an SSL stream that will close the client's stream.SslStream sslStream = new SslStream(client.GetStream(), false, new RemoteCertificateValidationCallback(ValidateServerCertificate), null);try{sslStream.AuthenticateAsClient("TestServer");}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();return;}// Encode a test message into a byte array.// Signal the end of the message using the "<EOF>".byte[] messsage = Encoding.UTF8.GetBytes("Hello from the client.<EOF>");// Send hello message to the server. sslStream.Write(messsage);sslStream.Flush();// Read message from the server.string serverMessage = ReadMessage(sslStream);Console.WriteLine("Server says: {0}", serverMessage);messsage = Encoding.UTF8.GetBytes("exit");sslStream.Write(messsage);sslStream.Flush();// Close the client connection.client.Close();Console.WriteLine("Client closed.");}static string ReadMessage(SslStream sslStream){// Read the message sent by the server.// The end of the message is signaled using the// "<EOF>" marker.byte[] buffer = new byte[2048];StringBuilder messageData = new StringBuilder();int bytes = -1;do{bytes = sslStream.Read(buffer, 0, buffer.Length);// Use Decoder class to convert from bytes to UTF8// in case a character spans two buffers.Decoder decoder = Encoding.UTF8.GetDecoder();char[] chars = new char[decoder.GetCharCount(buffer, 0, bytes)];decoder.GetChars(buffer, 0, bytes, chars, 0);messageData.Append(chars);// Check for EOF.if (messageData.ToString().IndexOf("<EOF>") != -1){break;}} while (bytes != 0);return messageData.ToString();}private static void DisplayUsage(){Console.WriteLine("To start the client specify:");Console.WriteLine("clientSync machineName [serverName]");Environment.Exit(1);}public static void Main(string[] args){string machineName = null;machineName = "192.168.1.25";try{RunClient(machineName);}catch (Exception ex){Console.WriteLine(ex.Message);}Console.ReadLine();}
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
- 93
- 94
- 95
- 96
- 97
- 98
- 99
- 100
- 101
- 102
- 103
- 104
- 105
- 106
- 107
- 108
- 109
- 110
- 111
}
运行效果如下图:
导致通讯失败可能问题如下:
1)证书没有导入到受信任的根证书列表中;2)证书失效;3)客户端在使用AuthenticateAsClient注册时没有正确使用服务器端证书名称。
二、 双向认证
第1步:创建所需证书,服务器端所需证书同单向认证中的创建过程
先进入到vs2005的命令行状态,即:
开始–>程序–>Microsoft Visual Studio 2005–>Visual Studio Tools–>Visual Studio 2005 命令提示
键入:
makecert -r -pe -n “CN=TestClient” -ss Root -sky exchange
第2步:创建服务端程序
服务端的程序同单向认证的服务器端代码
第3步:创建客户端程序
namespace ConsoleAppClient
{
using System;
using System.Collections;
using System.Net.Security;
using System.Net.Sockets;
using System.Security.Authentication;
using System.Text;
using System.Security.Cryptography.X509Certificates;
namespace Examples.System.Net
{public class SslTcpClient{private static Hashtable certificateErrors = new Hashtable();// The following method is invoked by the RemoteCertificateValidationDelegate.public static bool ValidateServerCertificate(object sender,X509Certificate certificate,X509Chain chain,SslPolicyErrors sslPolicyErrors){if (sslPolicyErrors == SslPolicyErrors.None)return true;
Console.WriteLine("Certificate error: {0}", sslPolicyErrors);// Do not allow this client to communicate with unauthenticated servers.return false;}public static void RunClient(string machineName){// Create a TCP/IP client socket.// machineName is the host running the server application.TcpClient client = new TcpClient(machineName, 901);Console.WriteLine("Client connected.");// Create an SSL stream that will close the client's stream.SslStream sslStream = new SslStream(client.GetStream(), false, new RemoteCertificateValidationCallback(ValidateServerCertificate), null);// The server name must match the name on the server certificate.X509Store store = new X509Store(StoreName.Root);store.Open(OpenFlags.ReadWrite);检索证书 X509Certificate2Collection certs = store.Certificates.Find(X509FindType.FindBySubjectName, "TestClient", false); try{sslStream.AuthenticateAsClient("TestServer", 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();return;}// Encode a test message into a byte array.// Signal the end of the message using the "<EOF>".byte[] messsage = Encoding.UTF8.GetBytes("Hello from the client.<EOF>");// Send hello message to the server. sslStream.Write(messsage);sslStream.Flush();// Read message from the server.string serverMessage = ReadMessage(sslStream);Console.WriteLine("Server says: {0}", serverMessage);messsage = Encoding.UTF8.GetBytes("exit");sslStream.Write(messsage);sslStream.Flush();// Close the client connection.client.Close();Console.WriteLine("Client closed.");}static string ReadMessage(SslStream sslStream){// Read the message sent by the server.// The end of the message is signaled using the// "<EOF>" marker.byte[] buffer = new byte[2048];StringBuilder messageData = new StringBuilder();int bytes = -1;do{bytes = sslStream.Read(buffer, 0, buffer.Length);// Use Decoder class to convert from bytes to UTF8// in case a character spans two buffers.Decoder decoder = Encoding.UTF8.GetDecoder();char[] chars = new char[decoder.GetCharCount(buffer, 0, bytes)];decoder.GetChars(buffer, 0, bytes, chars, 0);messageData.Append(chars);// Check for EOF.if (messageData.ToString().IndexOf("<EOF>") != -1){break;}} while (bytes != 0);return messageData.ToString();}private static void DisplayUsage(){Console.WriteLine("To start the client specify:");Console.WriteLine("clientSync machineName [serverName]");Environment.Exit(1);}public static void Main(string[] args){string machineName = null;machineName = "192.168.1.25";try{RunClient(machineName);}catch (Exception ex){Console.WriteLine(ex.Message);}Console.ReadLine();}
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
- 93
- 94
- 95
- 96
- 97
- 98
- 99
- 100
- 101
- 102
- 103
- 104
- 105
- 106
- 107
- 108
- 109
- 110
- 111
- 112
- 113
- 114
- 115
- 116
- 117
- 118
- 119
- 120
- 121
}
使用C#实现SSLSocket加密通讯相关推荐
- Javascript到PHP加密通讯的简单实现
互联网上大多数网站,用户的数据都是以明文形式直接提交到后端CGI,服务器之间的访问也大都是明文传输,这样可被一些别有用心之人通过一些手段监听到.对安全性要求较高的网站,比如银行和大型企业等都会使用HT ...
- Apache Httpd 2.2 配置CA证书,实现Https加密通讯
什么是CA证书 关于什么是CA证书,以及如何使用Open-SSL申请和搭建CA证书,我们在之前的文章中已经有过介绍,这里不再赘述.若有疑问,可参考之前的文章. http://www.pojun.tec ...
- (JS-PHP)使用RSA算法进行加密通讯
用户名密码明文直接POST到后端,很容易被别人从监听到.注:包括使用MD5等哈希函数处理后的数据,这里也算做明文(现在MD5爆破网站已经很多了~).对安全性要求较高的网站,比如银行和大型企业等都会使用 ...
- 外媒:伊朗政府封锁加密通讯应用Signal
自从加密通讯应用Signal于本月在伊朗Google Play商店中占据第一位以来,伊朗许多用户都报告无法连接.该应用程序已从伊朗应用程序商店Cafe Bazaar和Myket中删除.Signal发布 ...
- 马斯克推荐加密通讯聊天软件Signalv5.13.8跨平台国际版几何管家出品
手机软件 - 技术教程 - 电脑软件 - 7月 15, 2021 软件介绍 Signal 是由 Signal Foundation 和 Signal Messenger LLC 开发的跨平台加密消息通 ...
- 端对端加密通讯协议Signal protocol 学习(转)
转载:https://www.jianshu.com/p/e1f6f01c65f8 前段时间学习了对称加密/非对称加密算法,了解了不同类型加密算法的应用场景.最近一直在关注Mixin项目,对其采用的加 ...
- 极限钓鱼!FBI开发加密通讯设备并通过线人流入黑市,800多名罪犯被监控并抓捕...
来源|大数据文摘 文|王烨 抓一个黑帮老大最难的一步是什么? 答案是:找到他在什么地方. 在信息技术极度发达的今天,我们可能觉得只要警察想抓人,通过手机定位就可以轻易找到他,但现实并非如此,因为犯罪组 ...
- Python SSL Socket长连接加密通讯
加密通讯的必要性 我们在使用http或tcp协议传输数据时,都是明文的,用抓包工具截获数据后,很容易就能看到数据内容.你的用户名.密码和各种数据都一目了然.当你不希望别人看到你的数据时,可以使用加密通 ...
- 首个云上量子加密通讯服务实现
3月29日,在云栖大会·深圳峰会上,阿里云公布了云上量子加密通讯案例. 网商银行采用量子技术在专有云上完成了量子加密通讯试点. 阿里云也成为全世界第一家可以提供量子加密信息传送服务的云计算公司,也是最 ...
最新文章
- 适用于WIFI Hacking的无线网卡推荐
- Github 的 Pull Request 教程
- 利用virtualenv和pip构建虚环境并安装配置推送客户端
- linux下默认有哪些语言支持,修改
Linux操作系统下的显示默认支持语言
- 刷机包各个文件都是啥
- Css的filter常用濾波器屬性及語句大全
- 安全行业中的event与incident区别
- Silverlight Training
- 冒泡排序选择排序 以及时间效率对比
- 医疗卫生信息化 医学信息 医院管理 医疗信息化 资源下载
- 量子计算机对人类长寿,科学家称“极端长寿”在未来几十年可能会达到新的里程碑...
- 软件测试要求太高,软件“故障门”频现 对软件测试提出更高要求
- poj2778DNA Sequence (AC自动机+矩阵快速幂)
- 二维数据和一维指针数组
- lammps计算聚合物例子_LAMMPS中的系综(NPT/NVT)命令
- Jquery取得iframe下内容的方法
- python抓取豆瓣电影
- JUST技术:基于HMM的实时地图匹配
- linux 实现不同网段网络互通
- Label Matching Semi-Supervised Object Detection
热门文章
- 15个常用的sql优化技巧
- 关于QQ打开任何信息页面暂时无法显示 您可以点击刷新或稍后再试的解决办法。
- 华为数据之道(2):非数字原生企业数字化转型的4个挑战
- 《鲁滨逊漂流记》读书笔记精华分享
- Unix 和 Linux 上的基本脚本
- 小学语文阅读答题技巧
- 2020CVPR VSR Space-Time-Aware Multi-Resolution Video Enhancement
- Adobe PS 2021版本的Photoshop出来啦
- django.db.utils.DatabaseError: ORA-00904: “NAME“: invalid identifier
- python读取excel表格内容