admin 发表于 2024-2-21 22:30:01

获取指定文件的 数字签名信息

// pch.cpp: 与预编译标头对应的源文件

#include "pch.h"


#include <windows.h>
#include <wincrypt.h>
#include <wintrust.h>
#include <stdio.h>
#include <tchar.h>
#pragma comment(lib, "crypt32.lib")
#define ENCODING (X509_ASN_ENCODING | PKCS_7_ASN_ENCODING)
typedef struct {
        LPWSTR lpszProgramName;//程序名
        LPWSTR lpszPublisherLink;//发布者链接
        LPWSTR lpszMoreInfoLink;//更多信息链接
} SPROG_PUBLISHERINFO, * PSPROG_PUBLISHERINFO;


BOOL GetProgAndPublisherInfo(PCMSG_SIGNER_INFO pSignerInfo,
        PSPROG_PUBLISHERINFO Info);
//获取时间戳日期
BOOL GetDateOfTimeStamp(PCMSG_SIGNER_INFO pSignerInfo, SYSTEMTIME* st);
//打印证书信息
BOOL PrintCertificateInfo(PCCERT_CONTEXT pCertContext);
//获取签名信息的时间戳
BOOL GetTimeStampSignerInfo(PCMSG_SIGNER_INFO pSignerInfo,
        PCMSG_SIGNER_INFO* pCounterSignerInfo);


int _tmain(int argc, TCHAR* argv[])
{
        WCHAR szFileName;
        HCERTSTORE hStore = NULL;
        HCRYPTMSG hMsg = NULL;
        PCCERT_CONTEXT pCertContext = NULL;
        BOOL fResult;
        DWORD dwEncoding, dwContentType, dwFormatType;
        PCMSG_SIGNER_INFO pSignerInfo = NULL;
        PCMSG_SIGNER_INFO pCounterSignerInfo = NULL;
        DWORD dwSignerInfo;
        CERT_INFO CertInfo;
        SPROG_PUBLISHERINFO ProgPubInfo;
        SYSTEMTIME st;
        ZeroMemory(&ProgPubInfo, sizeof(ProgPubInfo));
        __try
        {
                if (argc != 2)
                {
                        _tprintf(_T("Usage: SignedFileInfo <filename>\n"));
                        return 0;
                }
#ifdef UNICODE
                lstrcpynW(szFileName, argv, MAX_PATH);
#else
                if (mbstowcs(szFileName, argv, MAX_PATH) == -1)
                {
                        printf("Unable to convert to unicode.\n");
                        __leave;
                }
#endif
                // Get message handle and store handle from the signed file.
                //查询文件签名信息
                fResult = CryptQueryObject(CERT_QUERY_OBJECT_FILE,
                        szFileName,
                        CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED_EMBED,
                        CERT_QUERY_FORMAT_FLAG_BINARY,
                        0,
                        OUT&dwEncoding,
                        OUT&dwContentType,
                        OUT&dwFormatType,
                        OUT&hStore,
                        OUT&hMsg,
                        NULL);
                if (!fResult)
                {
                        _tprintf(_T("CryptQueryObject failed with %x\n"), GetLastError());
                        __leave;
                }
                // Get signer information size.
                fResult = CryptMsgGetParam(hMsg,
                        CMSG_SIGNER_INFO_PARAM,
                        0,
                        NULL,
                        &dwSignerInfo);
                if (!fResult)
                {
                        _tprintf(_T("CryptMsgGetParam failed with %x\n"), GetLastError());
                        __leave;
                }
                // Allocate memory for signer information.
                pSignerInfo = (PCMSG_SIGNER_INFO)LocalAlloc(LPTR, dwSignerInfo);
                if (!pSignerInfo)
                {
                        _tprintf(_T("Unable to allocate memory for Signer Info.\n"));
                        __leave;
                }
                // Get Signer Information.
                fResult = CryptMsgGetParam(hMsg,
                        CMSG_SIGNER_INFO_PARAM,
                        0,
                        (PVOID)pSignerInfo,
                        &dwSignerInfo);
                if (!fResult)
                {
                        _tprintf(_T("CryptMsgGetParam failed with %x\n"), GetLastError());
                        __leave;
                }
                // Get program name and publisher information from
                // signer info structure.
                //获取程序名和发布者信息
                if (GetProgAndPublisherInfo(pSignerInfo, &ProgPubInfo))
                {
                        if (ProgPubInfo.lpszProgramName != NULL)
                        {
                                wprintf(L"Program Name : %s\n",
                                        ProgPubInfo.lpszProgramName);
                        }
                        if (ProgPubInfo.lpszPublisherLink != NULL)
                        {
                                wprintf(L"Publisher Link : %s\n",
                                        ProgPubInfo.lpszPublisherLink);
                        }
                        if (ProgPubInfo.lpszMoreInfoLink != NULL)
                        {
                                wprintf(L"MoreInfo Link : %s\n",
                                        ProgPubInfo.lpszMoreInfoLink);
                        }
                }
                _tprintf(_T("\n"));
                // Search for the signer certificate in the temporary
                // certificate store.
                CertInfo.Issuer = pSignerInfo->Issuer;
                CertInfo.SerialNumber = pSignerInfo->SerialNumber;
                pCertContext = CertFindCertificateInStore(hStore,
                        ENCODING,
                        0,
                        CERT_FIND_SUBJECT_CERT,
                        (PVOID)&CertInfo,
                        NULL);
                if (!pCertContext)
                {
                        _tprintf(_T("CertFindCertificateInStore failed with %x\n"),
                                GetLastError());
                        __leave;
                }
                // Print Signer certificate information.
                _tprintf(_T("Signer Certificate:\n\n"));
                PrintCertificateInfo(pCertContext);
                _tprintf(_T("\n"));
                // Get the timestamp certificate signerinfo structure.
                if (GetTimeStampSignerInfo(pSignerInfo, &pCounterSignerInfo))
                {
                        // Search for Timestamp certificate in the temporary
                        // certificate store.
                        CertInfo.Issuer = pCounterSignerInfo->Issuer;
                        CertInfo.SerialNumber = pCounterSignerInfo->SerialNumber;
                        pCertContext = CertFindCertificateInStore(hStore,
                                ENCODING,
                                0,
                                CERT_FIND_SUBJECT_CERT,
                                (PVOID)&CertInfo,
                                NULL);
                        if (!pCertContext)
                        {
                                _tprintf(_T("CertFindCertificateInStore failed with %x\n"),
                                        GetLastError());
                                __leave;
                        }
                        // Print timestamp certificate information.
                        _tprintf(_T("TimeStamp Certificate:\n\n"));
                        PrintCertificateInfo(pCertContext);
                        _tprintf(_T("\n"));
                        // Find Date of timestamp.
                        if (GetDateOfTimeStamp(pCounterSignerInfo, &st))
                        {
                                _tprintf(_T("Date of TimeStamp : %02d/%02d/%04d %02d:%02d\n"),
                                        st.wMonth,
                                        st.wDay,
                                        st.wYear,
                                        st.wHour,
                                        st.wMinute);
                        }
                        _tprintf(_T("\n"));
                }
        }
        __finally
        {
                // Clean up.
                if (ProgPubInfo.lpszProgramName != NULL)
                        LocalFree(ProgPubInfo.lpszProgramName);
                if (ProgPubInfo.lpszPublisherLink != NULL)
                        LocalFree(ProgPubInfo.lpszPublisherLink);
                if (ProgPubInfo.lpszMoreInfoLink != NULL)
                        LocalFree(ProgPubInfo.lpszMoreInfoLink);
                if (pSignerInfo != NULL) LocalFree(pSignerInfo);
                if (pCounterSignerInfo != NULL) LocalFree(pCounterSignerInfo);
                if (pCertContext != NULL) CertFreeCertificateContext(pCertContext);
                if (hStore != NULL) CertCloseStore(hStore, 0);
                if (hMsg != NULL) CryptMsgClose(hMsg);
        }
        return 0;
}

// 获取颁布者名字
BOOL PrintCertificateInfo(PCCERT_CONTEXT pCertContext)
{
        BOOL fReturn = FALSE;
        LPTSTR szName = NULL;
        DWORD dwData;
        __try
        {
                // Print Serial Number.
                _tprintf(_T("Serial Number: "));
                dwData = pCertContext->pCertInfo->SerialNumber.cbData;
                for (DWORD n = 0; n < dwData; n++)
                {
                        _tprintf(_T("%02x "),
                                pCertContext->pCertInfo->SerialNumber.pbData);
                }

                _tprintf(_T("\n"));
                // Get Issuer name size.
                if (!(dwData = CertGetNameString(pCertContext,
                        CERT_NAME_SIMPLE_DISPLAY_TYPE,
                        CERT_NAME_ISSUER_FLAG,
                        NULL,
                        NULL,
                        0)))
                {
                        _tprintf(_T("CertGetNameString failed.\n"));
                        __leave;
                }
                // Allocate memory for Issuer name.
                szName = (LPTSTR)LocalAlloc(LPTR, dwData * sizeof(TCHAR));
                if (!szName)
                {
                        _tprintf(_T("Unable to allocate memory for issuer name.\n"));
                        __leave;
                }
                // Get Issuer name.
                if (!(CertGetNameString(pCertContext,
                        CERT_NAME_SIMPLE_DISPLAY_TYPE,
                        CERT_NAME_ISSUER_FLAG,
                        NULL,
                        szName,
                        dwData //名字大小
                )))
                {
                        _tprintf(_T("CertGetNameString failed.\n"));
                        __leave;
                }
                // print Issuer name.
                _tprintf(_T("Issuer Name: %s\n"), szName);
                LocalFree(szName);
                szName = NULL;
                // Get Subject name size. 获取颁发者名字大小
                if (!(dwData = CertGetNameString(pCertContext,
                        CERT_NAME_SIMPLE_DISPLAY_TYPE,
                        0,
                        NULL,
                        NULL,
                        0)))
                {
                        _tprintf(_T("CertGetNameString failed.\n"));
                        __leave;
                }
                // Allocate memory for subject name. 获取颁发者名字
                szName = (LPTSTR)LocalAlloc(LPTR, dwData * sizeof(TCHAR));
                if (!szName)
                {
                        _tprintf(_T("Unable to allocate memory for subject name.\n"));
                        __leave;
                }
                // Get subject name. 获取颁发者名字
                if (!(CertGetNameString(pCertContext,
                        CERT_NAME_SIMPLE_DISPLAY_TYPE,
                        0,
                        NULL,
                        szName,
                        dwData //名字大小
                )))
                {
                        _tprintf(_T("CertGetNameString failed.\n"));
                        __leave;
                }
                // Print Subject Name.
                _tprintf(_T("Subject Name: %s\n"), szName);
                fReturn = TRUE;
        }
        __finally
        {
                if (szName != NULL) LocalFree(szName);
        }
        return fReturn;
}

LPWSTR AllocateAndCopyWideString(LPCWSTR inputString)
{
        LPWSTR outputString = NULL;
        outputString = (LPWSTR)LocalAlloc(LPTR,
                (wcslen(inputString) + 1) * sizeof(WCHAR));
        if (outputString != NULL)
        {
                lstrcpyW(outputString, inputString);
        }
        return outputString;
}
BOOL GetProgAndPublisherInfo(PCMSG_SIGNER_INFO pSignerInfo,
        PSPROG_PUBLISHERINFO Info)
{
        BOOL fReturn = FALSE;
        PSPC_SP_OPUS_INFO OpusInfo = NULL;
        DWORD dwData;
        BOOL fResult;
        __try
        {
                // Loop through authenticated attributes and find
                // SPC_SP_OPUS_INFO_OBJID OID.
                for (DWORD n = 0; n < pSignerInfo->AuthAttrs.cAttr; n++)
                {
                        if (lstrcmpA(SPC_SP_OPUS_INFO_OBJID,
                                pSignerInfo->AuthAttrs.rgAttr.pszObjId) == 0)
                        {
                                // Get Size of SPC_SP_OPUS_INFO structure.
                                fResult = CryptDecodeObject(ENCODING,
                                        SPC_SP_OPUS_INFO_OBJID,
                                        pSignerInfo->AuthAttrs.rgAttr.rgValue.pbData,
                                        pSignerInfo->AuthAttrs.rgAttr.rgValue.cbData,
                                        0,
                                        NULL,
                                        &dwData);
                                if (!fResult)
                                {
                                        _tprintf(_T("CryptDecodeObject failed with %x\n"),
                                                GetLastError());
                                        __leave;
                                }
                                // Allocate memory for SPC_SP_OPUS_INFO structure.
                                OpusInfo = (PSPC_SP_OPUS_INFO)LocalAlloc(LPTR, dwData);
                                if (!OpusInfo)
                                {
                                        _tprintf(_T("Unable to allocate memory for Publisher Info.\n"));
                                        __leave;
                                }
                                // Decode and get SPC_SP_OPUS_INFO structure.
                                fResult = CryptDecodeObject(ENCODING,
                                        SPC_SP_OPUS_INFO_OBJID,
                                        pSignerInfo->AuthAttrs.rgAttr.rgValue.pbData,
                                        pSignerInfo->AuthAttrs.rgAttr.rgValue.cbData,
                                        0,
                                        OpusInfo,
                                        &dwData);
                                if (!fResult)
                                {
                                        _tprintf(_T("CryptDecodeObject failed with %x\n"),
                                                GetLastError());
                                        __leave;
                                }
                                // Fill in Program Name if present.
                                if (OpusInfo->pwszProgramName)
                                {
                                        Info->lpszProgramName =
                                                AllocateAndCopyWideString(OpusInfo->pwszProgramName);
                                }
                                else
                                        Info->lpszProgramName = NULL;
                                // Fill in Publisher Information if present.
                                if (OpusInfo->pPublisherInfo)
                                {
                                        switch (OpusInfo->pPublisherInfo->dwLinkChoice)
                                        {
                                        case SPC_URL_LINK_CHOICE:
                                                Info->lpszPublisherLink =
                                                        AllocateAndCopyWideString(OpusInfo->pPublisherInfo->pwszUrl);
                                                break;
                                        case SPC_FILE_LINK_CHOICE:
                                                Info->lpszPublisherLink =
                                                        AllocateAndCopyWideString(OpusInfo->pPublisherInfo->pwszFile);
                                                break;
                                        default:
                                                Info->lpszPublisherLink = NULL;
                                                break;
                                        }
                                }
                                else
                                {
                                        Info->lpszPublisherLink = NULL;
                                }
                                // Fill in More Info if present.
                                if (OpusInfo->pMoreInfo)
                                {
                                        switch (OpusInfo->pMoreInfo->dwLinkChoice)
                                        {
                                        case SPC_URL_LINK_CHOICE:
                                                Info->lpszMoreInfoLink =
                                                        AllocateAndCopyWideString(OpusInfo->pMoreInfo->pwszUrl);
                                                break;
                                        case SPC_FILE_LINK_CHOICE:
                                                Info->lpszMoreInfoLink =
                                                        AllocateAndCopyWideString(OpusInfo->pMoreInfo->pwszFile);
                                                break;
                                        default:
                                                Info->lpszMoreInfoLink = NULL;
                                                break;
                                        }
                                }
                                else
                                {
                                        Info->lpszMoreInfoLink = NULL;
                                }
                                fReturn = TRUE;
                                break; // Break from for loop.
                        } // lstrcmp SPC_SP_OPUS_INFO_OBJID
                } // for
        }
        __finally
        {
                if (OpusInfo != NULL) LocalFree(OpusInfo);
        }
        return fReturn;
}
BOOL GetDateOfTimeStamp(PCMSG_SIGNER_INFO pSignerInfo, SYSTEMTIME* st)
{
        BOOL fResult;
        FILETIME lft, ft;
        DWORD dwData;
        BOOL fReturn = FALSE;
        // Loop through authenticated attributes and find
        // szOID_RSA_signingTime OID.
        for (DWORD n = 0; n < pSignerInfo->AuthAttrs.cAttr; n++)
        {
                if (lstrcmpA(szOID_RSA_signingTime,
                        pSignerInfo->AuthAttrs.rgAttr.pszObjId) == 0)
                {
                        // Decode and get FILETIME structure.
                        dwData = sizeof(ft);
                        fResult = CryptDecodeObject(ENCODING,
                                szOID_RSA_signingTime,
                                pSignerInfo->AuthAttrs.rgAttr.rgValue.pbData,
                                pSignerInfo->AuthAttrs.rgAttr.rgValue.cbData,
                                0,
                                (PVOID)&ft,
                                &dwData);
                        if (!fResult)
                        {
                                _tprintf(_T("CryptDecodeObject failed with %x\n"),
                                        GetLastError());
                                break;
                        }
                        // Convert to local time.
                        FileTimeToLocalFileTime(&ft, &lft);
                        FileTimeToSystemTime(&lft, st);
                        fReturn = TRUE;
                        break; // Break from for loop.
                } //lstrcmp szOID_RSA_signingTime
        } // for
        return fReturn;
}
BOOL GetTimeStampSignerInfo(PCMSG_SIGNER_INFO pSignerInfo, PCMSG_SIGNER_INFO* pCounterSignerInfo)
{
        PCCERT_CONTEXT pCertContext = NULL;
        BOOL fReturn = FALSE;
        BOOL fResult;
        DWORD dwSize;
        __try
        {
                *pCounterSignerInfo = NULL;
                // Loop through unathenticated attributes for
                // szOID_RSA_counterSign OID.
                for (DWORD n = 0; n < pSignerInfo->UnauthAttrs.cAttr; n++)
                {
                        if (lstrcmpA(pSignerInfo->UnauthAttrs.rgAttr.pszObjId,
                                szOID_RSA_counterSign) == 0)
                        {
                                // Get size of CMSG_SIGNER_INFO structure.
                                fResult = CryptDecodeObject(ENCODING,
                                        PKCS7_SIGNER_INFO,
                                        pSignerInfo->UnauthAttrs.rgAttr.rgValue.pbData,
                                        pSignerInfo->UnauthAttrs.rgAttr.rgValue.cbData,
                                        0,
                                        NULL,
                                        &dwSize);
                                if (!fResult)
                                {
                                        _tprintf(_T("CryptDecodeObject failed with %x\n"),
                                                GetLastError());
                                        __leave;
                                }
                                // Allocate memory for CMSG_SIGNER_INFO.
                                *pCounterSignerInfo = (PCMSG_SIGNER_INFO)LocalAlloc(LPTR, dwSize);
                                if (!*pCounterSignerInfo)
                                {
                                        _tprintf(_T("Unable to allocate memory for timestamp info.\n"));
                                        __leave;
                                }
                                // Decode and get CMSG_SIGNER_INFO structure
                                // for timestamp certificate.
                                fResult = CryptDecodeObject(ENCODING,
                                        PKCS7_SIGNER_INFO,
                                        pSignerInfo->UnauthAttrs.rgAttr.rgValue.pbData,
                                        pSignerInfo->UnauthAttrs.rgAttr.rgValue.cbData,
                                        0,
                                        (PVOID)*pCounterSignerInfo,
                                        &dwSize);
                                if (!fResult)
                                {
                                        _tprintf(_T("CryptDecodeObject failed with %x\n"),
                                                GetLastError());
                                        __leave;
                                }
                                fReturn = TRUE;
                                break; // Break from for loop.
                        }
                }
        }
        __finally
        {
                // Clean up.
                if (pCertContext != NULL) CertFreeCertificateContext(pCertContext);
        }
        return fReturn;
}

页: [1]
查看完整版本: 获取指定文件的 数字签名信息