What’s wrong with Web Cryptography

Introduction

Building full stack of cryptographic protection for modern applications includes working with the modern web browser, of course.

However, through 20+ years of history of web browsers, we’re at the stage where in-browser cryptography is still problematic, and best you can rely on is SSL. Which only protects data transport between you and server, leaving you hoping that you’re good enough to go. Which is not always the case.

With our products, we’re set to have zero compromises on security levels — even when it means going longer ways with tooling. So we decided not to go JavaScript crypto way (since it has plenty of security compromises in any scheme we’ve evaluated — a bit on that below), but do a proper browser-level Themis port instead.

To deliver proper cryptographic operations into the browser our way, we’ve had to create C++ port of Themis, make it build in PNaCl way and build things around it.

Is in-browser JS crypto useless?

It is not. In some distant future, when browsers and standards mature (see below), it might even become the right way to do front-end crypto, but certainly not now, due to the way browser and JavaScript-inside-browser works.

Problems with code authenticity:

  • Same origin policy restricts bad code from directly injecting more bad code from third parties. This is easily bypassable.
  • There’s no way to audit code: random pieces of code can download more code from different places at any moment of page’s execution, so ‘View source’ doesn’t actually reveal anything.
  • JS crypto code could’ve been simply replaced during an active MiTM attack.
  • Code behavior relies on DOM — which can be modified by any other piece of code.
  • Any function your crypto code depends on could be silently overwritten by any piece of content used to build the hosting page
  • Browser cache is uncontrollable: once again, you never know which version of the code you run.
  • What if we send all JS code via SSL? SSL is known to be vulnerable in some cases, yet, still, if you are transmitting anything outside SSL, attackers will use that least secure channel to hijack the code.

Approach problems:

  • Most JS crypto libraries supply only low-level primitives, requiring developers to compose cryptosystems themselves while writing browser code in JS. Not exactly the situation where you’d like cryptographic decisions to be made.
  • Too many platforms with different JS engines, some of them will execute JS code in a different manner, too many platforms to support equal experience or equal security model.
  • JS computations in the browser are plain slow compared to native code.

We are not aware of any really cryptographically secure PRNG in current JS libraries.

The worst thing is, there is no way to understand when and how the system was compromised as there are so many uncontrollable parts affecting code behaviour… You could end up with the illusion of being secure, right until the point where you’re not.

Some fence is still better than no fence, right?

WebCrypto W3C standard and API

There is a movement for good, however: new WebCrypto API standard draft, partially supported by browsers. However, at the current moment it’s still not enough for us:

  • It is the ‘construct yourself a cryptosystem’ kind of standard and API. However, forcing front-end developers to make decisions about constructing (not just implementing) cryptosystems does not seem to be a very good idea. We respect the hard work JavaScript programmers do to make things interactive and beautiful, but cryptography is a very different beast.
  • It still lacks many important primitives, including questionable curve choice and doubtfully working Diffie-Hellman.
  • Algorithm support is fragmented across browsers.
  • High level architecture problem: code is called from in-browser JavaScript application, which is prone to all the problems we’ve outlined above.

So, what we did?

Having to produce secure front-end web app as well, we chose to go another way: do a Chrome PNaCl-based port of Themis, and make our web application work with it. Covering half of web’s users with a strong crypto is much better than covering all of them with a bad one.

Stay tuned to updates

In the next weeks, we’ll summarize our experience of developing cryptography for Google Chrome, porting OpenSSL, building Themis for PNaCl, etc. So far, you can read the introductory post and follow other developments on our blog.