| ||||
| ||||
Добрый день, CryptAcquireContext(&m_hCryptProv, NULL, NULL, 75, 0) ... работает нормально на 2-х машинах с CSP3.0, а на машине с CSP2.0 не находит ключевой носитель (хотя он точно существует) - Keyset does not exist Что посоветуете? | ||||
Ответы: | ||||
| ||||
Вызов CryptAcquireContext с такими параметрами открывает контейнер по умолчанию в системе - его вполне может не существовать. | ||||
| ||||
Добрый день Следующий вопрос напрашивается: где задается контейнер по умолчанию? | ||||
| ||||
Второй параметр CryptAcquireContext может принимает имя контейнера в формате zero-terminate string | ||||
| ||||
Контейнер по умолчанию - это контейнер по умолчанию считывателя по умолчанию :) Для смарт-карт задается особым образом, для остальных считок - логин пользователя. Может Вам нужен CRYPT_VERIFYCONTEXT? | ||||
| ||||
Уважаемые господа, Грешно смеяться над несчастными людьми, которым по долгу службы приходится иметь дело с криптографией. Поэтому прошу еще раз и толком объяснить: 1. почему этот вызов нормально работает с CSP 3.0 и не работает с CSP 2.0? 2. каким образом его следует переписать, чтобы он работал и в CSP 3.0 и в CSP 2.0? Заранее благодарю | ||||
| ||||
А что дальше с контекстом провайдера делать собираетесь? | ||||
| ||||
Ну, во-первых, подписываться: CMSG_SIGNER_ENCODE_INFO signerInfo; memset(&signerInfo, 0, sizeof(CMSG_SIGNER_ENCODE_INFO)); signerInfo.cbSize = sizeof(CMSG_SIGNER_ENCODE_INFO); signerInfo.pCertInfo = pCert->pCertInfo; signerInfo.hCryptProv = m_hCryptProv; signerInfo.cAuthAttr = 1; signerInfo.cUnauthAttr = 0; signerInfo.dwKeySpec = keySpec; signerInfo.HashAlgorithm = HashAlgorithm; signerInfo.pvHashAuxInfo = NULL; signerInfo.rgAuthAttr = attributes; signerInfo.rgUnauthAttr = NULL; Во-вторых, проверять подпись: if ((hMsg = CryptMsgOpenToDecode(TYPE_DER, CMSG_DETACHED_FLAG, 0, m_hCryptProv, NULL, NULL)) == NULL) { THROW_ERR(_T("Ошибка чтения сообщения"), GetLastError()); } В-третьих, шифровать: CRYPT_ENCRYPT_MESSAGE_PARA EncryptParams; memset(&EncryptParams, 0, sizeof(EncryptParams)); EncryptParams.cbSize = sizeof(EncryptParams); EncryptParams.dwMsgEncodingType = TYPE_DER; EncryptParams.hCryptProv = m_hCryptProv; EncryptParams.ContentEncryptionAlgorithm = EncryptAlgorithm; Вот, собственно, и все! | ||||
| ||||
В Вашей ситуации для подписи логично использовать функцию CryptAcquireCertificatePrivateKey. Или получить имя провайдера/контейнера из сертификата и создавать контекст провайдера с этими параметрами. (Ваш код в первом посте открывает контекст для дефолтного контейнера, которого просто может не существовать) Для шифрования провайдер можно не указывать. Для проверки подписи тоже. | ||||
| ||||
Мерси за совет. На CSP 3.0 по-прежнему работает. А на CSP 2.0 дает уже другую ошибку (при попытке подписать): CRYPT_SIGN_MESSAGE_PARA param; memset(¶m, 0, sizeof(CRYPT_SIGN_MESSAGE_PARA)); param.cbSize = sizeof(CRYPT_SIGN_MESSAGE_PARA); param.dwMsgEncodingType = TYPE_DER; param.pSigningCert = pCert; param.HashAlgorithm.pszObjId = szOID_CP_GOST_28147; param.HashAlgorithm.Parameters.cbData = 0; param.HashAlgorithm.Parameters.pbData = NULL; param.pvHashAuxInfo = NULL; param.cMsgCert = 0; param.rgpMsgCert = NULL; param.cAuthAttr = 1; param.rgAuthAttr = attributes; param.dwInnerContentType = 0; param.cMsgCrl = 0; param.cUnauthAttr = 0; DWORD dwMsgLen; const BYTE *messages[] = { (PBYTE)pData->data }; DWORD messlens[] = { pData->cbSize }; if(!CryptSignMessage(¶m, detached, 1, messages, messlens, NULL, &dwMsgLen)) { FREE(bTime.pbData); CertFreeCertificateContext(pCert); THROW_GLE(); } И ошибка выглядит так: Unknowm cryptographic algorithm Куда рыть дальше? С уважением, | ||||
| ||||
param.HashAlgorithm.pszObjId = szOID_CP_GOST_28147; - это не алгоритм хэширования | ||||
| ||||
Уп-п-с! Это я лажанулся. Вы правы, с правильным алгоритмом все подписывается :-) | ||||