| ||||
| ||||
Добрый день. Столкнулся со следующей проблемой. CryptDecryptMessage срабатывает только после вызова CryptFindCertificateKeyProvInfo для соответствующего сертификата. Я генерирую ключ (CryptGenKey), создаю для него сертификат (CertCreateSelfSignCertificate), создаю хранилище сетрификатов на памяти (CertOpenStore( CERT_STORE_PROV_MEMORY...), добавляю сертификат в хранилище (CertAddCertificateContextToStore), экспортирую его в файл (PFXExportCertStoreEx). Всё проходит замечательно, создаётся файл с сертификатом. Передаю данный файл другому пользователю. Он шифрует при помощи данного сертификата некоторый текст (CryptEncryptMessage). Тоже всё проходит успешно. Проблемы начинаются, когда я пытаюсь его дешифровать. Я вызываю PFXImportCertStore, т.е. импортирую хранилище с данным сертификатом, (содержащим только открытый ключ) на машину получателя, затем CryptDecryptMessage и получаю CRYPT_E_NO_DECRYPT_CERT в GetLastError, несмотря на то, что ключевая дискета (на которой хранится сгенеренный закрытый ключ) установлена в дисковод. Но. Если между PFXImportCertStore и CryptDecryptMessage вызвать CryptFindCertificateKeyProvInfo для единственного ключа, содержащегося в импортированном хранилище, то выскакивает череда диалоговых окошек, спрашивающих пароли для всех контейнеров, наличиствующих в системе, функция возвращает true (т.е. что ключ есть). И последующий вызов CryptDecryptMessage приводит к повторному запросу пароля к контейнеру, содержащему ключ и успешной дешифрации. Отсюда вопрос - как добиться дешифровки без промежуточного вызова CryptFindCertificateKeyProvInfo? Пример кода: //publicPFX содержит ранее экспортированное хранилище с единственным сертификатом HCERTSTORE hStore=PFXImportCertStore(&publicPFX,0,0); CertStoreArray[certStoresCount]=hStore; certStoresCount++; //Вот этот кусок позволяет успешно декодировать BOOL certFound=FALSE; for (PCCERT_CONTEXT pCertContext = CertFindCertificateInStore(hStore,X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, 0, CERT_FIND_ANY,0,0); pCertContext!=NULL; pCertContext = CertFindCertificateInStore(hStore,X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, 0, CERT_FIND_ANY,0,pCertContext)) { BOOL t=CryptFindCertificateKeyProvInfo(pCertContext,0,0); } //Пытаемся декодировать CRYPT_DECRYPT_MESSAGE_PARA DecryptParams; memset(&DecryptParams, 0, sizeof (DecryptParams)); DecryptParams.cbSize = sizeof (DecryptParams); DecryptParams.dwMsgAndCertEncodingType = X509_ASN_ENCODING|PKCS_7_ASN_ENCODING; DecryptParams.cCertStore = certStoresCount; DecryptParams.rghCertStore = CertStoreArray; DWORD cbDecryptedMessage; //Выясняем размер - эта функция работает всегда успешно CryptDecryptMessage(&DecryptParams, pbEncryptedBlob, cbEncryptedBlob, NULL, &cbDecryptedMessage, NULL)ж BYTE* pbDecryptedMessage = (BYTE*)malloc(cbDecryptedMessage); //Декодируем - а вот это работает только при наличии CryptFindCertificateKeyProvInfo if(!CryptDecryptMessage(&DecryptParams, pbEncryptedBlob, cbEncryptedBlob, pbDecryptedMessage, &cbDecryptedMessage, NULL)) { free(pbEncryptedBlob); switch (GetLastError()) { //Если не вызывали CryptFindCertificateKeyProvInfo - попадаем сюда case CRYPT_E_NO_DECRYPT_CERT: HandleError("Ошибка при декодировании. Указан неверный секретный ключ."); break; default: HandleError("Ошибка при декодировании"); break; } } | ||||
Ответы: | ||||
| ||||
Надо установить в PCCERT_CONTEXT свойство CERT_KEY_CONTEXT_PROP_ID Это обсуждалось в темах "Вопрос про АРМ разбора конфликтов" <http://www.cryptopro.ru/CryptoPro/forum/myforum.asp?q=1258> и "Функция CryptEncodeObject" <https://www.cryptopro.ru:9443/CryptoPro/forum/myforum.asp?q=1277> или поищите по CertSetCertificateContextProperty | ||||
| ||||
Большое спасибо | ||||