| ||||
| ||||
После установки клиентского сертификата посредством вызова функций Crypto API и привязки сертификата к ключу на дискете (CryptSetKeyParam), при попытке установить соединение по SSL запрашивается диалог вставки ключевого носителя, после вставки выдается сообщение "Набор ключей не существует". Если с этого же носителя установить сертификат в личное хранилище, используя панель управления CryptoPro, все работает нормально. Подскажите, может есть какая-то секретная функция, которую еще нужно дополнительно вызывать? Вот последовательность вызовов, осуществляемая при программной установке сертификата в личное хранилище клиента, что здесь упущено? HCRYPTPROV hProv = NULL; if (CryptAcquireContext(&hProv, szContainerName, CP_DEF_PROV_A, PROV_GOST_DH, 0)) { HCRYPTKEY hKeySig = NULL; if (CryptGetUserKey(hProv, AT_KEYEXCHANGE, &hKeySig)) { DWORD dwNameLength = 0; DWORD dwProvLength = 0; DWORD dwUserCertLength = 0; DWORD dwOpenStore = CERT_SYSTEM_STORE_CURRENT_USER; CRYPT_KEY_PROV_INFO provInfoSig = {0}; if (CryptGetProvParam(hProv, PP_UNIQUE_CONTAINER, NULL, &dwNameLength, 0)) CryptGetProvParam(hProv, PP_UNIQUE_CONTAINER, (BYTE*)provInfoSig.pwszContainerName, &dwNameLength, 0); if (CryptGetProvParam(hProv, PP_NAME, NULL, &dwProvLength, 0)) CryptGetProvParam(hProv, PP_NAME, (BYTE*)provInfoSig.pwszProvName, &dwProvLength, 0); provInfoSig.dwFlags = 0; provInfoSig.dwKeySpec = AT_KEYEXCHANGE; DWORD pdw = sizeof(provInfoSig.dwProvType); CryptGetProvParam(hProv, PP_PROVTYPE, (BYTE*)&provInfoSig.dwProvType, &pdw, 0); if (CryptGetKeyParam(hKeySig, KP_CERTIFICATE, NULL, &dwUserCertLength, 0)) { BYTE *pbUserCert = (LPBYTE)malloc(dwUserCertLength); PCCERT_CONTEXT pUserCert = NULL; HANDLE hCertStore = 0; if (CryptGetKeyParam(hKeySig, KP_CERTIFICATE, pbUserCert, &dwUserCertLength, 0)) { pUserCert = CertCreateCertificateContext(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, pbUserCert, dwUserCertLength); if (pUserCert) { if (CertSetCertificateContextProperty(pUserCert, CERT_KEY_PROV_INFO_PROP_ID, 0, &provInfoSig)) { hCertStore = CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, 0, CERT_STORE_OPEN_EXISTING_FLAG | dwOpenStore, L"MY"); if (hCertStore) { if (CertAddCertificateContextToStore(hCertStore, pUserCert, /*CERT_STORE_ADD_USE_EXISTING*/CERT_STORE_ADD_REPLACE_EXISTING, NULL)) { if (!CryptSetKeyParam(hKeySig, KP_CERTIFICATE, pUserCert->pbCertEncoded, 0)) MessageBox(GetErrorMessage(GetLastError()), _T("Ошибка привязки сертификата к ключу"), MB_OK | MB_ICONSTOP); } // if !CertAddCertificateContextToStore else MessageBox(GetErrorMessage(GetLastError()), _T("Ошибка установки сертификата"), MB_OK | MB_ICONSTOP); } // if hCertStore } // if CertSetCertificateContextProperty } // if pUserCert } // if CryptGetKeyParam 2 if (hCertStore) CertCloseStore(hCertStore, CERT_CLOSE_STORE_FORCE_FLAG); if (pUserCert) CertFreeCertificateContext(pUserCert); if (pbUserCert) free(pbUserCert); } // if CryptGetKeyParam 1 } // if CryptGetUserKey else MessageBox(GetErrorMessage(GetLastError()), _T("Ошибка открытия ключа"), MB_OK | MB_ICONSTOP); if (hKeySig) CryptDestroyKey(hKeySig); } // if CryptAcquireContext if (hProv) CryptReleaseContext(hProv, 0); Заранее благодарен. | ||||
Ответы: | ||||
| ||||
Функция не секретная. Нужно заполнить структуру CRYPT_KEY_PROV_INFO и попользовать функцию CertSetCertificateContextProperty. Пример у нас в файле property.c | ||||
| ||||
Большое спасибо за ответ! | ||||
| ||||
Однако, использование этой функции CertSetCertificateContextProperty(pUserCert, CERT_KEY_PROV_INFO_PROP_ID, CERT_STORE_NO_CRYPT_RELEASE_FLAG, &provInfo) с предварительной установкой provInfo.dwFlags = CERT_SET_KEY_CONTEXT_PROP_ID как написано в property.c не привела к разрешению проблемы, по прежнему сертификат устанавливается корректно, привязывается к ключу, но при работе клиента выдается ошибка "Набор ключей не существует", хотелось бы получить подробные разъяснения по этому вопросу или ссылку на документацию, где подобная проблема описана???! | ||||
| ||||
Скорее всего вы делаете не то. Вы устанавливаете флаг кеширования ключа. А нужно сделать ссылку на секретный ключ. Описание функции: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/security/security/certsetcertificatecontextproperty.asp Описание структуры: typedef struct _CRYPT_KEY_PROV_INFO { LPWSTR pwszContainerName; LPWSTR pwszProvName; DWORD dwProvType; DWORD dwFlags; DWORD cProvParam; PCRYPT_KEY_PROV_PARAM rgProvParam; DWORD dwKeySpec; } CRYPT_KEY_PROV_INFO, *PCRYPT_KEY_PROV_INFO; Заполните структуру: имя ключевого контейнера, имя и тип провайдера. | ||||