如何将代码签名算法的 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.
当我 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.