I want to get the actual signature's algorithm (not the certificate's digest algorithm) that was used for signing a Windows installer file (msi).
Using Microsoft's crypt API, I was able to get what I want for exe's easily. By 1st getting the HCRYPTMSG, then getting the signer information size, then the signer information PCMSG_SIGNER_INFO and finally by getting the algorithm itself :
pSignerInfo->HashAlgorithm.pszObjId
BOOL bIsOk;
DWORD dwEncoding=0, dwContentType = 0, dwFormatType = 0, dwSignerInfo = 0;
std::string szFileName= "pathtothefile";
//Get message handle and store handle from the signed file.
HCERTSTORE hStore = NULL;
HCRYPTMSG hMsg = NULL;
bIsOk = CryptQueryObject(CERT_QUERY_OBJECT_FILE, szFileName.c_str(), CERT_QUERY_CONTENT_FLAG_ALL, CERT_QUERY_FORMAT_FLAG_ALL,
0, &dwEncoding, &dwContentType, &dwFormatType, &hStore, &hMsg, NULL);
For some reason running my code on msi installer files always returns
CRYPT_E_NO_MATCH 0x80092009 Cannot find the requested object.
Of course I have verified the paths and all the possible flags to the CryptQueryObject function but I feel the error might be misleading.
I'm wondering if the crypt API isn't compatible with msi files to begin with.
All topics out there seem to relate to the certificate's digest algorithm only.
Thanks in advance
The answer to your problem is in the documentation for CryptQueryObject:
CERT_QUERY_OBJECT_FILE
: This parameter is a pointer to a null-terminated Unicode string that contains the path and name of the file to query.
Unicode in Windows documentation means UTF-16LE. However, you are passing a std::string
(using char
as the code unit representation). A std::string
(on Windows) is encoded using either ASCII or ANSI (codepage encoding). You're going to have to change that to a std::wstring
instead, which uses wchar_t
as its code unit representation:
std::wstring szFileName= L"pathtothefile";
wchar_t
unambiguously means UTF-16LE on Windows.
Unicode: You need to use a Unicode string for the call (file name).
CString: As a quick test I used a standard CString
in Visual Studio 2017 (Unicode). Please check. Just to get it to run for further debugging. Maybe you can include <atlstr.h>
if you don't include CString
already.
//#include "atlstr.h"
BOOL bIsOk; DWORD dwEncoding = 0, dwContentType = 0, dwFormatType = 0, dwSignerInfo = 0;
CString test = "C:\\LibreOffice_6.2.3_Win_x64.msi";
<..>
bIsOk = CryptQueryObject(CERT_QUERY_OBJECT_FILE, test, CERT_QUERY_CONTENT_FLAG_ALL, CERT_QUERY_FORMAT_FLAG_ALL,
0, &dwEncoding, &dwContentType, &dwFormatType, &hStore, &hMsg, NULL);
Using CString
.CStringT Class
(some tech details).Links:
User contributions licensed under CC BY-SA 3.0