Закрепление сертификата с помощью WinHTTP API

Можно ли реализовать закрепление сертификата с помощью Win32 WinHTTP API, и если да, то как? т.е. как я могу проверить возвращенный сертификат сервера на «известный исправный», желательно без необходимости постоянной записи сертификата в локальное хранилище сертификатов.


person snowcrash09    schedule 04.08.2014    source источник


Ответы (2)


(вдохновленный ответом jww)

Во-первых, я нашел эту страницу отличной базой для чтения о закреплении и выборе между сертификатом и общедоступным ключом. закрепление ключей.

Я реализовал закрепление сертификата с помощью WinHTTP API следующим образом:

  1. После WinHttpOpen, но до WinHttpConnect настройте обратный вызов при отправке запросов:

    WinHttpSetStatusCallback(hSession, &callbackFunc, WINHTTP_CALLBACK_SENDING_REQUEST, NULL);

  2. В функции обратного вызова извлеките необработанный большой двоичный объект сертификата:

    PCCERT_CONTEXT pCert=NULL; DWORD dwSize=sizeof(pCert); WinHttpQueryOption(hInternet, WINHTTP_OPTION_SERVER_CERT_CONTEXT, &pCert, &dwSize);

  3. Затем, если вы выполняете полное закрепление сертификата, сравните sha1(pCert->pbCertEncoded) с отпечатком известного хорошего сертификата SHA1.

  4. -Или- если вместо этого выполняется закрепление открытого ключа, сравните sha1(pCert->pCertInfo->SubjectPublicKeyInfo.PublicKey.cbData) с заведомо исправным SHA1 открытого ключа сервера.

person snowcrash09    schedule 11.08.2014
comment
Обратите внимание, что обычно вы хотите хэшировать полную информацию об открытом ключе субъекта (SPKI) в целях безопасности и для соответствия контактам, используемым при закреплении открытого ключа HTTP (RFC 7230). Вы можете получить это, используя CryptEncodeObject(X509_ASN_ENCODING, X509_PUBLIC_KEY_INFO, ...) перед хешированием. Кстати, WINHTTP_CALLBACK_STATUS_SENDING_REQUEST теперь также кажется устаревшим, без очевидной замены :-( - person bobince; 24.08.2015
comment
Вам не нужно реализовывать функцию sha1. Вместо этого используйте этот API CertGetCertificateContextProperty(pCertContext, CERT_HASH_PROP_ID, thumbprint, &thumbprint_size) для получения отпечатка, то есть хэша SHA1. - person Robert; 28.01.2021

Можно ли реализовать закрепление сертификата с помощью Win32 WinHTTP API, и если да, то как?

Похоже, вы можете закрепить сертификат. Вы можете установить обратный вызов с помощью WINHTTP_STATUS_CALLBACK. Когда обратный вызов вызывается с помощью WINHTTP_CALLBACK_STATUS_CONNECTED_TO_SERVER, вы можете проверить сертификат с помощью WinHttpQueryOption и WINHTTP_OPTION_SECURITY_CERTIFICATE_STRUCT. Сертификат сервера возвращается в структуре WINHTTP_CERTIFICATE_INFO.

Есть страница по адресу SSL в WinHTTP., предлагающий дополнительную информацию.


... без необходимости постоянно записывать сертификат в локальное хранилище сертификатов.

Проблема с хранилищем сертификатов заключается в том, что другой орган может претендовать на сертификацию сайта, к которому вы подключаетесь. В этом случае настоящему доверенному лицу даже не нужно находиться в магазине, чтобы получить pwn'd. Это одна из [очевидных] проблем с моделью безопасности веб-приложений/браузеров и CA Zoo.

person jww    schedule 05.08.2014
comment
Привет, ваш ответ указал мне правильное направление, но могу ли я предложить два изменения, прежде чем я приму: (1) WINHTTP_OPTION_SECURITY_CERTIFICATE_STRUCT не дает достаточно информации для закрепления сертификата, вместо этого используйте WINHTTP_OPTION_SERVER_CERT_CONTEXT, чтобы получить полный закодированный сертификат. И (2) WINHTTP_CALLBACK_STATUS_CONNECTED_TO_SERVER устарел и также происходит до того, как сертификат будет доступен — вместо этого работает WINHTTP_CALLBACK_STATUS_SENDING_REQUEST. - person snowcrash09; 05.08.2014
comment
@ snowcrash09 - ничего страшного. Предоставьте свой собственный ответ и примите его. Я не обижусь и проголосую за него, потому что это лучший ответ :) Вот как работает SO. - person jww; 05.08.2014