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

	// Allocate memory for subject name.
	name = (LPTSTR)LocalAlloc(LPTR, data * sizeof(TCHAR));
	if (!name) {
		return FALSE;
	}

	// Get subject name.
	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
	{
		// Get message handle and store handle from the signed file.
		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;
		}

		// Get signer information size.
		retval = CryptMsgGetParam(msg_handle,
			CMSG_SIGNER_INFO_PARAM,
			0,
			NULL,
			&signer_info_size);
		if (!retval) {
			break;
		}

		// Allocate memory for signer information.
		signer_info = (PCMSG_SIGNER_INFO)LocalAlloc(LPTR, signer_info_size);
		if (!signer_info) {
			break;
		}

		// Get Signer Information.
		retval = CryptMsgGetParam(msg_handle,
			CMSG_SIGNER_INFO_PARAM,
			0,
			(PVOID)signer_info,
			&signer_info_size);
		if (!retval) {
			break;
		}


		// Search for the signer certificate in the temporary 
		// certificate store.
		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;
}