Pregunta

Ediciones más recientes en negritaEstoy usando .net HttpListener clase, pero no ejecutaré IIS y no usaré ASP.net.Este sitio web describe qué código utilizar realmente para implementar SSL con asp.net y este sitio describe cómo configurar los certificados (aunque no estoy seguro si funciona sólo para IIS o no).

La documentación de la clase describe varios tipos de autenticación (básica, resumida, Windows, etc.) --- ninguno de ellos hace referencia a SSL.Dice que si Se utiliza HTTPS, deberá configurar un certificado de servidor.¿Será esta una configuración de propiedad de una línea y HttpListener descubre el resto?

En resumen, necesito saber cómo configurar los certificados y cómo modificar el código para implementar SSL.

Aunque no ocurre cuando intento acceder a HTTPS, noté un error en el registro de eventos del sistema: la fuente es "Schannel" y el contenido del mensaje es:

Se produjo un error fatal al intentar acceder a la clave privada de la credencial del servidor SSL.El código de error devuelto del módulo criptográfico es 0x80090016.

Editar:
Pasos dados hasta el momento

  • Creó un HTTPListener funcional en C# que funciona para conexiones HTTP (p. ej."http://localhost:8089/nombre de carpeta/"
  • Creó un certificado usando makecert.exe
  • Se agregó el certificado en el que se puede confiar usando certmgr.exe
  • Usé Httpcfg.exe para escuchar conexiones SSL en un puerto de prueba (p. ej.8090)
  • Se agregó el puerto 8080 a HTTPListener a través de listener.Prefixes.Add(https://localhost:8090/nombre de carpeta/");
  • probó una conexión de cliente HTTP, p.(http://localhost:8089/nombre de carpeta/") en un navegador y recibir la devolución correcta
  • probó una conexión de cliente HTTPS, p.(http://localhost:8090/nombre de carpeta/") en un navegador y recibe "Transferencia de datos interrumpida" (en Firefox)
  • La depuración en Visual Studio muestra que la devolución de llamada del oyente que recibe las solicitudes nunca se activa cuando se inicia la conexión HTTPS; no veo ningún lugar donde pueda establecer un punto de interrupción para detectar algo más antes.
  • netstat muestra que los puertos de escucha están abiertos tanto para HTTPS como para HTTP.el puerto HTTPS pasa a TIME_WAIT después de intentar una conexión.
  • Violinista y Analizador HTTP No capta nada del tráfico, supongo que no llega lo suficientemente lejos en el proceso como para aparecer en esas herramientas de análisis HTTP.

Preguntas

  • ¿Cuál podría ser el problema?
  • ¿Me falta algún fragmento de código .Net (lo que significa que tengo que hacer más en C# aparte de simplemente agregar un prefijo al oyente que apunte a HTTPS, que es lo que he hecho)?
  • ¿Se ha perdido algún paso de configuración en alguna parte?
  • ¿Qué más puedo hacer para analizar el problema?
  • ¿El mensaje de error en el registro de eventos del sistema es una señal del problema?Si es así, ¿cómo se solucionaría?

No hay solución correcta

Otros consejos

Tengo un problema similar y parece que podría haber un problema con el certificado en sí.

Aquí está el camino que funcionó para mí:

makecert.exe -r -a sha1 -n CN=localhost -sky exchange -pe -b 01/01/2000 -e 01/01/2050 -ss my -sr localmachine

luego busque el certificado impresión del pulgar, cópialo al portapapeles y elimina espacios.Este será un parámetro después de -h en el siguiente comando:

HttpCfg.exe set ssl -i 0.0.0.0:801 -h 35c65fd4853f49552471d2226e03dd10b7a11755

luego ejecute un host de servicio en https://localhost:801/ y funciona perfectamente.

Lo que no puedo hacer que funcione es que https se ejecute en un certificado autogenerado.Aquí está el código que ejecuto para generar uno (se eliminó el manejo de errores para mayor claridad):

LPCTSTR pszX500 = subject;
DWORD cbEncoded = 0;
CertStrToName(X509_ASN_ENCODING, pszX500, CERT_X500_NAME_STR, NULL, pbEncoded, &cbEncoded, NULL);
pbEncoded = (BYTE *)malloc(cbEncoded);
CertStrToName(X509_ASN_ENCODING, pszX500, CERT_X500_NAME_STR, NULL, pbEncoded, &cbEncoded, NULL);

// Prepare certificate Subject for self-signed certificate
CERT_NAME_BLOB SubjectIssuerBlob;
memset(&SubjectIssuerBlob, 0, sizeof(SubjectIssuerBlob));
SubjectIssuerBlob.cbData = cbEncoded;
SubjectIssuerBlob.pbData = pbEncoded;

// Prepare key provider structure for self-signed certificate
CRYPT_KEY_PROV_INFO KeyProvInfo;
memset(&KeyProvInfo, 0, sizeof(KeyProvInfo));
KeyProvInfo.pwszContainerName = _T("my-container");
KeyProvInfo.pwszProvName = NULL;
KeyProvInfo.dwProvType = PROV_RSA_FULL;
KeyProvInfo.dwFlags = CRYPT_MACHINE_KEYSET;
KeyProvInfo.cProvParam = 0;
KeyProvInfo.rgProvParam = NULL;
KeyProvInfo.dwKeySpec = AT_SIGNATURE;

// Prepare algorithm structure for self-signed certificate
CRYPT_ALGORITHM_IDENTIFIER SignatureAlgorithm;
memset(&SignatureAlgorithm, 0, sizeof(SignatureAlgorithm));
SignatureAlgorithm.pszObjId = szOID_RSA_SHA1RSA;

// Prepare Expiration date for self-signed certificate
SYSTEMTIME EndTime;
GetSystemTime(&EndTime);
EndTime.wYear += 5;

// Create self-signed certificate
pCertContext = CertCreateSelfSignCertificate(NULL, &SubjectIssuerBlob, 0, &KeyProvInfo, &SignatureAlgorithm, 0, &EndTime, 0);
hStore = CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, 0, CERT_SYSTEM_STORE_LOCAL_MACHINE, L"MY");
CertAddCertificateContextToStore(hStore, pCertContext, CERT_STORE_ADD_REPLACE_EXISTING, 0);

El certificado se muestra bien y tiene una clave privada que funciona, pero https expirará como si la huella digital nunca se hubiera registrado.Si alguien sabe por qué, por favor comente.

EDITAR1:Después de jugar un poco, encontré la inicialización de CertCreateSelfSignCertificate que genera el certificado adecuado:

CRYPT_KEY_PROV_INFO KeyProvInfo;
memset(&KeyProvInfo, 0, sizeof(KeyProvInfo));
KeyProvInfo.pwszContainerName = _T("my-container");
KeyProvInfo.pwszProvName = _T("Microsoft RSA SChannel Cryptographic Provider");
KeyProvInfo.dwProvType = PROV_RSA_SCHANNEL;
KeyProvInfo.dwFlags = CRYPT_MACHINE_KEYSET;
KeyProvInfo.cProvParam = 0;
KeyProvInfo.rgProvParam = NULL;
KeyProvInfo.dwKeySpec = AT_KEYEXCHANGE;

Sólo tiene que vincular un certificado a un puerto ip: y luego abrir su oyente con un prefijo https://.0.0.0.0 se aplica a todas las IP.appid es cualquier GUID aleatorio y certhash es el hash del certificado (a veces llamado huella digital).

Ejecute lo siguiente con cmd.exe usando privilegios de administrador.

netsh http add sslcert ipport=0.0.0.0:1234 certhash=613bb67c4acaab06def391680505bae2ced4053b  appid={86476d42-f4f3-48f5-9367-ff60f2ed2cdc}

Si desea crear un certificado autofirmado para probar esto,

  1. Abrir IIS
  2. Haga clic en el nombre de su computadora
  3. Haga clic en el icono Certificados de servidor
  4. Haga clic en generar certificado autofirmado
  5. Haga doble clic y vaya a detalles
  6. Verás la huella digital allí, simplemente elimina los espacios.

    HttpListener listener = new HttpListener();
    listener.Prefixes.Add("https://+:1234/");
    listener.Start();
    Console.WriteLine("Listening...");
    HttpListenerContext context = listener.GetContext();
    
    using (Stream stream = context.Response.OutputStream)
    using (StreamWriter writer = new StreamWriter(stream))
        writer.Write("hello, https world");
    
    Console.ReadLine();
    

Después de ejecutar este programa, simplemente navegué a https://localhost:1234 para ver el texto impreso.Dado que el certificado CN no coincide con la URL y no está en el almacén de certificados confiables, recibirá una Advertencia de certificado.Sin embargo, el texto está cifrado, como puede verificar con una herramienta como Wire Shark.

Si desea tener más control sobre la creación de un certificado x509 autofirmado, openssl es una gran herramienta y hay un puerto para Windows.He tenido mucho más éxito con él que con la herramienta makecert.


También es muy importante que, si se comunica con un servicio https desde un código que tiene una advertencia SSL, debe configurar el validador de certificados en el administrador del punto de servicio para omitirlo con fines de prueba.

ServicePointManager.ServerCertificateValidationCallback += (sender, cert, chain, errors) => true;

Todavía no lo tengo completamente implementado, pero este sitio web parece dar una buen recorrido de configurar los certificados y el código.

Aquí hay una forma alternativa de vincular el certificado SSL a la combinación IP/PUERTO sin usar httpcfg.exe (XP) o netsh.exe (Vista+).

http://dotnetcodebox.blogspot.com.au/2012/01/how-to-work-with-ssl-certificate.html

La esencia es que puedes usar C++. Configuración de HttpSetService API integrada en Windows para hacerlo mediante programación en lugar de a través de la línea de comandos, eliminando así la dependencia del sistema operativo y teniendo httpcfg instalado.

El documentación de clase

tiene esta nota:

Si crea un httplistener usando https, debe seleccionar un certificado de servidor para ese oyente.De lo contrario, una consulta httpwebRequest de esta httplistener fallará con un cierre inesperado de la conexión.

y esto:

Puede configurar certificados de servidor y otras opciones de oyentes utilizando httpcfg.exe.Ver http://msdn.microsoft.com/library/default.asp?url=/library/en-us/http/http/httpcfg_exe.asppara más detalles.El ejecutable se envía con Windows Server 2003, o se puede construir a partir del código fuente disponible en el SDK de la plataforma.

¿La primera nota se explica por la segunda?Como se describe en la pregunta, utilicé httpcfg.exe para vincular el certificado a un puerto específico.Si pretenden algo distinto a esto, la nota es ambigua.

Me he encontrado con el mismo problema que tú.Afortunadamente, después de buscar en Google pasos difíciles esta página hacer que SSL funcione con mi HttpListener.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top