Web Assembly in a browser and beyond — Crypto Example

Web Assembly

  • is a low level portable binary format (bytecode) for a stack-based virtual machine

  • is a W3C web standard, that runs in a sandbox, on all major browsers

  • runs nearly as fast as native machine code, and enables high performance applications on the Web

  • language, hardware and platform independent (unlike Java applets and Flash)

  • can be generated from most high level compiled languages — C, C++, Java, Rust, Go, F#, C# etc

  • code is validated and executes in a memory-safe, sandboxed environment preventing data corruption or security breaches

  • memory safety means exploit techniques such as stack smashing and ROP are not possible

  • complements Javascript — for e.g. by enhancing the performance of CPU intensive components of a web app

It is important to reiterate that Wasm is a web standard and therefore part of the Web Platform. This is unlike Java and Flash Applets which were second class citizens on the browser — they used the browser’s plugin functionality and worked within a frame in a web page.

Note: Currently, there’s no way to interact with the DOM. This means you can’t do something like element.innerHTML to update a node from WebAssembly. Instead, you have to go through Javascript to set the value.

A cartoon intro to WebAssembly, a 6 part series of articles by Lin Clark explains WebAssembly very well.

As mentioned earlier, most major languages have compilers that generate Web Assembly. I will mention 2 of them here — Rust and Go.

Rust, from Mozilla, is a fantastic systems programming language, that gives you the performance of C without the nuisance of buffer overflows!

It compiles to machine code, has a fast startup time as there is no runtime1. You get automatic resource management — no need to close sockets or files, and no “use-after-release” bugs.

As there is no runtime overhead of (tracing) garbage collection, Rust is quite suitable for performance critical and embedded applications.

The learning curve for Rust is steeper than languages such as Go and Java, primarily because automatic memory management is achieved based on concepts such as ownership, references and borrowing. One can say that garbage collection happens at ‘compile time’ and for Rust newbies, getting the damn program to compile can be frustrating! But the error messages from the compiler are so good and specific that you can fix them after a few iterations of edit-compile cycle.

Rust’s rich type system and ownership model guarantee memory-safety and thread-safety — and enable you to eliminate many classes of bugs at compile-time. Major parts of the Firefox browser are written in Rust.

Rust can be compiled to Web Assembly which loads pretty fast in the browser as Rust doesn’t have a runtime.

Go (from Google) is another statically typed language. The reason I have listed Go here is that it comes standard with lots of Crypto libraries. Go is a nice language to write programs that use crypto libraries. It is a great learning tool as you can look up the implementation of the crypto libraries from your editor (like emacs) or IDEs.

I wanted to write a web app that shows some crypto operations like digital signatures, key exchange using Elliptic curves, some well known vulnerabilities etc etc. Doing Crypto with Javascript will be very slow. To be precise, as I am not a Javascript developer, I would have used a language like Haskell, F# Scala or Java and transpile it to Javascript. However, as all major browsers support Web Assembly and it is supposed to run nearly as fast as native machine code, I decided to write my program in F# which can be compiled to Web Assembly.

You can see this below. You have to scroll the window to see the complete app. You can also open the app by visiting https://crypto.srinivasan.biz in the browser. The app may take a few seconds to load — this is because it has to download the .NET runtime and BouncyCastle crypto dlls. Once loaded, it should run very fast. I plan to add more functionality.

  1. To be precise, only Assembly language is considered to have no runtime. But for practical purposes, languages like C and Rust are considered to have no runtime. 

Leave a Reply

Your email address will not be published.