1) Добрый день
В программе пользуюсь функциями которые указаны в примерах для вашего csp
Шифруется-подписывается-расшифровывается-проверяется все нормально, когда посылаю с помощью этих функций сообщения оутлуку, то тоже все хорошо, оутлук все понимает. Но когда просто пытаюсь с помощью cryptcp расшифровать что-то из файла, то проблемы:
C:\TEMP\distr\cryptcp>cryptcp -decr -f ayush.cer bs bsout -nochain
CryptCP 3.33 (c) "Крипто-Про", 2002-2010.
Утилита командной строки для защиты данных.
-decr - Расшифровать данные из сообщения.
Будет использован следующий сертификат:
Субъект:ayushchenko@rapida.ru, ayushchenko, iss, rapida, Moscow, RU, RU
Действителен с 18.01.2011 15:37:14 по 04.10.2014 07:09:41
Расшифрование данных... 0%Ошибка: Некорректное преобразование BASE64. (0x20000067)
[ErrorCode: 0x20000067]
C:\TEMP\distr\cryptcp>cryptcp -decr -f ayush.cer bin bsout -nochain
CryptCP 3.33 (c) "Крипто-Про", 2002-2010.
Утилита командной строки для защиты данных.
-decr - Расшифровать данные из сообщения.
Будет использован следующий сертификат:
Субъект:ayushchenko@rapida.ru, ayushchenko, iss, rapida, Moscow, RU, RU
Действителен с 18.01.2011 15:37:14 по 04.10.2014 07:09:41
Расшифрование данных...
Ошибка: Встречено неверное значение тега ASN1.
(0x8009310B)
[ErrorCode: 0x8009310b]
В чем может быть проблема?
Сами функции прилагаю
void MSCrypt::DecryptMessage(std::string &sEncryptedBlobStr,
char *CertMail,
std::string CertSN,
char *psStoreName,
std::string& sDecryptedMessage)
{
static HCRYPTPROV hCryptProv = 0; // дескриптор CSP
static HCERTSTORE hStoreHandle = 0; // дескриптор хранилища сертификатов
static PCCERT_CONTEXT pRecipientCert = NULL;
static char *szDName = NULL; // DName сертификата
std::string str = aria2::Base64::decode(sEncryptedBlobStr);
DWORD cbEncryptedBlob = str.size();
byte *pbEncryptedBlob = (byte*)malloc(cbEncryptedBlob);
pbEncryptedBlob = (byte*)str.c_str();
//memcpy((byte*)str.c_str(), pbEncryptedBlob, cbEncryptedBlob);
DWORD cbDecryptedMessage;
//wchar_t * EncryptedString = NULL;
CRYPT_DECRYPT_MESSAGE_PARA decryptParams;
BYTE* pbDecryptedMessage = NULL;
if(!CryptAcquireContext(
&hCryptProv, // Адрес возврашаемого дескриптора.
0, // Используется имя текущего зарегестрированного пользователя.
NULL, // Используется провайдер по умолчанию.
PROV_GOST_2001_DH, // Необходимо для зашифрования и подписи.
CRYPT_VERIFYCONTEXT)) // Никакие флаги не нужны.
{
HandleError("Cryptographic context could not be acquired.");
}
printf("CSP has been acquired. \n");
// Открытие системного хранилища сертификатов.
hStoreHandle = CertOpenSystemStore(hCryptProv, psStoreName);
if(!hStoreHandle)
{
HandleError( "Error getting store handle.");
}
printf("The MY store is open. \n");
// Получение указателя на сертификат получателя с помощью
// функции GetRecipientCert.
pRecipientCert = GetRecipientCert(hStoreHandle, CertMail, CertSN.c_str());
if(!pRecipientCert)
{
printf("No certificate with a CERT_KEY_CONTEXT_PROP_ID \n");
printf("property and an AT_KEYEXCHANGE private key available. \n");
printf("While the message could be encrypted, in this case, \n");
printf("it could not be decrypted in this program. \n");
printf("For more information, see the documentation for \n");
printf("CrypteEncryptMessage and CryptDecryptMessage.\n\n");
HandleError( "No Certificate with AT_KEYEXCHANGE key in store.");
}
GetCertDName(&pRecipientCert->pCertInfo->Subject, &szDName);
printf("A recipient's certificate has been acquired: %s\n", szDName);
// Получение указателя на зашифрованное сообщение, pbEncryptedBlob,
// и его длину, cbEncryptedBlob. В этом примере они устанавливаются
// как параметры совместно с CSP и дескриптором открытого хранилища.
// Просмотр зашифрованного BLOBа.
char * ep = getenv("COLUMNS");
int brk;
DWORD i;
brk = ep ? atoi(ep) : 80;
brk = ((brk <= 3) ? 80 : brk) / 3;
//printf("The encrypted string is: \n");
//for(i = 0; i < cbEncryptedBlob; i++)
// printf("%02x%c",pbEncryptedBlob[i],(i%brk == (brk - 1))?'\n':' ');
//printf("\n");
// В этом примере дескриптор хранилище MY установлен как параметр.
// Инициализация структуры CRYPT_DECRYPT_MESSAGE_PARA.
memset(&decryptParams, 0, sizeof(CRYPT_DECRYPT_MESSAGE_PARA));
decryptParams.cbSize = sizeof(CRYPT_DECRYPT_MESSAGE_PARA);
decryptParams.dwMsgAndCertEncodingType = TYPE_DER;
decryptParams.cCertStore = 1;
decryptParams.rghCertStore = &hStoreHandle;
// Расшифрование сообщения
// Вызов фнукции CryptDecryptMessage для получения возвращаемого размера данных.
if(!CryptDecryptMessage(
&decryptParams,
pbEncryptedBlob,
cbEncryptedBlob,
NULL,
&cbDecryptedMessage,
NULL))
{
free(pbEncryptedBlob);
HandleError( "Error getting decrypted message size");
}
printf("The size for the decrypted message is: %d.\n", cbDecryptedMessage);
// Выделение памяти под возвращаемые расшифрованные данные.
pbDecryptedMessage = (BYTE*)malloc(cbDecryptedMessage);
if(!pbDecryptedMessage)
{
free(pbEncryptedBlob);
HandleError("Memory allocation error while decrypting");
}
// Вызов функции CryptDecryptMessage для расшифрования данных.
if(!CryptDecryptMessage(
&decryptParams,
pbEncryptedBlob,
cbEncryptedBlob,
pbDecryptedMessage,
&cbDecryptedMessage,
NULL))
{
free(pbEncryptedBlob);
free(pbDecryptedMessage);
HandleError("Error decrypting the message");
}
printf("Message Decrypted Successfully. \n");
// printf("The decrypted string is: %s\n", (LPSTR) pbDecryptedMessage);
//sDecryptedMessage = "dsfsdfsadf";
sDecryptedMessage.clear();
sDecryptedMessage.append((char*)pbDecryptedMessage, cbDecryptedMessage);
/*if(pbEncryptedBlob)
free(pbEncryptedBlob);
if(pbDecryptedMessage)
free(pbDecryptedMessage); */
return;
}
void MSCrypt::CryptMessage(std::string& sCont,
char* CertMail,
std::string CertSN,
char* psStoreName,
std::string& sEncryptedStr
)
{
static HCRYPTPROV hCryptProv = 0; // дескриптор CSP
static HCERTSTORE hStoreHandle = 0; // дескриптор хранилища сертификатов
static PCCERT_CONTEXT pRecipientCert = NULL;
static char *szDName = NULL; // DName сертификата
BYTE* pbContent = (BYTE*)sCont.c_str(); // Сообщение
DWORD cbContent = (DWORD)(sCont.size()); // Длина сообщения
CRYPT_ALGORITHM_IDENTIFIER EncryptAlgorithm;
CRYPT_ENCRYPT_MESSAGE_PARA EncryptParams;
BYTE* pbEncryptedBlob = NULL;
DWORD cbEncryptedBlob;
printf("source message: %s\n", pbContent);
printf("message length: %d bytes \n", cbContent);
// Получение дескриптора криптографического провайдера.
if(!CryptAcquireContext(
&hCryptProv, // Адрес возврашаемого дескриптора.
0, // Используется имя текущего зарегестрированного пользователя.
NULL, // Используется провайдер по умолчанию.
PROV_GOST_2001_DH, // Необходимо для зашифрования и подписи.
CRYPT_VERIFYCONTEXT)) // Никакие флаги не нужны.
{
HandleError("Cryptographic context could not be acquired.");
}
printf("CSP has been acquired. \n");
// Открытие системного хранилища сертификатов.
hStoreHandle = CertOpenSystemStore(hCryptProv, psStoreName);
if(!hStoreHandle)
{
HandleError( "Error getting store handle.");
}
printf("The MY store is open. \n");
// Получение указателя на сертификат получателя с помощью
// функции GetRecipientCert.
pRecipientCert = GetRecipientCert(hStoreHandle, CertMail, CertSN.c_str());
if(!pRecipientCert)
{
printf("No certificate with a CERT_KEY_CONTEXT_PROP_ID \n");
printf("property and an AT_KEYEXCHANGE private key available. \n");
printf("While the message could be encrypted, in this case, \n");
printf("it could not be decrypted in this program. \n");
printf("For more information, see the documentation for \n");
printf("CrypteEncryptMessage and CryptDecryptMessage.\n\n");
HandleError( "No Certificate with AT_KEYEXCHANGE key in store.");
}
GetCertDName(&pRecipientCert->pCertInfo->Subject, &szDName);
printf("A recipient's certificate has been acquired: %s\n", szDName);
// Инициализация структуры с нулем.
memset(&EncryptAlgorithm, 0, sizeof(CRYPT_ALGORITHM_IDENTIFIER));
//EncryptAlgorithm.pszObjId = OID_CipherVar_Default;
EncryptAlgorithm.pszObjId = szOID_CP_GOST_28147;
// Инициализация структуры CRYPT_ENCRYPT_MESSAGE_PARA.
memset(&EncryptParams, 0, sizeof(CRYPT_ENCRYPT_MESSAGE_PARA));
EncryptParams.cbSize = sizeof(CRYPT_ENCRYPT_MESSAGE_PARA);
EncryptParams.dwMsgEncodingType = TYPE_DER;
EncryptParams.hCryptProv = hCryptProv;
EncryptParams.ContentEncryptionAlgorithm = EncryptAlgorithm;
// Вызов функции CryptEncryptMessage.
if(!CryptEncryptMessage(
&EncryptParams,
1,
&pRecipientCert,
pbContent,
cbContent,
NULL,
&cbEncryptedBlob))
{
HandleError( "Getting EncrypBlob size failed.");
}
printf("The encrypted message is %d bytes. \n", cbEncryptedBlob);
// Распределение памяти под возвращаемый BLOB.
pbEncryptedBlob = (BYTE*)malloc(cbEncryptedBlob);
if(!pbEncryptedBlob)
HandleError("Memory allocation error while encrypting.");
// Повторный вызов функции CryptEncryptMessage для зашифрования содержимого.
if(!CryptEncryptMessage(
&EncryptParams,
1,
&pRecipientCert,
pbContent,
cbContent,
pbEncryptedBlob,
&cbEncryptedBlob))
{
HandleError("Encryption failed.");
}
/*char * ep = getenv("COLUMNS");
int brk;
brk = ep ? atoi(ep) : 80;
brk = ((brk <= 3) ? 80 : brk) / 3;*/
//printf("The encrypted string is: \n");
//for(i = 0; i < cbEncryptedBlob; i++)
// printf("%02x%c",pbEncryptedBlob[i],(i%brk == (brk - 1))?'\n':' ');
//printf("\n");
sEncryptedStr.append((char*)pbEncryptedBlob, cbEncryptedBlob);
sEncryptedStr = aria2::Base64::encode(sEncryptedStr);
if(sEncryptedStr.length() != cbEncryptedBlob)
printf("V Encode!!");
printf( "Encryption succeeded. \n");
}
void MSCrypt::SignMessage(std::string &psCont, char *CertMail, std::string CertSN, char *psStoreName, std::string &pbEncodedBlobBase64)
{
Log log("C:\\Server log.txt");
byte *pbEncodedBlob = NULL;
HCRYPTPROV hCryptProv = 0; /* Дескриптор провайдера*/
HCERTSTORE hStoreHandle=0; //Дeскриптор сторе
PCCERT_CONTEXT pRecipientCert = NULL; /* Сертификат, используемый для формирования ЭЦП*/
PCCERT_CONTEXT pRecipientCertArray[1];
DWORD keytype = AT_KEYEXCHANGE; /* Тип ключа (возвращается)*/
HCRYPTMSG hMsg = 0; /* Дескриптор сообщения*/
CRYPT_ALGORITHM_IDENTIFIER HashAlgorithm; /* Идентификатор алгоритма хэширования*/
DWORD HashAlgSize;
CMSG_SIGNER_ENCODE_INFO SignerEncodeInfo; /* Структура, описывающая отправителя*/
CMSG_SIGNER_ENCODE_INFO SignerEncodeInfoArray[1]; /* Массив структур, описывающих отправителя*/
CERT_BLOB SignerCertBlob;
CERT_BLOB SignerCertBlobArray[1];
CMSG_SIGNED_ENCODE_INFO SignedMsgEncodeInfo; /* Структура, описывающая подписанное сообщение*/
BOOL bReleaseContext;
DWORD flags = 0;
DWORD cbContent = (DWORD)(psCont.size());//длина сообщения
DWORD cbEncodedBlob;
byte *pbContent = (byte*)psCont.c_str();
//--------------------------------------------------------------------
// Начало обработки данных.
//printf("About to begin with the message %s.\n",pbContent);
//printf("The message length is %d bytes. \n", cbContent);
//--------------------------------------------------------------------
// Открытие системного хранилища сертификатов.
//hStoreHandle = CertOpenSystemStore( 0, (LPCSTR)psStoreName);
hStoreHandle = CertOpenSystemStore( 0, "My");
if(hStoreHandle)
{
log.WriteLog("The MY store is open. \n");
}
else
{
HandleError( "Error getting store handle.");
}
//--------------------------------------------------функции GetRecipientCert.
log.WriteLog(CertMail);
log.WriteLog(CertSN);
pRecipientCert = GetRecipientCert(
hStoreHandle, CertMail, CertSN);
if(pRecipientCert)
{
log.WriteLog("A recipient's certificate has been acquired. \n");
}
else
{
log.WriteLog("No certificate with a CERT_KEY_CONTEXT_PROP_ID \n");
printf("property and an AT_KEYEXCHANGE private key available. \n");
printf("While the message could be sign, in this case, \n");
printf("it could not be veryfy in this program. \n");
printf("For more information, see the documentation \n");
HandleError( "No Certificate with AT_KEYEXCHANGE key in store.");
}
//--------------------------------------------------------------------
// Получение закрытого ключа
if (!CryptAcquireCertificatePrivateKey(pRecipientCert,
0,
NULL,
&hCryptProv,
&keytype,
&bReleaseContext))
{
HandleError( "Cannot acquire the certificate private key");
}
//--------------------------------------------------------------------
// Создание RecipientCertArray.
pRecipientCertArray[0] = pRecipientCert;
//--------------------------------------------------------------------
// Инициализация структуры идентификатора алгоритма.
HashAlgSize = sizeof(HashAlgorithm);
//--------------------------------------------------------------------
// Инициализация структуры с нулем.
memset(&HashAlgorithm, 0, HashAlgSize);
//--------------------------------------------------------------------
// Установка необходимого элемента.
//HashAlgorithm.pszObjId = szOID_CP_GOST_R3411;
printf(":%s; :%d; :%s; :%d;",pRecipientCert->pCertInfo->SignatureAlgorithm.pszObjId, pRecipientCert->pCertInfo->SignatureAlgorithm.pszObjId, szOID_CP_GOST_R3411_R3410EL,szOID_CP_GOST_R3411_R3410EL);
HashAlgorithm.pszObjId = pRecipientCert->pCertInfo->SignatureAlgorithm.pszObjId;
//HashAlgorithm.pszObjId = szOID_CP_GOST_R3411;
//szOID_RSA_SHA1RSA;
/*--------------------------------------------------------------------*/
/* Инициализируем структуру CMSG_SIGNER_ENCODE_INFO*/
memset(&SignerEncodeInfo, 0, sizeof(CMSG_SIGNER_ENCODE_INFO));
SignerEncodeInfo.cbSize = sizeof(CMSG_SIGNER_ENCODE_INFO);
SignerEncodeInfo.pCertInfo = pRecipientCert->pCertInfo;
SignerEncodeInfo.hCryptProv = hCryptProv;
SignerEncodeInfo.dwKeySpec = keytype;
// SignerEncodeInfo.dwKeySpec = AT_KEYEXCHANGE;
SignerEncodeInfo.HashAlgorithm = HashAlgorithm;
SignerEncodeInfo.pvHashAuxInfo = NULL;
/*--------------------------------------------------------------------*/
/* Создадим массив отправителей. Сейчас только из одного.*/
SignerEncodeInfoArray[0] = SignerEncodeInfo;
/*--------------------------------------------------------------------*/
/* Инициализируем структуру CMSG_SIGNED_ENCODE_INFO*/
SignerCertBlob.cbData = pRecipientCert->cbCertEncoded;
SignerCertBlob.pbData = pRecipientCert->pbCertEncoded;
/*--------------------------------------------------------------------*/
/* Инициализируем структуру массив структур CertBlob.*/
SignerCertBlobArray[0] = SignerCertBlob;
memset(&SignedMsgEncodeInfo, 0, sizeof(CMSG_SIGNED_ENCODE_INFO));
SignedMsgEncodeInfo.cbSize = sizeof(CMSG_SIGNED_ENCODE_INFO);
SignedMsgEncodeInfo.cSigners = 1;
SignedMsgEncodeInfo.rgSigners = SignerEncodeInfoArray;
SignedMsgEncodeInfo.cCertEncoded = 0;
SignedMsgEncodeInfo.rgCertEncoded = NULL;
SignedMsgEncodeInfo.rgCrlEncoded = NULL;
/*--------------------------------------------------------------------*/
/* Определим длину подписанного сообщения*/
cbEncodedBlob = CryptMsgCalculateEncodedLength(
TYPE_DER, /* Message encoding type*/
flags, /* Flags*/
CMSG_SIGNED, /* Message type*/
&SignedMsgEncodeInfo, /* Pointer to structure*/
NULL, /* Inner content object ID*/
(DWORD)cbContent); /* Size of content*/
if(cbEncodedBlob)
{
printf("The length of the data has been calculated. \n");
} else
{
HashAlgorithm.pszObjId = szOID_RSA_SHA1RSA;
SignerEncodeInfo.HashAlgorithm = HashAlgorithm;
SignerEncodeInfoArray[0] = SignerEncodeInfo;
SignedMsgEncodeInfo.rgSigners = SignerEncodeInfoArray;
cbEncodedBlob = CryptMsgCalculateEncodedLength(
TYPE_DER, /* Message encoding type*/
flags, /* Flags*/
CMSG_SIGNED, /* Message type*/
&SignedMsgEncodeInfo, /* Pointer to structure*/
NULL, /* Inner content object ID*/
(DWORD)cbContent); /* Size of content*/
if(cbEncodedBlob)
{
printf("The length of the data has been calculated. \n");
} else
HandleError("Getting cbEncodedBlob length failed.");
}
/*--------------------------------------------------------------------*/
/* Резервируем память, требуемой длины*/
pbEncodedBlob = (BYTE *) malloc(cbEncodedBlob);
if (!pbEncodedBlob)
HandleError("Memory allocation failed");
/*--------------------------------------------------------------------*/
/* Создадим дескриптор сообщения*/
hMsg = CryptMsgOpenToEncode(
TYPE_DER, /* Encoding type*/
flags, /* Flags (CMSG_DETACHED_FLAG )*/
CMSG_SIGNED, /* Message type*/
&SignedMsgEncodeInfo, /* Pointer to structure*/
NULL, /* Inner content object ID*/
NULL); /* Stream information (not used)*/
if(hMsg) {
printf("The message to be encoded has been opened. \n");
} else {
HandleError("OpenToEncode failed");
}
/*--------------------------------------------------------------------*/
/* Поместим в сообщение подписываемые данные*/
if(CryptMsgUpdate(
hMsg, /* Handle to the message*/
pbContent, /* Pointer to the content*/
cbContent, /* Size of the content*/
TRUE)) { /* Last call*/
printf("Content has been added to the encoded message. \n");
} else {
HandleError("MsgUpdate failed");
}
/*--------------------------------------------------------------------*/
/* Вернем подписанное сообщение*/
if(CryptMsgGetParam(
hMsg, /* Handle to the message*/
CMSG_CONTENT_PARAM, /* Parameter type*/
0, /* Index*/
pbEncodedBlob, /* Pointer to the blob*/
&cbEncodedBlob)) { /* Size of the blob*/
printf("Message encoded successfully. \n");
} else {
HandleError("MsgGetParam failed");
}
//освобождение памяти
if(hMsg)
CryptMsgClose(hMsg);
if(hCryptProv && bReleaseContext)
CryptReleaseContext(hCryptProv,0);
pbEncodedBlobBase64.append((char*)pbEncodedBlob, cbEncodedBlob);
pbEncodedBlobBase64 = aria2::Base64::encode(pbEncodedBlobBase64);
//printf("pbEncodedBlob in bas64 is %s \n", pbEncodedBlobBase64.data());
//printf("cbEncodedBlob 1= %d \n", cbEncodedBlob);
}//end of SignMessage
void MSCrypt::VerifyMessage(std::string &pbEncodedBlobBase64, char *CertMail, std::string CertSN, char *psStoreName)
{
HCRYPTPROV hCryptProv = 0; /* Дескриптор провайдера*/
PCCERT_CONTEXT pRecipientCert = NULL; /* Сертификат, используемый для проверки ЭЦП*/
DWORD keytype = 0; /* Возвращаемый тип ключа*/
BOOL should_release_ctx = FALSE;
BYTE *mem_signature = NULL;
size_t signature_len = 0;
HCRYPTMSG hMsg = 0; /* Дескриптор сообщения*/
DWORD cbDecoded;
BYTE *pbDecoded = NULL;
DWORD cbSignerCertInfo = 0;
PCERT_INFO pSignerCertInfo = NULL;
PCCERT_CONTEXT pSignerCertContext = NULL;
PCERT_INFO pSignerCertificateInfo = NULL;
HCERTSTORE hStoreHandle = NULL;
DWORD flags=0;
//char* str = (char*) pbEncodedBlob;
DWORD cbEncodedBlob = 0;
std::string str = aria2::Base64::decode(pbEncodedBlobBase64);
cbEncodedBlob = str.length();
byte *pbEncodedBlob = (byte*)malloc(cbEncodedBlob);
memcpy(pbEncodedBlob, (byte *)str.c_str(), str.length());
//printf("cbEncodedBlob 2= %d\n", cbEncodedBlob);
BYTE *mem_tbs = pbEncodedBlob;
//DWORD cbEncodedBlob = (DWORD)(strlen(pbEncodedBlob)+1);
//printf("cbEncodedBlob = %d\n", cbEncodedBlob);
BOOL bResult;
size_t mem_len = cbEncodedBlob;
if(CryptAcquireContext(
&hCryptProv, // Адрес возврашаемого дескриптора.
NULL,// Используется контейнер Test
NULL, // Используется провайдер по умолчанию.
75, // Необходимо для зашифрования и подписи.
CRYPT_VERIFYCONTEXT)) // Никакие флаги не нужны.
{
printf("A CSP has been acquired. \n");
}
else
{
HandleError("Cryptographic context could not be acquired.");
}
//--------------------------------------------------------------------
// Открытие системного хранилища сертификатов.
hStoreHandle = CertOpenSystemStore( 0, (LPCSTR)psStoreName);
if(hStoreHandle)
{
printf("The MY store is open. \n");
}
else
{
HandleError( "Error getting store handle.");
}
//--------------------------------------------------------------------
// Получение указателя на сертификат издателя с помощью
// функции GetRecipientCert.
pRecipientCert = GetRecipientCert(
hStoreHandle, CertMail, CertSN);
if(pRecipientCert)
{
printf("A recipient's certificate has been acquired. \n");
}
else
{
printf("No certificate with a CERT_KEY_CONTEXT_PROP_ID \n");
printf("property and an AT_KEYEXCHANGE private key available. \n");
printf("While the message could be sign, in this case, \n");
printf("it could not be veryfy in this program. \n");
printf("For more information, see the documentation \n");
HandleError( "No Certificate with AT_KEYEXCHANGE key in store.");
}
/*--------------------------------------------------------------------*/
/* Откроем сообщение для декодирования*/
hMsg = CryptMsgOpenToDecode(
TYPE_DER, /* Encoding type.*/
flags, /* Flags.*/
0, /* Use the default message type.*/
hCryptProv, /* Cryptographic provider.*/
NULL, /* Recipient information.*/
NULL); /* Stream information.*/
if (hMsg)
printf("The message to decode is open. \n");
else {
HandleError("OpenToDecode failed");
}
/*--------------------------------------------------------------------*/
/* Поместим в сообщение проверяемые данные*/
bResult = CryptMsgUpdate(
hMsg, /* Handle to the message*/
mem_tbs, /* Pointer to the encoded blob*/
(DWORD)mem_len, /* Size of the encoded blob*/
TRUE); /* Last call*/
if (bResult)
printf("The encoded blob has been added to the message. \n");
else {
HandleError("Decode MsgUpdate failed");
}
/*--------------------------------------------------------------------*/
/* Определим длину подписанных данных*/
bResult = CryptMsgGetParam(
hMsg, /* Handle to the message*/
CMSG_CONTENT_PARAM, /* Parameter type*/
0, /* Signed Index*/
NULL, /* Address for returned info*/
&cbDecoded); /* Size of the returned info*/
if (bResult)
printf("The message parameter (CMSG_CONTENT_PARAM) has been acquired. Message size: %u\n", cbDecoded);
else {
HandleError("Decode CMSG_CONTENT_PARAM failed");
}
/*--------------------------------------------------------------------*/
/* Резервируем память*/
pbDecoded = (BYTE *) malloc(cbDecoded);
if (!pbDecoded)
HandleError("Decode memory allocation failed");
/*--------------------------------------------------------------------*/
/* Вернем подписанные данные*/
bResult = CryptMsgGetParam(
hMsg, /* Handle to the message*/
CMSG_CONTENT_PARAM, /* Parameter type*/
0, /* Signer Index*/
pbDecoded, /* Address for returned info*/
&cbDecoded); /* Size of the returned info*/
if (bResult)
printf("The message param (CMSG_CONTENT_PARAM) returned. Length is %lu.\n", (unsigned long)cbDecoded);
else
{
HandleError("Decode CMSG_CONTENT_PARAM #2 failed");
}
for(int i = 0; i < cbDecoded; i++)
printf("%d - %c\n", i, pbDecoded[i]);
/*--------------------------------------------------------------------*/
/* Проверка ЭЦП*/
/* Сначала определим информация CERT_INFO об отправителе.*/
/*--------------------------------------------------------------------*/
/* Если сертификат задан */
/* создадим справочник в памяти с этим сертификатом.*/
/* Это сделано только для того, чтобы затем вернуть сертификат функцией */
/* CertGetSubjectCertificateFromStore, которая также используется, если*/
/* сертификат отправителя находится в самом сообщении.*/
if (pRecipientCert) {
hStoreHandle = CertOpenStore(CERT_STORE_PROV_MEMORY, TYPE_DER, 0, CERT_STORE_CREATE_NEW_FLAG,NULL);
if (!hStoreHandle)
HandleError("Cannot create temporary store in memory.");
/* Добавим сертификат в справочник*/
if (pRecipientCert) {
bResult = CertAddCertificateContextToStore(hStoreHandle, pRecipientCert, CERT_STORE_ADD_ALWAYS, NULL);
pSignerCertInfo = pRecipientCert->pCertInfo;
} else
bResult = 0;
if (!bResult) {
HandleError("Cannot add user certificate to store.");
}
}
/*--------------------------------------------------------------------*/
/* Найдем сертификат отправителя в справочнике*/
pSignerCertContext = CertGetSubjectCertificateFromStore(
hStoreHandle, /* Handle to store*/
TYPE_DER, /* Encoding type*/
pSignerCertInfo);
if(pSignerCertContext) { /* Pointer to retrieved CERT_CONTEXT*/
printf("A signer certificate has been retrieved.");
} else {
HandleError("Verify GetSubjectCert failed");
}
/*--------------------------------------------------------------------*/
/* Используя структуру CERT_INFO проверяем ЭЦП сообщения*/
pSignerCertificateInfo = pSignerCertContext->pCertInfo;
bResult = CryptMsgControl(
hMsg, /* Handle to the message*/
0, /* Flags*/
CMSG_CTRL_VERIFY_SIGNATURE, /* Control type*/
pSignerCertificateInfo); /* Pointer to the CERT_INFO*/
if(bResult) {
printf("\nSignature was VERIFIED.\n");
} else {
printf("\nThe signature was NOT VERIFIED.\n");
}
//освобождение памяти
CertFreeCertificateContext(pRecipientCert);
if(CertCloseStore(
hStoreHandle,
CERT_CLOSE_STORE_CHECK_FLAG))
{
printf("The MY store was closed without incident. \n");
}
else
{
printf("Store closed after encryption but \n not all certificates or CRLs were freed. \n");
}
if(hMsg)
CryptMsgClose(hMsg);
if(hCryptProv)
CryptReleaseContext(hCryptProv,0);
}//end of VerifyMessage
// В этом примере используется функция HandleError, функция обработки
// простых ошибок, для печати сообщения об ошибке в стандартный файл
// ошибок (stderr) и выхода из программы.
// В большинстве приложений эта функция заменяется другой функцией,
// которая выводит более полное сообщение об ошибке.