如何将代码签名算法的 OID 从 CRYPT_ALGORITHM_IDENTIFIER 转换为人类可读的字符串?

How to convert OID of a code-signing algorithm from CRYPT_ALGORITHM_IDENTIFIER to a human readable string?

当我 retrieving a code signing signature from an executable file on Windows, the CERT_CONTEXT of the certificate points to the CERT_INFO 时,有 CRYPT_ALGORITHM_IDENTIFIER SignatureAlgorithm 成员包含用于签名的算法。

如何将其转换为人类可读的格式?

比如SignatureAlgorithm.pszObjId可以设置为"1.2.840.113549.1.1.11"字符串,根据this long list就是szOID_RSA_SHA256RSA。我想我可以为它做一个很长的 switch 语句,然后 link 到 "sha256",但我宁愿避免它,因为我不知道这些值中的大部分是什么。有没有 API 可以为我做这一切的人?

使用 CryptFindOIDInfo 获取有关 OID 的信息,包括显示名称和 CNG 算法标识符字符串:

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);
        }
    }
}

上扩展。您还可以从调用 WinVerifyTrust() 的结果中获取此信息。它深深嵌套在 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);
        }
    }
}

注意:为简洁起见省略了详细的错误检查!

注意2:从Win 8开始(和打补丁的Win 7),WinVerifyTrust可用于验证和获取有关文件的多个签名的信息,更多信息在 this Q&A.