authentication - Comment ajouter SSL à une application .net qui utilise httplistener

Translate

Modifications les plus récentes en grasJ'utilise le .netHttpListenerclass, mais je n'exécuterai pas cette application sur IIS et n'utiliserai pas ASP.net. Cesite Internetdécrit le code à utiliser pour implémenter SSL avec asp.net etce sitedécrit comment configurer les certificats (même si je ne suis pas sûr que cela fonctionne uniquement pour IIS ou non).

La documentation de la classe décrit différents types d'authentification (basique, digest, Windows, etc.) --- aucun d'entre eux ne fait référence à SSL. Cela dit que siHTTPS est utilisé, vous devrez définir un certificat de serveur. Cela va-t-il être un paramètre de propriété sur une ligne etHttpListenercomprend le reste?

En bref, j'ai besoin de savoir comment configurer les certificats et comment modifier le code pour implémenter SSL.

Bien que cela ne se produise pas lorsque j'essaie d'accéder à HTTPS, j'ai remarqué une erreur dans mon journal des événements système - la source est "Schannel" et le contenu du message est:

Une erreur fatale s'est produite lors de la tentative d'accès à la clé privée des informations d'identification du serveur SSL. Le code d'erreur renvoyé par le module cryptographique est 0x80090016.

Éditer:
Mesures prises jusqu'à présent

  • Création d'un HTTPListener fonctionnel en C # qui fonctionne pour les connexions HTTP (par exemple "http: // localhost: 8089 / nomdossier /"
  • Création d'un certificat à l'aide de makecert.exe
  • Ajout du certificat à faire confiance à l'aide de certmgr.exe
  • Httpcfg.exe utilisé pour écouter les connexions SSL sur un port de test (par exemple 8090)
  • Ajout du port 8080 au HTTPListener via listener.Prefixes.Add (https: // localhost: 8090 / nomdossier /");
  • testé une connexion client HTTP, par exemple (http: // localhost: 8089 / nomdossier /") dans un navigateur et recevez un retour correct
  • testé une connexion client HTTPS, par exemple (http: // localhost: 8090 / nomdossier /") dans un navigateur et recevez" Transfert de données interrompu "(dans Firefox)
  • le débogage dans Visual Studio montre que le rappel de l'auditeur qui reçoit les demandes n'est jamais atteint lorsque la connexion HTTPS démarre - je ne vois aucun endroit où je pourrais définir un point d'arrêt pour attraper autre chose plus tôt.
  • netstat montre que les ports d'écoute sont ouverts à la fois pour HTTPS et HTTP. le port HTTPS passe à TIME_WAIT après une tentative de connexion.
  • VioloneuxetHTTPAnalyzern'attrapez aucun trafic, je suppose que cela ne va pas assez loin dans le processus pour apparaître dans ces outils d'analyse HTTP

Des questions

  • Quel pourrait être le problème?
  • Y a-t-il un morceau de code .Net qui me manque (ce qui signifie que je dois faire plus en C # autre que simplement ajouter un préfixe à l'auditeur qui pointe vers HTTPS, ce que j'ai fait)
  • Vous avez manqué une étape de configuration quelque part?
  • Que puis-je faire d'autre pour analyser le problème?
  • Le message d'erreur dans le journal des événements système est-il un signe du problème? Si oui, comment cela serait-il réglé?
This question and all comments follow the "Attribution Required."

Toutes les réponses

Translate

J'ai un problème similaire, et il semble qu'il pourrait y avoir un problème avec le certificat lui-même.

Voici le chemin qui a fonctionné pour moi:

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

puis recherchez le certificatempreinte, copiez-le dans le presse-papiers et supprimez les espaces. Ce sera un paramètre après -h dans la commande suivante:

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

puis exécutez un hôte de service surhttps: // localhost: 801 /et cela fonctionne parfaitement.

ce que je ne peux pas faire fonctionner, c'est que https s'exécute sur un certificat auto-généré. Voici le code que j'ai exécuté pour en générer un (gestion des erreurs supprimée pour plus de clarté):

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);

Le certificat montre bien et il a une clé privée fonctionnelle, mais https expirera comme si l'empreinte numérique n'avait jamais été enregistrée. Si quelqu'un sait pourquoi - commentaire plz

EDIT1: Après quelques jeux, j'ai trouvé l'initialisation de CertCreateSelfSignCertificate qui génère le certificat approprié:

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;
La source
Translate

Il vous suffit de lier un certificat à un ip: port, puis d'ouvrir votre écouteur avec un préfixe https: //. 0.0.0.0 s'applique à toutes les adresses IP. appid est n'importe quel GUID aléatoire et certhash est le hachage du certificat (parfois appelé thumprint).

Exécutez ce qui suit avec cmd.exe en utilisant les privilèges d'administrateur.

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

Si vous souhaitez créer un certificat auto-signé pour tester cela,

  1. Ouvrez IIS
  2. Cliquez sur le nom de votre ordinateur
  3. Cliquez sur l'icône Certificats de serveur
  4. Cliquez sur générer un certificat auto-signé
  5. Double-cliquez et accédez aux détails
  6. Vous y verrez l'empreinte numérique, supprimez simplement les espaces.

    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();
    

Après avoir exécuté ce programme, je viens de naviguer vershttps://localhost:1234pour voir le texte imprimé. Puisque le certificat CN ne correspond pas à l'URL et qu'il ne se trouve pas dans le magasin de certificats approuvés, vous recevrez un avertissement de certificat. Le texte est cependant crypté comme vous pouvez le vérifier avec un outil comme Wire Shark.

Si vous voulez plus de contrôle sur la création d'un certificat x509 auto-signé, openssl est un excellent outil et il existe un port pour Windows. J'ai eu beaucoup plus de succès avec lui que l'outil makecert.


Il est également très important que si vous communiquez avec un service https à partir d'un code comportant un avertissement ssl, vous devez configurer le validateur de certificat sur le gestionnaire de point de service pour le contourner à des fins de test.

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

Je ne l'ai pas encore entièrement implémenté, mais ce site Web semble donner unbonne procédure pas à pasde la mise en place des certificats et du code.

La source
Translate

Voici une autre façon de lier le certificat SSL à la combinaison IP / PORT sans utiliserhttpcfg.exe(XP) ounetsh.exe(Vista +).

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

L'essentiel est que vous pouvez utiliser un C ++HttpSetServiceConfigurationAPI intégrée à Windows pour le faire par programme plutôt que via la ligne de commande, supprimant ainsi la dépendance au système d'exploitation et installant httpcfg.

La source
Translate

ledocumentation de classe

a cette note:

Si vous créez un HttpListener à l'aide de https, vous devez sélectionner un certificat de serveur pour cet écouteur. Sinon, une requête HttpWebRequest de ce HttpListener échouera avec une fermeture inattendue de la connexion.

et ça:

Vous pouvez configurer des certificats de serveur et d'autres options d'écoute à l'aide de HttpCfg.exe. Voirhttp://msdn.microsoft.com/library/default.asp?url=/library/en-us/http/http/httpcfg_exe.asppour plus de détails. L'exécutable est livré avec Windows Server 2003 ou peut être créé à partir du code source disponible dans le SDK Platform.

La première note est-elle expliquée par la seconde? Comme indiqué dans la question, j'ai utilisé httpcfg.exe pour lier le certificat à un port spécifique. S'ils ont l'intention d'autre chose que cela, la note est ambiguë.

La source
Doreen Lee
Translate

J'ai rencontré le même problème que vous. Heureusement après avoir cherché sur Google des étapes difficilescette pagefaire fonctionner SSL avec mon HttpListener.

La source