Thoughts on Critiques of JavaScript Cryptography

Updated with new information and re-published on May 25, 2013.

In 2011, Matasano Security published “JavaScript Cryptography Considered Harmful,” an article in which it argued that web JavaScript cryptography is “doomed” due to a number of factors. Matasano suggested SSL/TLS (HTTPS) as a viable solution in the many use cases where JavaScript cryptography is sometimes being deployed. I myself deploy JavaScript cryptography in Cryptocat, my open source project.

While some of Matasano’s points against JavaScript cryptography are, of course, reasonable and worthy of investigation, many of their attacks against JavaScript cryptography lack a complete understanding of how the technology has advanced in the short-term past; the main point Matasano seems to be missing is that while JavaScript cryptography is, admittedly, very difficult to deploy correctly, it is still possible to use it to counter problems that HTTPS cannot counter alone.

One of these problems is that data sent via HTTPS will always be readable as plaintext on the server, even in situations where the server is supposed to simply store ciphertext without being able to read its plaintext equivalent. However, while JavaScript cryptography is theoretically capable of sending ciphertext that cannot be decrypted server-side, Matasano raises many interesting issues against using JavaScript cryptography in this scenario:

“Secure delivery of JavaScript to browsers is a chicken-egg problem.”

With Chrome, Firefox, and Safari, it is possible to deliver web apps as signed, local browser plugins, applications and extensions. This greatly helps with solving the problem. In fact, I believe that it is necessary to deliver JavaScript cryptography-using webapps as signed browser extensions, as any other method of delivery is too vulnerable to man-in-the-middle attacks to be considered secure.

“Any attacker who could swipe an unencrypted secret can, with almost total certainty, intercept and alter a web request.”

This problem is simply mitigated by deploying JavaScript cryptography in conjunction with HTTPS. While HTTPS has its own set of problems, not taking advantage of its benefits in the sensitive context of JavaScript cryptography is lazy.
However, while Matasano encourages the usage of HTTPS (referred to in their article as SSL/TLS,) they say that “having established a secure channel with SSL, you no longer need JavaScript cryptography; you have “real” cryptography.” They forget that HTTPS is incapable of sending ciphertext that the server cannot decrypt. JavaScript cryptography can do this; it remains very useful in such a context.

“JavaScript lacks a secure random number generator.”

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.

“JavaScript cryptography hasn’t implemented well-known standards such as PGP; such a high-level language can’t be trusted with cryptography.”

Crypto-JS is a JavaScript cryptography library that implements many primitives in a fashion that is natively compatible with OpenSSL.

“JavaScript’s ‘view-source transparency’ is illusory.”

It is the case in every cryptography implementation that the implementation will need to be reviewed by an expert before being declared secure. This is no different in JavaScript, C, or Python. The only benefit of view-source transparency is that the same code actually being executed by the browser can be read, which is impossible with compiled binary crypto. From that standpoint, “view-source transparency” is not illusory; it becomes illusory when we take the idea too far. With the use of a local signed browser plugin, it becomes only necessary to audit the plugin code once.

The Real Issue with Browser Crypto

There is no question that JavaScript cryptography is still a growing field that requires much work, somewhat on the part of browser providers to clamp down DOM sharing and other issues in their code, but also on the part of the crypto community to find ways to safely implement functions in JavaScript crypto. JavaScript cryptography is difficult, heck, downright dangerous to implement correctly, but creative solutions to difficult problems, such as those discussed above, are a way forward.

However, the ultimate problem with browser cryptography is that there is no standard for innate, in-browser encryption. Very much like HTML5 and CSS, there needs to be an international, vetted, audited, cross-browser standard  for browsers to be capable of securely encrypting and communicating sensitive information. There’s no denying the urgent need for such a standard , considering the ridiculous rate in which the browser is becoming pretty much the mainstream central command for personal information.

Fortunately, the W3C Web Cryptography Working Group, which I am a member of, is working hard on solving this problem.

Update (Sep 14, 2011): This post apparently sent Matasano Security employee Thomas Ptacek on a passive-aggressive tirade against me on his Twitter feed, where he posted a bunch of angry attacks that I feel really don’t speak well of Matasano Security’s reputation as a company. As a security researcher, I don’t appreciate having a particular company react against me with public personal attacks and rudeness when I take the time to write a considerate, respectful reply to their analysis.

Posted May 25, 2013 by Nadim in Computing, Internet, Security