Убедитесь, что сертификат поддерживает метод сигнатуры
В этом разделе описывается, как проверить, поддерживает ли сертификат определенный метод подписи.
CryptXmlEnumAlgorithmInfo в API шифрования Майкрософт перечисляет свойства сертификата и используется в этом примере кода для перечисления методов подписи, поддерживаемых сертификатом. Чтобы использовать CryptXmlEnumAlgorithmInfo для перечисления методов подписи, поддерживаемых сертификатом, вызывающий объект должен предоставить метод обратного вызова и структуру данных в вызове CryptXmlEnumAlgorithmInfo, что позволяет передавать данные методу обратного вызова.
Структура данных, используемая в следующем примере кода, содержит следующие поля:
Поле | Description |
---|---|
userSignatureAlgorithmToCheck | Поле LPWSTR, указывающее на строку, содержащую универсальный код ресурса (URI) алгоритма подписи, который должен быть проверка. |
certificateAlgorithmInfo | Указатель на структуру CRYPT_OID_INFO , содержащую сведения о алгоритме подписи, поддерживаемом сертификатом. |
userSignatureAlgorithmSupported | Логическое значение, указывающее, поддерживается ли алгоритм подписи сертификатом. |
struct SignatureMethodData
{
LPCWSTR userSignatureAlgorithmToCheck;
PCCRYPT_OID_INFO certificateAlgorithmInfo;
BOOL userSignatureAlgorithmSupported;
};
Метод API Crypto, который проверка сертификат использует метод обратного вызова для возврата данных вызывающей объекту. 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
-
Дополнительные сведения