Trivium in JavaScript

This is alpha-quality code. I wrote it in a fugue state and haven’t touched it since; I publish it as a curiosity, not a tool. Do not trust it. Known bug: when the ciphertext is an invalid UTF-16 string, browsers will (legitimately) truncate it. This could be avoided by adding a layer of base64 or similar.

This is a demonstration of fast but potentially good cryptography running entirely client-side. It uses Christophe De Cannière and Bart Preneel’s Trivium, which is so simple that it fits in about kilobyte of JavaScript, but (so far) appears fairly cryptographically credible.

In-browser crypto (besides SSL etc. used internally, obviously) is not news. There are several implementations of AES floating around. What’s new, as far as I know, is a working draft implementation of something fast enough that on short texts it can update live in recent browsers. Plus, it’s extremely easy to use: just an encrypt function taking a key, an initialization vector, and plaintext, all as normal JavaScript strings.

I make no claims whatsoever about the accuracy of this implementation except that I don’t know of any back doors in it. I tested it only very perfunctorily – basically, I saw that the first few bytes it produced with key and IV = 0…0 looked about like the corresponding test vector, and called that good enough. I do not suggest that you use this as-is for anything important. I certainly don’t trust it yet.

The core algorithm is probably reasonably close to as fast as it can be (short of major reshuffling to work in parallel or to take advantage of JS implementation quirks), but there are lots of opportunities for optimization in the helpers – bits-to-string conversion, the internal state storage class, and so on. These are noted in the code, which I hereby place in the public domain. (Incidentally, this demo page uses jQuery, but the code is standalone.)

Two obvious improvements come to mind. First is to use some kind of fast string compression layer, like UTS 6: as it is, when we have ordinary English input, every second byte is usually 0x00 (because JS strings only have a UTF-16 API), which is a waste of space and a crib. Second is to hash the key: as it is, only the first 5 characters (80 bits of key ÷ 16 bits per character) are used, which means people who aren’t thinking beyond the 100ish printable US-ASCII characters can only get about 9 bits worth of security from a randomly generated key! (Of course this goes for the IV too when it’s open like this.)

Charlie Loyd, 30 April 2009.

The starting ciphertext can be decrypted with foo, baz.

with , is: