Статус: Участник
Группы: Участники
Зарегистрирован: 22.10.2018(UTC) Сообщений: 15
|
Спасибо за оперативный ответ. Использую: Distributor ID: Ubuntu Description: Ubuntu 16.04.5 LTS Release: 16.04 Codename: xenial Thread model: posix gcc version 5.4.0 20160609 Криптопро CSP 5.0 Криптопро ЭЦП SDK 2.0 Более подробный код будет выглядеть приблизительно так: Код:
// на моей системе BYTE == unsigned char == uint8_t
std::vector<BYTE> data_ok(10, 25); // это подписывается и проверяется
std::vector<BYTE> data_fail(30, 30); // это НЕ подписывается
// Открываем хранилище сертификатов пользователя
HCERTSTORE hStoreHandle = CertOpenSystemStore(0, _TEXT("MY"));
if (!hStoreHandle)
{
std::cout << "Store handle was not got" << std::endl;
return;
}
// Получаем сертификат для подписания
PCCERT_CONTEXT context = get_recipient_certificaly(hStoreHandle);
// Если сертификат не найден, завершаем работу
if (!context)
{
std::cout << "There is no certificate with a CERT_KEY_CONTEXT_PROP_ID \n"
<< "property and an AT_KEYEXCHANGE private key available. \n"
<< "While the message could be sign, in this case, it could \n"
<< "not be verify in this program. \n"
<< "For more information, read the documentation http://cpdn.cryptopro.ru/" << std::endl;
return;
}
// Задаем параметры для подписи
CRYPT_SIGN_MESSAGE_PARA signPara = { sizeof(signPara) };
signPara.dwMsgEncodingType = X509_ASN_ENCODING | PKCS_7_ASN_ENCODING;
signPara.pSigningCert = context;
signPara.HashAlgorithm.pszObjId = (LPSTR) szOID_CP_GOST_R3411; // Хэш считается по ГОСТ Р 34.11-94
CADES_SIGN_PARA cadesSignPara = { sizeof(cadesSignPara) };
cadesSignPara.dwCadesType = CADES_BES; // Указываем тип усовершенствованной подписи CADES_BES
CADES_SIGN_MESSAGE_PARA para = { sizeof(para) };
para.pSignMessagePara = &signPara;
para.pCadesSignPara = &cadesSignPara;
// Формируем данные для подписания
const unsigned char *pbToBeSigned[] = { &data_ok[0] };
DWORD cbToBeSigned[] = { (DWORD)data_ok.size() };
PCRYPT_DATA_BLOB pSignedMessage = 0;
// Создаем подписанное сообщение
if (!CadesSignMessage(¶,
true, // отсоединенная подпись
1, pbToBeSigned, cbToBeSigned, &pSignedMessage))
{
std::cout << "CadesSignMessage() failed" << std::endl;
}
// Получили подпись:
std::vector<unsigned char> detached_sign(pSignedMessage->cbData);
std::copy(pSignedMessage->pbData, pSignedMessage->pbData + pSignedMessage->cbData, detached_sign.begin());
// ======= проверка =========
CRYPT_VERIFY_MESSAGE_PARA crypt_verify_message_parameters = { sizeof(crypt_verify_message_parameters) };
crypt_verify_message_parameters.dwMsgAndCertEncodingType = X509_ASN_ENCODING | PKCS_7_ASN_ENCODING;
// по примерам эти параметры не заполнены
// но полазив по руководствам их можно заполнить вот так (толку от этого никакого):
//crypt_verify_message_parameters.cbSize = задан в конструкторе
// crypt_verify_message_parameters.hCryptProv = NULL; // т. к. не исп. согласно MSDN
// crypt_verify_message_parameters.pfnGetSignerCertificate = NULL; // так по умолчанию
// crypt_verify_message_parameters.pvGetArg = (void*)context;
CADES_VERIFICATION_PARA cades_verify_parameters = { sizeof(cades_verify_parameters) };
cades_verify_parameters.dwCadesType = CADES_BES;
cades_verify_parameters.hStore = hStoreHandle;
// по примерам эти параметры не заполнены
// но полазив по руководствам их можно заполнить вот так (толку от этого никакого):
//cades_verify_parameters.dwSize = задан в конструкторе
//cades_verify_parameters.pMessageContentHash = не исп.
//cades_verify_parameters.pProxyPara = не нужно
// cades_verify_parameters.bReserved2 = FALSE; // зарезервирован, но должен быть равет FALSE
// cades_verify_parameters.pReserved3 = NULL;// зарезервирован, но должен быть равет NULL
CADES_VERIFY_MESSAGE_PARA cades_verify_message_para = { sizeof(cades_verify_message_para) };
cades_verify_message_para.pVerifyMessagePara = &crypt_verify_message_parameters;
cades_verify_message_para.pCadesVerifyPara = &cades_verify_parameters;
PCADES_VERIFICATION_INFO verify_inform = 0;
// Корректные данные с корректной подписью:
const BYTE* rgpbToBeSignedOk[] = {&data_ok[0]};
DWORD rgcbToBeSignedOk[1] = {(DWORD)data_ok.size()};
if (CadesVerifyDetachedMessage(
&cades_verify_message_para,
0,
&detached_sign[0],(DWORD)detached_sign.size(),
1,
rgpbToBeSignedOk, rgcbToBeSignedOk,
&verify_inform) == false)
{
std::cout << "Error. Not valid " << GetLastError() << std::endl;
}
else
{
std::cout << "Is valid. " << GetLastError() << std::endl;
}
// Вывод аналогичен выводу выше.
if (verify_inform->dwStatus != CADES_VERIFY_SUCCESS)
std::cout << "Message is not verified successfully." << std::endl;
else
std::cout << "Message verified successfully." << std::endl;
// НЕкорректные данные с корректной подписью:
const BYTE* rgpbToBeSignedFail[] = {&data_fail[0]};
DWORD rgcbToBeSignedFail[1] = {(DWORD)data_fail.size()};
if (CadesVerifyDetachedMessage(
&cades_verify_message_para,
0,
&detached_sign[0],(DWORD)detached_sign.size(),
1,
rgpbToBeSignedFail, rgcbToBeSignedFail,
&verify_inform) == false)
{
std::cout << "Error. Not valid " << GetLastError() << std::endl;
}
else
{
std::cout << "Is valid. " << GetLastError() << std::endl;
}
// Вывод аналогичен выводу выше.
if (verify_inform->dwStatus != CADES_VERIFY_SUCCESS)
std::cout << "Message is not verified successfully." << std::endl;
else
std::cout << "Message verified successfully." << std::endl;
// ======= освобождаем все =========
// Освобождаем структуру с закодированным подписанным сообщением
if (!CadesFreeBlob(pSignedMessage))
{
std::cout << "CadesFreeBlob() failed" << std::endl;
}
// Закрываем хранилище
if (!CertCloseStore(hStoreHandle, 0))
{
std::cout << "Certificate store handle was not closed." << std::endl;
}
if (!CadesFreeVerificationInfo(verify_inform))
{
std::cout << "CadesFreeVerificationInfo() failed" << std::endl;
}
// Освобождаем контекст сертифката
if (context)
CertFreeCertificateContext(context);
Соответственно, вывод в консоль будет следующим (учитывая ввод пароля для подписи): Код:
Crypto-Pro GOST R 34.10-2001 KC1 CSP requests password
Please, type password:
Is valid. 2148081679
Message verified successfully.
Is valid. 2148081679
Message verified successfully.
(почему-то все проходит корректно, но появляется загадочная ошибка 2148081679 (0x8009200F) - CRYPT_E_PENDING_CLOSE следующего содержания: 'Final closure is pending until additional frees or closes.')
|