c# - services - ¿Cómo aplicar el archivo de certificado PFX al escucha de socket SslStream?
download winhttpcertcfg (1)
Puede cargar el archivo pfx directamente con:
byte[] pfxData = File.ReadAllBytes("myfile.pfx");
cert = new X509Certificate2(pfxData, "password", X509KeyStorageFlags.MachineKeySet | X509KeyStorageFlags.Exportable);
Si lo está cargando desde el almacén de certificados, es importante que la clave sea exportable para la aplicación.
Información: SSL versión 3.0 ya no es segura. Quizás es por eso que no puedes tener una conexión. Chrome y Firefox deshabilitaron el soporte.
Consejo: escriba un cliente SSL simple para enviar algunos bytes "Hello World".
Probé tu código con un certificado autofirmado en formato pfx sobre ac # client y el navegador chrome. ambos clientes pueden conectarse y enviar / recibir datos.
lo único que cambié configuré SSLProtocol en TLS
stream.AuthenticateAsServer(_cert, false, System.Security.Authentication.SslProtocols.Tls, true);
Información: HTTPS es el protocolo HTTP sobre una conexión tcp / tls. Tiene una conexión tcp / tls sin el protocolo http.
CONSEJO: ¡No olvide abrir el Firewall Port 9002!
Tengo un oyente de socket de múltiples hilos. Escucha en un puerto. Recibe datos de sitios web HTTP y envía respuestas de acuerdo con su solicitud. Funciona bien
Ahora quiero hacer lo mismo con un sitio web HTTPS. Así que lo cambié para poder leer y escribir a través de SslStream en lugar de socket.
El propietario del sitio web me dio un archivo pfx y una contraseña. Lo coloqué en la lista de certificados de confianza de mi tienda local de certificación.
El archivo de certificación se retiró de la tienda con éxito. Pero después de llamar al método AuthenticateAsServer, mi socket del manejador parece estar vacío. Así que no puedo ver ningún dato dentro del método ReceiveCallBack.
¿Cómo puedo aplicar el certificado pfx a mi socket SslStream?
Aquí está mi código:
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();
}
}
EDITAR: Creo que tengo un problema con la lógica SSL. El archivo PFX pertenece al sitio web HTTPS. Pero las solicitudes provienen de HTTPS para mi oyente de socket. Entonces mi oyente de socket envía respuesta. En esta situación, ¿soy servidor o cliente? ¿Usaré AuthenticateAsServer o AuthenticateAsClient?
No arroja un error si llamo a AuthenticateAsServer. Se autentica sin ningún problema. Pero no puedo transportar los datos en el socket del manejador al método ReceiveCallBack a través del SslStream de mi StateObject.