Monday, July 15, 2013

NfWebCrypto: a Web Cryptography API Native Polyfill

At Netflix we are excited to build an HTML5-based player for our service, as described in a previous blog post.  One of the “Premium Video Extensions” mentioned in that post is the Web Cryptography API, which “describes a JavaScript API for performing basic cryptographic operations in web applications, such as hashing, signature generation and verification, and encryption and decryption.” Netflix uses this API to secure the communication between our JavaScript and the Netflix servers.

The Web Cryptography WG of the W3C (of which Netflix is a member) produces the Web Cryptography API specification. Currently the spec is in the Working Draft stage and some browser vendors are waiting until the spec is more finalized before proceeding with their implementations. A notable exception is Microsoft, who worked with us to implement a draft version of the spec in Internet Explorer 11 for Windows 8.1 Preview, which now allows plugin-free Netflix video streaming.

To continue integrating our HTML5 application with other browsers, we decided to implement a polyfill based on the April 22, 2013 Editor’s Draft of the Web Cryptography API specification plus some other proposals under discussion. While similar in principle to JavaScript-based Web Crypto polyfills such as PolyCrypt, ours is implemented in native C++ (using OpenSSL 1.0.1c) to avoid the security risks of doing crypto in pure JavaScript. And because crypto functionality does not require deep browser integration, we were able to implement the polyfill as a stand-alone browser plugin, with our first implementation targeting Google’s Chrome browser using the Pepper Plugin API (PPAPI) framework.

So that you can also experiment with cryptography on the web, and to support the ongoing development of the specification in the W3C, we’ve released this NfWebCrypto plugin implementation as open source under the Apache Version 2.0 license. While NfWebCrypto is not yet a complete implementation of the Web Cryptography API, and may differ from the most recent version of the rapidly changing spec, we believe it has the mainstream crypto features many web applications will require. This means that you can use this plugin to try a version of the Web Cryptography API now, before it comes to your favorite browser.

At the moment the plugin is only supported in Chrome on Linux amd64 (tested in Ubuntu 12.04). For the latest details of what works and what does not, please see the README file in the NfWebCrypto GitHub repository. Here is a summary of the algorithms that are currently supported:

  • SHA1, SHA224, SHA256, SHA384, SHA512: digest
  • HMAC SHA: sign, verify, importKey, exportKey, generateKey
  • AES-128 CBC w/ PKCS#5 padding: encrypt, decrypt, importKey, exportKey, generateKey
  • RSASSA-PKCS1-v1_5: sign, verify, importKey, generateKey
  • RSAES-PKCS1-v1_5: encrypt, decrypt, importKey, exportKey, generateKey
  • Diffie-Hellman: generateKey, deriveKey
  • RSA-OAEP: wrapKey*, unwrapKey*
  • AES-KW: wrapKey*, unwrapKey*
*Wrap/Unwrap operations follow the Netflix KeyWrap Proposal and support protection of the JWE payload with AES128-GCM.

NfWebCrypto will of course be obsolete once browser vendors complete their implementations. In the meantime, this plugin is a stop-gap measure to allow people to move forward with cryptography on the web.  Since finalization of the spec may still be some time away, we hope the community will benefit from this early look. We also hope that a concrete implementation will provide a backdrop against which the evolving spec can be evaluated. Finally, the NfWebCrypto JavaScript unit tests and perhaps the actual C++ implementation may be useful references for browser vendors.

Moving forward, we plan to keep pace with the W3C spec the best we can as it evolves. We welcome contributions to NfWebCrypto from the open source community, particularly in the areas of security audits, expanding the unit tests, and porting to other browser plugin frameworks and platforms.

You can find NfWebCrypto at the Netflix Open Source Center on GitHub.