这是一个后续问题问题 1072540,“WinVerifyTrust 检查特定签名?”.
我想写一个 C++ 函数 让我们调用它TrustedByUs
形式:
bool TrustedByUs(std::string pathToBinary, std::string pathToPublicKey)
我们的想法是,我们为该函数提供一个指向已使用数字签名签名的二进制 .dll 或 .exe 文件的路径。这pathToPublicKey
string 是我们特定签名证书的公钥的路径。
使用中的代码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,
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
,我应该使用什么技术来确保目标文件实际上是使用与执行上述代码时可用的公钥相对应的私钥进行签名的?