问题描述:

I'm opening the certificate store using the "CertOpenStore" API and get the certificates using the "CertEnumCertificatesInStore" API.

The CERT_CONTEXT data returned by the API gives the issuer name in CERT_NAME_BLOB type.

How to get the CERT_RDN or CERT_NAME_INFO from the certificate.?

My requirement is to get the issuer name attributes (O, OU, etc.). I do not want to parse the string returned by the CertNameToStr API.

网友答案:

The above comment is correct, you do need to decode the ASN.1 encoded data in the CERT_NAME_BLOB. However, the CryptoAPI has a function to do this for you - CryptDecodeObject.

If you have a PCCERT_CONTEXT handle pCertContext, you can decode it to a CERT_NAME_INFO structure as follows:

BOOL success = CryptDecodeObject(
    X509_ASN_ENCODING,
    X509_NAME,
    pCertContext->pCertInfo->Issuer.pbData,
    pCertContext->pCertInfo->Issuer.cbData,
    0,
    NULL,
    &dwNameInfoSize);

// (check that CryptDecodeObject succeeded)    

PCERT_NAME_INFO pCertNameInfo = (PCERT_NAME_INFO) malloc(dwNameInfoSize);

// (check that malloc succeeded)

CryptDecodeObject(
    X509_ASN_ENCODING,
    X509_NAME,
    pCertContext->pCertInfo->Issuer.pbData,
    pCertContext->pCertInfo->Issuer.cbData,
    0,
    pCertNameInfo,
    &dwNameInfoSize);

Now you can loop through the different components of the RDN like this:

for (DWORD i = 0; i < pCertNameInfo->cRDN; i++)
{
    for (DWORD j = 0; j < pCertNameInfo->rgRDN[i].cRDNAttr; j++)
    {
        CERT_RDN_ATTR &rdnAttribute = pCertNameInfo->rgRDN[i].rgRDNAttr[j];

        //
        // Do stuff with the RDN attribute
        //
    }
}

With each iteration, rdnAttribute will be set to a different component of the issuer name like you want.

Finally, free the memory when you're done:

free(pCertNameInfo);
相关阅读:
Top