1

(对不起我的英语不好。)我的代码有一些问题。所以我会尝试解释我的问题。我有一个带有签名(pkcs7)的简单 exe 文件。我想验证这个文件(没有互联网连接)。我不想使用WinVerifyTrust(),因为我想知道 windows 如何验证 PE 文件。我写了一些代码,首先CryptQueryObject()用 BLOB_DATA(映射的 pe 文件)调用,它工作正常。然后我可以获得证书信息:签名者、序列号等(带有CryptGetMsgParam()),它也可以正常工作;但是,当我去验证它时,CertGetCertificateChain()我得到了错误。那么,你能帮我解决这个问题吗,我认为是我没有CertGetCertificateChain()正确使用?

BOOL bRet = FALSE;
DWORD dwMsgAndCertEncodingType = 0;
DWORD dwContentType = 0;
DWORD dwFormatType = 0;
HCERTSTORE  hStore = NULL;
HCRYPTMSG   hMsg = NULL;
PCCERT_CONTEXT      pCertContext = NULL;
CERT_BLOB   blob_data = { 0 };
// CERT_INFO    CertInfo = { 0 };
DWORD dwSignerInfo = 0;
PCCERT_CHAIN_CONTEXT pChainContext = NULL;
PCMSG_SIGNER_INFO pSignerInfo = NULL;
CERT_CHAIN_PARA          ChainPara = { 0 };


blob_data.pbData = pBuff;
blob_data.cbData = dwSize;


ChainPara.cbSize = sizeof(CERT_CHAIN_PARA);


bRet = CryptQueryObject(CERT_QUERY_OBJECT_BLOB,
    &blob_data,
    CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED_EMBED,
    CERT_QUERY_FORMAT_FLAG_BINARY,
    0,
    NULL,
    &dwContentType,
    NULL,
    &hStore,
    &hMsg,
    &pCertContext);


if (bRet != TRUE)
{
    printf("Error CryptQueryObject\n");
    return FALSE;
}


if (dwContentType != CERT_QUERY_CONTENT_PKCS7_SIGNED_EMBED)
{
    printf("Error type\n");
    return FALSE;
}


CryptMsgGetParam(hMsg, CMSG_SIGNER_INFO_PARAM, 0, NULL, &dwSignerInfo);

pSignerInfo = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dwSignerInfo);


CryptMsgGetParam(hMsg, CMSG_SIGNER_INFO_PARAM, 0, pSignerInfo, &dwSignerInfo);



bRet = CertGetCertificateChain(NULL, (PCCERT_CONTEXT)pCertContext, NULL, NULL, NULL, CERT_CHAIN_REVOCATION_CHECK_CACHE_ONLY,
    NULL, &pChainContext);

if (bRet != TRUE)
{
    printf("Error there\n");
}
4

1 回答 1

1

一个问题(尽管可能不是唯一的问题)是您的第五个参数CertGetCertificateChain()NULL? 这应该指向一个CERT_CHAIN_PARA结构。(您声明了一个,但似乎没有初始化或使用它。)

我不确切知道您应该在其中输入什么数据,但这里有一个示例,它使用了从检查数字证书的真实(工作)程序(我自己制作的程序)中获取的代码:

//...
CERT_CHAIN_PARA ChainPara;  memset(&ChainPara, 0, sizeof(CERT_CHAIN_PARA));
ChainPara.cbSize = sizeof(CERT_CHAIN_PARA);
ChainPara.RequestedUsage.dwType = USAGE_MATCH_TYPE_AND;
ChainPara.RequestedUsage.Usage.cUsageIdentifier = 0;
//...
bRet = CertGetCertificateChain(NULL, (PCCERT_CONTEXT)pCertContext, NULL, NULL, &ChainPara,
    CERT_CHAIN_REVOCATION_CHECK_CACHE_ONLY, NULL, &pChainContext);
//...

您可以查看文档CERT_CHAIN_PARA以获取有关您应该设置哪些实际数据/值的一些提示。

希望这可以帮助!(请随时要求进一步澄清和/或建议。)

于 2019-09-24T15:48:49.820 回答