14.10.2006 16:12:32"Доподписывание" сообщения Ответов: 8
Андрей Горячев
Есть у кого-нибудь пример этой операции в CryptoAPI? Что то у меня этого никак не получается осуществить :\ Буду очень благодарен, ибо срочно нужно...
 
Ответы:
14.10.2006 16:48:35Андрей Горячев
extern "C" bool __declspec(dllexport) CosignMessage(const BYTE* signedMessage, DWORD signedMessageSize,
BYTE* cosignedMessageBlob, DWORD* cosignedMessageBlobSize,
LPCSTR certHash, DWORD certHashLength)
{
HCRYPTMSG cryptMsg;
BYTE* pbCertHash;
DWORD dwCertHashLength;
HCERTSTORE hStoreHandle;
PCCERT_CONTEXT certContext;
CRYPT_HASH_BLOB blobCert;
HCRYPTPROV hCryptProv = NULL;

if (!CryptAcquireContext(&hCryptProv, NULL, NULL, CRYPT_PROV_TYPE, CRYPT_VERIFYCONTEXT))
{
setLastError();
return false;
}

if (!CryptStringToBinaryA(certHash, certHashLength, CRYPT_STRING_HEX, NULL, &dwCertHashLength, 0, 0))
{
CryptReleaseContext(hCryptProv, 0);
setLastError();
return false;
}

pbCertHash = (BYTE*)malloc(dwCertHashLength);
if (!pbCertHash)
{
CryptReleaseContext(hCryptProv, 0);
setLastError();
return false;
}

if (!CryptStringToBinaryA(certHash, certHashLength, CRYPT_STRING_HEX, pbCertHash, &dwCertHashLength, 0, 0))
{
CryptReleaseContext(hCryptProv, 0);
free(pbCertHash);
setLastError();
return false;
}

blobCert.cbData = dwCertHashLength;
blobCert.pbData = pbCertHash;

if (!(hStoreHandle = CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, NULL, CERT_SYSTEM_STORE_CURRENT_USER, PERSONAL_STORE_NAME)))
{
CryptReleaseContext(hCryptProv, 0);
free(pbCertHash);
setLastError();
return false;
}

if(!(certContext = CertFindCertificateInStore(hStoreHandle, MY_ENCODING_TYPE, 0, CERT_FIND_HASH, &blobCert, NULL)))
{
CryptReleaseContext(hCryptProv, 0);
CertCloseStore(hStoreHandle, 0);
free(pbCertHash);
setLastError();
return false;
}

if (!(cryptMsg = CryptMsgOpenToDecode(MY_ENCODING_TYPE, 0, 0, NULL, NULL, NULL)))
{
CryptReleaseContext(hCryptProv, 0);
CertCloseStore(hStoreHandle, 0);
CertFreeCertificateContext(certContext);
free(pbCertHash);
setLastError();
return false;
}

if(!CryptMsgUpdate(cryptMsg, signedMessage, signedMessageSize, TRUE))
{
CryptReleaseContext(hCryptProv, 0);
CertCloseStore(hStoreHandle, 0);
CertFreeCertificateContext(certContext);
free(pbCertHash);
setLastError();
return false;
}

CMSG_SIGNER_ENCODE_INFO *signerInfo;
memset(signerInfo, 0, sizeof(CMSG_SIGNER_ENCODE_INFO));
signerInfo->cbSize = sizeof(CMSG_SIGNER_ENCODE_INFO);
signerInfo->pCertInfo = certContext->pCertInfo;
signerInfo->hCryptProv = hCryptProv;
signerInfo->cAuthAttr = 0;
signerInfo->cUnauthAttr = 0;
signerInfo->dwKeySpec = AT_SIGNATURE;
signerInfo->HashAlgorithm = certContext->pCertInfo->SignatureAlgorithm;
signerInfo->pvHashAuxInfo = NULL;
signerInfo->rgAuthAttr = NULL;
signerInfo->rgUnauthAttr = NULL;

// Вот тут вылетает в ретурн с ошибкой "Операция завершена успешно"!!!! Как так?

if (!CryptMsgControl(cryptMsg, 0, CMSG_CTRL_ADD_SIGNER, signerInfo))
{
CryptReleaseContext(hCryptProv, 0);
CertCloseStore(hStoreHandle, 0);
CertFreeCertificateContext(certContext);
free(pbCertHash);
setLastError();
return false;
}

if (!CryptMsgGetParam(cryptMsg, CMSG_ENCODED_MESSAGE, 0, cosignedMessageBlob, cosignedMessageBlobSize))
{
CryptReleaseContext(hCryptProv, 0);
CertCloseStore(hStoreHandle, 0);
CertFreeCertificateContext(certContext);
free(pbCertHash);
setLastError();
return false;
}

CryptReleaseContext(hCryptProv, 0);
CertCloseStore(hStoreHandle, 0);
CertFreeCertificateContext(certContext);
free(pbCertHash);
return true;
}
16.10.2006 12:41:45Kirill Sobolev
С флагом CRYPT_VERIFYCONTEXT можно проверять подпись, но никак уж не подписывать. Вам нужен хэндл именно того контейнера, секретным ключем которого вы будете доподписывать.
16.10.2006 13:28:34Андрей Горячев
Это само собой понятно (случайно написалось). Изменил ну другой флаг. Разницы нет, всё равно не работает. Ошибка: "Ключ не существует"
16.10.2006 13:35:42Kirill Sobolev
А
signerInfo->HashAlgorithm = certContext->pCertInfo->SignatureAlgorithm?
Алгортим хеширования сообщения и алгортим, которым пописан сертификат - это совсем не одно и тоже.
Ключ не существует - значит в указанном контейнере нет секретного ключа AT_SIGNATURE.
16.10.2006 13:40:54Андрей Горячев
а как получить signerInfo->HashAlgorithm?
16.10.2006 14:03:11Kirill Sobolev
Посмотреть, какие алгортимы подписи поддерживает hCryptProv, если использовать ОК из сертификата.
16.10.2006 14:40:37Андрей Горячев
Что то не совсем понимаю, что имеете в виду. что за "OK" ?
16.10.2006 16:42:36Kirill Sobolev
ОК - открытый ключ, имеется ввиду его алгоритм.