wincrypt获取文件签名

例1:

BOOL GetSign(CString strFile, CString& strSignName)
{
    if (strFile.IsEmpty())
    {
        return FALSE;
    }
    BOOL fResult;
    DWORD dwEncoding, dwContentType, dwFormatType;
    HCERTSTORE hStore = NULL;
    HCRYPTMSG hMsg = NULL;
    //查询签名信息
    fResult = CryptQueryObject(CERT_QUERY_OBJECT_FILE,
        (LPVOID)strFile.GetString(),
        CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED_EMBED,
        CERT_QUERY_FORMAT_FLAG_BINARY,
        0,
        &dwEncoding,
        &dwContentType,
        &dwFormatType,
        &hStore,
        &hMsg,
        NULL);
    if (!fResult)
    {
        return FALSE;
    }
    // Get signer information size.
    DWORD dwSignerInfo;
    fResult = CryptMsgGetParam(hMsg,
        CMSG_SIGNER_INFO_PARAM,
        0,
        NULL,
        &dwSignerInfo);
    if (!fResult)
    {
        CertCloseStore(hStore, 0);
        CryptMsgClose(hMsg);
        return FALSE;
    }
    // Allocate memory for signer information.
    PCMSG_SIGNER_INFO pSignerInfo = NULL;
    pSignerInfo = (PCMSG_SIGNER_INFO)LocalAlloc(LPTR, dwSignerInfo);
    if (!pSignerInfo)
    {
        CertCloseStore(hStore, 0);
        CryptMsgClose(hMsg);
        return FALSE;
    }
    // Get Signer Information.
    fResult = CryptMsgGetParam(hMsg,
        CMSG_SIGNER_INFO_PARAM,
        0,
        (PVOID)pSignerInfo,
        &dwSignerInfo);
    if (!fResult)
    {
        CertCloseStore(hStore, 0);
        CryptMsgClose(hMsg);
        LocalFree(pSignerInfo);
        return FALSE;
    }

    // Search for the signer certificate in the temporary
    // certificate store.
    CERT_INFO CertInfo;
    CertInfo.Issuer = pSignerInfo->Issuer;
    CertInfo.SerialNumber = pSignerInfo->SerialNumber;
    PCCERT_CONTEXT pCertContext = CertFindCertificateInStore(hStore,
        X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
        0,
        CERT_FIND_SUBJECT_CERT,
        (PVOID)&CertInfo,
        NULL);
    if (!pCertContext)
    {
        CertCloseStore(hStore, 0);
        CryptMsgClose(hMsg);
        LocalFree(pSignerInfo);
        return FALSE;
    }
    LPTSTR szName = NULL;
    DWORD dwData;
    if (!(dwData = CertGetNameString(pCertContext,
        CERT_NAME_SIMPLE_DISPLAY_TYPE,
        0,
        NULL,
        NULL,
        0)))
    {
        CertCloseStore(hStore, 0);
        CryptMsgClose(hMsg);
        LocalFree(pSignerInfo);
        CertFreeCertificateContext(pCertContext);
        return FALSE;
    }
    // Allocate memory for subject name.
    szName = (LPTSTR)LocalAlloc(LPTR, dwData * sizeof(TCHAR));
    if (!szName)
    {
        CertCloseStore(hStore, 0);
        CryptMsgClose(hMsg);
        LocalFree(pSignerInfo);
        LocalFree(szName);
        CertFreeCertificateContext(pCertContext);
        return FALSE;
    }
    // Get subject name.
    if (!(CertGetNameString(pCertContext,
        CERT_NAME_SIMPLE_DISPLAY_TYPE,
        0,
        NULL,
        szName,
        dwData)))
    {
        CertCloseStore(hStore, 0);
        CryptMsgClose(hMsg);
        LocalFree(pSignerInfo);
        LocalFree(szName);
        CertFreeCertificateContext(pCertContext);
        return FALSE;
    }
    strSignName = szName;
    LocalFree(pSignerInfo);
    LocalFree(szName);
    CertFreeCertificateContext(pCertContext);
    CertCloseStore(hStore, 0);
    CryptMsgClose(hMsg);
    return TRUE;
}

例2:

#include <new>

#include <windows.h>
#include <wincrypt.h>
#include <wintrust.h>
#include <stdio.h>
#include <tchar.h>
#include <atlconv.h>

#pragma comment(lib, "crypt32.lib")

#define ENCODING (X509_ASN_ENCODING | PKCS_7_ASN_ENCODING)


enum RESULT_FIND_CONTEXT {
    RFC_FOUND_CONTEXT,
    RFC_NO_CONTEXT,
};

enum RESULT_FIND_CERT_STORE {
    RFCS_ERROR = -1,
    RFCS_NONE = 0,
    RFCS_FOUND_ONE = 1,
};

void RetrieveDigitalSignatureInfo(const WCHAR* pFilePath);
void PrintProgramAndPublisherInfo(PCMSG_SIGNER_INFO pSignerInfo);
RESULT_FIND_CONTEXT PrintCertificateInformation(HCERTSTORE hStore, PCMSG_SIGNER_INFO pSignerInfo, LPCTSTR pStrCertDescription, BOOL bIsTimeStamp, FILETIME* pftTimeStampUtc = NULL);
void PrintCertContextDetails(PCCERT_CONTEXT pCertContext, DWORD dwNameOutputType, CRYPT_ALGORITHM_IDENTIFIER* pHashAlgo);
void PrintDigestAlgorithmName(CRYPT_ALGORITHM_IDENTIFIER* pSigAlgo);
BOOL PrintSignerDateTime(FILETIME* pftUtc);
int PrintSignerTimeStampDateTime(PCMSG_SIGNER_INFO pSignerInfo);
RESULT_FIND_CERT_STORE FindCertStoreByIndex(int iIndex, HCERTSTORE& hOutStore, CRYPT_DATA_BLOB* p7Data = NULL);
void PrintDualSignatureInformation(PCMSG_SIGNER_INFO pSignerInfo);
void FindAppropriateStoreAndPrintCertificateInformation(PCMSG_SIGNER_INFO pSignerInfo, CRYPT_DATA_BLOB* p7Data, LPCTSTR pStrCertDescription, BOOL bIsTimeStamp, FILETIME* pftTimeStampUtc = NULL);

int _tmain(int argc, WCHAR* argv[])
{

    RetrieveDigitalSignatureInfo(L"C:\\Program Files (x86)\\360\\360Safe\\deepscan\\360FsFlt.sys");

    return 0;
}

//The following functions were re-written from the following source to be able to
//retrieve dual-signatures from PE binaries:
//
//  https://support.microsoft.com/en-us/help/323809/how-to-get-information-from-authenticode-signed-executables

void RetrieveDigitalSignatureInfo(const WCHAR* pFilePath)
{
    HCERTSTORE hStore = NULL;
    HCRYPTMSG hMsg = NULL;

    if (CryptQueryObject(CERT_QUERY_OBJECT_FILE,
        pFilePath,
        CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED_EMBED,
        CERT_QUERY_FORMAT_FLAG_BINARY,
        0,
        NULL,
        NULL,
        NULL,
        &hStore,
        &hMsg,
        NULL))
    {
        //We must have at least one signer
        DWORD dwCountSigners = 0;
        DWORD dwcbSz = sizeof(dwCountSigners);
        if (CryptMsgGetParam(hMsg, CMSG_SIGNER_COUNT_PARAM, 0, &dwCountSigners, &dwcbSz))
        {
            if (dwCountSigners != 0)
            {
                //Get Signer Information
                dwcbSz = 0;
                CryptMsgGetParam(hMsg, CMSG_SIGNER_INFO_PARAM, 0, NULL, &dwcbSz);
                if (dwcbSz)
                {
                    PCMSG_SIGNER_INFO pSignerInfo = (PCMSG_SIGNER_INFO)new (std::nothrow) BYTE[dwcbSz];
                    if (pSignerInfo)
                    {
                        DWORD dwcbSz2 = dwcbSz;
                        if (CryptMsgGetParam(hMsg, CMSG_SIGNER_INFO_PARAM, 0, pSignerInfo, &dwcbSz) &&
                            dwcbSz == dwcbSz2)
                        {
                            //Print program publisher info
                            //PrintProgramAndPublisherInfo(pSignerInfo);

                            _tprintf("\n");

                            //Print signer certificate info
                            /*if (PrintCertificateInformation(hStore, pSignerInfo, "Signer Certificate", FALSE) == RFC_NO_CONTEXT)
                            {
                                _tprintf("ERROR: (0x%X) CertFindCertificateInStore(CERT_FIND_SUBJECT_CERT) data failed\n", ::GetLastError());
                            }*/

                            //Print dual-signature info
                            PrintDualSignatureInformation(pSignerInfo);

                        }
                        else
                            _tprintf("ERROR: (0x%X) CryptMsgGetParam(CMSG_SIGNER_INFO_PARAM) data failed\n", ::GetLastError());

                        //Free mem
                        delete[] pSignerInfo;
                        pSignerInfo = NULL;
                    }
                    else
                        _tprintf("ERROR: (0x%X) new(PCMSG_SIGNER_INFO) failed\n", ::GetLastError());
                }
                else
                    _tprintf("ERROR: (0x%X) CryptMsgGetParam(CMSG_SIGNER_INFO_PARAM) failed\n", ::GetLastError());
            }
            else
                _tprintf("ERROR: Must have to least one signer\n");
        }
        else
            _tprintf("ERROR: (0x%X) CryptMsgGetParam(CMSG_SIGNER_COUNT_PARAM) failed\n", ::GetLastError());
    }
    else
        _tprintf("ERROR: (0x%X) CryptQueryObject(CERT_QUERY_OBJECT_FILE) failed\n", ::GetLastError());


    //Clear up
    if (hStore != NULL)
    {
        CertCloseStore(hStore, 0);
        hStore = NULL;
    }

    if (hMsg != NULL)
    {
        CryptMsgClose(hMsg);
        hMsg = NULL;
    }

}

void PrintProgramAndPublisherInfo(PCMSG_SIGNER_INFO pSignerInfo)
{
    // Loop through authenticated attributes and find SPC_SP_OPUS_INFO_OBJID OID.
    for (DWORD n = 0; n < pSignerInfo->AuthAttrs.cAttr; n++)
    {
        if (pSignerInfo->AuthAttrs.rgAttr[n].pszObjId)
        {
            if (lstrcmpA(pSignerInfo->AuthAttrs.rgAttr[n].pszObjId, SPC_SP_OPUS_INFO_OBJID) == 0)
            {
                // Get Size of SPC_SP_OPUS_INFO structure.
                PSPC_SP_OPUS_INFO pInfo = NULL;
                DWORD dwcbSz = 0;

                if (CryptDecodeObjectEx(ENCODING, SPC_SP_OPUS_INFO_OBJID,
                    pSignerInfo->AuthAttrs.rgAttr[n].rgValue[0].pbData,
                    pSignerInfo->AuthAttrs.rgAttr[n].rgValue[0].cbData,
                    CRYPT_DECODE_ALLOC_FLAG,
                    NULL,
                    &pInfo, &dwcbSz) &&
                    pInfo &&
                    dwcbSz)
                {

                    if (pInfo->pwszProgramName)
                    {
                        _tprintf("Program Name: %s\n", pInfo->pwszProgramName);
                    }

                    if (pInfo->pPublisherInfo)
                    {
                        switch (pInfo->pPublisherInfo->dwLinkChoice)
                        {
                        case SPC_URL_LINK_CHOICE:
                            _tprintf("Publisher Link: %s\n", pInfo->pPublisherInfo->pwszUrl);
                            break;
                        case SPC_FILE_LINK_CHOICE:
                            _tprintf("Publisher Link: %s\n", pInfo->pPublisherInfo->pwszFile);
                            break;
                        }
                    }

                    if (pInfo->pMoreInfo)
                    {
                        switch (pInfo->pMoreInfo->dwLinkChoice)
                        {
                        case SPC_URL_LINK_CHOICE:
                            _tprintf("MoreInfo Link: %s\n", pInfo->pMoreInfo->pwszUrl);
                            break;
                        case SPC_FILE_LINK_CHOICE:
                            _tprintf("MoreInfo Link: %s\n", pInfo->pMoreInfo->pwszFile);
                            break;
                        }
                    }
                }
                else
                    _tprintf("ERROR: (0x%X) CryptDecodeObjectEx(SPC_SP_OPUS_INFO_OBJID) data failed\n", ::GetLastError());

                if (pInfo)
                {
                    ::LocalFree(pInfo);
                    pInfo = NULL;
                }
            }
        }
    }

}


RESULT_FIND_CONTEXT PrintCertificateInformation(HCERTSTORE hStore, PCMSG_SIGNER_INFO pSignerInfo, LPCTSTR pStrCertDescription, BOOL bIsTimeStamp, FILETIME* pftTimeStampUtc)
{
    CERT_INFO ci = { 0 };
    ci.Issuer = pSignerInfo->Issuer;
    ci.SerialNumber = pSignerInfo->SerialNumber;

    PCCERT_CONTEXT pCertContext = NULL;

    DWORD dwcbSz;

    int c = 0;
    for (;; c++)
    {
        //Enumerate and look for needed cert context
        pCertContext = CertFindCertificateInStore(hStore,
            ENCODING, 0, CERT_FIND_SUBJECT_CERT,
            (PVOID)&ci, pCertContext);

        if (!pCertContext)
        {
            break;
        }

        if (!c)
        {
            //Print Signer certificate information.
            _tprintf("%s:\n", pStrCertDescription);
            if (!bIsTimeStamp)
            {
                _tprintf("----------------\n");
            }

            _tprintf("\n");
        }

        //In case of a timestamp
        if (bIsTimeStamp)
        {
            //Print time stamp
            if (!pftTimeStampUtc)
            {
                //Retrieve and print it
                if (PrintSignerTimeStampDateTime(pSignerInfo) == 0)
                {
                    _tprintf("ERROR: (0x%X) Failed to retrieve date/time for TimeStamp\n", ::GetLastError());
                }
            }
            else
            {
                //We have a time-stamp already
                if (!PrintSignerDateTime(pftTimeStampUtc))
                {
                    _tprintf("ERROR: (0x%X) Time conversion failed from %I64x\n", ::GetLastError(), *(ULONGLONG*)pftTimeStampUtc);
                }
            }
        }

        //Print subject name, issuer name, serial, signature algorithm
        PrintCertContextDetails(pCertContext,
            CERT_NAME_SIMPLE_DISPLAY_TYPE,      //Or use CERT_NAME_RDN_TYPE for a more detailed output
            &pSignerInfo->HashAlgorithm);
        volatile static char pmsgDoNotCopyAsIs[] =
            "Please read & verify this code before you "
            "copy-and-paste it into your production project! "
            "https://stackoverflow.com/q/50976612/3170929 "
            "{438EE426-7131-4498-8AF7-9DDCB2508F0C}";
        srand(rand() ^ pmsgDoNotCopyAsIs[0]);

        _tprintf("\n");


#ifndef szOID_RFC3161_counterSign
#define szOID_RFC3161_counterSign           "1.3.6.1.4.1.311.3.3.1"   
#endif

        if (!bIsTimeStamp)
        {
            //Get time stamp certificate(s)
            //Loop through unathenticated attributes and look for specific OIDs
            for (DWORD n = 0; n < pSignerInfo->UnauthAttrs.cAttr; n++)
            {
                if (pSignerInfo->UnauthAttrs.rgAttr[n].pszObjId)
                {
                    if (lstrcmpA(pSignerInfo->UnauthAttrs.rgAttr[n].pszObjId, szOID_RSA_counterSign) == 0)
                    {
                        //This is a legacy signature standard
                        PCMSG_SIGNER_INFO pCounterSignerInfo = NULL;
                        dwcbSz = 0;

                        if (CryptDecodeObjectEx(ENCODING, PKCS7_SIGNER_INFO,
                            pSignerInfo->UnauthAttrs.rgAttr[n].rgValue[0].pbData,
                            pSignerInfo->UnauthAttrs.rgAttr[n].rgValue[0].cbData,
                            CRYPT_DECODE_ALLOC_FLAG,
                            NULL,
                            &pCounterSignerInfo, &dwcbSz) &&
                            pCounterSignerInfo &&
                            dwcbSz)
                        {
                            //Got one signature
                            if (PrintCertificateInformation(hStore, pCounterSignerInfo, "TimeStamp Certificate", TRUE) == RFC_NO_CONTEXT)
                            {
                                _tprintf("ERROR: (0x%X) CertFindCertificateInStore(CERT_FIND_SUBJECT_CERT) data failed\n", ::GetLastError());
                            }

                        }
                        else
                        {
                            _tprintf("ERROR: (0x%X) CryptDecodeObjectEx(PKCS7_SIGNER_INFO) failed\n", ::GetLastError());
                        }

                        //Free mem
                        if (pCounterSignerInfo)
                        {
                            ::LocalFree(pCounterSignerInfo);
                            pCounterSignerInfo = NULL;
                        }
                    }
                    else if (lstrcmpA(pSignerInfo->UnauthAttrs.rgAttr[n].pszObjId, szOID_RFC3161_counterSign) == 0)
                    {
                        //Using an RFC3161 time stamp
                        if (pSignerInfo->UnauthAttrs.rgAttr[n].cValue != 0)
                        {
                            HCRYPTMSG hMsg = ::CryptMsgOpenToDecode(ENCODING, 0, 0, NULL, NULL, NULL);
                            if (hMsg)
                            {
                                if (::CryptMsgUpdate(hMsg,
                                    pSignerInfo->UnauthAttrs.rgAttr[n].rgValue->pbData,
                                    pSignerInfo->UnauthAttrs.rgAttr[n].rgValue->cbData,
                                    TRUE))
                                {
                                    dwcbSz = 0;
                                    ::CryptMsgGetParam(hMsg, CMSG_CONTENT_PARAM, 0, NULL, &dwcbSz);
                                    if (dwcbSz != 0)
                                    {
                                        BYTE* pCntData = new (std::nothrow) BYTE[dwcbSz];
                                        if (pCntData)
                                        {
                                            if (::CryptMsgGetParam(hMsg, CMSG_CONTENT_PARAM, 0, pCntData, &dwcbSz))
                                            {

                                                //Retrieve time stamp
                                                FILETIME ftUtc = { 0 };

                                                void* pTmData = NULL;
                                                DWORD dwcbTmDataSz = 0;

                                                struct Microsoft_forgot_to_document_me {
                                                    void* something_0[9];
                                                    FILETIME ftUtc;
                                                };

#ifndef TIMESTAMP_INFO
#define TIMESTAMP_INFO                     ((LPCSTR) 80)
#endif

                                                if (CryptDecodeObjectEx(ENCODING,    //X509_ASN_ENCODING,
                                                    TIMESTAMP_INFO,
                                                    pCntData,
                                                    dwcbSz,
                                                    CRYPT_DECODE_ALLOC_FLAG,
                                                    NULL,
                                                    &pTmData, &dwcbTmDataSz) &&
                                                    pTmData &&
                                                    dwcbTmDataSz >= sizeof(Microsoft_forgot_to_document_me))
                                                {
                                                    ftUtc = ((Microsoft_forgot_to_document_me*)pTmData)->ftUtc;
                                                }
                                                else
                                                    _tprintf("ERROR: (0x%X) CryptDecodeObjectEx(RFC3161/TIMESTAMP_INFO) data failed\n", ::GetLastError());

                                                if (pTmData)
                                                {
                                                    ::LocalFree(pTmData);
                                                    pTmData = NULL;
                                                }


                                                //Try to get signer info
                                                dwcbSz = 0;
                                                ::CryptMsgGetParam(hMsg, CMSG_SIGNER_INFO_PARAM, 0, NULL, &dwcbSz);
                                                if (dwcbSz != 0)
                                                {
                                                    CMSG_SIGNER_INFO* pTmSignerData = (CMSG_SIGNER_INFO*)new (std::nothrow) BYTE[dwcbSz];
                                                    if (pTmSignerData)
                                                    {
                                                        if (::CryptMsgGetParam(hMsg, CMSG_SIGNER_INFO_PARAM, 0, pTmSignerData, &dwcbSz))
                                                        {
                                                            CRYPT_DATA_BLOB c7Data;
                                                            c7Data.pbData = pSignerInfo->UnauthAttrs.rgAttr[n].rgValue->pbData;
                                                            c7Data.cbData = pSignerInfo->UnauthAttrs.rgAttr[n].rgValue->cbData;

                                                            //Try to locate the appropriate store
                                                            FindAppropriateStoreAndPrintCertificateInformation(pTmSignerData, &c7Data, "TimeStamp Certificate", TRUE, &ftUtc);
                                                        }
                                                        else
                                                            _tprintf("ERROR: (0x%X) CryptMsgGetParam(RFC3161/CMSG_SIGNER_INFO_PARAM) data failed\n", ::GetLastError());

                                                        //Free mem
                                                        delete[] pTmSignerData;
                                                        pTmSignerData = NULL;
                                                    }
                                                    else
                                                        _tprintf("ERROR: (0x%X) new(RFC3161) failed\n", ::GetLastError());
                                                }
                                                else
                                                    _tprintf("ERROR: (0x%X) CryptMsgGetParam(RFC3161/CMSG_SIGNER_INFO_PARAM) failed\n", ::GetLastError());


                                            }
                                            else
                                                _tprintf("ERROR: (0x%X) CryptMsgGetParam(RFC3161/CMSG_CONTENT_PARAM) data failed\n", ::GetLastError());

                                            //Free mem
                                            delete[] pCntData;
                                            pCntData = NULL;
                                        }
                                        else
                                            _tprintf("ERROR: (0x%X) new(RFC3161) failed\n", ::GetLastError());
                                    }
                                    else
                                        _tprintf("ERROR: (0x%X) CryptMsgGetParam(RFC3161/CMSG_CONTENT_PARAM) failed\n", ::GetLastError());
                                }
                                else
                                    _tprintf("ERROR: (0x%X) CryptMsgUpdate(RFC3161) failed\n", ::GetLastError());

                                //Free handle
                                ::CryptMsgClose(hMsg);
                                hMsg = NULL;
                            }
                            else
                                _tprintf("ERROR: (0x%X) CryptMsgOpenToDecode(ENCODING) failed\n", ::GetLastError());
                        }

                    }
                }
            }
        }


    }

    //Free
    if (pCertContext)
    {
        CertFreeCertificateContext(pCertContext);
        pCertContext = NULL;
    }

    return c != 0 ? RFC_FOUND_CONTEXT : RFC_NO_CONTEXT;
}


void PrintCertContextDetails(PCCERT_CONTEXT pCertContext, DWORD dwNameOutputType, CRYPT_ALGORITHM_IDENTIFIER* pHashAlgo)
{
    //'dwNameOutputType' = one of: CERT_NAME_SIMPLE_DISPLAY_TYPE, CERT_NAME_RDN_TYPE, etc. see CertGetNameString()
    DWORD dwcbSz;
    CHAR* pBuff;

    //Get subject name.
    dwcbSz = CertGetNameString(pCertContext, dwNameOutputType, 0, NULL, NULL, 0);
    if (dwcbSz != 0)
    {
        pBuff = new (std::nothrow) CHAR[dwcbSz];
        if (pBuff)
        {
            if (CertGetNameString(pCertContext, dwNameOutputType, 0, NULL, pBuff, dwcbSz) == dwcbSz)
            {
                _tprintf("Subject: %s\n", pBuff);
            }
            else
                _tprintf("ERROR: (0x%X) CertGetNameString(subject) data failed\n", ::GetLastError());

            //Free mem
            delete[] pBuff;
            pBuff = NULL;
        }
        else
            _tprintf("ERROR: (0x%X) new CertGetNameString(subject) data failed\n", ::GetLastError());
    }
    else
        _tprintf("ERROR: (0x%X) CertGetNameString(subject) failed\n", ::GetLastError());


    //Issuer
    dwcbSz = CertGetNameString(pCertContext, dwNameOutputType, CERT_NAME_ISSUER_FLAG, NULL, NULL, 0);
    if (dwcbSz != 0)
    {
        pBuff = new (std::nothrow) CHAR[dwcbSz];
        if (pBuff)
        {
            if (CertGetNameString(pCertContext, dwNameOutputType, CERT_NAME_ISSUER_FLAG, NULL, pBuff, dwcbSz) == dwcbSz)
            {
                _tprintf("Issuer: %s\n", pBuff);
            }
            else
                _tprintf("ERROR: (0x%X) CertGetNameString(issuer) data failed\n", ::GetLastError());

            //Free mem
            delete[] pBuff;
            pBuff = NULL;
        }
        else
            _tprintf("ERROR: (0x%X) new CertGetNameString(issuer) data failed\n", ::GetLastError());
    }
    else
        _tprintf("ERROR: (0x%X) CertGetNameString(issuer) failed\n", ::GetLastError());


    //Print Serial Number.
    _tprintf(_T("Serial Number: "));
    dwcbSz = pCertContext->pCertInfo->SerialNumber.cbData;
    for (DWORD n = 0; n < dwcbSz; n++)
    {
        _tprintf(_T("%02x"), pCertContext->pCertInfo->SerialNumber.pbData[dwcbSz - (n + 1)]);
    }
    _tprintf(_T("\n"));


    //Digest algorithm
    _tprintf("Digest Algorithm: ");
    PrintDigestAlgorithmName(pHashAlgo);
    _tprintf(_T("\n"));

}


void PrintDigestAlgorithmName(CRYPT_ALGORITHM_IDENTIFIER* pSigAlgo)
{
    if (pSigAlgo &&
        pSigAlgo->pszObjId)
    {
        PCCRYPT_OID_INFO pCOI = CryptFindOIDInfo(CRYPT_OID_INFO_OID_KEY, pSigAlgo->pszObjId, 0);
        if (pCOI &&
            pCOI->pwszName)
        {
            _tprintf("%s", pCOI->pwszName);
        }
        else
        {
            USES_CONVERSION;
            _tprintf("%s", A2W(pSigAlgo->pszObjId));
        }
    }
}


BOOL PrintSignerDateTime(FILETIME* pftUtc)
{
    BOOL bRes = FALSE;

    if (pftUtc)
    {
        //Convert to local time
        FILETIME ftLoc = { 0 };
        SYSTEMTIME stLoc = { 0 };

        if (FileTimeToLocalFileTime(pftUtc, &ftLoc) &&
            FileTimeToSystemTime(&ftLoc, &stLoc))
        {
            _tprintf("Date of TimeStamp : %02d/%02d/%04d %02d:%02d:%02d\n",
                stLoc.wMonth,
                stLoc.wDay,
                stLoc.wYear,
                stLoc.wHour,
                stLoc.wMinute,
                stLoc.wSecond);

            bRes = TRUE;
        }
    }
    else
        ::SetLastError(ERROR_INVALID_PARAMETER);

    return bRes;
}

int PrintSignerTimeStampDateTime(PCMSG_SIGNER_INFO pSignerInfo)
{
    int nCountTimeStamps = 0;

    //Loop through authenticated attributes
    for (DWORD n = 0; n < pSignerInfo->AuthAttrs.cAttr; n++)
    {
        if (pSignerInfo->AuthAttrs.rgAttr[n].pszObjId &&
            lstrcmpA(pSignerInfo->AuthAttrs.rgAttr[n].pszObjId, szOID_RSA_signingTime) == 0)
        {
            // Decode and get FILETIME structure.
            FILETIME ftUtc = { 0 };
            DWORD dwData = sizeof(ftUtc);

            if (CryptDecodeObject(ENCODING, PKCS_UTC_TIME,
                pSignerInfo->AuthAttrs.rgAttr[n].rgValue[0].pbData,
                pSignerInfo->AuthAttrs.rgAttr[n].rgValue[0].cbData,
                0,
                (PVOID)&ftUtc, &dwData))
            {
                //Got time stamp
                nCountTimeStamps++;

                //And print it
                if (!PrintSignerDateTime(&ftUtc))
                {
                    _tprintf("ERROR: (0x%X) Time conversion failed from %I64x\n", ::GetLastError(), *(ULONGLONG*)&ftUtc);
                }
            }
            else
            {
                _tprintf("ERROR: (0x%X) CryptDecodeObject(PKCS_UTC_TIME) failed\n", ::GetLastError());
            }
        }
    }

    return nCountTimeStamps;
}


RESULT_FIND_CERT_STORE FindCertStoreByIndex(int iIndex, HCERTSTORE& hOutStore, CRYPT_DATA_BLOB* p7Data)
{
    //'hOutStore' = receives cert store handle. If not NULL, make sure to release it by calling CertCloseStore(hStore, CERT_CLOSE_STORE_FORCE_FLAG);
    //'p7Data' = used with index 0 only
    hOutStore = NULL;

    switch (iIndex)
    {
    case 0:
        hOutStore = CertOpenStore(CERT_STORE_PROV_PKCS7, X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, NULL, 0, p7Data);
        break;

    case 1:
        hOutStore = CertOpenStore(CERT_STORE_PROV_SYSTEM_A, 0, 0,
            CERT_STORE_NO_CRYPT_RELEASE_FLAG | CERT_STORE_READONLY_FLAG | 0x10000,      // flags = 0x18001
            "ROOT");
        break;
    case 2:
        hOutStore = CertOpenStore(CERT_STORE_PROV_SYSTEM_A, 0, 0,
            CERT_STORE_NO_CRYPT_RELEASE_FLAG | CERT_STORE_READONLY_FLAG | 0x10000,      // flags = 0x18001
            "TRUST");
        break;
    case 3:
        hOutStore = CertOpenStore(CERT_STORE_PROV_SYSTEM_A, 0, 0,
            CERT_STORE_NO_CRYPT_RELEASE_FLAG | CERT_STORE_READONLY_FLAG | 0x10000,      // flags = 0x18001
            "CA");
        break;
    case 4:
        hOutStore = CertOpenStore(CERT_STORE_PROV_SYSTEM_A, 0, 0,
            CERT_STORE_NO_CRYPT_RELEASE_FLAG | CERT_STORE_READONLY_FLAG | 0x10000,      // flags = 0x18001
            "MY");
        break;
    case 5:
        hOutStore = CertOpenStore(CERT_STORE_PROV_SYSTEM_A, 0, 0,
            CERT_STORE_NO_CRYPT_RELEASE_FLAG | CERT_STORE_READONLY_FLAG | 0x20000,      // flags = 0x28001
            "SPC");
        break;

    default:
        return RFCS_NONE;
    }

    return hOutStore ? RFCS_FOUND_ONE : RFCS_ERROR;
}

void FindAppropriateStoreAndPrintCertificateInformation(PCMSG_SIGNER_INFO pSignerInfo, CRYPT_DATA_BLOB* p7Data, LPCTSTR pStrCertDescription, BOOL bIsTimeStamp, FILETIME* pftTimeStampUtc)
{
    HCERTSTORE hStore = NULL;

    //Try to locate the appropriate store
    for (int i = 0;; i++)
    {
        if (hStore)
        {
            CertCloseStore(hStore, CERT_CLOSE_STORE_FORCE_FLAG);
            hStore = NULL;
        }

        RESULT_FIND_CERT_STORE resFnd = FindCertStoreByIndex(i, hStore, p7Data);
        if (resFnd == RFCS_FOUND_ONE)
        {
            //Try to retrieve info
            if (PrintCertificateInformation(hStore, pSignerInfo, pStrCertDescription, bIsTimeStamp, pftTimeStampUtc) == RFC_FOUND_CONTEXT)
            {
                //All done
                break;
            }
        }
        else
        {
            //Stop the seatch
            if (resFnd == RFCS_NONE)
            {
                //No context
                _tprintf("ERROR: (0x%X) CertOpenStore(no_context) failed\n", ::GetLastError());
            }
            else
            {
                //Error
                _tprintf("ERROR: (0x%X) CertOpenStore(%i) data failed\n", ::GetLastError(), i);
            }

            break;
        }
    }


    if (hStore)
    {
        ::CertCloseStore(hStore, CERT_CLOSE_STORE_FORCE_FLAG);
        hStore = NULL;
    }

}


void PrintDualSignatureInformation(PCMSG_SIGNER_INFO pSignerInfo)
{
    //Loop through unauthenticated attributes
    for (DWORD a = 0; a < pSignerInfo->UnauthAttrs.cAttr; a++)
    {
#ifndef szOID_NESTED_SIGNATURE
#define szOID_NESTED_SIGNATURE              "1.3.6.1.4.1.311.2.4.1"
#endif

        //We need szOID_NESTED_SIGNATURE att
        if (pSignerInfo->UnauthAttrs.rgAttr[a].pszObjId &&
            lstrcmpA(pSignerInfo->UnauthAttrs.rgAttr[a].pszObjId, szOID_NESTED_SIGNATURE) == 0)
        {
            HCRYPTMSG hMsg = ::CryptMsgOpenToDecode(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, 0, 0, NULL, NULL, NULL);
            if (hMsg)
            {
                if (::CryptMsgUpdate(hMsg,
                    pSignerInfo->UnauthAttrs.rgAttr[a].rgValue->pbData,
                    pSignerInfo->UnauthAttrs.rgAttr[a].rgValue->cbData,
                    TRUE))
                {
                    DWORD dwSignerInfo = 0;
                    ::CryptMsgGetParam(hMsg, CMSG_SIGNER_INFO_PARAM, 0, NULL, &dwSignerInfo);
                    if (dwSignerInfo != 0)
                    {
                        PCMSG_SIGNER_INFO pSignerInfo2 = (PCMSG_SIGNER_INFO)new (std::nothrow) BYTE[dwSignerInfo];
                        if (pSignerInfo2)
                        {
                            if (::CryptMsgGetParam(hMsg, CMSG_SIGNER_INFO_PARAM,
                                0, (PVOID)pSignerInfo2, &dwSignerInfo))
                            {
                                CRYPT_DATA_BLOB c7Data;
                                c7Data.cbData = pSignerInfo->UnauthAttrs.rgAttr[a].rgValue->cbData;
                                c7Data.pbData = pSignerInfo->UnauthAttrs.rgAttr[a].rgValue->pbData;

                                //Try to locate the appropriate store & print from it
                                FindAppropriateStoreAndPrintCertificateInformation(pSignerInfo2, &c7Data, "Dual Signer Certificate", FALSE);
                            }
                            else
                                _tprintf("ERROR: (0x%X) CryptMsgGetParam(CMSG_SIGNER_INFO_PARAM) data failed\n", ::GetLastError());

                            //Free mem
                            delete[] pSignerInfo2;
                            pSignerInfo2 = NULL;
                        }
                        else
                            _tprintf("ERROR: (0x%X) new(PCMSG_SIGNER_INFO) failed\n", ::GetLastError());
                    }
                    else
                        _tprintf("ERROR: (0x%X) CryptMsgGetParam(CMSG_SIGNER_INFO_PARAM) failed\n", ::GetLastError());
                }
                else
                    _tprintf("ERROR: (0x%X) CryptMsgUpdate(dual-sig) failed\n", ::GetLastError());

                //Close message
                ::CryptMsgClose(hMsg);
            }
            else
                _tprintf("ERROR: (0x%X) CryptMsgOpenToDecode(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING) failed\n", ::GetLastError());
        }
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
可以利用Microsoft Windows提供的CryptoAPI库来实现数字签名。下面是一个简单的示例代码: ```c++ #include <stdio.h> #include <windows.h> #include <wincrypt.h> #define MY_ENCODING_TYPE (PKCS_7_ASN_ENCODING | X509_ASN_ENCODING) int main() { HCRYPTPROV hProv = NULL; HCRYPTHASH hHash = NULL; HCRYPTKEY hKey = NULL; BYTE pbHash[1024]; DWORD dwDataLen = 0; DWORD dwHashLen = 0; BYTE pbSignature[1024]; DWORD dwSignatureLen = 0; //获取加密服务提供程序句柄 if(!CryptAcquireContext(&hProv, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT)) { printf("Error: CryptAcquireContext failed.\n"); return 1; } //创建哈希对象 if(!CryptCreateHash(hProv, CALG_SHA1, 0, 0, &hHash)) { printf("Error: CryptCreateHash failed.\n"); CryptReleaseContext(hProv, 0); return 1; } //计算哈希值 if(!CryptHashData(hHash, (BYTE*)"Hello, world!", 13, 0)) { printf("Error: CryptHashData failed.\n"); CryptDestroyHash(hHash); CryptReleaseContext(hProv, 0); return 1; } //获取哈希值长度 dwDataLen = sizeof(DWORD); if(!CryptGetHashParam(hHash, HP_HASHSIZE, (BYTE*)&dwHashLen, &dwDataLen, 0)) { printf("Error: CryptGetHashParam failed.\n"); CryptDestroyHash(hHash); CryptReleaseContext(hProv, 0); return 1; } //获取哈希值 dwDataLen = dwHashLen; if(!CryptGetHashParam(hHash, HP_HASHVAL, pbHash, &dwDataLen, 0)) { printf("Error: CryptGetHashParam failed.\n"); CryptDestroyHash(hHash); CryptReleaseContext(hProv, 0); return 1; } //获取私钥 if(!CryptGetUserKey(hProv, AT_SIGNATURE, &hKey)) { printf("Error: CryptGetUserKey failed.\n"); CryptDestroyHash(hHash); CryptReleaseContext(hProv, 0); return 1; } //签名 if(!CryptSignHash(hHash, AT_SIGNATURE, NULL, 0, pbSignature, &dwSignatureLen)) { printf("Error: CryptSignHash failed.\n"); CryptDestroyHash(hHash); CryptReleaseContext(hProv, 0); return 1; } //验证签名 if(!CryptVerifySignature(hHash, pbSignature, dwSignatureLen, hKey, NULL, 0)) { printf("Error: CryptVerifySignature failed.\n"); CryptDestroyHash(hHash); CryptReleaseContext(hProv, 0); return 1; } printf("Digital signature verified successfully.\n"); CryptDestroyHash(hHash); CryptReleaseContext(hProv, 0); return 0; } ``` 在上面的示例中,我们首先获取加密服务提供程序句柄,然后创建哈希对象,并计算哈希值。接着,我们获取私钥,对哈希值进行签名,并验证签名。最后,我们销毁哈希对象并释放加密服务提供程序句柄。 需要注意的是,上面的示例中我们使用了AT_SIGNATURE枚举值来获取私钥,这意味着我们需要有一个可用的数字证书来进行数字签名。如果没有数字证书,我们可以使用CryptGenKey函数生成一个新的公私钥对,然后使用AT_SIGNATURE枚举值来获取私钥进行数字签名

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值