Поделиться через


Убедитесь, что сертификат поддерживает метод сигнатуры

В этом разделе описывается, как проверить, поддерживает ли сертификат определенный метод подписи.

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

Дальнейшие действия

Загрузка сертификата из файла

Проверка того, что система поддерживает дайджест-метод

Внедрение цепочек сертификатов в документ

Используется в этом примере

CryptFindOIDInfo

CRYPT_OID_INFO

CryptXmlEnumAlgorithmInfo

Дополнительные сведения

API шифрования

Криптографические функции

Ошибки API цифровых подписей XPS

Ошибки документа XPS

Спецификация XML-бумаги