다음을 통해 공유


인증서가 서명 메서드를 지원하는지 확인

이 항목에서는 인증서가 특정 서명 방법을 지원하는지 확인하는 방법을 설명합니다.

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

다음 코드 예제에서는 유효성 검사 기능을 단일 메서드로 래핑합니다. 이 메서드는 인증서가 서명 메서드를 지원하는지 여부와 시스템에서 서명 메서드를 지원하는지 여부를 나타내는 부울 값을 반환합니다.

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

암호화 함수

XPS 디지털 서명 API 오류

XPS 문서 오류

XML Paper Specification