I'm investigating the HTML5 attribute Keygen and discovered that it sends this data on a Form POST to the server. Here is an example POST:


When I parse this using an ASN.1 parser it contains

  • A RSA key (oid 1.2.840.113549.1.1.1),
  • A MD5 hash (oid 1.2.840.113549.1.1.4)
  • A 2048 bit string which is the signature.

Further investigation reveals this is likely called the Signed Public Key and Challenge (SPKAC) format and this format is accepted by the Microsoft CA server.


  1. The keygen docs at Mozilla, and the keygen docs at w3 don't specify a return format after the POST. What should I return?
  2. After keygen is run, (see links at the bottom of this page) I don't see a certificate in my local store. Where is it?
  3. My understanding is that Keygen is used to create a Browser Certificate. What logical steps do I need to complete in order to finish this process?

2 Answers 2

  1. The keygen docs at Mozilla, and the keygen docs at w3 don't specify a return format after the POST. What should I return?

The reason this information is not listed is because the KeyGen element sends an SPKAC to the server and once a CSR (Certificate Signing Request) is generated and sent to a reputable CA (Certificate Authority) an x.509 signed client certificate is to be sent back to the client that created the private key.

A typical procedural event for handling SPKAC's from the KeyGen element would be as follows:

  1. User specifies a unique 'challenge' which gets encoded within the KeyGen generated SPKAC (signed public key & challenge ASN.1 value).
  2. The KeyGen element generates a Private key which is then stored within the browser certificate store.
  3. A public key is then derived from the private key.
  4. The derived public key & the user submitted challenge is then encoded as an ASN.1 SPKAC formatted string (see the 'certificate request format' below).
  5. A CSR is then created (see below) and sent to a reputable certificate authority.
  6. The CA generates an x.509 certificate which can the be used for pass-wordless authentication (as long as the web server is configured to do so)

Essentially setting the 'Content-Type' header to 'application/x-x509-user-cert' will force the browser to load it into it's certificate store.

  1. After keygen is run, (see links at the bottom of this page) I don't see a certificate in my local store. Where is it?

KeyGen does not generate a certificate. It generates a private key. The public key is derived from the private key (which is not accessible from the browsers certificate store, nor through the JS engine API) then encoded as an SPKAC.

The SPKAC is to be used within a CSR (Certificate Signing Request) and an example of which would look like the example below, the more traditional CSR can be shown here, and see here for references:

CN=Joe Snuffy
OU=Snake Oil, LLC
O=Department of pricing
L=City name
ST=State or province
C=United States
[email protected]
  1. My understanding is that Keygen is used to create a Browser Certificate. What logical steps do I need to complete in order to finish this process?

The entire process for using a keygen element for a practical client certificate authentication within web applications is as follows:

  1. Within an administrative panel of a web application (using an existing account) the user has the option to create a client certificate (x.509) to use for authentication. This loads the SPKAC KeyGen element along with a form providing the following attributes (everything in the parenthesis corresponds to the above CSR example):

    • organizationalUnitName (OU)
    • organizationName (O)
    • localityName (L)
    • stateOrProvinceName (ST)
    • countryName (C)
    • emailAddress (E)
    • commonName (CN)
  2. Once the form is provided to the server a CSR is generated. This is to then be provided to a CA (Certificate Authority) for signing.

  3. Once signed the client is notified to log back into the web application at which time the x.509 header 'content-type' can then be used to force the certificate into the browser's certificate store.
  4. As long as the web server is configured to do so, it can force the client to send any x.509 certificates for client certificate authentication. The apache web server documentation provides this information.

Some additional notes regarding the SPKAC; the challenge string provided should be unique to each users client certificate. An example of setting this based on user input would be the following snippit:

/* Gather up our form & its elements */
var form = document.getElementById("myForm")
  , challenge = document.getElementById("challenge")
  , spkac = document.getElementById("spkac");

/* Add an event handler to move the value from the 'challenge' input
   to the keygen element challenge attribute */
form.addEventListener("blur", setSpki, true);

/* Our function which sets the challenge */
function setSpki(){
  spkac.setAttribute('challenge', challenge.value());

This is essential because once the signed client certificate is in the browser store anyone using that browser potentially has access to their account.

The challenge provided during the initial SPKAC should be used as a secondary form of proof of ownership for the private key corresponding to the private key used for the SPKAC.

As an example; the user logs out, closes the browser destroying the authenticated session. A malicious user sits down at the same terminal and attempts use the x.509 to provide authentication and is then prompted for the challenge.


It seems that the answer lies in the updated w3 link I just found. Specifically

This specification does not specify how the private key generated is to be used. It is expected that after receiving the SignedPublicKeyAndChallenge (SPKAC) structure, the server will generate a client certificate and offer it back to the user for download; this certificate, once downloaded and stored in the key store along with the private key, can then be used to authenticate to services that use TLS and certificate authentication.

The process of saving the certificate into the local store is up to each browser. (IE uses the Windows store, some other browsers have their own private store)

Validation of the browser certificate would involve verifying the CA chain matches the internal CA root, and associating the browser cert with the user.

If the application is designed to permit the user to have multiple certificates for a single account, then this many to one relationship should be tracked on a per user basis. (This is useful if mutual authentication of the TLS session is considered the primary feature of Browser Certificates, and forms based (even multifactor) authentication is done in addition to this)


You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .