29.10.2007 10:58:17CryptAcquireContext + 75 + CSP2.0 + CSP3.0 Ответов: 11
Владислав Бабин
Добрый день,

CryptAcquireContext(&m_hCryptProv, NULL, NULL, 75, 0)
...

работает нормально на 2-х машинах с CSP3.0, а на машине с CSP2.0 не находит ключевой носитель (хотя он точно существует) - Keyset does not exist
Что посоветуете?
 
Ответы:
29.10.2007 11:02:50maxdm
Вызов CryptAcquireContext с такими параметрами открывает контейнер по умолчанию в системе - его вполне может не существовать.
29.10.2007 12:13:24Владислав Бабин
Добрый день

Следующий вопрос напрашивается: где задается контейнер по умолчанию?
29.10.2007 12:50:08Альт
Второй параметр CryptAcquireContext может принимает имя контейнера в формате zero-terminate string
29.10.2007 13:21:53maxdm
Контейнер по умолчанию - это контейнер по умолчанию считывателя по умолчанию :) Для смарт-карт задается особым образом, для остальных считок - логин пользователя.
Может Вам нужен CRYPT_VERIFYCONTEXT?
29.10.2007 18:38:48Владислав Бабин
Уважаемые господа,
Грешно смеяться над несчастными людьми, которым по долгу службы приходится иметь дело с криптографией. Поэтому прошу еще раз и толком объяснить:
1. почему этот вызов нормально работает с CSP 3.0 и не работает с CSP 2.0?
2. каким образом его следует переписать, чтобы он работал и в CSP 3.0 и в CSP 2.0?
Заранее благодарю
29.10.2007 20:04:51maxdm
А что дальше с контекстом провайдера делать собираетесь?
29.10.2007 20:52:30Владислав Бабин
Ну, во-первых, подписываться:

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;

Вот, собственно, и все!


29.10.2007 21:57:47maxdm
В Вашей ситуации для подписи логично использовать функцию
CryptAcquireCertificatePrivateKey. Или получить имя провайдера/контейнера из сертификата и создавать контекст провайдера с этими параметрами. (Ваш код в первом посте открывает контекст для дефолтного контейнера, которого просто может не существовать)
Для шифрования провайдер можно не указывать. Для проверки подписи тоже.
30.10.2007 12:59:18Владислав Бабин
Мерси за совет. На CSP 3.0 по-прежнему работает.
А на CSP 2.0 дает уже другую ошибку (при попытке подписать):

CRYPT_SIGN_MESSAGE_PARA param;
memset(&param, 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(&param, detached, 1, messages, messlens, NULL, &dwMsgLen))
{
FREE(bTime.pbData);
CertFreeCertificateContext(pCert);
THROW_GLE();
}

И ошибка выглядит так:

Unknowm cryptographic algorithm

Куда рыть дальше?

С уважением,
30.10.2007 13:31:43maxdm
param.HashAlgorithm.pszObjId = szOID_CP_GOST_28147; - это не алгоритм хэширования
30.10.2007 13:54:39Владислав Бабин
Уп-п-с!
Это я лажанулся. Вы правы, с правильным алгоритмом все подписывается :-)