How to create a certificate request that uses key archival with CertEnroll (JavaScript)

Hi all,

If you want to request certificates to a CA and make use of Key Archival feature, first you need to prepare the environment to enable this feature on your CA: Certificate Services example implementation: Key archival and recovery or Implementing Key Archival Walkthrough will be of assistance here.

After that you could use a code like the following sample to make the request with CertEnroll (based on How to create a certificate request with CertEnroll (JavaScript) sample):

 <html>
<head>
    <title>Certificate Request test</title>
</head>
<body> 
  <object id="objCertEnrollClassFactory" classid="clsid:884e2049-217d-11da-b2a4-000e7bbb2b09"></object>    
  <script language="javascript">

    function CreateRequest() 
    {
      document.write("<br>Create Request...");                      

      try {
        // Variables
        var objCSP = objCertEnrollClassFactory.CreateObject("X509Enrollment.CCspInformation");
        var objCSPs = objCertEnrollClassFactory.CreateObject("X509Enrollment.CCspInformations");
        var objPrivateKey = objCertEnrollClassFactory.CreateObject("X509Enrollment.CX509PrivateKey");
        var objRequest = objCertEnrollClassFactory.CreateObject("X509Enrollment.CX509CertificateRequestPkcs10");
        var objCmcRequest = objCertEnrollClassFactory.CreateObject("X509Enrollment.CX509CertificateRequestCmc");
        var objObjectIds = objCertEnrollClassFactory.CreateObject("X509Enrollment.CObjectIds");
        var objObjectId = objCertEnrollClassFactory.CreateObject("X509Enrollment.CObjectId");
        var objX509ExtensionEnhancedKeyUsage = objCertEnrollClassFactory.CreateObject("X509Enrollment.CX509ExtensionEnhancedKeyUsage");
        var objExtensionTemplate = objCertEnrollClassFactory.CreateObject("X509Enrollment.CX509ExtensionTemplateName");
        var objDn = objCertEnrollClassFactory.CreateObject("X509Enrollment.CX500DistinguishedName");
        var objEnroll = objCertEnrollClassFactory.CreateObject("X509Enrollment.CX509Enrollment");

        //  Initialize the csp object using the desired Cryptograhic Service Provider (CSP)
        objCSP.InitializeFromName("Microsoft Enhanced Cryptographic Provider v1.0");

        //  Add this CSP object to the CSP collection object
        objCSPs.Add(objCSP);

        //  Provide key container name, key length and key spec to the private key object
        //objPrivateKey.ContainerName = "AlejaCMa";
        objPrivateKey.Length = 1024;
        objPrivateKey.KeySpec = 1; // AT_KEYEXCHANGE = 1
        //objPrivateKey.ExportPolicy = 0; // XCN_NCRYPT_ALLOW_EXPORT_NONE = 0

        //  Provide the CSP collection object (in this case containing only 1 CSP object)
        //  to the private key object
        objPrivateKey.CspInformations = objCSPs;

        // Initialize P10 based on private key
        objRequest.InitializeFromPrivateKey(1, objPrivateKey, ""); // context user = 1

        // 1.3.6.1.5.5.7.3.2 Oid - Extension
        objObjectId.InitializeFromValue("1.3.6.1.5.5.7.3.2");
        objObjectIds.Add(objObjectId);
        objX509ExtensionEnhancedKeyUsage.InitializeEncode(objObjectIds);
        objRequest.X509Extensions.Add(objX509ExtensionEnhancedKeyUsage);

        // 1.3.6.1.5.5.7.3.3 Oid - Extension
        //objExtensionTemplate.InitializeEncode("1.3.6.1.5.5.7.3.3");
        //objRequest.X509Extensions.Add(objExtensionTemplate);

        // DN related stuff
        objDn.Encode("CN=alejacma", 0); // XCN_CERT_NAME_STR_NONE = 0
        objRequest.Subject = objDn;

        // Enroll
        objCmcRequest.InitializeFromInnerRequest(objRequest);
        objCmcRequest.KeyArchivalCertificate = 
      "MIIFxDCCBKygAwIBAgIKG2cmPwAAAAAADDANBgkqhkiG9w0BAQUFADBJMRMwEQYK" +
...
      "9Hwz0oPmQfi3VEXw16eBHf6EpmyOC8nBFeYPv9FKfuVHB9W3JNh+ZA=="
      
        objEnroll.InitializeFromRequest(objCmcRequest);
        var pkcs10 = objEnroll.CreateRequest(3); // XCN_CRYPT_STRING_BASE64REQUESTHEADER = 3

        document.write("<br>" + pkcs10);
        document.write("<br>The end!");
      }
      catch (ex) {
        document.write("<br>" + ex.description);
        return false;
      }

      return true;
    }       

    CreateRequest();

  </script>
    
</body>
</html>

Note that if we don't set the right certificate to the KeyArchivalCertificate property, we will get the following issue: CertEnroll::CX509Enrollment::p_CreateRequest returns error 0x80070057.

Other issues we may get when creating the request:

- CertEnroll::CX509Enrollment::p_CreateRequest returns error 0x800b0112

- CertEnroll::CX509Enrollment::p_CreateRequest returns error 0x80092012

- CertEnroll::CX509Enrollment::p_CreateRequest returns error 0x8009000b

 

If we want to install the response from the CA, we may use the same code that we used here: How to create a certificate request with CertEnroll (ASP) or here: How to create a certificate request with CertEnroll (JavaScript). But instead of using the .cer or the .p7b file containing the response, we have to use an .rsp file. What is an .rsp file? What happens if I don't use it? Please, check this post for details: CertEnroll::CX509Enrollment::p_InstallResponse returns error 0x80095002.

 

I hope this helps. 

Regards,

Alex (Alejandro Campos Magencio)