Acquiring Certificates

Now that you have a basic understanding of how the process of acquiring and using certificates works, it's time to learn how to actually perform some of these tasks yourself. The first task is to request and retrieve a certificate from a Certificate Authority. Luckily, Microsoft has made this task fairly simple to perform, thanks to a couple of COM objects that are available for use.

Note

The remaining portion of this chapter requires that you have installed Windows 2000 Server or NT Server 4.0 with the Windows NT 4 Option Pack.


Generating a Certificate Request

Included with the latest version of Microsoft's Certificate Server is a COM object that can be used to generate certificate requests. It is also used to process and store the request, keys, and certificate in the appropriate certificate store. This object is the Certificate Enrollment Control; you can find it in xenroll.dll in the system32 directory. This control, which is a wrapper for Crypto API functions, simplifies the act of creating and processing a certificate request. It per forms all the steps involved with requesting and retrieving a certificate, including generating the public/private key pair, except for the actual communication with the Certificate Authority.

When using the Certificate Enrollment Control, you do not include the reference to the control's type library. Instead, you declare a variable as an object and then use the CreateObject function as in the following code:

Dim m_objXen As Object

Set m_objXen = CreateObject("CEnroll.CEnroll.1")

Note

The xenroll.dll type library uses some variant types not available in Visual Basic, and thus cannot be used by including the type library in a Visual Basic project. As long as you use late binding, as previously shown, you can easily use most of the methods and properties of this object.


The Certificate Enrollment Control has several properties that can be set to control how it performs its tasks. They are listed in Table 5.1.

Table 5.1. Certificate Enrollment Control Properties
Property Data Type Description
CAStoreFlags Long Passed directly to the CertOpenStore function (which you'll look at in the next chapter), controlling how the certificate store is opened.
CAStoreName String Specifies the name of the certificate store for all non-ROOT and non-MY certificates to be stored
CAStoreType String Specifies the type of certificate store to use for the store specified in the CAStoreName property.
ContainerName String Specifies the name of the key container to use.
DeleteRequestCert Boolean Deletes the dummy certificate that is created to hold the place of the requested certificate until the certificate is issued.
GenKeyFlags Long Passed directly to the CryptGenKey function to con trol how the keys are generated.
HashAlgorithm String Specifies the preferred hash algorithm to use for signing the PKCS #10 certificate request.
KeySpec Long Specifies the key type to be generated.
MyStoreFlags Long Passed directly to the CertOpenStore function, controlling how the MY certificate store is opened.
MyStoreName String Specifies where certificates with linked private keys are kept.
MyStoreType String Specifies the type of store to use for the store specified in the MyStoreName property.
ProviderFlags Long The use of this property is controlled by the CSP used for generating the certificate request.
ProviderName String Specifies the CSP to use.
ProviderType String The use of this property is controlled by the CSP used for generating the certificate request.
PVKFileName String Specifies that the private key is to be generated as an exportable key and is to be stored in the file specified by this property.
RequestStoreFlags Long Passed directly to the CertOpenStore function, controlling how the REQUEST certificate store is opened.
RequestStoreName String Specifies the certificate store in which the dummy certificate is to be stored while waiting for the certificate to be issued.
RequestStoreType String Specifies the type of store to use for the store specified in the RequestStoreName property.
RootStoreFlags Long Passed directly to the CertOpenStore function, controlling how the ROOT certificate store is opened.
RootStoreName String Specifies where all trusted, self-signed ROOT certificates are kept.
RootStoreType String Specifies the type of store to use for the store specified in the RootStoreName property.
SPCFileName String Specifies a file to which the PKCS #7 certificate response is written.
UseExistingKeySet Boolean Specifies that an existing key set is to be used, instead of generating a new one.
WriteCertToCSP Boolean Specifies whether a certificate should be written to the CSP.

Creating a Certificate Request

You can create a certificate request by using one of two methods. The first of these two methods, createPKCS10, returns a string value that contains the certificate request. The syntax for this method is as follows:

 createPKCS10(DNName as String, Usage as String) as String

The first parameter (DNName ) to this method is a string containing a series of identifying information. The elements in this string are in the format of one- or two-character codes, followed by an equal sign, and the value, with each element separated from the others by a comma. This string looks like the following:

CN=Davis Chapman,OU=Bullfrog Unit,O=The Frog Pond,L=Dallas,S=TX,C=US,[email protected]

The possible elements that are available for including in this string are listed in Table 5.2.

Table 5.2. X.500 Distinguished Name Fields
Code Description
CN Common Name—The user's name, or if this is a request for a certificate for a server, the fully qualified hostname or URL.
O Organization—The name of the organization or company for which the certificate is being requested. It should be the legal name for the company or organization.
OU Organizational Unit—This name is used to differentiate different divisions within an organization or company. It can also be used to specify a DBA (Doing Business As) name for the certificate.
L Locality—The city in which the organization or person resides.
S State—The state in which the organization or person resides.
C Country—The country in which the organization or person resides. The X.500 naming scheme limits this field to a two-character country code. For example, the code for the United States is US, and the code for Canada is CA.
E Email Address—The email address for the person requesting the certificate (this element is optional).

The second parameter (Usage ) is the OID (Object Identifier) that identifies the purpose of the certificate being generated. Some of the standard OIDs are listed in Table 5.3.

OID

An Object Identifier (OID) is a series of integers separated by periods. The organization of these numbers is similar to the organization of TCP/IP addresses. It is always treated as a string value when passing to functions.


Table 5.3. Certificate Purpose OIDs
Certificate Purpose OID
Base Key OID 1.3.6.1.5.5.7.3
Server Authentication 1.3.6.1.5.5.7.3.1
Client Authentication 1.3.6.1.5.5.7.3.2
Code Signing 1.3.6.1.5.5.7.3.3
Email Protection 1.3.6.1.5.5.7.3.4

The return value from this function is a string containing the certificate request. A typical use of this function is as follows:

Dim strDN As String
Dim strReq As String

'--- Specify the certificate usage
m_strKeyUsage = "1.3.6.1.5.5.7.3.2"

'--- Build the distinguished name string
strDN = "CN=" + m_strUserName _
        + ",OU=" + m_strUnit _
        + ",O=" + m_strOrganization _
        + ",L=" + m_strCity _
        + ",S=" + m_strState _
        + ",C=" + m_strCountry

'--- Specify the key type
m_objXen.KeySpec = AT_KEYEXCHANGE

'--- Create the PKCS #10 request
strReq = m_objXen.createPKCS10(strDN, m_strKeyUsage)
							
							
							
							
							
							
						

The second method available for creating a certificate request is the createFilePKCS10 func tion. This function takes the same two parameters and has a third parameter (PKCSFileName ) that is the name of the file to write the certificate request into. The syntax for this function is as follows:

 createFilePKCS10(DNName as String, Usage as String, _  
         PKCSFileName as String)

This version writes the certificate request to a file that can be read in by the user and pasted into a Web form when submitting to the Certificate Authority.

Accepting a Certificate

When you are issued a certificate from the Certificate Authority, you need to retrieve the cer tificate and import it into your certificate store. The certificate is returned in a PKCS #7 format, so the function to import the certificate into the certificate store is called acceptPKCS7 . It takes one parameter (NewCert ), the certificate that was retrieved from the CA. The syntax for this function is as follows:

 acceptPKCS7(NewCert as String)

As with the methods for creating the certificate request, two methods are available for importing the certificate. The second version reads the certificate in from a file. This method, acceptFilePKCS7 , takes the filename as its only parameter (NewCertFileName ). The syntax for this method is as follows:

 acceptFilePKCS7(NewCertFileName as String)
							
							
							
						

Enumerating Containers

If you need to see what all the available certificate containers for the current CSP are, you can use the enumContainers method. This method takes a single parameter (Index), the container number to return, and returns a string containing the name of the container. The syntax for this function is as follows:

 enumContainers(Index as Long) as String

The container index number starts with zero (0) for the first container. After the last container has been passed, either the ERROR_NO_MORE_ITEMS or the ERROR_NO_MORE_DATA error is thrown. You might use this method as follows:

Public Const ERROR_NO_MORE_ITEMS = 259&
Public Const ERROR_NO_MORE_DATA = &H80070103
Dim strContainer as String
Dim lIndex as Long

'--- Set up the error handling
On Error GoTo EnumContainerErr

'--- Initialize the index
lIndex = 0
strContainer = ""

'--- Get the first container
strContainer = m_objXen.enumContainers(lIndex)

'--- Loop until out of containers
While (strContainer <> "")

    '--- Do whatever with the container name
    .
    .
    .
    '--- Increment the index
    lIndex = lIndex + 1
    strContainer = ""

    '--- Get the next container
    strContainer = m_objXen.enumContainers(lIndex)
Wend
'--- Perform Error Handling
EnumContainerErr:
'--- Have we run out of containers?
If Err.Number = ERROR_NO_MORE_ITEMS Then Resume Next
If Err.Number = ERROR_NO_MORE_DATA Then Resume Next
							
							
							
							
							
							
							
							
							
						

Enumerating Providers

When you need to determine which CSPs are available on a system for a particular provider type, you can use the enumProviders method. This method works virtually the same as the enumContainers method. The syntax for this function is as follows:

 
 enumProviders(Index as Long, Flags as Long) as String

This method has two parameters. The first parameter (Index) is the provider index, just as with the enumContainers method. This index starts at zero (0) for the first provider and can be incremented to loop through each provider. The second parameter (Flags ) is passed to the flags parameter of the CryptEnumProviders function, so it should always be passed zero (0).

This method returns a string variable containing the name of the current CSP. Just like with the enumContainers method, after all the CSPs of the current provider type have been passed, either the ERROR_NO_MORE_ITEMS or the ERROR_NO_MORE_DATA error is thrown. You might use this method as follows:

Public Const ERROR_NO_MORE_ITEMS = 259&
Public Const ERROR_NO_MORE_DATA = &H80070103
Dim strProvider as String
Dim lIndex as Long

'--- Set up the error handling
On Error GoTo EnumProviderErr

'--- Initialize the index
lIndex = 0
strProvider = ""

'--- Get the first provider
strProvider = m_objXen.enumProviders(lIndex, 0)

'--- Loop until out of providers
While (strProvider <> "")

							
							
							
							
							
							
							
    '--- Do whatever with the provider name
    .
    .
    .
    '--- Increment the index
    lIndex = lIndex + 1
    strProvider = ""

    '--- Get the next provider
    strProvider = m_objXen.enumProviders(lIndex, 0)
Wend
'--- Perform Error Handling
EnumProviderErr:
'--- Have we run out of providers?
If Err.Number = ERROR_NO_MORE_ITEMS Then Resume Next
If Err.Number = ERROR_NO_MORE_DATA Then Resume Next
							
							
							
							
							
							
							
						

Retrieving Certificates

Now that you know how to generate certificate requests and accept issued certificates, the other piece of the puzzle is interacting with the Certificate Authority. If the Certificate Authority happens to be running Microsoft's Certificate Server, this interaction can be performed through another COM object. If the Certificate Authority is running a different Certificate Server, you'll probably have to paste the certificate into a Web form and retrieve the issued certificate either through an email message or another Web form.

For the remainder of this chapter, I'll assume that you are interacting with a Microsoft Certificate Server, so I'll describe the CCertRequest COM object. You can find this object in the CertCli type library in the CertCli.DLL. You can include this object in your Visual Basic project through the Project References dialog.

Submitting the Certificate Request

When you have the certificate request ready to send to the Certificate Authority, you can use the Submit method of the CCertRequest object to send it. This method submits the certificate request to a Microsoft Certificate Server CA. The syntax for this method is as follows:

 Submit(Flags as Long, strRequest as String, strAttributes as String, _
         strConfig as String) as Long

The first parameter (Flags) to this method is a combination of flags that specify the certificate request format. Three sets of flag values can be combined. The first set of flag values is listed in Table 5.4. These flag values specify how the certificate request is encoded.

Table 5.4. Submit Encoding Flag Values
Flag Value Description
CR_IN_BASE64HEADER 0 The request is encoded in Base64 encoding with begin/end markers.
CR_IN_BASE64 &H1 The request is encoded in Base64 encoding with no begin/end markers.
CR_IN_BINARY &H2 The request is in binary form.

The second set of flag values is used to specify the request format. These flag values are specified in Table 5.5.

Table 5.5. Submit Format Flag Values
Flag Value Description
CR_IN_PKCS10 &H100 The request is in PKCS #10 format.
CR_IN_KEYGEN &H200 The request is in keygen (Netscape) format.

The third set of flag values is used to specify any encrypting of the request that has been performed. These possible values are listed in Table 5.6.

Table 5.6. Submit Encryption Flag Values
Flag Value Description
CR_IN_ENCRYPTED_REQUEST &H10000 The request is encrypted using the CA's public key.
CR_IN_ENCRYPTED_ATTRIBUTES &H20000 The request attributes are encrypted.

The second parameter (strRequest ) is the certificate request. It can be the string value that was returned by the Certificate Enrollment Control.

The third parameter (strAttributes ) is a string of additional attributes to be included in the certificate request. These extra attributes are in name/value pairs, with a colon separating the name from the value, and each pair separated by the newline character (vbLf). A sample is as follows:

"Name1:Value1" + vbLf + "Name2:Value2"
							
						

The fourth parameter (strConfig ) is a combination of the name of the computer on which the Certificate Authority is running and the name of the Certificate Authority. These names are separated by a backslash character, as follows:

"caserver.ca.comMy Certificate Authority"
							
							
							
							
							
							
							
						

The return value from the Submit method is a long value that indicates the status of the certificate request. The possible status codes are listed in Table 5.7.

Table 5.7. Certificate Request Status Codes
Status Code Value `Description
CR_DISP_INCOMPLETE 0 The request was not complete or didn't complete.
CR_DISP_ERROR &H1 The request failed, was corrupt, or otherwise had a problem.
CR_DISP_DENIED &H2 The request was denied.
CR_DISP_ISSUED &H3 The certificate has been issued.
CR_DISP_ISSUED_OUT_OF_BAND &H4 The certificate was issued separately.
CR_DISP_UNDER_SUBMISSION &H5 The request is being processed.

A typical use of this method is as follows:

Dim lDisp As Long

'--- Submit the request to the CA
lDisp = m_objReq.Submit(CR_IN_BASE64 Or CR_IN_PKCS10, _
                            strReq, "", m_strServer + "" + m_strCA)
							
							
							
							
							
							
							
						

Obtaining the Request ID

After you submit the certificate request to the CA, you need to get the request ID. You can use it to make subsequent requests to the CA to get updates of the status of your request and eventually retrieve the certificate once it's been issued. You do so by using the GetRequestId method.

The GetRequestId method takes no parameters and returns a long value that is the ID of your certificate request. This method should probably be called shortly after submitting the certificate request because the certificate may be issued much later. A typical use of this method is as follows:

Dim lReqID As Long

'--- Get the request ID
lReqID = m_objReq.GetRequestId
							
							
							
							
							
							
							
						

Obtaining the Request Status

Two methods are useful for determining the current status of a certificate request and for providing a readable status message for the user. The first of these methods is the RetrievePending method, which gets the current status of a certificate request from the CA. The syntax for this method is as follows:

 RetrievePending(RequestID as Long, strConfig as String) as Long

The first parameter (RequestID ) this method takes is the request ID returned from the GetRequestId method. The second parameter (strConfig ) is the machine name/Certificate Authority name combination used in the Submit method to specify the CA to submit the certificate request to.

The return value from this method is the current status code of the request. For a list of the possible status codes, refer to Table 5.7.

If you want to provide your users with a more readable status message, you can use the GetDispositionMessage method. This method, which doesn't take any parameters, returns a string containing the current status of the request in a readable form. A typical use of these two methods might be as follows:

Dim lDisp As Long
Dim strMsg As String

'--- Retrieve the current status of our request
lDisp = m_objReq.RetrievePending(m_lReqID, m_strServer + "" + m_strCA)

'--- Get the textual description of the request status
strMsg = m_objReq.GetDispositionMessage
'--- Display it for the user
MsgBox strMsg, vbOKOnly, "Certificate Request"

If you want to get the status code from the last time you checked, you can use the GetLastStatus method to retrieve the last status code that was returned. This status code is one of the codes listed in Table 5.7.

Retrieving the Certificate

After the certificate has been issued, you can retrieve it by using the GetCertificate method. The syntax for this method is as follows:

 GetCertificate(Flags as Long) as String

The only parameter (Flags ) for this method is a flag that specifies how the certificate should be retrieved. The first set of flag values specifies the certificate encoding. The possible values for this flag value are listed in Table 5.8.

Table 5.8. GetCertificate Encoding Flag Values
Flag Value Description
CR_OUT_BASE64HEADER 0 The certificate is encoded in Base64 encoding with begin/end markers.
CR_OUT_BASE64 &H1 The certificate is encoded in Base64 encoding with no begin/end markers.
CR_OUT_BINARY &H2 The certificate is in binary form.

If the CA is using Microsoft Certificate Server 2.0 (released with Windows 2000), you can also use a second flag value to retrieve the entire certificate chain, including all the CA certificates in the chain of trust. To do so, you can use the flag value in Table 5.9.

Table 5.9. GetCertificate Certificate Chain Flag Values
Flag Value Description
CR_OUT_CHAIN &H100 The complete certificate chain is returned in PKCS #7 format.

The return value is the certificate that was retrieved from the CA. You can take this returned certificate and import it into the certificate store by using the acceptPKCS7 method of the Certificate Enrollment Control.

Retrieving the CA's Certificate

When you need to retrieve the Certificate Authority's certificate, you can use the GetCACertificate method. This method's syntax is as follows:

 GetCACertificate(fExchangeCert as Long, strConfig as String, _
      Flags as Long) as String

The first parameter (fExchangeCert ) is a Boolean value (0 is FALSE, <>0 is TRUE) that specifies whether to get the CA's Signature certificate or Key Exchange certificate. You can use the Key Exchange certificate to encrypt certificate requests that you are sending to the CA, whereas you can use the Signature certificate only to verify the signatures on the certificates issued by this CA. This parameter is used only with the version of Certificate Server that is included with NT 4 Option Pack. For the version of Certificate Server shipped with Windows 2000, this parameter must be zero (0), limiting you to only retrieving the CA's Signature certificate.

The second parameter (strConfig ) is the machine name/CA name combination that you used in the Submit method. The third parameter (Flags ) is the option flags that you used to retrieve your certificate with the GetCertificate method. The possible values for this flag are given in Table 5.8 and Table 5.9. The return value from this method is the certificate for the CA.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset