IE7 Certificate Request/Enrollment

With IE7, I've noticed the original ActiveX method of generating a client certificate request and installing the signed certificate no longer work (xenroll.dll calling CreatePKCS10() and acceptPKCS7()).

How do you do this now with IE7. Vista customers with IE7 don't even have access to xenroll.dll. I have been unable to find much documentation on this change, only that the old way was replaced with "something new", but no details on what the something new is called.

Any help would be greatly appreciated!

Thanks,
Andy



Answer this question

IE7 Certificate Request/Enrollment

  • Ceres629

    I tried with the following code in installing certificate test, and it turns out to be an object.

    <html>

    <SCRIPT language="vbscript">

    Dim enroll1

    Set enroll1 = CreateObject("X509Enrollment.CX509Enrollment")

    If IsObject(enroll1) Then msgbox("Is an Object") end if

    enroll1.Initialize(1)

    Set fso = CreateObject("Scripting.FileSystemObject")

    Set ts = fso.OpenTextFile("c:\test\zz.response")

    strResponse = ts.ReadAll

    ts.Close

    MsgBox (strResponse)

    on error resume next

    a = enroll1.InstallResponse(0, strResponse, 1, "")

    if err.number<>0 then msgbox(err.Description) end if

    </script>

    </html>


  • gmeadows94410

    <Script Language="VBSCRIPT">
    Const ContextUser = 1
    Const ContextMachine = 2
    Const XCN_NCRYPT_ALLOW_EXPORT_FLAG = 1
    Const XCN_NCRYPT_UI_NO_PROTECTION_FLAG = 0
    Const XCN_NCRYPT_UI_PROTECT_KEY_FLAG = 1
    </Script>
    <Script Language="JavaScript">
    function XEp_SetGenKeyFlags(objPrivateKey, nGenKeyFlags)
    {

    // some constants defined in wincrypt.h:
    var CRYPT_EXPORTABLE=1;
    var CRYPT_USER_PROTECTED=2;

    objPrivateKey.KeyProtection = (0 != (CRYPT_USER_PROTECTED & nGenKeyFlags)) XCN_NCRYPT_UI_PROTECT_KEY_FLAG : XCN_NCRYPT_UI_NO_PROTECTION_FLAG;
    objPrivateKey.ExportPolicy = (0 != (CRYPT_EXPORTABLE & nGenKeyFlags)) XCN_NCRYPT_ALLOW_EXPORT_FLAG : 0;
    objPrivateKey.Length = nGenKeyFlags >> 16;



    }

    </Script>
    <Script Language="VBSCRIPT">
    Function CreateRequest(lFlags, ssDistinguishedName, sCertUsage)
    On Error Resume Next
    document.form1.CertRequest.value= _
    XE_Enroll_CreateRequest(g_objEnroll, lFlags, ssDistinguishedName, sCertUsage)
    CreateRequest=Err.Number
    End Function

    Function XE_Enroll_CreateRequest(objEnroll, lFlags, ssDistinguishedName, sCertUsage)
    XE_Enroll_CreateRequest = objEnroll.CreateRequest(CRYPT_STRING_BASE64)
    End Function

    Function XE_Request_InitializeCspInformation( _
    objRequest, objPrivateKey,bMachine,nKeySpec, nGenKeyFlags, _
    sProviderName, nProviderType, sContainerName, bReuseKey )

    Dim nContext
    objPrivateKey.ProviderName = "Microsoft Enhanced RSA and AES Cryptographic Provider"
    objPrivateKey.ProviderType = "24"
    objPrivateKey.KeySpec = "1"
    Call XEp_SetGenKeyFlags(objPrivateKey, nGenKeyFlags)
    nContext = ContextUser
    objPrivateKey.MachineContext = bMachine
    On Error Resume Next
    Call objRequest.InitializeFromPrivateKey(nContext, objPrivateKey, "")
    ' True=bLH
    If 0<>Err.Number Then
    XE_Request_InitializeCspInformation = Err.Number
    Exit Function
    Else
    XE_Request_InitializeCspInformation = 0
    End If
    End Function


    Function XE_InitializeCmcObject()
    g_objRequestCmc.InitializeFromInnerRequest(g_objRequest)
    End Function
    Function XE_InitializeEnrollObject(objRequest)
    g_objEnroll.InitializeFromRequest(objRequest)
    End Function


    Function XE_Request_AddDistinguishedName(objRequest, sDN)
    Const XCN_CERT_NAME_STR_NONE = 0
    Dim X500DistinguishedName
    Set X500DistinguishedName = g_objClassFactory.CreateObject("X509Enrollment.CX500DistinguishedName")
    Call X500DistinguishedName.Encode(sDN, XCN_CERT_NAME_STR_NONE)
    objRequest.Subject = X500DistinguishedName
    End Function

    </Script>
    <Script Language="JavaScript">
    //----------------------------------------------------------------
    // convert a (signed) number into a (unsigned) hex string
    function toHex(number) {
    var sRight=(number&0x0FFFFFFF).toString(16).toUpperCase();
    sRight="0000000".substring(0, 7-sRight.length)+sRight;
    return ((number>>28)&0x0000000F).toString(16).toUpperCase()+sRight;
    }
    </Script>
    <Script Language="VBScript">

    <% If Session("Vista") = "vista" Then %>
    Dim g_objClassFactory
    Dim g_objEnroll
    Dim g_objPrivateKey
    Dim g_objRequest
    Dim g_objRequestCMC

    Set g_objClassFactory = CreateObject("X509Enrollment.CX509EnrollmentWebClassFactory")
    Set g_objEnroll = g_objClassFactory.CreateObject("X509Enrollment.CX509Enrollment")
    Set g_objPrivateKey = g_objClassFactory.CreateObject("X509Enrollment.CX509PrivateKey")
    Set g_objRequest = g_objClassFactory.CreateObject("X509Enrollment.CX509CertificateRequestPkcs10")
    Set g_objRequestCMC = g_objClassFactory.CreateObject("X509Enrollment.CX509CertificateRequestCmc")
    <%end if%>

    </Script>
    <script language="javascript" src="/CertRequest/BrowserCompatible.js"></script>
    <Script Language="VBSCRIPT">
    '-----------------------------------------------------------------
    ' IE SPECIFIC:
    ' call XEnroll to create a request, since javascript has no error handling
    Function CreateRequest(lFlags, sDistinguishedName, sCertUsage)
    On Error Resume Next
    Call XE_ReuseHardwareKeyIfUnableToGenNew(False)
    document.CertificateForm.CertRequest.value= _
    XE_Enroll_CreateRequest(g_objEnroll, lFlags, sDistinguishedName, sCertUsage)
    CreateRequest=Err.Number
    End Function
    </Script>

    <script language="javascript">

    var sDistinguishedName=""
    + "CN=\""+document.CertificateForm.txtName.value.replace(/"/g, "\"\"") +"\";"
    + "C=\""+document.CertificateForm.ddlCountry.value.replace(/"/g, "\"\"") +"\";"
    + "S=\""+document.CertificateForm.txtState.value.replace(/"/g, "\"\"") +"\";"
    + "L=\""+document.CertificateForm.txtCity.value.replace(/"/g, "\"\"") +"\";"
    + "OU=\""+document.CertificateForm.txtcompanyname.value.replace(/"/g, "\"\"") +"\";"
    + "E=\""+document.CertificateForm.txtEmail.value.replace(/"/g, "\"\"")+"\";";


    //---Windows Vista.
    var XECR_CMC=3;
    var nResult;
    var sCertUsage="1.3.6.1.5.5.7.3.2";

    document.getElementById("CertAttrib").value ="UserAgent:<%=Request.ServerVariables("HTTP_USER_AGENT")%>\r\n"// navigator.userAgent.toLowerCase();
    nResult = XE_Request_InitializeCspInformation(g_objRequest,g_objPrivateKey, false, "1", "0", "Microsoft Enhanced RSA and AES Cryptographic Provider", "24", "", false);
    XE_Request_AddDistinguishedName(g_objRequest, sDistinguishedName);
    XE_InitializeCmcObject();
    bCmcInitialized = true;
    XE_InitializeEnrollObject(g_objRequestCmc)
    lRequestFlag=XECR_CMC;
    nResult=CreateRequest(lRequestFlag, sDistinguishedName, sCertUsage);
    </Script>



  • Sriman

    Hi,

    If you test the object you created by using IsObject function, You may find that the result is false.


  • plaszlo

    The function which replaces the Xenroll::acceptPKCS7() seems to be CertEnroll::X509Enrollment::InstallResponse()
  • simon chow

    Hi,

    I’am having the same problem and the documentation that i found is not very friendly.

    I have an old version of Netscape Certificate Server with Enrollment pages that use the CreatePLKCS10() and acceptPKCS7() method’s in VBScript.

    Did you solve the problem

    Thanks for any help.


  • carjo

    Hi,

    I tried something like and it turns an object to.

    But i have a permissions problem. When i call the Initialize on object x509PKCS10 i get a "Access Denied". If i put it on a Vbs file works fine. This must be an IE permission, did you know which one

    Thanks

    <html>

    <SCRIPT LANGUAGE=VBS>

    const ContextUser = 1

    Dim CertEnroll

    Set x509PKCS10 = CreateObject( "X509Enrollment.CX509CertificateRequestPkcs10" )
    x509PKCS10.Initialize(ContextUser)


    Set CertEnroll = CreateObject( "X509Enrollment.CX509Enrollment" )
    Dim RequestStr, CertRequest, Disposition, ID

    CertEnroll.InitializeFromRequest(x509PKCS10)

    szCertReq = CertEnroll.createRequest(1)

    MsgBox(Err.Description)
    theError = Err.Number

    MsgBox(szCertReq)

    MsgBox(Err.Description)
    </SCRIPT>

    </html>


  • GrandpaB

    Hey,

    According the document, many objects ,such as X509CertificateRequestPkcs10, can created by calling CreateObject () upon X509EnrollmentWebClassFactory. You can try it to see if it works.


  • invoke

    XEnroll has been deprecated in Vista. It has been replaced by CertEnroll. The CertEnroll API is available on MSDN http://msdn2.microsoft.com/en-us/library/aa374850.aspx.

    In my experience, the API is a PAIN.

  • VashTheStampede

    I have run into this issue as well. I am not primarily a Windows user or developer; I am a CA administrator/developer, and the documentation that I have found is completely unhelpful. My CA currently uses the following Javascript to handle clients with IE:

    // $Id: msenroll.js,v 1.2 2005/12/16 22:42:39 wollman Exp $
    function install() {
    var pkcs7data = document.getElementById("pkcs7data").firstChild.data;
    enroll.acceptPKCS7(pkcs7data);
    }
    function genkey() {
    // var keylen = parseInt(document.getElementById("keysize").value);
    enroll.GenKeyFlags = (2048 * 65536) | 1;
    document.getElementById("csr").value = enroll.createPKCS10("", "");
    document.getElementById("submit").disabled = false;
    document.getElementById("generate").disabled = true;
    }

    (The variable "enroll" is instantiated by an OBJECT element in the document which references this code.) What I need is an example to follow that does the same thing for Vista clients (preferably in a way that also works on XP/Server 2003 clients). Has anyone done this

    While debugging this, I also noticed that the line numbers in the IE7 script error alert do not seem to bear much relationship to reality.

  • Drudkh

    If IE7 is running on Window Vista, You can set it to "run as administrator" by right click IE icon and select "run as administrator";

    Or you can check the option box for "Run this program as an administrator" on Comatibility tab of IE property, since on Window vista IE is running as user mode even if you login as administrator


  • J. Clark

    When I create the request the way you have described I get the 80070005 error later on when I try to install it:

    Sub Install_OnClick

    Dim enroll

    Dim result, Message

    Set enroll = CreateObject("X509Enrollment.CX509Enrollment")

    enroll.Initialize(1)

    on error resume next

    pkcs7 = Document.TheForm.pkcs7.Value

    MsgBox(pkcs7)

    a = enroll.InstallResponse(1, pkcs7, 1, "")

    If ( err.Number = 0 ) Then

    Message = "Your new certificate has been successfully installed!"

    result = MsgBox (Message, 64, "Certificate Installation")

    Else

    Message = "Unable to install the certificate." & vbcrlf & vbcrlf

    Message = Message & "Error code: " & Hex(err)

    End If

    End Sub

    Any ideas why it happens


  • Grant Jenkins

    Because Widnows vista Microsoft is not supporting Xenroll.

    For certificate enrollment the windows server uses xenroll active x control. But windows vista uses dula interface COM object known as CertEnroll.



  • Ronaldlee Ejalu

    It can even work without quoting the webfactory object.

    codes like:

    Set enroll = CreateObject("X509Enrollment.CX509Enrollment")
    Set privatekey = CreateObject("X509Enrollment.CX509PrivateKey")

    can work.

    And the API doc has something difficult for the readers regarding optional parameters and return value.


  • NickNotYet

    The code doesn't work in webpage, because X509CertificateRequestPkcs10.Initialize(Context) is not Webenabled. In webpage, some methods and properties that marked WebEnabled can work well.

    If we want to do a simple certficate request demo, then we can use enroll.Initialize(Context) and then enroll.Create(encodeType).

    If we want to specify some attributes of the certificate request, then we can set attributes to the privatekey and initialize the requestpkcs10 from the privatekey, and then initialize the enroll from the request.


  • IE7 Certificate Request/Enrollment