Following up on last week’s post, it was decided that we would generate the private keys in the user’s browser, and then it would be uploaded to the server for the creation of the certificate. At first glance, this seemed to compromise security because by right the private key should not be anywhere else other than in the user’s possession. However, it would even have its own MIME type if it is not allowed to transmit the private keys somewhere else. Its transmission would require to have to have some form of security measures in place. In our case, it would be done using the HTTPS protocol, hence the connection to the server is encrypted. Moreover, the all the information regarding the user is stored on the server side, which will be used to fill in the relevant attributes of the Certificate Signing Request (CSR), and its creation requires the corresponding private key.
At the moment, this is how I planned the initial phase of the certificate installation procedure to be. The download URL would point to a REST endpoint of the server, and when the user clicks on that URL, the browser would prompt the user for any valid client certificate to send to the server. In that particular REST endpoint, we could handle for the case where the user does not provide any client certificate, and another case where they actually do provide a valid certificate. Note that the latter case would only happen when the user decides to renew their subscription early, i.e before their monthly renewal due date, hence this would mean that they would still be holding to the old valid client certificate. Such certificate should be revoked and the server provides a new certificate following the new subscription period. Anyhow, more details of that will be revealed when I actually start implementing that part.
For now, I concerned myself to the case when the user has no valid certificate at all. If that happens, the server would send a 302 redirect to a HTML file stored on the server. That HTML file would have JavaScript code for generating the private key. Later on, I could also add some loading indicator in the HTML body, so that the user could see that the installation procedure is under way. The code for generating the private keys would be done on the fly, as soon as the HTML document has fully loaded in the browser. This is done using the Web Cryptography API, which is a fairly new part of the Web standards today, although it already has a good amount of browser support. There are examples for how to generate different kinds of private keys. For us, we would be using the ECDSA keys. So yeah, that was simple enough.
But then, a problem unexpectedly arises. After creating the private key, it would still need to be exported in a format such that it could be transmitted to the server, like the PKCS#8 format. This is done using the exportKey()
method of the Web Crypto API. However, the Firefox browser that I am using for development does not support exporting ECDSA nor ECDH keys in PKCS#8 format. There’s a bug report on it since 4 years ago, but for reasons unknown, it has yet to be addressed by the Mozilla developers. It is frustrating, I must say. There is also another format for transmitting the private keys, which is JSON Web Keys (JWK). Apparently, there are no errors exporting the key in this format, but I have yet to figure out how it works. So all hope is not lost, I suppose. Tune in next week to find out.
0 Comments