43 votes

Comment puis-je ajouter SSL à une application .net qui utilise httplistener - il * ne * fonctionnera pas sur IIS

Modifications les plus récentes en gras Je suis en utilisant le .net HttpListener classe, mais je suis de ne pas être en cours d'exécution sur IIS et ne suis pas à l'aide de ASP.net. Ce site web décrit ce code à l'utilisation réelle de mettre en œuvre le protocole SSL avec asp.net et ce site explique comment configurer les certificats (bien que je ne suis pas sûr si elle ne fonctionne que pour IIS ou pas).

Quand j'ai de la documentation de classe, il décrit les divers types d'authentification (basic, digest, Windows, etc.) - aucun d'entre eux font référence à SSL. Il ne dit que si le protocole HTTPS est utilisé, vous devez disposer d'un certificat de serveur. Est-ce que ça va être une une ligne de la propriété et de l' HttpListener chiffres le reste?

En bref, j'ai besoin de savoir comment mettre en place les certificats et comment modifier le code pour mettre en œuvre le protocole SSL.

Bien qu'il ne se produit pas lorsque j'essaye d'accéder à HTTPS, j'ai remarqué une erreur dans mon journal d'Événements du Système - la source est "Schannel" et le contenu du message est le suivant:

Une erreur irrécupérable s'est produite lors de la tentative pour accéder aux informations d'identification du serveur SSL la clé privée. Le code d'erreur retourné depuis le module cryptographique est 0x80090016.

Edit:
Les mesures prises jusqu'à présent

  • Créé un HTTPListener en C# qui fonctionne pour les connexions HTTP (par ex. "http://localhost:8089/foldername/"
  • Créé un certificat à l'aide de makecert.exe
  • Ajouté le certificat de confiance à l'aide de certmgr.exe
  • Utilisé Httpcfg.exe pour écouter les connexions SSL sur un port d'essai (p. 8090)
  • Ajoutée le port 8080 de la HTTPListener par l'auditeur.Les préfixes.Ajouter(https://localhost:8090/foldername/");
  • testé un client HTTP de connexion, par exemple (http://localhost:8089/foldername/") dans un navigateur et de recevoir de retour correctes
  • testé HTTPS, client de connexion, par exemple (http://localhost:8090/foldername/") dans un navigateur et de recevoir "Transfert de Données Interrompue" (dans Firefox)
  • débogage dans visual studio montre que le rappel de l'écouteur qui reçoit la demande n'est jamais atteint lorsque la connexion HTTPS commence - je ne vois pas toute la place que je pourrais définir un point d'arrêt à attraper quoi que ce soit d'autre.
  • netstat montre que l'écoute ports sont ouverts pour HTTPS et HTTP. le port HTTPS ne va TIME_WAIT après une tentative de connexion.
  • Fiddler et HTTPAnalyzer ne pas accrocher le trafic, je suppose qu'il ne va pas assez loin dans le processus à apparaître dans ces HTTP outils d'analyse

Questions

  • Quel pourrait être le problème?
  • Est-il un morceau de .Net code, je suis absent (ce qui signifie que j'ai à faire plus en C# d'autres que de simplement ajouter un préfixe à l'auditeur qui pointe vers HTTPS, qui est ce que j'ai fait)
  • Manqué une étape de configuration quelque part?
  • Quoi d'autre pourrais-je faire pour analyser le problème?
  • Est le message d'erreur dans le journal des Événements Système un signe de problème? Si oui, comment serait-il fixe?

10voto

galets Points 4119

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 d'accès 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

regardez en haut certificat d' empreinte, le copier dans le presse-papiers et de supprimer 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

ensuite, exécutez un service d'accueil sur https://localhost:801/ et il fonctionne parfaitement.

ce que je ne peut pas faire le travail est pour https pour exécuter sur le certificat auto-généré. Voici le code que j'ai exécuté pour générer un (gestion des erreurs 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);

Certificat de montre fine et il a un travail à la clé privée, mais https expire comme si l'empreinte n'a jamais été enregistré. Si quelqu'un sait pourquoi - commentaire plz

EDIT1: Après quelques de jouer, j'ai trouvé l'initialisation pour CertCreateSelfSignCertificate qui génère un bon certificat:

	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;

6voto

Despertar Points 5365

Vous avez juste à lier un certificat ip:port, puis ouvrez votre écouteur avec un préfixe https://. 0.0.0.0 s'applique à toutes les adresses ip. appid est tout GUID aléatoire, et certhash est le hachage du certificat (parfois appelé un thumprint).

Exécutez les opérations suivantes avec les cmd.exe à l'aide des 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. Ouvrir IIS
  2. Cliquez sur le nom de votre ordinateur
  3. Cliquez sur Certificats de Serveur icône
  4. Cliquez sur générer un certificat Auto-Signé
  5. Double-cliquez et aller de détails
  6. Vous verrez l'empreinte de là, il suffit de supprimer 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 l'exécution de ce programme, j'ai juste navigué https://localhost:1234 voir le texte imprimé. Depuis le certificat CN ne correspond pas à l'url et il n'est pas dans le magasin de Certificats de Confiance, vous obtiendrez un Avertissement de Certificat. Le texte est chiffré cependant, comme vous pouvez le vérifier avec un outil comme le Fils du Requin.

Si vous voulez plus de contrôle sur la création d'une auto-signé certificat x509 openssl est un outil génial et il y a un port pour windows. J'ai eu beaucoup plus de succès à ce que le makecert outil.


Il est également très important que si vous communiquez avec un service https à partir du code qui a une alerte ssl, vous devez installer le certificat du programme de validation sur le service gestionnaire de point de le contourner pour des fins de test.

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

5voto

pc1oad1etter Points 3910

Je ne l'ai pas encore entièrement implémenté, mais ce site Web semble donner une bonne solution pour configurer les certificats et le code.

3voto

pc1oad1etter Points 3910

La documentation de classe

a cette remarque:

Si vous créez un HttpListener à l'aide de https, vous devez sélectionner un Serveur Certificat pour l'auditeur. Sinon, une HttpWebRequest requête de cette HttpListener échouera avec une inattendu, à proximité de la connexion.

et ceci:

Vous pouvez configurer le Serveur de Certificats et d'autres auditeur options à l'aide de HttpCfg.exe. Voir http://msdn.microsoft.com/library/default.asp?url=/library/en-us/http/http/httpcfg_exe.asp pour plus de détails. L'exécutable est livré avec Windows Server 2003, ou peut être construit à partir du code source disponible dans le kit de développement Platform SDK.

Est la première note explique par le second? Comme indiqué dans la question, j'ai utilisé httpcfg.exe pour lier le certificat à un port spécifique. S'ils ont l'intention de quelque chose d'autre que cela, la note est ambigu.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X