Christopher Meyer

About Christopher Meyer

Chris works as a researcher and is eagerly looking for bugs in SSL/TLS, the Java platform and various applications. In addition, he is primarily interested in secure coding and exploiting coding mistakes.

Browser-based Key Generation and interaction with the Browser’s Key/Certificate Store

Imagine the following scenario:
You need to get a key (in the asymmetric case the user’s public key) from a user visiting your website and want the browser to remember the private part without bothering the user with lengthy import procedures. To be honest, in practice you don’t even want the user to deal with cryptographic details – details that many users are not able to know and do not know anything about it rightly. It should simply work and in the best case the user shouldn’t even notice that crypto is doing it’s magic!
Imagine for example an enterprise-wide Certification Authority where employees can apply for certificates or renew existing ones which are required to log on to the corporate webmail system. This is not part of the employee’s primary tasks, so the process has to be simple, quick and without the need to read any
 
documentation.Thank god – or in this case Netscape – HTML ships, since HTML 5 even browser independent, as part of the official standards, with a tag dedicated to key generation: <KeyGen />. To put it in a nutshell, the tag can force a user’s browser to create an asymmetric key pair, sign the corresponding public key and a server provided challenge and finally send it back to the server (more precisely to the location defined in the form action attribute).  The private key is automatically encrypted and stored in the browser’s key store. The format used for public key, challenge and signature encapsulation is called SPKAC. If the server responds with a X.509 certificate the certificate is directly linked to the private key and stored in the browser’s certificate store.
 
As a result, the browser is now in possession of a server supplied (maybe newly created)  certificate and the corresponding private key. And all of this with a single, simple click on the submit button. (Yeah, maybe the user should also add some details into form fields…)And here is how to do this in Java. For the sake of simplicity we will use a quick and dirty solution on server side, by directly registering as a Servlet.

At first, we will start with the initial website which presents a form where some details of the certificate requester have to be entered. Please note that these form fields are NOT protected by the signature with the newly generated private key! This signature only protects the public key and the challenge which in this case is – for the sake of simplicity – hard coded, but has to be a fresh value chosen by the server in a real world scenario. Hence, it is essential to protect both: the delivery of the website including the form (it contains security critical values, the challenge, the form action, … which must be integrity protected) and the transfer of the data back to the server. Once again, if you fail to protect the communication and ensure at least the security goal integrity, an attacker may break your whole security concept!

<form action="CreateCertificate" method="POST">
<table>
       <tbody>
                <tr>
                    <td>Country name</td>
                    <td>C</td>
                    <td><input name="c" type="text" value="" /></td>
                </tr>
                <tr>
                    <td>Common name</td>
                    <td>CN</td>
                    <td><input name="cn" type="text" value="" /></td>
                </tr>
                <tr>
                    <td>Organizational unit</td>
                    <td>OU</td> 
                    <td><input name="ou" type="text" value="" /></td>
                </tr>
                <tr>
                    <td>Organization</td>
                    <td>O</td>
                    <td><input name="o" type="text" value="" /></td>
                </tr>
                <tr>
                    <td></td>
                    <td><keygen challenge="replaceMe" keyparams="2048" keytype="rsa" 
                      name="newSPKAC"></keygen></td>
                    <td><input type="submit" value="Generate!" /></td>
                </tr>
       </tbody>
</table>
</form>

On server side it is necessary to register a processing class for the form action target. This is done in your web.xml configuration file.

<web-app version="3.0" xmlns:xsi="..." xmlns="..." xsi:schemalocation="...">
    <servlet>
        <servlet-name>CreateCertificate</servlet-name>
        <servlet-class>
            com.blogspot.armoredbarista.examples.certificates.CreateCertificate
        </servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>CreateCertificate</servlet-name>
        <url-pattern>/CreateCertificate</url-pattern>
    </servlet-mapping>
    <session-config>
        <session-timeout>
            30
        </session-timeout>
    </session-config>
</web-app>

This causes any call to  the path /CreateCertificate to be handled by the CreateCertificate class. The CreateCertificate class in turn, does what we expect from the name: it creates a certificate including the received public key and the requester’s details. The public key and the challenge are included in the SPKAC structure, created by the KeyGen tag (which in this case is identified by the name newSPKAC).

public class CreateCertificate extends HttpServlet {
    /**
     * Processes requests for both HTTP GET and POST methods.
     *
     * @param request servlet request
     * @param response servlet response
     * @throws ServletException if a servlet-specific error occurs
     * @throws IOException if an I/O error occurs
     */
    protected void processRequest(final HttpServletRequest request,
            final HttpServletResponse response)
            throws ServletException, IOException {

        OutputStream out = response.getOutputStream();
        byte[] content = "An error occured".getBytes("UTF-8");
        try {
            String c = request.getParameter("c");
            String cn = request.getParameter("cn");
            String o = request.getParameter("o");
            String ou = request.getParameter("ou");
            String newSPKAC = request.getParameter("newSPKAC");

            X509Certificate cert = createCertificate(c, cn, ou, o, newSPKAC);
            content = cert.getEncoded();

            response.setContentType("application/x-x509-user-cert");
            response.setHeader("Pragma", "No-Cache");
            response.setDateHeader("EXPIRES", -1);
        } catch (...) {
          // error processing
        } finally {
            out.write(content);
            out.flush();
            out.close();
        }
    }

    /**
     * Handles the HTTP
     * GET method.
     *
     * @param request servlet request
     * @param response servlet response
     * @throws ServletException if a servlet-specific error occurs
     * @throws IOException if an I/O error occurs
     */
    @Override
    protected void doGet(final HttpServletRequest request,
            final HttpServletResponse response)
            throws ServletException, IOException {
        processRequest(request, response);
    }

    /**
     * Handles the HTTP
     * POST method.
     *
     * @param request servlet request
     * @param response servlet response
     * @throws ServletException if a servlet-specific error occurs
     * @throws IOException if an I/O error occurs
     */
    @Override
    protected void doPost(final HttpServletRequest request,
            final HttpServletResponse response)
            throws ServletException, IOException {
        processRequest(request, response);
    }
}

The ContentType used for the response is in this case application/x-x509-user-cert.

And that’s all. After the user has entered his details and clicked on the button, he should find a new certificate in the browser’s certificate store:
 

 

 

A final word on the fiddly disassembling of SPKAC: BouncyCastle may help you fighting the ASN.1 and DER beast!
 

Related Whitepaper:

Web Application Security; How to Minimize Prevalent Risk of Attacks

Vulnerabilities in web applications are now the largest vector of enterprise security attacks.

Stories about exploits that compromise sensitive data frequently mention culprits such as cross-site scripting, SQL injection, and buffer overflow. Vulnerabilities like these fall often outside the traditional expertise of network security managers.

Get it Now!  

One Response to "Browser-based Key Generation and interaction with the Browser’s Key/Certificate Store"

  1. rohit says:

    hi
    can you please me how to resolve this line
    createCertificate(c, cn, ou, o, newSPKAC);
    createCertificate method not find.

    thank you.

Leave a Reply


7 − one =



Java Code Geeks and all content copyright © 2010-2014, Exelixis Media Ltd | Terms of Use | Privacy Policy
All trademarks and registered trademarks appearing on Java Code Geeks are the property of their respective owners.
Java is a trademark or registered trademark of Oracle Corporation in the United States and other countries.
Java Code Geeks is not connected to Oracle Corporation and is not sponsored by Oracle Corporation.

Sign up for our Newsletter

20,709 insiders are already enjoying weekly updates and complimentary whitepapers! Join them now to gain exclusive access to the latest news in the Java world, as well as insights about Android, Scala, Groovy and other related technologies.

As an extra bonus, by joining you will get our brand new e-books, published by Java Code Geeks and their JCG partners for your reading pleasure! Enter your info and stay on top of things,

  • Fresh trends
  • Cases and examples
  • Research and insights
  • Two complimentary e-books