Последние изменения, выделенные жирным шрифтом,
я использую HttpListener
класс .net , но я не буду запускать это приложение на IIS и не использую ASP.net. Этот веб-сайт описывает, какой код на самом деле использовать для реализации SSL с asp.net, а этот сайт описывает, как настроить сертификаты (хотя я не уверен, работает ли он только для IIS или нет).
Документация класса описывает различные типы аутентификации (базовая, дайджест, Windows и т. Д.) - ни один из них не относится к SSL. Это говорит о том, что если используется HTTPS, вам нужно будет установить сертификат сервера . Будет ли это однострочное свойство, а HttpListener
остальные?
Короче говоря, мне нужно знать, как настроить сертификаты и как изменить код для реализации SSL.
Хотя это не происходит, когда я пытаюсь получить доступ к HTTPS, я заметил ошибку в моем журнале системных событий - источником является «Schannel», а содержание сообщения:
Произошла неустранимая ошибка при попытке доступа к закрытому ключу учетных данных сервера SSL. Код ошибки, возвращаемый криптографическим модулем, - 0x80090016.
Изменить:
шаги, предпринятые до сих пор
- Создан работающий HTTPListener в C #, который работает для HTTP-соединений (например, « http: // localhost: 8089 / foldername / »
- Создан сертификат с использованием makecert.exe
- Добавлен сертификат, которому можно доверять, используя certmgr.exe
- Использовал Httpcfg.exe для прослушивания SSL-соединений на тестовом порту (например, 8090)
- Добавлен порт 8080 в HTTPListener через listener.Prefixes.Add ( https: // localhost: 8090 / foldername / ");
- проверил HTTP-соединение клиента, например ( http: // localhost: 8089 / foldername / ") в браузере, и получил правильный ответ
- проверил клиентское соединение HTTPS, например ( http: // localhost: 8090 / foldername / ") в браузере и получил сообщение« Передача данных прервана »(в Firefox)
- Отладка в Visual Studio показывает, что обратный вызов слушателя, который получает запросы, никогда не срабатывает при запуске соединения HTTPS - я не вижу места, где я мог бы установить точку останова, чтобы перехватить что-либо еще раньше.
- netstat показывает, что порты прослушивания открыты как для HTTPS, так и для HTTP. порт HTTPS переходит в TIME_WAIT после попытки подключения.
- Fiddler и HTTPAnalyzer не улавливают какой-либо трафик, я полагаю, что он недостаточно далеко уходит в процессе, чтобы отображаться в этих инструментах анализа HTTP
Вопросов
- В чем может быть проблема?
- Есть ли фрагмент кода .Net, который мне не хватает (имеется в виду, что в C # мне нужно сделать больше, чем просто добавить префикс к слушателю, указывающий на HTTPS, что я и сделал)
- Вы где-то пропустили этап настройки?
- Что еще я могу сделать, чтобы проанализировать проблему?
- Является ли сообщение об ошибке в журнале системных событий признаком проблемы? Если так, то как бы это исправить?
Я еще не полностью его реализовал, но этот веб-сайт, кажется, дает хорошее представление о настройке сертификатов и кода.
имеет это примечание:
Если вы создаете HttpListener с помощью https, вы должны выбрать сертификат сервера для этого прослушивателя. В противном случае запрос HttpWebRequest этого HttpListener завершится неудачно с неожиданным закрытием соединения.
и это:
Вы можете настроить сертификаты сервера и другие параметры прослушивателя с помощью HttpCfg.exe. См. Http://msdn.microsoft.com/library/default.asp?url=/library/en-us/http/http/httpcfg_exe.asp для получения дополнительной информации. Исполняемый файл поставляется с Windows Server 2003 или может быть собран из исходного кода, доступного в Platform SDK.
Первая нота объясняется второй? Как указано в вопросе, я использовал httpcfg.exe для привязки сертификата к определенному порту. Если они намереваются что-то иное, примечание неоднозначное.
Я столкнулся с той же проблемой, что и вы. К счастью, после непростых шагов на этой странице заставьте SSL работать с моим HttpListener.
У меня похожая проблема, и кажется, что может быть проблема с самим сертификатом.
Вот путь, который работал для меня:
makecert.exe -r -a sha1 -n CN=localhost -sky exchange -pe -b 01/01/2000 -e 01/01/2050 -ss my -sr localmachine
затем найдите отпечаток сертификата , скопируйте его в буфер обмена и удалите пробелы. Это будет параметр после -h в следующей команде:
HttpCfg.exe set ssl -i 0.0.0.0:801 -h 35c65fd4853f49552471d2226e03dd10b7a11755
затем запустите сервисный хост на https: // localhost: 801 /, и он отлично работает.
я не могу заставить работать HTTPS по самогенерируемому сертификату. Вот код, который я запускаю, чтобы сгенерировать его (обработка ошибок вычтена для ясности):
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);
Сертификат показывает нормально, и у него есть рабочий закрытый ключ, но https истечет время ожидания, как будто отпечаток большого пальца никогда не был зарегистрирован. Если кто знает почему - плз комментируйте
РЕДАКТИРОВАТЬ1 : После некоторой игры, я нашел инициализацию для CertCreateSelfSignCertificate, которая генерирует соответствующий сертификат:
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;
Вам просто нужно привязать сертификат к порту ip :, а затем открыть прослушиватель с префиксом https: //. 0.0.0.0 применяется ко всем IP. appid - это любой произвольный GUID, а certhash - хеш сертификата (иногда называемый thumprint).
Запустите следующее с cmd.exe, используя права администратора.
netsh http add sslcert ipport=0.0.0.0:1234 certhash=613bb67c4acaab06def391680505bae2ced4053b appid={86476d42-f4f3-48f5-9367-ff60f2ed2cdc}
Если вы хотите создать самоподписанный сертификат, чтобы проверить это,
- Откройте IIS
- Нажмите на имя вашего компьютера
- Нажмите значок сертификаты сервера
- Нажмите создать самоподписанный сертификат
- Дважды щелкните и перейдите к деталям
Там вы увидите отпечаток, просто удалите пробелы.
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();
После запуска этой программы я просто перешел https://localhost:1234
к просмотру напечатанного текста. Поскольку сертификат CN не соответствует URL-адресу и его нет в хранилище доверенных сертификатов, вы получите предупреждение о сертификате. Однако текст зашифрован, как вы можете проверить с помощью такого инструмента, как Wire Shark.
Если вам нужен больший контроль над созданием самозаверяющего сертификата x509, openssl - отличный инструмент, и в нем есть порт для Windows. У меня был намного больший успех, чем у инструмента makecert.
Также очень важно, чтобы, если вы связываетесь со службой https из кода с предупреждением ssl, вы должны настроить средство проверки сертификатов в диспетчере точек обслуживания, чтобы обойти его в целях тестирования.
ServicePointManager.ServerCertificateValidationCallback += (sender, cert, chain, errors) => true;
Вот альтернативный способ привязать сертификат SSL к комбинации IP / PORT без использования httpcfg.exe
(XP) или netsh.exe
(Vista +).
http://dotnetcodebox.blogspot.com.au/2012/01/how-to-work-with-ssl-certificate.html
Суть его в том, что вы можете использовать встроенный в Windows API-интерфейс HttpSetServiceConfiguration C ++, чтобы делать это программно, а не через командную строку, следовательно, удаляя зависимость от ОС и устанавливая httpcfg.