Certificate Sign Request Demo/Interop

Interoperate with the Redwax Certificate Sign Request module.

We have implemented a RFC2986 PKCS10 / Certificate Sign Request endpoint that allows you to test your client implementation against a Redwax Server.

This module allows you to work with a Microsoft CertEnroll certificate request as implemented by Internet Explorer 11.

The code being run is the most up to date build from trunk/master in source control, and is built and deployed automatically. The Redwax Interop server is for testing purposes only.

Certificate Sign Request Demo/Interop Server

When testing your Certificate Sign Request client implementation, use the following details.

Summary

Server URL https://interop.redwax.eu/test/csr
Time Source System Clock
Serial Numbers Random

Redwax Module Configuration

The following configuration is used to implement this CSR endpoint. The configuration below is added to a standard secure virtualhost Apache configuration, as described here.

Configuration

Here we set the csr handler, and set the certificates and keys to be used for signing the certificate.

<IfModule !ca_module>
  LoadModule ca_module /usr/lib64/httpd/modules/mod_ca.so
</IfModule>
<IfModule !ca_simple_module>
  LoadModule ca_simple_module /usr/lib64/httpd/modules/mod_ca_simple.so
</IfModule>
<IfModule !csr_module>
  LoadModule csr_module /usr/lib64/httpd/modules/mod_csr.so
</IfModule>

<Location /test/simple/csr>
  Require all granted
  SetHandler csr
  CsrParamChallenge challenge
  CsrSubjectRequest CN
  CsrSubjectRequest O
  CsrSubjectRequest C
  CsrSubjectAltNameRequest rfc822Name
</Location>

                

CertEnroll with Microsoft Internet Explorer 11

The following example form shows how to generate a request based on the CertEnroll functionality in Internet Explorer 11.

Html Form

To request a certificate be generated, submit the form below.

Object Tag

The following object tag must be present in the page to embed the objCertEnrollClassFactory and make this accessible from the javascript.

<object classid="clsid:884e2049-217d-11da-b2a4-000e7bbb2b09"
  id="objCertEnrollClassFactory"
  height="0"
  width="0"></object>

                

Javascript

The javascript used to trigger the CertEnroll functionality can be downloaded here, and is included for reference below.

/* make sure we can only submit once */
document
        .getElementById('createform')
        .addEventListener(
                "submit",
                function certenroll(event) {

    document.getElementById('submit').disabled = true;

    try {
        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 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 objObjectIdChallenge = objCertEnrollClassFactory
                .CreateObject("X509Enrollment.CObjectId");
        var objX509ExtensionChallenge = objCertEnrollClassFactory
                .CreateObject("X509Enrollment.CX509Extension");
        var objEnroll = objCertEnrollClassFactory
                .CreateObject("X509Enrollment.CX509Enrollment")

        /*
         * initialize the CSP using the desired Cryptograhic
         * Service Provider
         */
        objCSP
            .InitializeFromName(
                "Microsoft Enhanced RSA and AES Cryptographic Provider");

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

        /*
         * provide key container name, key length and key spec
         * to the private key object
         */
        // objPrivateKey.ContainerName = $('#name').val();
        objPrivateKey.Length = 4096;
        objPrivateKey.KeySpec = 1; // AT_KEYEXCHANGE = 1
        objPrivateKey.ProviderType = '24'; // XCN_PROV_RSA_AES
                                            // = 24

        /*
         * 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="
                + document.getElementById('name').value, 0); // XCN_CERT_NAME_STR_NONE
                                                                // = 0
        objRequest.Subject = objDn;

        // objChallengeObjectId.
        //    InitializeFromName(CERTENROLL_OBJECTID.XCN_OID_RSA_challengePwd);
        // objChallengeObjectId.InitializeFromValue("1.2.840.113549.1.9.7");

        objObjectIdChallenge
                .InitializeFromValue("1.2.840.113549.1.9.7");
        objX509ExtensionChallenge.Initialize(
                objObjectIdChallenge, 6, window
                        .btoa('Hello, world')); // XCN_CRYPT_STRING_BASE64_ANY
                                                // = 6
        objRequest.X509Extensions
                .Add(objX509ExtensionChallenge);

        /* enroll */
        objEnroll.InitializeFromRequest(objRequest);
        document.getElementById('pkcs10').value = objEnroll
                .CreateRequest(3); // XCN_CRYPT_STRING_BASE64REQUESTHEADER
                                    // = 3

        /* send the request */
        var xhr = new XMLHttpRequest();

        xhr.onerror = function() {
            alert('A network error occcurred trying to contact the certificate' +
                    'authority. Click create to try again.');
            document.getElementById('submit').disabled = false;
        }

        xhr.onload = function() {
            if (xhr.status != 200) {
                alert('The certificate authority responded with '
                        + xhr.status + ': ' + xhr.statusText); // e.g.
                                                                // 404:
                                                                // Not
                                                                // Found
                document.getElementById('submit').disabled = false;
            } else {
                try {
                    var allow = 4; // AllowUntrustedRoot
                    objEnroll.InstallResponse(allow,
                            xhr.response, 0, "");
                } catch (ex) {
                    console.log(ex);
                }
                alert('The certificate has been installed successfully.');
                // document.getElementById('continue').disabled
                // = false;
            }
        };

        xhr.open('POST',
                document.getElementById('createform').action,
                true);
        xhr.setRequestHeader('Content-Type',
                'application/x-www-form-urlencoded');
        xhr
                .setRequestHeader('Accept',
                        'application/pkcs7-mime');
        xhr.responseType = 'text';
        // var formData = new
        // FormData(document.getElementById('createform'));
        var formData = encodeURIComponent('pkcs10')
                + '='
                + encodeURIComponent(document
                        .getElementById('pkcs10').value);
        console.log(formData);
        xhr.send(formData);

        event.preventDefault();

        return false;
    } catch (ex) {
        console.log(ex);
        if (ex instanceof TypeError) {
            alert('Microsoft CertEnroll is not supported on this browser');
        } else {
            alert(ex);
        }

        document.getElementById('submit').disabled = false;

        event.preventDefault();

        return false;
    }

    return true;
});