Открыть сервис

CertFindCertificateInStore

CertFindCertificateInStore — это функция из набора криптографических API (CryptoAPI) операционной системы Windows, предназначенная для поиска сертификата X.509 в заданном хранилище сертификатов по заданным критериям. Функция входит в состав библиотеки crypt32.dll и широко используется при разработке приложений, работающих с цифровыми подписями, шифрованием, аутентификацией и защищёнными соединениями (например, TLS/SSL).

Назначение и область применения

Функция CertFindCertificateInStore позволяет разработчику программно найти сертификат в уже открытом хранилище (контексте HCERTSTORE), не перебирая все записи вручную. Она применяется в системном и прикладном программном обеспечении, где требуется автоматический выбор подходящего сертификата — например, для подписания кода, расшифровки данных, проверки цепочки сертификатов или установления защищённого канала связи.

Синтаксис и параметры

Функция объявлена в заголовочном файле wincrypt.h и имеет следующий прототип:

``c PCCERT_CONTEXT CertFindCertificateInStore( HCERTSTORE hCertStore, DWORD dwCertEncodingType, DWORD dwFindFlags, DWORD dwFindType, const void *pvFindPara, PCCERT_CONTEXT pPrevCertContext ); ``

Параметры

  • hCertStore — дескриптор открытого хранилища сертификатов (например, полученный с помощью CertOpenStore).
  • dwCertEncodingType — тип кодировки сертификата. Обычно используется комбинация флагов X509_ASN_ENCODING и PKCS_7_ASN_ENCODING.
  • dwFindFlags — дополнительные флаги поиска. Может быть нулём или комбинацией значений, таких как CERT_FIND_OPTIONAL_ENHKEY_USAGE_FLAG (игнорировать расширенное использование ключа) или CERT_FIND_EXT_ONLY_ENHKEY_USAGE_FLAG (искать только по расширенному использованию ключа).
  • dwFindType — тип критерия поиска. Определяет, как интерпретируется параметр pvFindPara. Список возможных значений включает:
  • CERT_FIND_ANY — поиск любого сертификата (параметр pvFindPara игнорируется).
  • CERT_FIND_SHA1_HASH — поиск по хешу SHA-1 сертификата.
  • CERT_FIND_MD5_HASH — поиск по хешу MD5.
  • CERT_FIND_PROPERTY — поиск по свойству сертификата.
  • CERT_FIND_PUBLIC_KEY — поиск по открытому ключу.
  • CERT_FIND_SUBJECT_NAME — поиск по имени субъекта (владельца) сертификата.
  • CERT_FIND_ISSUER_NAME — поиск по имени издателя.
  • CERT_FIND_SUBJECT_STR — поиск по строке, содержащей часть имени субъекта.
  • CERT_FIND_ISSUER_STR — поиск по строке, содержащей часть имени издателя.
  • CERT_FIND_KEY_SPEC — поиск по типу использования ключа.
  • CERT_FIND_ENHKEY_USAGE — поиск по расширенному использованию ключа (EKU).
  • CERT_FIND_CTL_USAGE — поиск по использованию списка доверия сертификатов.
  • CERT_FIND_EXISTING — поиск существующего контекста сертификата.
  • CERT_FIND_CERT_ID — поиск по идентификатору сертификата.
  • CERT_FIND_SHA256_HASH — поиск по хешу SHA-256.
  • pvFindParaуказатель на структуру данных, содержащую критерии поиска. Тип структуры зависит от значения dwFindType. Например, для CERT_FIND_SUBJECT_STR это указатель на строку LPCWSTR, для CERT_FIND_SHA1_HASH — на массив байт хеша.
  • pPrevCertContext — указатель на предыдущий контекст сертификата для итеративного поиска. При первом вызове должен быть NULL. Для получения следующего сертификата, соответствующего критериям, передаётся результат предыдущего вызова.

Возвращаемое значение

При успешном поиске функция возвращает указатель на контекст сертификата (PCCERT_CONTEXT). Если сертификат не найден или произошла ошибка, возвращается NULL. Для получения кода ошибки следует вызвать GetLastError.

Типы поиска и примеры использования

Поиск по имени субъекта

Наиболее распространённый сценарий — поиск сертификата по имени владельца, например, по доменному имени или названию организации:

``c LPCWSTR subjectName = L"example.com"; PCCERT_CONTEXT pCert = CertFindCertificateInStore( hStore, X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, 0, CERT_FIND_SUBJECT_STR, subjectName, NULL); ``

Поиск по хешу SHA-1

Используется для точного нахождения конкретного сертификата по его отпечатку:

``c BYTE hash[20] = {0x12, 0x34, ...}; // 20 байт SHA-1 PCCERT_CONTEXT pCert = CertFindCertificateInStore( hStore, X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, 0, CERT_FIND_SHA1_HASH, hash, NULL); ``

Итеративный поиск

Для перебора всех сертификатов, удовлетворяющих условию, используется цикл с передачей предыдущего контекста:

``c PCCERT_CONTEXT pCert = NULL; while (pCert = CertFindCertificateInStore( hStore, X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, 0, CERT_FIND_ANY, NULL, pCert)) { // Обработка pCert CertFreeCertificateContext(pCert); } ``

Особенности работы

  • Функция не изменяет хранилище, а только производит поиск. Для добавления или удаления сертификатов используются другие функции CryptoAPI (CertAddCertificateContextToStore, CertDeleteCertificateFromStore).
  • Возвращаемый контекст сертификата (PCCERT_CONTEXT) должен быть освобождён вызовом CertFreeCertificateContext, чтобы избежать утечки памяти.
  • При использовании строковых критериев (CERT_FIND_SUBJECT_STR, CERT_FIND_ISSUER_STR) поиск выполняется по подстроке без учёта регистра. Это может привести к неоднозначности, если в хранилище есть несколько сертификатов с похожими именами.
  • Для поиска по расширенному использованию ключа (EKU) необходимо передать указатель на структуру CERT_ENHKEY_USAGE, содержащую массив OID-ов.

Ограничения и рекомендации

  • Функция не поддерживает поиск по отпечатку SHA-256 в системах Windows до Windows Vista и Windows Server 2008. Для более старых версий следует использовать SHA-1 или MD5.
  • При поиске в больших хранилищах (например, в системном хранилище «Доверенные корневые центры сертификации») производительность может быть низкой, если не использовать индексы. Рекомендуется предварительно открывать хранилище с флагом CERT_STORE_READONLY_FLAG и, если возможно, ограничивать область поиска.
  • Для поиска сертификатов, соответствующих определённым политикам (например, для подписи кода или шифрования), следует комбинировать CertFindCertificateInStore с проверкой свойств контекста (CertGetCertificateContextProperty), таких как CERT_KEY_SPEC_PROP_ID или CERT_ENHKEY_USAGE_PROP_ID.

Сравнение с альтернативами

В современных версиях Windows (начиная с Windows 8 и Windows Server 2012) появились более высокоуровневые API для работы с сертификатами, такие как CryptFindCertificateByKeyIdentifier и функции из набора Cryptography API: Next Generation (CNG). Однако CertFindCertificateInStore остаётся основной функцией для поиска в классическом CryptoAPI и поддерживается во всех версиях Windows, начиная с Windows 2000.

Пример кода на C++

Ниже приведён упрощённый пример поиска сертификата по имени субъекта и вывода его серийного номера:

```cpp

include <windows.h>

include <wincrypt.h>

include <iostream>

pragma comment(lib, "crypt32.lib")

void FindCertBySubject(const std::wstring& subject) { HCERTSTORE hStore = CertOpenStore( CERT_STORE_PROV_SYSTEM, X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, NULL, CERT_STORE_READONLY_FLAG, L"MY"); if (!hStore) { std::cerr << "Failed to open store" << std::endl; return; }

PCCERT_CONTEXT pCert = CertFindCertificateInStore( hStore, X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, 0, CERT_FIND_SUBJECT_STR, subject.c_str(), NULL);

if (pCert) { // Вывод серийного номера DWORD serialLen = pCert->pCertInfo->SerialNumber.cbData; BYTE* serial = pCert->pCertInfo->SerialNumber.pbData; std::cout << "Serial number: "; for (DWORD i = 0; i < serialLen; ++i) { printf("%02X", serial[i]); } std::cout << std::endl; CertFreeCertificateContext(pCert); } else { std::cerr << "Certificate not found" << std::endl; }

CertCloseStore(hStore, 0); } ```

Источники

  • Microsoft Docs: «CertFindCertificateInStore function» (документация по CryptoAPI).
  • MSDN Library: «Certificate Store Functions».
  • Windows SDK: заголовочный файл wincrypt.h.
  • Книга: «Programming Windows Security» by Keith Brown (глава о сертификатах и CryptoAPI).

BFOmetr — база данных и аналитика по компаниям России.

На главную BFOmetr →