I’m happy to announce that the 0.7 release of Converse.js now supports Off-the-record (OTR) encrypted messaging.

The OTR protocol not only encrypts your messages, it provides ways to verify the identity of the person you are talking to, plausible deniability and perfect forward secrecy by generating new encryption keys for each conversation.

How this works is actually fascinating. The encryption keys are generated via a Diffie-Helman exchange. On youtube there is a video with a very simple and intuitive explanation on how the Diffie-Helman key exchange works. For more details, you can also read the OTR version 3 protocol spec.

I was able to add OTR support for converse.js by using Arlo Breault’s excellent otr.js library, which is also used in Cryptocat and Diaspora.

Many thanks go out to him for this.

Note:

Arlo cautions that the otr.js library has not yet been properly vetted by security researchers and shouldn’t be used in life or death situations.

This word of caution applies doubly so to its integration into converse.js!

I’m not a professional cryptographer and this should be seen as an experimental feature.

Caveat emptor!

Screencast

Note: For detailed fullscreen, make sure that video quality is set to HD, by clicking the gear icon on the video player.

On Javascript Cryptography

Implementing Cryptography in Javascript is relatively controversial and in 2011 Matasano security wrote a scathing criticism called Javascript Cryptography Considered Harmful.

I read that article before I started working on OTR support for converse.js and I’d like to go through some of its criticisms step by step to explain how they might apply to converse.js and what I’ve done to mitigate them.

If you’re going to read on, it would make sense to go read that article first.

Secure delivery of Javascript to browsers being a chicken-egg problem

Their criticism appears to apply to the case where developers use Javascript cryptography to implement secure communications with a server instead of relying on a standard protocol such as SSL/TLS.

The OTR crypto is not trying to compete with or replace SSL/TLS.

Sending data in the clear with normal HTTP is not secure and should be avoided. Therefore, if you are going to use OTR with converse.js, always make sure that the site users HTTPS (i.e. SSL/TLS).

Ideally you would also want a mechanism to sign the Javascript and then verify it’s authenticity once it’s been downloaded.

This can be done with code that runs in browser extensions (like Cryptocat does), but (AFAIK) unfortunately not with browser-agnostic javascript (like converse.js).

This looks to me like the achilles heel for browser javascript crypto.

Besides the webserver serving the Javascript, it’s also important that the BOSH service you use employs SSL/TLS, as well as the XMPP server the BOSH service connects to.

The XMPP community is on a drive to secure all the major public XMPP servers. See the Manifesto created by Peter Saint-Andre and signed by many in the XMPP community.

On xmpp.net they let you test the security of servers on the Jabber/XMPP network.

Besides using javascript served via TLS, you can also download the converse.js tarball to your computer, unpack the files and access them directly. The index.html page will open up a page identical to the one on conversejs.org.

Browser Javascript being hostile to cryptography

The prevalence of content-controlled code.

If the website fetches javascript from thirdparty websites (for example to serve advertisements), then you not only have to trust the server to serve non-malicious code, but also all those 3rd party servers.

The solution is to not use such a site for secure communications. Clear your cache regularly, Use hosts you trust, or as I’ve mentioned above, bypass the webserver entirely by using converse.js from your own filesystem.

The malleability of the Javascript runtime.

Javascript is indeed very malleable. Methods and attributes on objects can be replaced during run-time (see Duck Typing and Monkey Patching),

This makes it easy to inject malicious code into Javascript.

However, in order to do this, the attacker’s code needs access to those Javascript objects, and fortunately Javascript provides a way of hiding sensitive objects inside closures, thereby preventing an attacker from accessing and manipulating them.

Simply put, a closure defines a limited scope for objects, variables and functions which when used correctly, cannot be accessed from any other Javascript code.

Any variables, objects or functions defined locally inside another (parent) function (with the var) keyword, are not accessible outside of that parent function.

If the parent functions is anonoymous (is not referenced anywhere) or the child function’s runtime outlives the parent’s, you have a private, enclosed scope with data that cannot be accessed from outside that scope.

All the data in converse.js is encapsulated inside such closure.

The lack of systems programming primitives needed to implement crypto.

Matasano claims that Javascript lacks a secure random number generator RNG.

Without having authoritative knowledge on whether their claim is valid, I’ll refer you to this blog post by Nadim Kobeissi (author of Cryptocat), where he claims:

This is in fact not the case. window.crypto.getRandomValues() is a secure random number generator available in JavaScript, and supported by major web browsers.

His blog post is well worth reading, and he also addresses some other criticisms for which I didn’t have anything to add.

Conclusion

OTR encryption in converse.js provides increased security and privacy for your chats. Messages are encrypted and not logged or cached

Any Jabber/XMPP services that snoop on your communications by logging your messages (like for example Facebook does) will only have access to the encrypted ciphertext, making it useless for surveillance or exploitation.

Features coming future releases

The current implementation of OTR doesn’t have any encryption policy support. With that, I mean the ability to set a policy such as Always encrypt messages.

Currently you need to always manually enable encryption.

Distributed services and self-hosting

There are more and more Free and Open Source (FOSS) self-hosted web-applications becoming available as alternatives to so-called centralized “cloud” solutions.

See for example roundcube, kolab, ownCloud, MailPile, friendica and buddycloud.

Converse.js can be integrated into any of these applications, and since you should ideally host them yourself, you’ll have more control on what Javascript is actually being served.

Feedback, patches, donations

All of the work I did on OTR integration was in my free time and free of charge. A gift and my personal contribution towards the movement for providing free communication solutions that are not founded upon surveillance and commercial exploitation of personal data.

All the code is open source and contributions are always welcome, be it in audits, features, bugfixes, documentation, words of encouragement or tips.


Hello, I'm JC Brand, software developer and consultant.
I created and maintain Converse, a popular web-based XMPP chat client,
I can help you integrate chat and instant messaging features into your website or intranet.

You can follow me on the Fediverse or on Twitter.