1

When I'm retrieving a code signing signature from an executable file on Windows, the CERT_CONTEXT of the certificate points to the CERT_INFO, that has CRYPT_ALGORITHM_IDENTIFIER SignatureAlgorithm member that contains the algorithm used for signing.

How do I convert that to a human readable form as such?

enter image description here

For instance, SignatureAlgorithm.pszObjId may be set to "1.2.840.113549.1.1.11" string, which is szOID_RSA_SHA256RSA according to this long list. I guess I can make a very long switch statement for it, and link it to "sha256", but I'd rather avoid it since I don't know what most of those values are. Is there an API that can do all that for me?

MikeF
  • 1,021
  • 9
  • 29

2 Answers2

2

Use CryptFindOIDInfo to get information about a OID including the display name and the CNG algorithm identifier string:

void PrintSigAlgoName(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(_T("%ls"), pCOI->pwszName);
        }
        else
        {
            _tprintf(_T("%hs"), pSigAlgo->pszObjId);
        }
    }
}
Anders
  • 97,548
  • 12
  • 110
  • 164
  • Thanks. It worked. Although it would be nice to have a code example for that function. It's not easy to follow how exactly to use it. Wanna copy it from my edited answer above and I'll mark it here? – MikeF Jun 21 '18 at 18:59
0

Expanding on the answer of Anders. You can also get this information from the result of a call to WinVerifyTrust(). It is deeply nested inside CRYPT_PROVIDER_DATA:

GUID policyGUID = WINTRUST_ACTION_GENERIC_VERIFY_V2;
WINTRUST_DATA trustData;
// omitted: prepare trustData

DWORD lStatus = ::WinVerifyTrust( NULL, &policyGUID, &trustData );

if( lStatus == ERROR_SUCCESS )
{
    CRYPT_PROVIDER_DATA* pData = ::WTHelperProvDataFromStateData( trustData.hWVTStateData ); 

    if( pData && pData->pPDSip && pData->pPDSip->psIndirectData && 
        pData->pPDSip->psIndirectData->DigestAlgorithm.pszObjId )
    {
        CRYPT_ALGORITHM_IDENTIFIER const& sigAlgo = pData->pPDSip->psIndirectData->DigestAlgorithm;

        PCCRYPT_OID_INFO pCOI = ::CryptFindOIDInfo( CRYPT_OID_INFO_OID_KEY, sigAlgo.pszObjId, 0 ); 

        if(pCOI && pCOI->pwszName)
        {
            _tprintf(_T("%ls"), pCOI->pwszName);
        }
        else
        {
            _tprintf(_T("%hs"), sigAlgo.pszObjId);
        }
    }
}

Note: Detailed error checking omitted for brevity!

Note2: From Win 8 onwards (and patched Win 7), WinVerifyTrust can be used to verify and get information about multiple signatures of a file, more info in this Q&A.

zett42
  • 25,437
  • 3
  • 35
  • 72