//------------------------------------------------------------------------------------- // Данный пример демонстрирует поиск контейнера соответствующего сертификату. // Для проверки работы примера необходимо создать контейнер и положить соответствующий // ему сертификат в файл test_search.cer. Программа возвращает имя найденного контейнера. //------------------------------------------------------------------------------------- BOOL CmpCertAndContFP(LPCSTR szContainerName, LPBYTE pbFPCert, DWORD cbFPCert); static void HandleError(const char *s); int main(int argc, char **argv) { //------------------------------------------------------------------------ // Объявление переменных HCERTSTORE hFileStore; // Дескриптор хранилища сертификатов PCCERT_CONTEXT pCertCtx; // Контекст сертификата HCRYPTPROV hCryptProv; // Дескриптор криптопровайдера HCRYPTKEY hPublicKey; // Дескриптор ключа из сертификата LPBYTE pbFPCert; // Параметр FP из сертификата DWORD cbFPCert; // Размер параметра FP из сертификата LPBYTE pbContainerName; // Имя контейнера DWORD cbContainerName; // Размер имени контейнера DWORD dwFlags; if (2 != argc) { HandleError("Wrong arguments!"); } //------------------------------------------------------------------------ // Создание хранилища сертификатов из файла if ((hFileStore = CertOpenStore( CERT_STORE_PROV_FILENAME_A, 0, 0, CERT_STORE_OPEN_EXISTING_FLAG, argv[1] // Файл с сертификатом ))) { printf("The file store was created successfully.\n"); } else { HandleError("An error occurred during creation of the file store!"); } //------------------------------------------------------------------------ // Получение контекста сертификата из хранилища if ((pCertCtx = CertEnumCertificatesInStore(hFileStore, NULL))) { printf("Certificate context was loaded from store.\n"); } else { HandleError("Error during CertEnumCertificatesInStore!"); } //------------------------------------------------------------------------ // Получение дескриптора криптопровайдера if (CryptAcquireContext( &hCryptProv, NULL, NULL, PROV_GOST_2012_256, CRYPT_VERIFYCONTEXT)) { printf("CryptAcquireContext succeeded. \n"); } else { HandleError("Error during CryptAcquireContext!"); } //------------------------------------------------------------------------ // Получение дескриптора открытого ключа из сертификата if (CryptImportPublicKeyInfo( hCryptProv, pCertCtx->dwCertEncodingType, &pCertCtx->pCertInfo->SubjectPublicKeyInfo, &hPublicKey)) { printf("CryptImportPublicKeyInfo succeeded. \n"); } else { HandleError("Error during CryptImportPublicKeyInfo!"); } //------------------------------------------------------------------------ // Получение параметра KP_FP открытого ключа из сертификата // Получение размера параметра if (CryptGetKeyParam(hPublicKey, KP_FP, NULL, &cbFPCert, 0)) { printf("CryptGetKeyParam KP_FP succeeded. \n"); } else { HandleError("Error during CryptGetKeyParam!"); } // Выделение памяти pbFPCert = (LPBYTE)malloc(cbFPCert); if (!pbFPCert) { HandleError("Fail to allocate memory!"); } // Получение параметра if (CryptGetKeyParam(hPublicKey, KP_FP, pbFPCert, &cbFPCert, 0)) { printf("CryptGetKeyParam KP_FP succeeded. \n"); } else { HandleError("Error during CryptGetKeyParam!"); } //------------------------------------------------------------------------ // Получение имени первого контейнера // Получение размера параметра if (CryptGetProvParam(hCryptProv, PP_ENUMCONTAINERS, NULL, &cbContainerName, CRYPT_FIRST)) { printf("CryptGetProvParam PP_ENUMCONTAINERS succeeded. \n"); } else { HandleError("Error during CryptGetProvParam!"); } // Выделение памяти pbContainerName = (LPBYTE)malloc(cbContainerName); if (!pbContainerName) { HandleError("Fail to allocate memory!"); } //------------------------------------------------------------------------ // Перебор всех контейнеров dwFlags = CRYPT_FIRST; while (CryptGetProvParam(hCryptProv, PP_ENUMCONTAINERS, pbContainerName, &cbContainerName, dwFlags | CRYPT_FQCN)) { if (CmpCertAndContFP((LPCSTR)pbContainerName, pbFPCert, cbFPCert)) { printf("Container found! Name: '%s'\n", pbContainerName); break; } dwFlags = CRYPT_NEXT; } //------------------------------------------------------------------------ // Освобождение памяти free(pbContainerName); free(pbFPCert); if (hFileStore) { if (!CertCloseStore(hFileStore, CERT_CLOSE_STORE_FORCE_FLAG)) { HandleError("Error during CertCloseStore!"); } } if (hPublicKey) { if (!CryptDestroyKey(hPublicKey)) { HandleError("Error during CryptDestroyKey!"); } } if (hCryptProv) { if (!CryptReleaseContext(hCryptProv, 0)) { HandleError("Error during CryptReleaseContext!"); } } return 0; } BOOL CmpCertAndContFP(LPCSTR szContainerName, LPBYTE pbFPCert, DWORD cbFPCert) { HCRYPTPROV hProvCont; LPBYTE pbFPCont; DWORD cbFPCont; BOOL result = FALSE; //------------------------------------------------------------------------ // Получение дескриптора контейнера if (CryptAcquireContextA( &hProvCont, szContainerName, NULL, PROV_GOST_2012_256, CRYPT_VERIFYCONTEXT)) { printf("CryptAcquireContext for '%s' succeeded. \n", szContainerName); } else { HandleError("Error during CryptAcquireContext!\n"); } //------------------------------------------------------------------------ // Получение параметра PP_SIGNATURE_KEY_FP для ключа в контейнере cbFPCont = cbFPCert; // Размер FP из контейнера равен размеру FP из сертификата pbFPCont = (LPBYTE)malloc(cbFPCont); if (CryptGetProvParam(hProvCont, PP_SIGNATURE_KEY_FP, pbFPCont, &cbFPCont, 0)) { printf("CryptGetProvParam PP_SIGNATURE_KEY_FP for '%s' succeeded. \n", szContainerName); // Сравнение FP из сертификата с FP из контейнера if (!memcmp(pbFPCont, pbFPCert, cbFPCert)) { result = TRUE; goto Done; } } //------------------------------------------------------------------------ // Получение параметра PP_EXCHANGE_KEY_FP для ключа в контейнере if (CryptGetProvParam(hProvCont, PP_EXCHANGE_KEY_FP, pbFPCont, &cbFPCont, 0)) { printf("CryptGetProvParam PP_EXCHANGE_KEY_FP for '%s' succeeded. \n", szContainerName); // Сравнение FP из сертификата с FP из контейнера if (!memcmp(pbFPCont, pbFPCert, cbFPCert)) { result = TRUE; goto Done; } } Done: free(pbFPCont); if (hProvCont) { if (!CryptReleaseContext(hProvCont, 0)) { HandleError("Error during CryptReleaseContext!"); } } return result; } // Конец примера
AIX: 6/7.
FreeBSD: 11/12, pfSense 2.x.
Linux: LSB 4.x (RHEL 5/6/7/8, SuSE 11SP4/12/15, Oracle Linux 5/6/7/8, CentOS 6/7/8, Ubuntu 14.04/16.04/18.04/19.10, Linux Mint 18/19, Fedora 28/29/30/31, Debian 8/9/10 и др.).
Solaris: 10/11.
Mac OS X: 10.9/10.10/10.11/10.12/10.13/10.14/10.15.
iOS: 8/9/10/11/12/13.
Sailfish: 2/3.
Windows: 7/8/8.1/10, Server 2008/2008R2/2012/2012R2/2016/2019.