Статус: Новичок
Группы: Участники
Зарегистрирован: 27.02.2008(UTC) Сообщений: 7
|
Возникла проблема с CryptSignMessage. При вызове эта функция показывает окно ввода пина. Но, тк для того, чтобы создать подпись, ее надо вызывать дважды, окно для ввода пина тоже появляется дважды. Чтобы этого избежать, включаю кэширование: замечательно, окно ввода появляется один раз, потом появляться перестает. НО проблема в том, что при следующем подписывании мне нужно, чтобы оно опять появилось. Выключаю кэширование-- никакой реакции. Кэширование выключается только если я закрываю хранилище сертификатов, что мне делать каждый раз при попытке что-то подписать очень не хочется. Если кто-нибудь поведает, как отключить кэширование или еще как-то сделать так, чтобы CryptSignMessage не просила пароль во время второго вызова, буду премного благодарна. Вот код, натыренный из всяких примеров: Код:
HCERTSTORE hStoreHandle;
if ( !( hStoreHandle = CertOpenStore(
CERT_STORE_PROV_SYSTEM,
0,
NULL,
CERT_SYSTEM_STORE_CURRENT_USER,
L"MY")))
{
HandleError("Unable to open MY.");
}
// Получаем указатель на сертификат
PCCERT_CONTEXT pSignerCert;
if(pSignerCert = CertFindCertificateInStore(
hStoreHandle,
MY_TYPE,
0,
CERT_FIND_SUBJECT_STR,
SIGNER_NAME,
NULL))
{
printf("Cert found.\n");
}
else
{
HandleError( "Cert not found.");
}
BYTE *pbSignedMessageBlob;
DWORD cbSignedMessageBlob;
// Создаем и заполняем структуру для создания цифровой подписи
CRYPT_SIGN_MESSAGE_PARA SigParams;
SigParams.cbSize = sizeof(CRYPT_SIGN_MESSAGE_PARA);
SigParams.dwMsgEncodingType = MY_TYPE;
SigParams.pSigningCert = pSignerCert;
SigParams.HashAlgorithm.pszObjId = szOID_RSA_MD5;
SigParams.HashAlgorithm.Parameters.cbData = NULL;
SigParams.cMsgCert = 0;
SigParams.rgpMsgCert = NULL;
SigParams.cAuthAttr = 0;
SigParams.dwInnerContentType = 0;
SigParams.cMsgCrl = 0;
SigParams.cUnauthAttr = 0;
SigParams.dwFlags = 0;
SigParams.pvHashAuxInfo = NULL;
SigParams.rgAuthAttr = NULL;
BYTE* pbMessage = (BYTE*)"ABCdef123";
DWORD cbMessage = (DWORD)strlen((char*) pbMessage)+1;
const BYTE* MessageArray[] = {pbMessage};
DWORD MessageSizeArray[1];
MessageSizeArray[0] = cbMessage;
//Включаем кэширование
DWORD cData;
PCCERT_CONTEXT pCert= SigParams.pSigningCert;
int ret = CertGetCertificateContextProperty(pCert, CERT_KEY_PROV_INFO_PROP_ID, NULL, &cData);
CRYPT_KEY_PROV_INFO* pCryptKeyProvInfo = NULL;
if (ret) {
pCryptKeyProvInfo = (CRYPT_KEY_PROV_INFO *)malloc(cData);
if(!pCryptKeyProvInfo)
HandleError("Error in allocation of memory.");
ret = CertGetCertificateContextProperty(pCert,CERT_KEY_PROV_INFO_PROP_ID, pCryptKeyProvInfo,&cData);
if (ret)
{
/* Установим флаг кеширования провайдера*/
pCryptKeyProvInfo->dwFlags = CERT_SET_KEY_CONTEXT_PROP_ID;
/* Установим свойства в контексте сертификата*/
ret = CertSetCertificateContextProperty(pCert, CERT_KEY_PROV_INFO_PROP_ID,0, pCryptKeyProvInfo);
}
}
// Получаем длину буфера подписи. Тут появляется окно ввода пина
if(CryptSignMessage(
&SigParams, // указатель на SigParams
TRUE, // подпись создается отдельно
1, // число сообщений
MessageArray, // сообщение
MessageSizeArray, // длина сообщения
NULL, // буфер для подписи
&cbSignedMessageBlob)) // размер буфера
{
printf("Signature size %d.\n",cbSignedMessageBlob);
}
else
{
HandleError("Error in CryptSignMessage.");
}
// выделяем память под подпись
if(!(pbSignedMessageBlob = new BYTE[cbSignedMessageBlob]))
{
HandleError("Error in new[].");
}
// формируем подпись. Окна ввода пина нет-- как надо.
if(CryptSignMessage(
&SigParams, // указатель на SigParams
TRUE, // подпись создается отдельно
1, // число сообщений
MessageArray, // сообщение
MessageSizeArray, // длина сообщения
pbSignedMessageBlob, // буфер для подписи
&cbSignedMessageBlob)) // размер буфера
{
printf("Signature: \n");
print_signature(cbSignedMessageBlob, pbSignedMessageBlob);
}
else
{
HandleError("Errror in cryptsignmessage 2");
}
//выключаем кэширование
ret = CertGetCertificateContextProperty(pCert, CERT_KEY_PROV_INFO_PROP_ID, NULL, &cData);
if (ret) {
if(pCryptKeyProvInfo)
free(pCryptKeyProvInfo);
pCryptKeyProvInfo = (CRYPT_KEY_PROV_INFO *)malloc(cData);
if(!pCryptKeyProvInfo)
HandleError("Error in allocation of memory.");
ret = CertGetCertificateContextProperty(pCert,CERT_KEY_PROV_INFO_PROP_ID, pCryptKeyProvInfo,&cData);
if (ret)
{
/* Убираем флаг кеширования провайдера*/
pCryptKeyProvInfo->dwFlags = 0;
/* Установим свойства в контексте сертификата*/
ret = CertSetCertificateContextProperty(pCert, CERT_KEY_PROV_INFO_PROP_ID,0, pCryptKeyProvInfo);
}
}
//Подписываем второй раз. Тут должно появиться окно ввода пина. Ан нет.
if(CryptSignMessage(
&SigParams, // указатель на SigParams
TRUE, // подпись создается отдельно
1, // число сообщений
MessageArray, // сообщение
MessageSizeArray, // длина сообщения
NULL, // буфер для подписи
&cbSignedMessageBlob)) // размер буфера
{
printf("Signature size %d.\n",cbSignedMessageBlob);
}
else
{
HandleError("Error in CryptSignMessage.");
}
if(pbSignedMessageBlob)
delete[] pbSignedMessageBlob;
if(!(pbSignedMessageBlob = new BYTE[cbSignedMessageBlob]))
{
HandleError("Error in new[].");
}
// формируем подпись
if(CryptSignMessage(
&SigParams, // указатель на SigParams
TRUE, // подпись создается отдельно
1, // число сообщений
MessageArray, // сообщение
MessageSizeArray, // длина сообщения
pbSignedMessageBlob, // буфер для подписи
&cbSignedMessageBlob)) // размер буфера
{
printf("Signature: \n");
print_signature(cbSignedMessageBlob, pbSignedMessageBlob);
}
else
{
HandleError("Errror in cryptsignmessage 2");
}
Отредактировано пользователем 21 марта 2008 г. 13:55:45(UTC)
| Причина: Не указана
|