如何验证我的组织是否签署了受信任的 Windows 二进制文件? [英] How to verify that my orgainization signed a trusted windows binary?

查看:34
本文介绍了如何验证我的组织是否签署了受信任的 Windows 二进制文件?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这是 问题 1072540WinVerifyTrust 检查具体签名?'.

我想写一个 C++ 函数我们称之为 TrustedByUs 的形式:

I want to write a C++ function Lets call it TrustedByUs of the form:

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

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

The idea is that we give this function a path to a binary .dll or .exe file that has been signed with a digital signature. The pathToPublicKey string is the path to a public key of our particular signing certificate.

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

Using the code in http://support.microsoft.com/kb/323809 it's pretty straight forward to verify that the pathToBinary file is in fact trusted by the operating system.

现在我和问题 1072540 的作者在同一个地方,我知道操作系统信任此二进制文件的签名者,但我想知道我的组织的 RSA 密钥是否是对二进制文件进行签名的那个.

Now I'm in the same place as the writer of question 1072540, I know the OS trusts the signer of this binary, but I want to know if my organization's RSA key is the one that signed the binary.

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

The KB323809 shows how to extract the strings from certificate embedded in our binary file. This example shows how to extract strings from the signing certificate in its GetProgAndPublisherInfo function, but I'm uncomfortable using a string match to verfiy the certificate.

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

What I would like to do is extract the public key from the embedded signature and compare it to the public key that corresponds with the private key that signed my binary file in the first place.

CryptMsgGetParam 的文档说 CMSG_SIGNER_CERT_ID_PARAM参数返回消息签名者的信息,以识别签名者的公钥".我使用此密钥成功获取了证书的序列号.我的代码如下所示:

The documentation for CryptMsgGetParam says that the CMSG_SIGNER_CERT_ID_PARAM parameter 'Returns information on a message signer needed to identify the signer's public key'. I succeed in getting the certificate's serial number with this key. My code looks like this:

// 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
");
}

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

This is close to what I want, but really I'd like to use the signing certificate's public key to verify that the target signed binary file was in fact created with my particular public/private key pair.

使用 CMSG_ENCRYPTED_DIGEST 标志此代码成功:

Using the CMSG_ENCRYPTED_DIGEST flag this code succeeds:

// 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 发现的证书信息,我应该使用什么技术来确保目标文件实际上是使用对应的私钥签名的执行上述代码时我可以使用的公钥?

Bottom line question: Given the certificate information discovered by CryptQueryObject, what technique should I used to ensure that the target file was in fact signed using the private key that corresponds to the public key that is available to me when the above code executes?

推荐答案

你想要 CMSG_SIGNER_INFO_PARAM 代替.

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

You can use this to get the entire certificate by looking up the certificate in the certificate store returned by 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

这篇关于如何验证我的组织是否签署了受信任的 Windows 二进制文件?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆