Creating Certificate Requests
To receive a certificate from a certification authority (CA), a user makes an electronic request to the CA via a certificate request, a specially formatted electronic message. This section discusses the process of creating a certificate request.
The following two illustrations show the initialization map for initializing all the data necessary to create a certificate request. The first illustration depicts the process for initializing a CERT_NAME_INFO structure for the Subject name in the certificate. That structure is then used as input to the CryptEncodeObject function, the output of which is the initialized (encoded) CERT_NAME_BLOB structure, which is pointed to by the Subject member of the CERT_REQUEST_INFO structure (shown in the second illustration).
Additionally, the CryptExportPublicKeyInfo function exports the public key into the CERT_PUBLIC_KEY_INFO structure, which is pointed to by the SubjectPublicKeyInfo member of the CERT_REQUEST_INFO structure.
If you want to add customized information to the request, this can be done by initializing a CRYPT_ATTR_BLOB structure with the data, including it in the CRYPT_ATTR_BLOB array, then pointing the rgValue member of a CRYPT_ATTRIBUTE structure contained in a CRYPT_ATTRIBUTE array, to the CRYPT_ATTR_BLOB array. Finally, the rgAttribute member of the CERT_REQUEST_INFO structure must be pointed to the CRYPT_ATTRIBUTE array.
Once the CERT_REQUEST_INFO structure is completely initialized, the CryptSignAndEncodeCertificate function can be used to prepare the data for transmission.
The following is a procedure for creating and initializing a certificate request. It is followed by example code demonstrating how to implement the procedure.
To create a certificate request and prepare it for transmission
-
Create a string containing the certificate request Subject name.
-
Declare a CERT_RDN_ATTR array, initializing each array element with the following data: the object ID string, the ValueType, the length of the string created in step 1, and the string created in step 1 (cast as a BYTE*).
-
Declare a CERT_RDN array, initializing each element with the RDNAttr count, and the address of an index of the CERT_RDN_ATTR array initialized in step 2.
-
Declare a CERT_NAME_INFO structure, initializing it with the number of CERT_RDN array elements, and the CERT_RDN array address.
-
Call the CryptEncodeObject function, providing the CERT_NAME_INFO for the appropriate argument. Its output will be a CERT_NAME_BLOB structure that has been initialized with the encoded data.
-
Set the Subject member of the CERT_REQUEST_INFO structure to point to the CERT_NAME_BLOB structure created and initialized in step 5.
-
If extra custom information is to be included in the certificate request, a CRYPT_ATTR_BLOB array must be initialized with the custom data, and a CRYPT_ATTRIBUTE array, containing a CRYPT_ATTRIBUTE structure, must be initialized with the CRYPT_ATTR_BLOB array. For the sake of clarity, this step will not be demonstrated in the example code.
-
The version number must be added to the CERT_REQUEST_INFO structure.
-
Call the CryptExportPublicKeyInfo function to return an initialized CERT_PUBLIC_KEY_INFO structure.
-
Set the SubjectPublicKeyInfo member of the CERT_REQUEST_INFO structure to point to the CERT_PUBLIC_KEY_INFO structure created in step 9.
-
Call the CryptSignAndEncodeCertificate function, providing the CERT_REQUEST_INFO structure for the appropriate argument. This encodes the CERT_REQUEST_INFO structure and all of the data pointed to by it, signs this encoded information, and encodes the signed, encoded information.