我有一个多线程套接字监听器。它侦听一个端口。它从HTTP网站接收数据并根据其请求发送响应。它运作良好。
现在我想用HTTPS网站做同样的事情。所以我把它改为能够通过SslStream而不是socket来读写。
网站所有者给了我一个pfx文件和一个密码。我将它放入我当地认证商店的可信证书列表中。
成功从商店中检索认证文件。但在调用AuthenticateAsServer方法后,我的处理程序套接字似乎是空的。所以我在ReceiveCallBack方法中看不到任何数据。
如何将pfx证书应用于我的SslStream套接字?
这是我的代码:
using System;
using System.Net;
using System.Net.Sockets;
using System.Net.Security;
using System.Threading;
using System.Security.Cryptography.X509Certificates;
using System.Text;
using System.IO;
namespace SslStreamTestApp
{
public class SslStreamSocketListener
{
private static readonly ManualResetEvent _manualResetEvent = new ManualResetEvent(false);
private readonly string pfxSerialNumber = "12345BLABLABLA";
X509Certificate _cert = null;
private void GetCertificate()
{
X509Store store = new X509Store(StoreName.Root, StoreLocation.CurrentUser);
store.Open(OpenFlags.ReadOnly);
X509Certificate2Collection certificateCollection = store.Certificates.Find(X509FindType.FindBySerialNumber, pfxSerialNumber, true);
if (certificateCollection.Count == 1)
{
_cert = certificateCollection[0];
}
}
private void StartListening()
{
GetCertificate();
IPEndPoint localEndPoint = new IPEndPoint(IPAddress.Any, 9002);
if (localEndPoint != null)
{
Socket listener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
if (listener != null)
{
listener.Bind(localEndPoint);
listener.Listen(5);
Console.WriteLine("Socket listener is running...");
listener.BeginAccept(new AsyncCallback(AcceptCallback), listener);
}
}
}
private void AcceptCallback(IAsyncResult ar)
{
_manualResetEvent.Set();
Socket listener = (Socket)ar.AsyncState;
Socket handler = listener.EndAccept(ar);
SslStream stream = new SslStream(new NetworkStream(handler, true));
stream.AuthenticateAsServer(_cert, false, System.Security.Authentication.SslProtocols.Ssl3, true);
StateObject state = new StateObject();
state.workStream = stream;
stream.BeginRead(state.buffer, 0, StateObject.BufferSize, ReceiveCallback, state);
listener.BeginAccept(new AsyncCallback(AcceptCallback), listener);
}
private void ReceiveCallback(IAsyncResult result)
{
StateObject state = (StateObject)result.AsyncState;
SslStream stream = state.workStream;
// Check how many bytes received
int byteCount = stream.EndRead(result);
Decoder decoder = Encoding.UTF8.GetDecoder();
char[] chars = new char[decoder.GetCharCount(state.buffer, 0, byteCount)];
decoder.GetChars(state.buffer, 0, byteCount, chars, 0);
state.sb.Append(chars);
string check = state.sb.ToString();
if (state.sb.ToString().IndexOf("<EOF>") == -1 && byteCount != 0)
{
// We didn't receive all data. Continue receiving...
stream.BeginRead(state.buffer, 0, state.buffer.Length, new AsyncCallback(ReceiveCallback), stream);
}
else
{
string[] lines = state.sb.ToString().Split('\n');
// send test message to client
byte[] test = Encoding.UTF8.GetBytes("\"infoMessage\":\"test\"");
stream.BeginWrite(test, 0, test.Length, WriteAsyncCallback, stream);
}
}
private void WriteAsyncCallback(IAsyncResult ar)
{
SslStream sslStream = (SslStream)ar.AsyncState;
Console.WriteLine("Sending message to client...");
try
{
sslStream.EndWrite(ar);
}
catch (IOException)
{
Console.WriteLine("Unable to complete send.");
}
finally
{
sslStream.Close();
}
}
}
public class StateObject
{
public SslStream workStream = null;
public const int BufferSize = 1024;
public byte[] buffer = new byte[BufferSize];
public StringBuilder sb = new StringBuilder();
}
}
修改 我想我有一些关于SSL逻辑的问题。 PFX文件属于HTTPS网站。但请求来自HTTPS到我的套接字侦听器。然后我的套接字侦听器发送响应。在这种情况下,我是服务器还是客户端?我会使用AuthenticateAsServer还是AuthenticateAsClient?
如果我调用AuthenticateAsServer,它不会抛出错误。它变得经过身份验证没有问题。但我不能通过我的StateObject的SslStream将处理程序套接字中的数据传递给ReceiveCallBack方法。
答案 0 :(得分:1)
您可以直接加载pfx文件:
byte[] pfxData = File.ReadAllBytes("myfile.pfx");
cert = new X509Certificate2(pfxData, "password", X509KeyStorageFlags.MachineKeySet | X509KeyStorageFlags.Exportable);
如果要从证书库加载它的导入和那个 密钥可以导出应用程序。
信息:SSL 3.0版不再安全。 也许这就是为什么你不能得到一个联系。 Chrome和Firefox停用了支持。
提示:编写一个简单的SSL-Client来发送一些“Hello World”字节。
我使用pfx格式的自签名证书测试了您的代码 通过c#客户端和chrome浏览器。 两个客户端都可以连接并发送/接收数据。
我唯一改变的是我将SSLProtocol设置为TLS
stream.AuthenticateAsServer(_cert, false, System.Security.Authentication.SslProtocols.Tls, true);
信息:HTTPS是tcp / tls连接上的HTTP协议。你有一个没有http协议的原始tcp / tls连接。
提示:别忘了打开防火墙端口9002!