You are here:   Home >> Win32/MFC >> How to retrieve the authenticode information

How to retrieve the authenticode information

Chinese verion author: Quaful@newsmth.net.
When an ActiveX will be installed in IE, the authenticode information will be showed out. And how to get the information by programming?
In microsoft KB323809: HOWTO: Get Information from Authenticode Signed Executables, there is a full example code. But it’s not very easy to use in your program directly. So Quaful made a function for us. Many thanks to Quaful.
The declaration of the function is:


BOOL
GetAuthenticodeInformation(
LPCTSTR lpszFileName, //the file name
PSPROG_SIGNATUREINFO pInfo // a structure of authenticode information
);

Here is the SPROG_SIGNATUREINFO structure, which contains the authenticode information.


typedef struct {

LPWSTR lpszProgramName;
LPWSTR lpszPublisherLink;
LPWSTR lpszMoreInfoLink;

DWORD cbSerialSize;
LPBYTE lpSerialNumber;
LPTSTR lpszIssuerName;
LPTSTR lpszSubjectName;

} SPROG_SIGNATUREINFO, *PSPROG_SIGNATUREINFO;

When you run the demo app, you can get such result ouput.

F:\quaful>SignedFileInfo sdkinst.cab
Program Name: SDKUpdate ActiveX Control
Publisher Link: (null)
More Info Link: http://www.microsoft.com/
msdownload/platformsdk/sdkupdate
Serial Number: 61 07 11 43 00 00 00 00 00 34
Issuer Name: Microsoft Code Signing PCA
Subject Name: Microsoft Corporation

The full source code is here.

#include ublisherLink;
#include
#include
#include
#include erialNumber;

#pragma comment(lib, “crypt32.lib”)

// the Authenticode Signature is encode in PKCS7
#define ENCODING (X509_ASN_ENCODING | PKCS_7_ASN_ENCODING)

// Infomation structure of authenticode sign
typedef struct {
LPWSTR lpszProgramName; LPWSTR lpszPublisherLink;
LPWSTR lpszMoreInfoLink;

DWORD cbSerialSize;
LPBYTE lpSerialNumber;
LPTSTR lpszIssuerName;
LPTSTR lpszSubjectName;
} SPROG_SIGNATUREINFO, *PSPROG_SIGNATUREINFO;

VOID GetProgAndPublisherInfo(
PCMSG_SIGNER_INFO pSignerInfo,
PSPROG_SIGNATUREINFO pInfo);

VOID GetCertificateInfo(
HCERTSTORE hStore,
PCMSG_SIGNER_INFO pSignerInfo,
PSPROG_SIGNATUREINFO pInfo);


BOOL GetAuthenticodeInformation(
LPCTSTR lpszFileName,
PSPROG_SIGNATUREINFO pInfo)
{
HCERTSTORE hStore = NULL;
HCRYPTMSG hMsg = NULL;
PCMSG_SIGNER_INFO pSignerInfo = NULL;
DWORD dwSignerInfo;

BOOL bRet = FALSE;

__try
{
// as CryptQueryObject() only accept WCHAR file name, convert first
WCHAR wszFileName[MAX_PATH];
#ifdef UNICODE
if ( !lstrcpynW( wszFileName, lpszFileName, MAX_PATH))
__leave;
#else
if ( mbstowcs( wszFileName, lpszFileName, MAX_PATH) == -1)
__leave;
#endif
//Retrieve the Message Handle and Store Handle
DWORD dwEncoding, dwContentType, dwFormatType;
if ( !CryptQueryObject( CERT_QUERY_OBJECT_FILE, wszFileName,
CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED_EMBED,
CERT_QUERY_FORMAT_FLAG_BINARY, 0, &dwEncoding,
&dwContentType, &dwFormatType, &hStore,
&hMsg, NULL))
__leave;

//Get the length of SignerInfo
if ( !CryptMsgGetParam( hMsg, CMSG_SIGNER_INFO_PARAM, 0, NULL,
&dwSignerInfo))
__leave;

// allocate the memory for SignerInfo
if ( !(pSignerInfo = (PCMSG_SIGNER_INFO)LocalAlloc( LPTR, dwSignerInfo)))
__leave;

// get the SignerInfo
if ( !CryptMsgGetParam( hMsg, CMSG_SIGNER_INFO_PARAM, 0, (PVOID)
pSignerInfo, &dwSignerInfo))
__leave;

//get the Publisher from SignerInfo
GetProgAndPublisherInfo( pSignerInfo, pInfo);

//get the Certificate from SignerInfo
GetCertificateInfo( hStore, pSignerInfo, pInfo);

bRet = TRUE;
}
__finally
{
// release the memory
if (pSignerInfo != NULL) LocalFree(pSignerInfo);
if (hStore != NULL) CertCloseStore(hStore, 0);
if (hMsg != NULL) CryptMsgClose(hMsg);
}
return bRet;
}


LPWSTR AllocateAndCopyWideString(LPCWSTR inputString)
{
LPWSTR outputString = NULL;

// allocate the memory
outputString = (LPWSTR)VirtualAlloc(NULL, (wcslen(inputString) + 1) *
sizeof(TCHAR), MEM_COMMIT, PAGE_READWRITE);

// copy
if (outputString != NULL)
{
lstrcpyW(outputString, inputString);
}

return outputString;
}


VOID GetProgAndPublisherInfo(PCMSG_SIGNER_INFO pSignerInfo,
PSPROG_SIGNATUREINFO pInfo)
{
PSPC_SP_OPUS_INFO OpusInfo = NULL;
DWORD dwData;

__try
{
// query SPC_SP_OPUS_INFO_OBJID OID in Authenticated Attributes
for (DWORD n = 0; n < pSignerInfo->AuthAttrs.cAttr; n++)
{
if (lstrcmpA(SPC_SP_OPUS_INFO_OBJID, pSignerInfo->AuthAttrs.rgAttr[n].pszObjId) == 0)
{
// get the length of SPC_SP_OPUS_INFO
if ( !CryptDecodeObject(ENCODING,
SPC_SP_OPUS_INFO_OBJID,
pSignerInfo->AuthAttrs.rgAttr[n].rgValue[0].pbData,
pSignerInfo->AuthAttrs.rgAttr[n].rgValue[0].cbData,
0,
NULL,
&dwData))
__leave;

// allocate the memory for SPC_SP_OPUS_INFO
if ( !(OpusInfo = (PSPC_SP_OPUS_INFO)LocalAlloc(LPTR, dwData)))
__leave;

// get SPC_SP_OPUS_INFO structure
if ( !CryptDecodeObject(ENCODING,
SPC_SP_OPUS_INFO_OBJID,
pSignerInfo->AuthAttrs.rgAttr[n].rgValue[0].pbData,
pSignerInfo->AuthAttrs.rgAttr[n].rgValue[0].cbData,
0,
OpusInfo,
&dwData))
__leave;

// copy the Program Name of SPC_SP_OPUS_INFO to the return variable
if (OpusInfo->pwszProgramName)
{
pInfo->lpszProgramName =
AllocateAndCopyWideString(OpusInfo->pwszProgramName);
}
else
pInfo->lpszProgramName = NULL;

// copy the Publisher Info of SPC_SP_OPUS_INFO to the return variable
if (OpusInfo->pPublisherInfo)
{

switch (OpusInfo->pPublisherInfo->dwLinkChoice)
{
case SPC_URL_LINK_CHOICE:
pInfo->lpszPublisherLink =
AllocateAndCopyWideString(OpusInfo->pPublisherInfo->pwszUrl);
break;

case SPC_FILE_LINK_CHOICE:
pInfo->lpszPublisherLink =
AllocateAndCopyWideString(OpusInfo->pPublisherInfo->pwszFile);
break;

default:
pInfo->lpszPublisherLink = NULL;
break;
}
}
else
{
pInfo->lpszPublisherLink = NULL;
}

// copy the More Info of SPC_SP_OPUS_INFO to the return variable
if (OpusInfo->pMoreInfo)
{
switch (OpusInfo->pMoreInfo->dwLinkChoice)
{
case SPC_URL_LINK_CHOICE:
pInfo->lpszMoreInfoLink =
AllocateAndCopyWideString(OpusInfo->pMoreInfo->pwszUrl);
break;

case SPC_FILE_LINK_CHOICE:
pInfo->lpszMoreInfoLink =
AllocateAndCopyWideString(OpusInfo->pMoreInfo->pwszFile);
break;

default:
pInfo->lpszMoreInfoLink = NULL;
break;
}
}
else
{
pInfo->lpszMoreInfoLink = NULL;
}

break; // we have got the information, break
}
}
}
__finally
{
if (OpusInfo != NULL) LocalFree(OpusInfo);
}
}


VOID GetCertificateInfo(
HCERTSTORE hStore,
PCMSG_SIGNER_INFO pSignerInfo,
PSPROG_SIGNATUREINFO pInfo)
{
PCCERT_CONTEXT pCertContext = NULL;

__try
{
CERT_INFO CertInfo;
DWORD dwData;

// query Signer Certificate in Certificate Store
CertInfo.Issuer = pSignerInfo->Issuer;
CertInfo.SerialNumber = pSignerInfo->SerialNumber;

if ( !(pCertContext = CertFindCertificateInStore( hStore,
ENCODING, 0, CERT_FIND_SUBJECT_CERT,
(PVOID)&CertInfo, NULL)))
__leave;

dwData = pCertContext->pCertInfo->SerialNumber.cbData;

// SPROG_SIGNATUREINFO.cbSerialSize
pInfo->cbSerialSize = dwData;

// SPROG_SIGNATUREINFO.lpSerialNumber
pInfo->lpSerialNumber = (LPBYTE)VirtualAlloc(NULL, dwData,
MEM_COMMIT, PAGE_READWRITE);
memcpy( pInfo->lpSerialNumber, pCertContext->pCertInfo->SerialNumber.pbData, dwData);

// SPROG_SIGNATUREINFO.lpszIssuerName
__try
{
// get the length of Issuer Name
if (!(dwData = CertGetNameString( pCertContext,
CERT_NAME_SIMPLE_DISPLAY_TYPE,
CERT_NAME_ISSUER_FLAG, NULL, NULL, 0)))
__leave;

// allocate the memory
if ( !(pInfo->lpszIssuerName = (LPTSTR)
VirtualAlloc(NULL, dwData * sizeof(TCHAR), MEM_COMMIT, PAGE_READWRITE)))
__leave;

// get Issuer Name
if (!(CertGetNameString( pCertContext,
CERT_NAME_SIMPLE_DISPLAY_TYPE,
CERT_NAME_ISSUER_FLAG, NULL, pInfo->
lpszIssuerName, dwData)))
__leave;
}
__finally
{
}

// SPROG_SIGNATUREINFO.lpszSubjectName
__try
{
//get the length of Subject Name
if (!(dwData = CertGetNameString( pCertContext,
CERT_NAME_SIMPLE_DISPLAY_TYPE, 0, NULL, NULL, 0)))
__leave;

// allocate the memory
if ( !(pInfo->lpszSubjectName = (LPTSTR)
VirtualAlloc(NULL, dwData * sizeof(TCHAR), MEM_COMMIT, PAGE_READWRITE)))
__leave;

// get Subject Name
if (!(CertGetNameString( pCertContext,
CERT_NAME_SIMPLE_DISPLAY_TYPE, 0, NULL, pInfo->lpszSubjectName, dwData)))
__leave;
}
__finally
{
}
}
__finally
{
if (pCertContext != NULL)
CertFreeCertificateContext(pCertContext);
}
}


int _tmain(int argc, TCHAR *argv[])
{
if (argc != 2)
{
_tprintf(_T(“Usage: SignedFileInfo \n”));
return 0;
}
else
{
SPROG_SIGNATUREINFO SignInfo;

ZeroMemory(&SignInfo, sizeof(SignInfo));

GetAuthenticodeInformation( argv[1], &SignInfo);

wprintf(L”Program Name: %s\n”, SignInfo.lpszProgramName);
wprintf(L”Publisher Link: %s\n”, SignInfo.lpszPublisherLink);
wprintf(L”More Info Link: %s\n”, SignInfo.lpszMoreInfoLink);

{
_tprintf(_T(“Serial Number: “));
DWORD dwData = SignInfo.cbSerialSize;
for (DWORD n = 0; n < dwData; n++)
{
_tprintf(_T("%02x "),
SignInfo.lpSerialNumber[dwData - (n + 1)]);
}
_tprintf(_T("\n"));
}
_tprintf(_T("Issuer Name: %s\n"), SignInfo.lpszIssuerName);
_tprintf(_T("Subject Name: %s\n"), SignInfo.lpszSubjectName);
if ( SignInfo.lpszProgramName) VirtualFree(SignInfo.lpszProgramName, 0, MEM_RELEASE);
if ( SignInfo.lpszPublisherLink) VirtualFree(SignInfo.lpszPublisherLink, 0, MEM_RELEASE);
if ( SignInfo.lpszMoreInfoLink) VirtualFree(SignInfo.lpszMoreInfoLink, 0, MEM_RELEASE);
if ( SignInfo.lpSerialNumber) VirtualFree(SignInfo.lpSerialNumber, 0, MEM_RELEASE);
if ( SignInfo.lpszIssuerName) VirtualFree(SignInfo.lpszIssuerName, 0, MEM_RELEASE);
if ( SignInfo.lpszSubjectName) VirtualFree(SignInfo.lpszSubjectName, 0, MEM_RELEASE);

return 0;
}
}

Permalink: Code Library » http://www.ucosoft.com/how-to-program-to-retrieve-the-authenticode-information.html

Related Posts

4 Responses to “How to retrieve the authenticode information”

  1. David says:

    Does anyone know how to sign a CAB file? Which aer the diferences?

    Any code?

  2. Mr Col says:

    Thankyou so much for this, I have spent the last few days tearing my hair out try to do this.

  3. cipcipcia says:

    how can I add to bookrmark your blog? would you like to visit mine? regards!

  4. Diego Romar says:

    Thanks a lot for posting this code, it’s really helpful!

    Needed to check out the digital signing and the issuers’ names of some files I download via a setup.exe. This works magnificently!

Leave a Reply