如何验证我的组织是否签署了受信任的 Windows 二进制文件?

2023-11-23

这是一个后续问题问题 1072540,“WinVerifyTrust 检查特定签名?”.

我想写一个 C++ 函数 让我们调用它TrustedByUs形式:

bool TrustedByUs(std::string pathToBinary, std::string pathToPublicKey)

我们的想法是,我们为该函数提供一个指向已使用数字签名签名的二进制 .dll 或 .exe 文件的路径。这pathToPublicKeystring 是我们特定签名证书的公钥的路径。

使用中的代码http://support.microsoft.com/kb/323809验证是非常简单的pathToBinary文件实际上是受操作系统信任的。

现在我与问题 1072540 的作者处于同一位置,我知道操作系统信任该二进制文件的签名者,但我想知道我的组织的 RSA 密钥是否是签署该二进制文件的密钥。

KB323809 展示了如何从二进制文件中嵌入的证书中提取字符串。此示例演示如何从其签名证书中提取字符串GetProgAndPublisherInfo函数,但我不喜欢使用字符串匹配来验证证书。

我想做的是从嵌入的签名中提取公钥,并将其与最初签署我的二进制文件的私钥对应的公钥进行比较。

的文档CryptMsgGetParamCMSG_SIGNER_CERT_ID_PARAM参数“返回识别签名者公钥所需的消息签名者信息”。我成功地用这个密钥获取了证书的序列号。我的代码如下所示:

// Get message handle and store handle from the signed file.
fResult = CryptQueryObject(CERT_QUERY_OBJECT_FILE,
    L"C:\\Program Files\\MySignedProgram.exe",
    CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED_EMBED,
    CERT_QUERY_FORMAT_FLAG_BINARY,
    0, &dwEncoding, &dwContentType, &dwFormatType, &hStore, &hMsg, NULL);

// Get the public key information about the signer
// First get the size
DWORD dwCertIdSize(0);
fResult = CryptMsgGetParam(hMsg, CMSG_SIGNER_CERT_ID_PARAM,
    0, NULL, &dwCertIdSize);
BYTE* pCertId = new BYTE(dwCertIdSize);
::ZeroMemory(pCertId,dwCertIdSize);

// Now get the cert info
fResult = CryptMsgGetParam(hMsg, CMSG_SIGNER_CERT_ID_PARAM,
    0, (PVOID)pCertId, &dwCertIdSize);

if(fResult)
{      
    CERT_ID* pId = (CERT_ID*)pCertId;  
    pId->HashId;
    pId->dwIdChoice;
    pId->IssuerSerialNumber;  // Valid serial number (reversed)
    pId->KeyId;   
    _tprintf("pid\n");
}

这接近我想要的,但实际上我想使用签名证书的公钥来验证目标签名的二进制文件实际上是使用我的特定公钥/私钥对创建的。

使用CMSG_ENCRYPTED_DIGEST标记此代码成功:

// Get digest which was encrypted with the private key
DWORD digestSize(0);
fResult = CryptMsgGetParam(hMsg, CMSG_ENCRYPTED_DIGEST, 0, NULL, &digestSize);

BYTE* pDigest = new BYTE[digestSize];

// Next CryptMsgGetParam call succeds,
// pDigest looks valid, can I use this to confirm my public key
// was used to sign MySignedProgram.exe ?
fResult = CryptMsgGetParam(hMsg, CMSG_ENCRYPTED_DIGEST, 0, pDigest, &digestSize);

底线问题:给定发现的证书信息CryptQueryObject,我应该使用什么技术来确保目标文件实际上是使用与执行上述代码时可用的公钥相对应的私钥进行签名的?


你想要的CMSG_SIGNER_INFO_PARAM反而。

您可以使用它通过在返回的证书存储中查找证书来获取整个证书CryptQueryObject:

CryptMsgGetParam(hMsg, 
                 CMSG_SIGNER_INFO_PARAM, 
                 0, 
                 NULL, 
                 &dwSignerInfo);
PCMSG_SIGNER_INFO pSignerInfo = (PCMSG_SIGNER_INFO) malloc(dwSignerInfo);
CryptMsgGetParam(hMsg, 
                 CMSG_SIGNER_INFO_PARAM, 
                 0, 
                 pSignerInfo, 
                 &dwSignerInfo);

PCCERT_CONTEXT pCertContext = CertFindCertificateInStore(hStore,
                                          ENCODING,
                                          0,
                                          CERT_FIND_SUBJECT_CERT,
                                          (PVOID)pSignerInfo,
                                          NULL);
// Compare with your certificate:
// - check pCertContext->pbCertEncoded (length is pCertContext->cbCertEncoded)

// *OR*
// Compare with your public-key:
// - check pCertContext->pCertInfo->SubjectPublicKeyInfo.Algorithm and
//   pCertContext->pCertInfo->SubjectPublicKeyInfo.PublicKey
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何验证我的组织是否签署了受信任的 Windows 二进制文件? 的相关文章

随机推荐