Verifikasi bahwa Sertifikat Mendukung Metode Tanda Tangan

Topik ini menjelaskan cara memverifikasi bahwa sertifikat mendukung metode tanda tangan tertentu.

CryptXmlEnumAlgorithmInfo di Microsoft Crypto API menghitung properti sertifikat dan digunakan dalam contoh kode ini untuk menghitung metode tanda tangan yang didukung sertifikat. Untuk menggunakan CryptXmlEnumAlgorithmInfo untuk menghitung metode tanda tangan yang didukung sertifikat, pemanggil harus menyediakan metode panggilan balik dan struktur data dalam panggilan ke CryptXmlEnumAlgorithmInfo, memungkinkannya meneruskan data ke metode panggilan balik.

Struktur data yang digunakan dalam contoh kode berikutnya memiliki bidang berikut:

Bidang Deskripsi
userSignatureAlgorithmToCheck Bidang LPWSTR yang menunjuk ke string yang berisi URI algoritma tanda tangan yang akan diperiksa.
certificateAlgorithmInfo Penunjuk ke struktur CRYPT_OID_INFO yang berisi informasi tentang algoritma tanda tangan yang didukung oleh sertifikat.
userSignatureAlgorithmSupported Nilai Boolean yang menunjukkan apakah algoritma tanda tangan didukung oleh sertifikat.

 

struct SignatureMethodData
{
    LPCWSTR             userSignatureAlgorithmToCheck; 
    PCCRYPT_OID_INFO    certificateAlgorithmInfo; 
    BOOL                userSignatureAlgorithmSupported; 
};

Metode Crypto API yang memeriksa sertifikat menggunakan metode panggilan balik untuk mengembalikan data ke pemanggil. CryptXmlEnumAlgorithmInfo menghitung metode tanda tangan yang didukung sertifikat, dan memanggil metode panggilan balik untuk setiap metode tanda tangan sampai metode panggilan balik mengembalikan FALSE atau sampai semua metode tanda tangan dalam sertifikat telah dijumlahkan.

Metode panggilan balik dalam contoh kode berikutnya mencari metode tanda tangan yang diteruskan oleh CryptXmlEnumAlgorithmInfo yang cocok dengan metode tanda tangan yang disediakan oleh metode panggilan. Ketika kecocokan ditemukan, metode panggilan balik memeriksa apakah metode tanda tangan juga didukung oleh sistem. Jika metode tanda tangan cocok dan didukung oleh sistem, metode tanda tangan ditandai sebagai didukung sistem dan metode panggilan balik mengembalikan 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;
}

Contoh kode berikut membungkus fungsionalitas validasi ke dalam satu metode. Metode ini mengembalikan nilai Boolean yang menunjukkan apakah sertifikat mendukung metode tanda tangan dan apakah metode tanda tangan didukung oleh sistem.

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

Langkah berikutnya

Memuat Sertifikat dari File

Memverifikasi Sistem Mendukung Metode Hash

Menyematkan Rantai Sertifikat dalam Dokumen

Digunakan dalam Contoh Ini

CryptFindOIDInfo

CRYPT_OID_INFO

CryptXmlEnumAlgorithmInfo

Untuk Informasi Selengkapnya

API Kriptografi

Fungsi Kriptografi

Kesalahan XPS Digital Signature API

Kesalahan Dokumen XPS

Spesifikasi Kertas XML