Subscribe to receive notifications of new posts:

How we built Origin CA: Web Crypto

2016-05-10

3 min read

At CloudFlare we strive to combine features that are simple, secure, and backed by solid technology. The Origin CA is a great example of this. You no longer need to go to a third-party certificate authority to protect the connection between CloudFlare and your origin server. You can now get a certificate to encrypt the connection between CloudFlare and the origin from CloudFlare directly with one click.

In certificate-based security, the most important thing is protecting the private key. We designed the one-click certificate dashboard to maximize private key security. Your private key is created client-side in your browser using the W3C’s Web Crypto API and only the public key is sent to CloudFlare’s servers. This security feature turned out to be a big win for usability as well as an interesting technical challenge.

Certificate authorities don’t need your private key

Most certificate authorities (CAs) specialize in one type of transaction: they take a certificate signing request (CSR) (and sometimes a fee) and in return they provide a signed certificate. A CSR is a way to tell a certificate authority what your public key is and to prove you have control of the corresponding private key. The certificate authority doesn’t need to see your private key to validate the CSR. This is a good thing. Sharing your private key with anybody, including your CA, makes it more vulnerable to theft.

Getting a certificate

Like most CAs, the CloudFlare Origin CA requires you to send a CSR signed by your private key to get a certificate. If you take a look at the API for the Origin CA you’ll see that CSRs are exchanged for certificates and private keys are not involved. This API is the only way to get a certificate from CloudFlare’s Origin CA: both the CloudFlare dashboard and the Origin CA CLI use it under the hood.

If you want full control over your private key, you can create it yourself using OpenSSL or CFSSL and select “I have my own private key and CSR” in the dashboard. We recommend this for experienced sysadmins. However, we wanted to provide a simpler and more convenient way to get a certificate, preferably one that didn’t require a series of command-line incantations. This posed an interesting problem: how do we let customers create CSRs and private keys without asking them to install or run cryptographic software?

Web Crypto and PKI.js

The solution to our problem was to create a client-side web application for generating keys and CSRs. By generating the private key and CSR in the customer’s browser, the CSR could be sent to the API while keeping the private key safely on the customer’s machine. Doing anything complex in the browser usually means using JavaScript, and there have been convincing arguments that doing cryptography in JavaScript is a bad idea. These arguments were made a half-decade ago and the web changes quickly so we surveyed the landscape to see if these arguments were still convincing in 2016. Things have changed.

In the last few years, a new addition to Web standards was introduced that changes everything: support for native cryptography in the browser. The W3C Web Crypto group has made a lot of progress towards standardizing a set of APIs to do standard cryptographic operations including encryption, digital signatures and key generation. As of today, Web Crypto features are supported by almost all modern browsers. With native web crypto, we no longer need to use problematic JavaScript cryptography to create private keys and sign CSRs.

With the pure cryptographic operations handled by the browser, we still needed some code to structure and format the CSRs and certificates. For this we used PKI.js, an open source JavaScript library by our friends at GlobalSign that is built on the WebCrypto API. PKI.js a full featured PKI toolkit that can create CSRs and certificates as well as handle a wide variety of certificate formats including DER, PEM, PKCS#7 and PKCS#12.

In the Origin CA dashboard, we use WebCrypto to generate the key and PKI.js to create CSRs. When you click “next” in the one-click certificate dialog, your CSR is sent to the CloudFlare API. When the certificate comes back from the API, we use PKI.js to convert it to the right format and display it with your private key.

CloudFlare’s servers don’t see your private key and you get to save yourself the hassle of learning obscure OpenSSL commands.

Origin CA Data Flow

Of course, not everything smells of roses. Because Web Crypto is an evolving standard, we have to deal with uneven support for the APIs we need. While working on the project, we realized that Firefox was unable to export ECDSA keys in the formats we needed—if we left it as is, a huge portion of our user base would be unable to use modern cryptography. We want our features to be used by as many people as possible, so we built a shim over the WebCrypto API which supports the formatting we need. We intend to continue working on this shim, adding support for Safari, Internet Explorer and other browsers.

Conclusion

The Origin CA posed some interesting challenges to the team and hopefully this blog post illustrated one of them. A big shout-out goes to CloudFlare engineers Andrew Kennedy and Brendan McMillion for making this part of the project happen. Here’s to encrypting the back-end of the Internet!

If these sort of development projects are interesting to you, CloudFlare is hiring.

Cloudflare's connectivity cloud protects entire corporate networks, helps customers build Internet-scale applications efficiently, accelerates any website or Internet application, wards off DDoS attacks, keeps hackers at bay, and can help you on your journey to Zero Trust.

Visit 1.1.1.1 from any device to get started with our free app that makes your Internet faster and safer.

To learn more about our mission to help build a better Internet, start here. If you're looking for a new career direction, check out our open positions.
Certificate AuthorityJavaScriptAPISecurityCryptography

Follow on X

Nick Sullivan|@grittygrease
Cloudflare|@cloudflare

Related posts