Статус: Участник
Группы: Участники
Зарегистрирован: 10.09.2010(UTC) Сообщений: 12 Откуда: Москва
|
Доброго времени суток. У меня возникла проблема с данной функцией. Задача довольно простая: есть ЭЦП (ну пусть на флэшке), есть сертификат. Шифруем сообщение с помощью сертификата (CryptEncryptMessage), отправляем получателю (с этим все хорошо). Получатель пытается расшифровать. И тут начинаются проблемы.. У получателя: вставлена ЭЦП, установлен подписанный сертификат от нее (в "личные"), ОС - Windows 7 x64 При попытке расшифровать (код на С) (компилится mingw (gcc)): Код:
#define ENC_TYPE (PKCS_7_ASN_ENCODING | X509_ASN_ENCODING)
typedef BOOL WINAPI (*CertSetCertificateContextP)
(PCCERT_CONTEXT pCertContext,
DWORD dwPropId,
DWORD dwFlags,
const void *pvData); // Сделано, т.к. почему-то линкер не хочет ее нормально находить.. а так работает (что тоже не понятно.. стоит КриптоПро 3.6 RC1, Win 7 x64 Pro (со всеми обновлениями)
.....
CertSetCertificateContextP CertSetCertificateContextProp;
HINSTANCE hinstLib = LoadLibrary("Crypt32.dll");
CertSetCertificateContextProp = (CertSetCertificateContextP)GetProcAddress(hinstLib, "CertSetCertificateContextProperty");
HCRYPTPROV prov;
HCRYPTKEY Ekey;
HCERTSTORE store;
PCCERT_CONTEXT cert;
CRYPT_DECRYPT_MESSAGE_PARA decryptParams;
CERT_KEY_CONTEXT PrivateKeyInfo;
BYTE* params;
BYTE* data;
DWORD size;
DWORD cType = AT_KEYEXCHANGE;
FILE* in;
if (!CryptAcquireContext(&prov,NULL,NULL,75,CRYPT_VERIFYCONTEXT))
{
HandleError("Unable to Verify Context.",1);
}
if (!CryptGetProvParam(prov,PP_ENUMCONTAINERS,NULL,&size,CRYPT_FIRST))
{
HandleError("Unable to Gep Prov Param Len",1);
}
params = (BYTE*) malloc(size);
if (!CryptGetProvParam(prov,PP_ENUMCONTAINERS,params,&size,CRYPT_FIRST))
{
HandleError("Unable to Gep Prov Param",1);
}
if (!CryptAcquireContext(&prov,(char*)params,NULL,75,0))
{
HandleError("Unable to Acquire Context.",1);
}
if(!CryptGetUserKey(prov,cType,&Ekey))
{
HandleError("Unable to Get User Key.",1);
}
store = CertOpenSystemStore(prov,"My");
if (store == NULL)
{
HandleError("Can not Open Store, error:",1);
}
in = fopen("fname","rb");
data = malloc(sizeof(BYTE)*4096);
len = (DWORD)fread(data, 1, 4096, in); // Файл гарантированно укладывается в 4096 байт
memset(&decryptParams, 0, sizeof(CRYPT_DECRYPT_MESSAGE_PARA));
decryptParams.cbSize = sizeof(CRYPT_DECRYPT_MESSAGE_PARA);
decryptParams.dwMsgAndCertEncodingType = ENC_TYPE;
decryptParams.cCertStore = 1;
decryptParams.rghCertStore = &store;
if(!CryptDecryptMessage(&decryptParams,data,len,NULL,&cbDecryptedMessage,NULL))
{
HandleError( "Error getting decrypted message size",1);
}
pbDecryptedMessage = (BYTE*)malloc(cbDecryptedMessage);
if(!CryptDecryptMessage(&decryptParams,data,len,pbDecryptedMessage,&cbDecryptedMessage,NULL))
{
HandleError("Error decrypting the message",1);
}
При выполнении 2-ого декрипта выпадает с ошибкой. Выясняется, что ошибка CRYPT_E_NO_DECRYPT_CERT (что в My этот сертификат есть - точно). Поискав по форуму, обнаружил, что все должно начать работать, если после openstore поставить следующее: Код:
if (!(cert = CertFindCertificateInStore(store,ENC_TYPE,0,CERT_FIND_ANY,NULL,NULL)))
{
HandleError("Can not Find Certificate in store",1);
} // Что характерно, сертификат он находит. Этот сертификат там один (тоже проверял).
PrivateKeyInfo.hCryptProv = prov;
PrivateKeyInfo.dwKeySpec = AT_KEYEXCHANGE;
PrivateKeyInfo.cbSize = sizeof(PrivateKeyInfo);
if (!CertSetCertificateContextProp(cert, CERT_KEY_CONTEXT_PROP_ID, 0, &PrivateKeyInfo))
{
HandleError("Can not Set Certificate Context Prop",1);
}
Но, после этого на том же самом декрипте я получаю ошибку 0x00000057.. Вот к чему она может быть, и как ее лечить - найти не смог..
|