次の方法で共有


証明書が署名メソッドをサポートしていることを確認する

このトピックでは、証明書が特定の署名方法をサポートしていることを確認する方法について説明します。

Microsoft Crypto API の CryptXmlEnumAlgorithmInfo は、証明書のプロパティを列挙し、このコード例で使用して、証明書がサポートする署名メソッドを列挙します。 CryptXmlEnumAlgorithmInfo を使用して証明書がサポートするシグネチャ メソッドを列挙するには、呼び出し元が CryptXmlEnumAlgorithmInfo の呼び出しでコールバック メソッドとデータ構造を提供し、コールバック メソッドにデータを渡せるようにする必要があります。

次のコード例で使用するデータ構造には、次のフィールドがあります:

フィールド 説明
userSignatureAlgorithmToCheck チェックする署名アルゴリズムの URI を含む文字列を指す LPWSTR フィールド。
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;
}

次のコード例では、検証機能を 1 つのメソッドにラップします。 このメソッドは、証明書が署名メソッドをサポートしているかどうか、および署名メソッドがシステムでサポートされているかどうかを示すブール値を返します。

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

詳細情報

Cryptography API

暗号化関数

XPS デジタル署名 API のエラー

XPS ドキュメントのエラー

XML Paper Specification