验证证书是否支持签名方法
本主题介绍如何验证证书是否支持特定的签名方法。
Microsoft Crypto API 中的 CryptXmlEnumAlgorithmInfo 枚举证书的属性,并在此代码示例中用于枚举证书支持的签名方法。 若要使用 CryptXmlEnumAlgorithmInfo 枚举证书支持的签名方法,调用方必须在对 CryptXmlEnumAlgorithmInfo 的调用中提供一个回调方法和数据结构,使其能够将数据传递给回调方法。
下一个代码示例中使用的数据结构具有以下字段:
字段 | 说明 |
---|---|
userSignatureAlgorithmToCheck | 一个 LPWSTR 字段,指向包含要检查的签名算法 URI 的字符串。 |
certificateAlgorithmInfo | 一个指向 CRYPT_OID_INFO 结构的指针,包含证书支持的签名算法的相关信息。 |
userSignatureAlgorithmSupported | 一个布尔值,指示证书是否支持签名算法。 |
struct SignatureMethodData
{
LPCWSTR userSignatureAlgorithmToCheck;
PCCRYPT_OID_INFO certificateAlgorithmInfo;
BOOL userSignatureAlgorithmSupported;
};
检查证书的 Crypto API 方法使用回调方法将数据返回到调用方。 CryptXmlEnumAlgorithmInfo 枚举证书支持的签名方法,并调用每个签名方法的回调方法,直到回调方法返回 FALSE,或直到已枚举证书中的所有签名方法为止。
下一个代码示例中的回调方法搜索由 CryptXmlEnumAlgorithmInfo 传入的签名方法,该方法与调用方法提供的签名方法匹配。 找到匹配项时,回调方法检查系统是否也支持签名方法。 如果签名方法匹配并受系统支持,则签名方法将标记为“系统支持”,且回调方法返回 FALSE。
BOOL WINAPI
EnumSignatureMethodCallback (
__in const CRYPT_XML_ALGORITHM_INFO *certMethodInfo,
__inout_opt void *userArg
)
{
// MAX_ALG_ID_LEN is used to set the maximum length of the
// algorithm URI in the string comparison. The URI is not
// likely to be longer than 128 characters so a fixed-size
// buffer is used in this example.
// To make this function more robust, you might consider
// setting this value dynamically.
static const size_t MAX_ALG_ID_LEN = 128;
SignatureMethodData *certificateAlgorithmData = NULL;
if (NULL != userArg) {
// Assign user data to local data structure
certificateAlgorithmData = (SignatureMethodData*)userArg;
} else {
// Unable to continue this enumeration
// without data from calling method.
return FALSE;
}
// For each algorithm in the enumeration, check to see if the URI
// of the algorithm supported by the certificate matches the URI
// of the algorithm being tested.
int cmpResult = 0;
cmpResult = wcsncmp(
certMethodInfo->wszAlgorithmURI,
certificateAlgorithmData->userSignatureAlgorithmToCheck,
MAX_ALG_ID_LEN );
if ( 0 == cmpResult )
{
// This is a match...
// Check to see if the algorithm supported by the
// certificate matches any of the supported algorithms
// on the system.
cmpResult = wcsncmp(
certMethodInfo->wszCNGExtraAlgid,
certificateAlgorithmData->certificateAlgorithmInfo->pwszCNGAlgid,
MAX_ALG_ID_LEN );
if ( 0 == cmpResult )
{
// This is also a match so set the field in the data structure
// provided by the calling method.
certificateAlgorithmData->userSignatureAlgorithmSupported = TRUE;
// A match was found so there is no point in continuing
// the enumeration.
return FALSE;
}
}
// The enumeration stops when the callback method returns FALSE.
// If here, then return TRUE because a matching algorithm has
// not been found.
return TRUE;
}
以下代码示例将验证功能包装到单个方法中。 此方法返回一个布尔值,该值指示证书是否支持签名方法,以及签名方法是否受系统支持。
BOOL
SupportsSignatureAlgorithm (
__in LPCWSTR signingMethodToCheck,
__in PCCERT_CONTEXT certificateToCheck
)
{
HRESULT hr = S_OK;
// Initialize the structure that contains the
// information about the signature algorithm to check
SignatureMethodData certificateAlgorithmData;
certificateAlgorithmData.userSignatureAlgorithmSupported =
FALSE;
certificateAlgorithmData.userSignatureAlgorithmToCheck =
signingMethodToCheck;
// Call the crypt API to get information about the algorithms
// that are supported by the certificate and initialize
// certificateAlgorithmData
certificateAlgorithmData.certificateAlgorithmInfo = CryptFindOIDInfo (
CRYPT_OID_INFO_OID_KEY,
certificateToCheck->pCertInfo->SubjectPublicKeyInfo.Algorithm.pszObjId,
CRYPT_PUBKEY_ALG_OID_GROUP_ID | CRYPT_OID_PREFER_CNG_ALGID_FLAG);
if (certificateAlgorithmData.certificateAlgorithmInfo != NULL)
{
// Enumerate the algorithms that are supported by the
// certificate, and use our callback method to determine if
// the user supplied signature algorithm is supported by
// the certificate.
//
// Note that CRYPT_XML_GROUP_ID_SIGN is used to enumerate
// the signature methods
hr = CryptXmlEnumAlgorithmInfo(
CRYPT_XML_GROUP_ID_SIGN, // NOTE: CRYPT_XML_GROUP_ID_SIGN
CRYPT_XML_FLAG_DISABLE_EXTENSIONS,
(void*)&certificateAlgorithmData,
EnumSignatureMethodCallback);
// when the enumeration has returned successfully,
// certificateAlgorithmData.userSignatureAlgorithmSupported
// will be TRUE if the signing method is supported by
// the certificate
}
return certificateAlgorithmData.userSignatureAlgorithmSupported;
}
相关主题
-
后续步骤
-
已在本示例中使用
-
CryptXmlEnumAlgorithmInfo
-
详细信息