A random story on WebCrypto and WebAssembly

For instance, we can look at how Chromium-based browsers generate random values for cryptographic operations since the code is open source.

However, we couldn't do that for all of our target browsers (e.

g.

IE11 and Edge are closed-source).

Also, implementations on Windows typically rely on RtlGenRandom() from the operating system's API which is also closed-source.

As such it cannot be proven to provide the necessary level of entropy.

Overall, while the Web Cryptography API is very well suited to cryptographically transform data it is not capable of generating keys in a way that is compliant with our entropy requirements.

WebAssembly: leaving the bubble, entering the wildAs much as we loved working with the Web Crypto API, we needed a solution that gave us the control over what entropy sources are used while still having a performance that can compete with the Web Crypto API.

We needed something that the browser did not offer.

While there certainly were libraries for different languages that solved our use case, we were simply locked-out.

At that time, we already had a desktop client for Bdrive up and running for a while, written in C++.

That desktop client faced the same entropy requirements.

But being implemented in C++ we were free to pick a crypto library that supported this use case and went for Botan.

Botan is a quite popular C++ library implementing a wide variety of low-level cryptographic algorithms.

Moreover, Botan is open-sourced and has already been analyzed and approved by the BSI (German-only version of the analysis can be found here).

Lucky for us, WebAssembly (short: WASM) became available in all major browsers a short while ago (except IE11).

WebAssembly is a portable instruction format that other languages (e.

g.

C++) can compile to and that can, for instance, be embedded and run inside a browser application's execution context.

WebAssembly code example as compiled by ChromeFor us this meant that we could actually make use of Botan inside of our JavaScript browser application by turning it into a WebAssembly module.

That's why we decided to solve our issue of controlling the entropy of key generation by compiling the necessary parts of Botan to WASM.

To put it mildly, this idea was thrilling.

Suddenly, if we are having an implementation challenge, we are no longer locked-in to what the JavaScript ecosystem and native APIs have to offer.

Instead, the entire set of languages becomes available to use (well, more or less).

Simply compile the code down to WebAssembly and put it into the browser.

No more waiting for W3C API specifications to be proposed, discussed, tried out, standardized and adopted.

Is WebAssembly better than Web Crypto, then?When having a code base that relies on WebAssembly to do some parts of cryptography and on the Web Crypto API for the other parts, one might ask if we couldn't just go for WebAssembly for all cryptographic operations.

There are a couple of reasons preventing us from doing so:Bundle sizeA compiled WebAssembly file (.

wasm) containing only those parts of Botan that allows us to source entropy, obtain random bytes and generate RSA keypairs is already 2.

4 MB in size.

A combination of code splitting and prefetching compensates a little for that.

If Botan is compiled to WASM with all modules enabled though, the resulting .

wasm file weighs about 13 MB.

Even if we used it for all other algorithms as well and compiled those parts too, we would end up with a file that simply cannot be downloaded anymore in a reasonable time on slower connections.

This would impair the user experience a lot and thus not align with our goal of making E2E-encryption easy.

PerformanceWe found the Web Cryptography API to have a better performance than our WASM-compiled version of Botan.

For instance, we compared the performance in Chrome 73 on macOS when generating an RSA key pair with a modulus length of 4096 bits.

Using the Web Crypto API will take 1.

4 seconds on average for a single key pair.

The same task takes 6.

3 seconds on average when using Botan (as WASM).

To better visualize the overhead that calling into a WebAssembly module causes, we also compared the time it takes to generate 1024 random bytes 1024 times in a row.

It took the Web Cryptography API in our Chrome (macOS) implementation just 6ms to generate those 65536 bytes.

The implementation using WebAssembly took 46ms in average.

This immediately makes sense when considering that there is little overhead when calling into the Web Crypto API implementation of the browser.

Moreover, this is exactly what the API can optimize for.

Nonetheless, it is likely that performance of WebAssembly execution will improve a lot in the future — specifically with upcoming features such as threads.

Using features such as dynamic linking and improved tooling support, it is very imaginable that even the loading times due to large bundle sizes might decrease in the future.

Summing it upWe've been happy with the fusion of a WebAssembly-compiled Botan and the Web Crypto API for some months now.

Naturally, using both at once is a compromise that comes with some downsides like added complexity or an increased bundle size.

This compromise, however, allows us to enjoy the upsides of both solutions to the fullest.

So let’s sum up where each of them shines:Advantages of WebAssemblyvery flexible since many libraries in different languages can be compiled and used (allowed us to meet our certification requirement)will probably be used more often in the futureAdvantages of W3C Web Cryptography APIfaster than probably any WebAssembly-compiled implementation could beno increase in bundle size since the platform (browser) includes the implementationno need for additional build stepsSince it is unlikely that the Web Crpyto API will evolve to cover entropy level guarantees we'll likely keep the Botan/WASM solution.

Since it's also unlikely that WebAssembly will reduce the downsides of performances and bundle size drastically in the near future, we'll also likely stick with the Web Crypto API wherever possible for a while.

However, it is exciting to see where things are moving.

Maybe, in a couple of years, the need to use the native JavaScript APIs of the browser will vanish and instead, WebAssembly will be the platform default.

Are you interested in using or creating safer software with us?.We are always looking for customers, partners and motivated engineers.

Get in touch at nexenio.

com.

.. More details

Leave a Reply