这是
question 1072540,‘WinVerifyTrust to check for a specific signature?’的后续问题.
我想写一个C函数让我们称之为TrustedByUs的形式:
bool TrustedByUs(std::string pathToBinary,std::string pathToPublicKey)
我们的想法是,我们为此函数指定已使用数字签名签名的二进制.dll或.exe文件的路径. pathToPublicKey字符串是我们特定签名证书的公钥的路径.
使用http://support.microsoft.com/kb/323809中的代码,可以非常直接地验证pathToBinary文件实际上是否受操作系统信任.
现在我和问题1072540的作者在同一个地方,我知道操作系统信任这个二进制文件的签名者,但我想知道我的组织的RSA密钥是否是签署二进制文件的密钥.
KB323809显示了如何从嵌入在我们的二进制文件中的证书中提取字符串.此示例显示如何从其GetProgAndPublisherInfo函数中的签名证书中提取字符串,但是使用字符串匹配来验证证书时我感到很不舒服.
我想要做的是从嵌入式签名中提取公钥,并将其与首先签署我的二进制文件的私钥对应的公钥进行比较.
CryptMsgGetParam的文档说CMSG_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,&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,NULL,&dwCertIdSize); BYTE* pCertId = new BYTE(dwCertIdSize); ::ZeroMemory(pCertId,dwCertIdSize); // Now get the cert info fResult = CryptMsgGetParam(hMsg,(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,&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,pDigest,&digestSize);
底线问题:鉴于CryptQueryObject发现的证书信息,我应该使用什么技术来确保目标文件实际上使用与上述代码执行时可用的公钥对应的私钥进行签名?
您想要CMSG_SIGNER_INFO_PARAM.
您可以通过在CryptQueryObject返回的证书存储区中查找证书来使用它来获取整个证书:
CryptMsgGetParam(hMsg,CMSG_SIGNER_INFO_PARAM,&dwSignerInfo); PCMSG_SIGNER_INFO pSignerInfo = (PCMSG_SIGNER_INFO) malloc(dwSignerInfo); CryptMsgGetParam(hMsg,pSignerInfo,&dwSignerInfo); PCCERT_CONTEXT pCertContext = CertFindCertificateInStore(hStore,ENCODING,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