JavaScript Cryptography Considered Somewhat Useful In Some Special Cases
Over the years there have been a few articles published about the “dangers” of JavaScript cryptography. In this article I am going to make the claim that this is often misunderstood, and that there are in fact some specialized uses of JS crypto. Hopefully it will be interesting for someone.
Claim: In general, JavaScript is an unsuited language to implement interactive, real-time cryptographic protocols.
The reason for this is the difficulty in implementing cryptographic primitives in an interpretive language that does not leak information, for example subtle timing differences. In a compiled language such as C, you can more easily (though it’s still difficult) write constant time algorithms without having to worry about the interpreter doing optimizations making it suspicable to timing attacks (or other side channel attacks for that matter).
I’d personally be on my guard if I saw something like “pure JavaScript server implementation of TLS”, or any kind of JavaScript implementation that allows an untrusted party real-time interaction with the implementation (think key exchanges and similar).
Caveat to above claim: If the cryptographic primitives are implemented in a low level language but exposed to JavaScript, such as the new W3 Web Cryptography API proposal, then there may be possible to implement interactive protocols in JavaScript.
Claim: There’s nothing inherently wrong with using JavaScript for non-interactive, non-real-time cryptography - outside of the web browser, with normal caveats about cryptography applied.
Assuming you have code that you trust that does some “offline” cryptographic operation - the fact that it’s written in JavaScript doesn’t make it less secure than if it was written in another language. The “normal caveat” in the claim is that the code should of course be written by a security expert.
A good example of this is the new Google project “End-to-End”, which is an OpenPGP implementation in JavaScript. This is a web browser extension that happens to use JavaScript for cryptography, and it is not timing sensitive.
Claim: In general, JavaScript Cryptography in the web browser is a fundamentally bad idea...
(...Hold on to your hats, because here is the main point of this article...)
Claim: … However, there are some potential uses cases for non-interactive, non-real-time JavaScript cryptography if the JavaScript cryptography as well as the entire website is delivered over a secure connection, such as TLS, and the information that the JavaScript cryptography is meant to protect is not more sensitive than would otherwise be acceptable to give to the server.
There we have it, the main point of this article.
JavaScript delivered over an unsecure connection (such as the normal http protocol) is easily intercepted by an attacker and cannot be trusted. That JavaScript could do anything. So in this case all the articles are correct. Do not send JavaScript cryptography over plain http.
However, if JavaScript is delivered over a secure connection then that JavaScript code can be trusted to the extent that everything else on that website can be trusted. This can for example be used to protect against some information leakage on the server side.
As an example to this, consider key strengthening. Pretty much all websites nowadays have some username/password login form delivered over a secure connection. If you already trust that website with your password, then there is nothing wrong with trusting that website with a JavaScript transformed version of your password (unless the presence of this transformation would make you use a different password that you would not otherwise trust to the server). That may help the website owner in case he doesn’t want your cleartext password show up in server logs, crash dumps, debugging tools (strace, gdb...) or similar.
The same argument can be made about different applications. For example say there is a website that offers some kind of JavaScript based chat feature. The owner of that service may decide to encrypt your messages before they are sent to the server, for the same reason (avoid plaintext in logs and similar). The presence of this JavaScript cryptography should not, as the claim above state, make you use the chat for more sensitive information than you would without the JavaScript crypto.
JavaScript - the language
This article is mostly about JavaScript cryptography delivered by web services, but before we go into this let’s just briefly discuss the language itself, for example as it pertains to NodeJS and similar.Claim: In general, JavaScript is an unsuited language to implement interactive, real-time cryptographic protocols.
The reason for this is the difficulty in implementing cryptographic primitives in an interpretive language that does not leak information, for example subtle timing differences. In a compiled language such as C, you can more easily (though it’s still difficult) write constant time algorithms without having to worry about the interpreter doing optimizations making it suspicable to timing attacks (or other side channel attacks for that matter).
I’d personally be on my guard if I saw something like “pure JavaScript server implementation of TLS”, or any kind of JavaScript implementation that allows an untrusted party real-time interaction with the implementation (think key exchanges and similar).
Caveat to above claim: If the cryptographic primitives are implemented in a low level language but exposed to JavaScript, such as the new W3 Web Cryptography API proposal, then there may be possible to implement interactive protocols in JavaScript.
Claim: There’s nothing inherently wrong with using JavaScript for non-interactive, non-real-time cryptography - outside of the web browser, with normal caveats about cryptography applied.
Assuming you have code that you trust that does some “offline” cryptographic operation - the fact that it’s written in JavaScript doesn’t make it less secure than if it was written in another language. The “normal caveat” in the claim is that the code should of course be written by a security expert.
A good example of this is the new Google project “End-to-End”, which is an OpenPGP implementation in JavaScript. This is a web browser extension that happens to use JavaScript for cryptography, and it is not timing sensitive.
JavaScript in the web browser
First of all I am going to make the same claim as everyone else:Claim: In general, JavaScript Cryptography in the web browser is a fundamentally bad idea...
(...Hold on to your hats, because here is the main point of this article...)
Claim: … However, there are some potential uses cases for non-interactive, non-real-time JavaScript cryptography if the JavaScript cryptography as well as the entire website is delivered over a secure connection, such as TLS, and the information that the JavaScript cryptography is meant to protect is not more sensitive than would otherwise be acceptable to give to the server.
There we have it, the main point of this article.
Discussion
The fallacy that most “don’t use JavaScript cryptography” articles make is the assumption that a web site would use JavaScript cryptography instead of TLS. The second fallacy is that if the website uses TLS, then there is no point in using JavaScript cryptography. Lets have a look at both.JavaScript delivered over an unsecure connection (such as the normal http protocol) is easily intercepted by an attacker and cannot be trusted. That JavaScript could do anything. So in this case all the articles are correct. Do not send JavaScript cryptography over plain http.
However, if JavaScript is delivered over a secure connection then that JavaScript code can be trusted to the extent that everything else on that website can be trusted. This can for example be used to protect against some information leakage on the server side.
As an example to this, consider key strengthening. Pretty much all websites nowadays have some username/password login form delivered over a secure connection. If you already trust that website with your password, then there is nothing wrong with trusting that website with a JavaScript transformed version of your password (unless the presence of this transformation would make you use a different password that you would not otherwise trust to the server). That may help the website owner in case he doesn’t want your cleartext password show up in server logs, crash dumps, debugging tools (strace, gdb...) or similar.
The same argument can be made about different applications. For example say there is a website that offers some kind of JavaScript based chat feature. The owner of that service may decide to encrypt your messages before they are sent to the server, for the same reason (avoid plaintext in logs and similar). The presence of this JavaScript cryptography should not, as the claim above state, make you use the chat for more sensitive information than you would without the JavaScript crypto.