Sysinternal(http://forum.sysinternals.com/howto-verify-the-digital-signature-of-a-file_topic19247.html)上有关于验证签名的代码,不过代码有点问题,他只能验证PE签名,无法验证文件签名,所以我这里稍作了点修改,记录一下
#define ENCODING (X509_ASN_ENCODING | PKCS_7_ASN_ENCODING)
BOOL CheckFileTrust(LPCTSTR filename, CString &signer_file)
{
HCATADMIN cat_admin_handle = NULL;
if (!CryptCATAdminAcquireContext(&cat_admin_handle, NULL, 0))
{
return FALSE;
}
HANDLE hFile = CreateFileW(filename, GENERIC_READ, FILE_SHARE_READ,
NULL, OPEN_EXISTING, 0, NULL);
if (INVALID_HANDLE_VALUE == hFile)
{
CryptCATAdminReleaseContext(cat_admin_handle, 0);
return FALSE;
}
DWORD hash_count = 100;
BYTE hash_data[100];
CryptCATAdminCalcHashFromFileHandle(hFile, &hash_count, hash_data, 0);
CloseHandle(hFile);
LPWSTR member_tag = new WCHAR[hash_count * 2 + 1];
for (DWORD dw = 0; dw < hash_count; ++dw)
{
wsprintfW(&member_tag[dw * 2], L"%02X", hash_data[dw]);
}
WINTRUST_DATA wd = { 0 };
WINTRUST_FILE_INFO wfi = { 0 };
WINTRUST_CATALOG_INFO wci = { 0 };
CATALOG_INFO ci = { 0 };
HCATINFO cat_admin_info = CryptCATAdminEnumCatalogFromHash(cat_admin_handle,
hash_data, hash_count, 0, NULL);
if (NULL == cat_admin_info)
{
wfi.cbStruct = sizeof(WINTRUST_FILE_INFO);
wfi.pcwszFilePath = filename;
wfi.hFile = NULL;
wfi.pgKnownSubject = NULL;
wd.cbStruct = sizeof(WINTRUST_DATA);
wd.dwUnionChoice = WTD_CHOICE_FILE;
wd.pFile = &wfi;
wd.dwUIChoice = WTD_UI_NONE;
wd.fdwRevocationChecks = WTD_REVOKE_NONE;
wd.dwStateAction = WTD_STATEACTION_IGNORE;
wd.dwProvFlags = WTD_SAFER_FLAG;
wd.hWVTStateData = NULL;
wd.pwszURLReference = NULL;
signer_file = filename;
}
else
{
CryptCATCatalogInfoFromContext(cat_admin_info, &ci, 0);
wci.cbStruct = sizeof(WINTRUST_CATALOG_INFO);
wci.pcwszCatalogFilePath = ci.wszCatalogFile;
wci.pcwszMemberFilePath = filename;
wci.pcwszMemberTag = member_tag;
wci.pbCalculatedFileHash = hash_data;
wci.cbCalculatedFileHash = hash_count;
wd.cbStruct = sizeof(WINTRUST_DATA);
wd.dwUnionChoice = WTD_CHOICE_CATALOG;
wd.pCatalog = &wci;
wd.dwUIChoice = WTD_UI_NONE;
wd.fdwRevocationChecks = WTD_REVOKE_WHOLECHAIN;
wd.dwProvFlags = 0;
wd.hWVTStateData = NULL;
wd.pwszURLReference = NULL;
signer_file = ci.wszCatalogFile;
}
GUID action = WINTRUST_ACTION_GENERIC_VERIFY_V2;
HRESULT hr = WinVerifyTrust(NULL, &action, &wd);
BOOL retval = SUCCEEDED(hr);
if (NULL != cat_admin_info) {
CryptCATAdminReleaseCatalogContext(cat_admin_handle, cat_admin_info, 0);
}
CryptCATAdminReleaseContext(cat_admin_handle, 0);
delete[] member_tag;
return retval;
}
BOOL GetCertificateInfo(PCCERT_CONTEXT cert_context, CString &signer_name)
{
LPTSTR name = NULL;
DWORD data;
if (!(data = CertGetNameString(cert_context,
CERT_NAME_SIMPLE_DISPLAY_TYPE,
0,
NULL,
NULL,
0))) {
return FALSE;
}
name = (LPTSTR)LocalAlloc(LPTR, data * sizeof(TCHAR));
if (!name) {
return FALSE;
}
if (!(CertGetNameString(cert_context,
CERT_NAME_SIMPLE_DISPLAY_TYPE,
0,
NULL,
name,
data))) {
LocalFree(name);
return FALSE;
}
signer_name = name;
LocalFree(name);
return TRUE;
}
BOOL GetFileSigner(LPCTSTR szFileName, CString &signer_name)
{
HCERTSTORE store_handle = NULL;
HCRYPTMSG msg_handle = NULL;
PCCERT_CONTEXT cert_context = NULL;
BOOL retval = FALSE;
DWORD encoding, content_type, format_type;
PCMSG_SIGNER_INFO signer_info = NULL;
DWORD signer_info_size;
CERT_INFO cert_info;
do
{
retval = CryptQueryObject(CERT_QUERY_OBJECT_FILE,
szFileName,
CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED_EMBED,
CERT_QUERY_FORMAT_FLAG_BINARY,
0,
&encoding,
&content_type,
&format_type,
&store_handle,
&msg_handle,
NULL);
if (!retval) {
break;
}
retval = CryptMsgGetParam(msg_handle,
CMSG_SIGNER_INFO_PARAM,
0,
NULL,
&signer_info_size);
if (!retval) {
break;
}
signer_info = (PCMSG_SIGNER_INFO)LocalAlloc(LPTR, signer_info_size);
if (!signer_info) {
break;
}
retval = CryptMsgGetParam(msg_handle,
CMSG_SIGNER_INFO_PARAM,
0,
(PVOID)signer_info,
&signer_info_size);
if (!retval) {
break;
}
cert_info.Issuer = signer_info->Issuer;
cert_info.SerialNumber = signer_info->SerialNumber;
cert_context = CertFindCertificateInStore(store_handle,
ENCODING,
0,
CERT_FIND_SUBJECT_CERT,
(PVOID)&cert_info,
NULL);
if (!cert_context) {
break;
}
retval = GetCertificateInfo(cert_context, signer_name);
} while (0);
if (signer_info != NULL) {
LocalFree(signer_info);
}
if (cert_context != NULL) {
CertFreeCertificateContext(cert_context);
}
if (store_handle != NULL) {
CertCloseStore(store_handle, 0);
}
if (msg_handle != NULL) {
CryptMsgClose(msg_handle);
}
return retval;
}