The CERT_INFO structure is the heart of the certificate. It contains, either in direct form or in encoded form, all the basic information in the certificate. The following illustration shows the CERT_INFO structure, with all the encoded members shown as shaded.
It should be noted that the IssuerUniqueID and SubjectUniqueID structure members are a part of the X.509 version 2 certificate implementation, and are seldom used anymore. Their functionality has been replaced by the version 3 "Extensions" functionality.
If the information contained in the encoded (shaded) members Issuer and Subject is needed, those members must be decoded. To decode one of these members, the CryptDecodeObject function must be used. The process of decoding one of these members is depicted in the following illustration.
In the illustrated case, the CryptDecodeObject function outputs a CERT_NAME_INFO structure, an array of CERT_RDN structures, a corresponding array of CERT_RDN_ATTR structures, and a string containing the name. It is important to note that what is contained in the string is determined by the other members of the CERT_RDN_ATTR structure. For example, if the pszObjId member is set to "2.5.4.3", this equates to a common name. If it were set to "2.5.4.10" then the string would contain an organization name. For a list of these ObjIds, see CERT_RDN_ATTR.
The dwValueType member contains information pertaining to the type of string—for example, if it were set to CERT_RDN_PRINTABLE_STRING the value member would contain a byte-width, zero-terminated character string; if it were set to CERT_RDN_UNICODE_STRING, it would contain a double-width (word-sized) character string.
The encoded object (data member) is always provided as the input to the CryptDecodeObject function, and the output is a C structure that may or may not have encoded members, depending on how far into the process you are.
There is one other member that requires some decoding, and that is the Extension member. Although it is not encoded at the CERT_INFO level, it does contain some encoded information. To decode this information, proceed as shown in the following illustration.
In the CERT_INFO structure, data member rgExtension is a pointer to an array of CERT_EXTENSION structures. Each CERT_EXTENSION structure has a Value data member that is in encoded form and needs to be decoded. The Value data member is passed to the CryptDecodeObject function, and then the output from the function depends on the value of the pszObjId data member. Notice that in the illustration, two different structures are produced, one of type CERT_BASIC_CONSTRAINTS_INFO and one of type CERT_AUTHORITY_KEY_ID_INFO, depending on the value of pszObjId.