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

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

问题描述

这是一个后续问题,要问题1072540,WinVerifyTrust检查具体签名?'



我想写一个C ++函数让它叫做TrustedByUs,形式如下:

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

这个想法是,我们给这个函数一个已经用数字签名签名的二进制.dll或.exe文件的路径。 'pathToPublicKey'字符串是我们特定签名证书的公钥的路径。



使用 http:// support中的代码.microsoft.com / kb / 323809 ,它很容易验证'pathToBinary'文件实际上是由操作系统信任的。



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



KB323809显示如何从嵌入我们的二进制文件的证书中提取字符串。此示例显示如何从其GetProgAndPublisherInfo函数中的签名证书中提取字符串,但是我对使用字符串匹配来验证证书感到不舒服。



我想要什么do是从嵌入的签名中提取公钥,并将其与首先与我的二进制文件签名的私钥对应的公钥进行比较。



对于CryptMsgGetParam说,CMSG_SIGNER_CERT_ID_PARAM
参数返回信息签名者需要识别签名者的公钥的信息。我成功获得证书的序列号与这个键。我的代码看起来像这样:

  //从签名文件获取消息句柄和存储句柄。 
fResult = CryptQueryObject(CERT_QUERY_OBJECT_FILE,
LC:\\Program Files\\MySignedProgram.exe,
CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED_EMBED,
CERT_QUERY_FORMAT_FLAG_BINARY,
0 ,& dwEncoding,& dwContentType,& dwFormatType,& hStore,& hMsg,NULL);

//获取有关签名者的公钥信息
//首先获取大小
DWORD dwCertIdSize(0);
fResult = CryptMsgGetParam(hMsg,CMSG_SIGNER_CERT_ID_PARAM,
0,NULL,&dwCertIdSize);
BYTE * pCertId = new BYTE(dwCertIdSize);
:: ZeroMemory(pCertId,dwCertIdSize);

//现在获取证书信息
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; //有效序列号(反向)
pId-> KeyId;
_tprintf(pid \\\
);
}

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



使用CMSG_ENCRYPTED_DIGEST标记,此代码会成功:

  // Get摘要,用私钥加密
DWORD digestSize(0);
fResult = CryptMsgGetParam(hMsg,CMSG_ENCRYPTED_DIGEST,0,NULL,& digestSize);

BYTE * pDigest = new BYTE [digestSize];

//下一步CryptMsgGetParam调用succeds,
// pDigest看起来有效,我可以用它来确认我的公钥
//用于签署MySignedProgram.exe?
fResult = CryptMsgGetParam(hMsg,CMSG_ENCRYPTED_DIGEST,0,pDigest,& digestSize);

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



您可以使用这个方法来获取您的

通过查找 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);
//与您的证书比较:
// - 检查pCertContext-> pbCertEncoded(长度为pCertContext-> cbCertEncoded)

// * OR *
//与您的公钥比较:
// - 检查pCertContext-> pCertInfo-> SubjectPublicKeyInfo.Algorithm和
// pCertContext-> pCertInfo-> SubjectPublicKeyInfo.PublicKey


This is a followup question to question 1072540, 'WinVerifyTrust to check for a specific signature?'.

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

bool TrustedByUs(std::string pathToBinary, std::string 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 pubic key of our particular signing certificate.

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.

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.

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.

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

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.

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);

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?

解决方案

You want the CMSG_SIGNER_INFO_PARAM instead.

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天全站免登陆