
JavaScript Cryptography Considered Harmful (2011) - pcr910303
https://www.nccgroup.trust/us/about-us/newsroom-and-events/blog/2011/august/javascript-cryptography-considered-harmful/
======
s_tec
You can't roll your own TLS replacement using Javascript, because you need
some way to _deliver_ that Javascript to the browser in the first place. If
you don't use TLS for that, you're doomed. Sure.

On the other hand, that's a pretty narrow definition of "Javascript
Cryptography". The article overlooks a bunch of other useful cryptographic
things you can do in the browser, like end-to-end encrypted messaging. You
can't lose a giant database of customer data if you don't _have_ a giant
database of customer data sitting around. Javascript can encrypt stuff before
it even leaves the browser.

If you build your service this way, an attacker would have to carry out an
active attack that injects bad code into your Javascript bundle. That's much
harder than stealing a database, and even if it works, it can only compromises
the users who log in during the breach.

So, no, the right kind of Javascript Cryptography is actually quite
beneficial.

~~~
iudqnolq
You're skipping over the part about users having to recheck what you serve
them every request to see you haven't added a backdoor. Not sure how much
security people being able to look at and pin versions with traditional
software they build adds, but probably nonzero.

~~~
s_tec
Right, and the only solution is to audit and compile all the code running on
your computer, including firmware. Otherwise, you have no idea what your
computer is really running.

In the real world, most people run pre-built software, which is worse than
this ideal. I agree that browser Javascript is worse still, but it's still
better than sending secrets to a centralized server somewhere.

Security is a spectrum, not a binary on/off thing like this article tries to
paint it. Things can still be helpful, even if they aren't perfect.

~~~
iudqnolq
I agree completely. I didn't intend to say you were wrong, just that you
didn't mention an important consideration.

------
tptacek
Much as I'd like it to, this article will never die. I'm still convinced
directionally of the argument I made here: browser Javascript cryptography is
essentially cosmetic and provides none of the assurance that cryptography
normally offers for client/server applications with clientside secrets. I
think I could make a better, shorter, simpler can now than I did way back when
I wrote this.

Just to head off as many of the standard arguments I can remember occurring
whenever this shows up on HN:

* I'm talking about browsers-qua-browsers: while Javascript is not especially hospitable to cryptography the way, say, Rust is, it's not my claim that something intrinsic to Javascript is what makes cryptography hard. In particular: Node.js serverside applications and Electron clientside applications (with some caveats) are capable hosts for cryptographic features.

* Yes, Chrome extensions do complicate the analysis for the browsers themselves (of course: application providers don't want to do Chrome extensions, because it drastically cuts down user adoption). The story with extensions is not as simple as for Electron applications.

* No, WebCrypto doesn't make any of these problems better. WebCrypto provides primitives, but the interesting vulnerabilities in cryptosystems are in the joinery; a malicious server can still exfiltrate secrets even if you're using WebCrypto.

* It remains Hard to effectively assure the integrity of whole programs delivered to browsers, because there are too many ways to update an instance of content-controlled Javascript. The standard answer of "we'll just hash the js files" has never been credible!

~~~
TimTheTinker
Recently, I heard a smart person[0] make the argument that application-level
encryption, even in the browser, is a net win. It's also worth mentioning that
ProtonMail and 1Password both practice application-level encryption/decryption
in the browser in their front-end web clients.

App-level crypto in the browser certainly provides no added security to data
transmitted over the wire, since (a) connections to back-end servers are
already TLS-encrypted, (b) a breakdown of TLS implies the code running on the
endpoint can't be trusted, therefore (c) assume data exfiltration when TLS
breaks down regardless of other variables. I think this line of reasoning is
just a restatement of your points above.

However, depending on how the back-end is set up, a zero-knowledge end-to-end
encrypted vault would be impractical and even dangerous to _decrypt_ in the
cloud prior to serving it. Hence, in an end-to-end encrypted app, the chain of
trust in client connections is anchored at the static file servers, the JS
code they serve, and the TLS connection itself, not application servers -- the
less trust app servers have to have, the better. I posit that it's easier to
secure a static file server and TLS endpoint than it is to secure application
servers. Furthermore, client crypto protects servers from ever seeing (or
having to store/hash/cache) the whole symmetric key.

So client-side crypto _can_ improve the security and trust calculus for
server-side systems. In that case, a back-end breach of _all but_ TLS
endpoints and static file services would not expose user data.

If anyone can explain what's wrong with or missing from this line of
reasoning, I am all ears -- please do!

[0]
[https://qconsf.com/sf2019/presentation/security](https://qconsf.com/sf2019/presentation/security)

~~~
acqq
> (b) a breakdown of TLS implies the code running on the endpoint can't be
> trusted, therefore (c) assume data exfiltration when TLS breaks down
> regardless of other variables

In security engineering the main question is always "from whom do you want to
protect it." If your assumed adversary can overtake both your TLS and deliver
modified scripts, yes, the encryption in browser doesn't bring anything. If
your assumed adversary is somebody less powerful like a passive listener
somewhere the traffic is comes out of TLS, or somebody who has access to the
data, but the data are already encrypted, then yes, the encryption can make a
difference.

Or as one great thinker wrote for Usenix 2014: "In the real world, threat
models are much simpler (see Figure 1). Basically, you’re either dealing with
Mossad or not-Mossad." "If your adversary is the Mossad, YOU’RE GONNA DIE AND
THERE’S NOTHING THAT YOU CAN DO ABOUT IT. The Mossad is not intimidated by the
fact that you employ [https://](https://) If the Mossad wants your data,
they’re going to use a drone to replace your cellphone with a piece of uranium
that’s shaped like a cellphone, and when you die of tumors filled with tumors,
they’re going to hold a press conference and say “It wasn’t us” as they wear
t-shirts that say “IT WAS DEFINITELY US,” and then they’re going to buy all of
your stuff at your estate sale so that they can directly look at the photos of
your vacation instead of reading your insipid emails about them."

[https://www.usenix.org/system/files/1401_08-12_mickens.pdf](https://www.usenix.org/system/files/1401_08-12_mickens.pdf)

------
rubyn00bie
Uhhhh... like what's the point of this? Like who is doing what they suggest
folks are doing with JavaScript? Who isn't using SSL and who is rolling their
own encryption layer?

It seems like a clickbait rant more than something actionable or even really
relevant. They even go on to say in the article you totally can do crypto
"right" with JS it's just really hard. Isn't that known? Isn't that why we
have libraries which are audited for security vulnerabilities by experts in
the field? Isn't that true for literally _every_ language/runtime/vm ? I'm not
saying JavaScript's number types and quirks aren't a huge pain in the ass but
so is managing memory.

/shrug just my two cents.

~~~
geofft
This is from 2011, when people (usually correctly) believed things like "SSL
certificates are expensive," "SSL connections are expensive," "it's reasonable
to host just the secure parts of your website on SSL," "if you only need
authenticity and not confidentiality, it's better to avoid SSL if possible,"
etc.

In the years since 2011, we could have implemented high-quality side-channel-
resistant JS crypto libraries (plus added browser features to allow storing
secret data that wasn't accessible to the website, auditing JS source, etc.),
or we could have just deployed SSL everywhere. The world chose the latter, and
it was a better choice.

------
Ajedi32
This article is a little outdated. (2011; that should probably be in the
title.) JS in the browser _does_ have a cryptographically secure random number
generator now, for example (Crypto.getRandomValues) and a secure way to
generate and store keys (SubtleCrypto.generateKey).

A lot of the article's other concerns are still valid, but there are a few new
standards on the horizon which could eventually fix most of those and make
cryptography in the browser viable, such as the Web Package standard. The
Signed HTTP Exchanges standard's section on binary transparency is especially
interesting for this use case: [https://wicg.github.io/webpackage/draft-
yasskin-http-origin-...](https://wicg.github.io/webpackage/draft-yasskin-http-
origin-signed-responses.html#name-binary-transparency)

------
geofft
Mods, can we add (2011) to this? A bunch of the comments seem to be saying
this advice doesn't make much sense in 2019, and in fact, it doesn't - it's
written for a world where people are trying to avoid SSL if they can.

------
dang
Thread from 2014:
[https://news.ycombinator.com/item?id=7903720](https://news.ycombinator.com/item?id=7903720)

2013:
[https://news.ycombinator.com/item?id=5123165](https://news.ycombinator.com/item?id=5123165)

Discussed at the time:
[https://news.ycombinator.com/item?id=2935220](https://news.ycombinator.com/item?id=2935220)

------
danShumway
From a purely technical perspective, this article raises multiple valid
points. From a practical perspective, there can be legal and logistical
benefits to not knowing what your customers are doing.

I think articles like this get treated like they're referring to a broad
category of activities, or making very broad statements, when in fact they're
talking about a very narrow aspect of security. And to be fair, people do
treat Javascript Crypto like it's the same thing as normal, native E2E
encryption, so maybe that pushback is sometimes necessary. But this isn't a
binary, black-and-white principle.

JS crypto is problematic in environments like the web because it is very hard
to validate or pin the code that is sent to your browser (and for a few other
reasons). This means that E2E crypto is not a good way of protecting yourself
_from a malicious provider_. JS crypto does not remove your need to trust your
host, and to trust your host's security.

It does not follow the E2E crypto has no uses at all on the web. It just means
you have to be open about what benefits it does and doesn't provide. It isn't
a silver bullet that will protect you everywhere.

------
sl1ck731
Is using some other encryption for client interactions common vs just using
TLS? I don't think I've seen anyone ever recommend any of these things.

"You can't simply send a single Javascript file over SSL/TLS. You have to send
all the page content over SSL/TLS."

Is this a common problem in some way? It doesn't seem like a big deal unless
you are trying to shave a few bytes off of your traffic.

~~~
nwallin
The article is from 2011. Certs were expensive back then. People thought TLS
was an unnecessary hassle, difficult to configure etc. There was an idea that
you just do the really important parts (logins, authorizing fund transfers)
over TLS and do the mundane stuff offer HTTP. (Static site assets) XSS was so
rampant they gave it its own acronym. The natural extension of that was to do
everything over HTTP and for the handful of objects that need to be secured,
you just encrypt those ~100 bytes of important data.

Then let's encrypt happened and all that went out the window.

------
3pt14159
> Any attacker who could swipe an unencrypted secret can, with almost total
> certainty, intercept and alter a web request.

Not really. Modification risks exposure and some attacks are only possible
after hours of compute time. For example if the HTTPS connection uses a cypher
that's later found to be insecure then they can analyze the data pushed
through the connection after the fact, but they can't intercept the now-closed
connection. The NSA layers encryption for this purpose, and I don't really see
the harm in encrypting with JavaScript as an additional layer in addition to
HTTPS.

Plus, there are many places where passive attacks are much more likely than
someone that's actually going to change your JavaScript. For example, many
organizations terminate HTTPS at the perimeter of their network in order to
monitor employee actions on the web. Using JS to encrypt is going to keep your
secrets safer there, though some would argue that it's hostile to the orgs
that downgrade the protocol on purpose.

------
ravenstine
Cryptography in JS is useful when you have a secure channel and you only want
the plaintext available to one party. (ex. a secure file store or encrypted
mail server)

------
avmich
Interesting that author seem to omit the possibility of PGP functionality
available locally in the browser - as, say, a bookmarklet.

Surely websites aren't designed in a way to take advantage of that, but I
still don't see in the article a good argument why that is impossible - given
that the local code is a carefully written (e.g. Stanford crypto library seems
to be a good example of crypto JS code).

------
kerng
This is not the best article, it fundamentally sees security as a black and
white concept. Whereas its shades of gray and levels of defense.

------
motohagiography
Interesting to relitigate this every few years. We can sum it up every time
with, "private/secret keys accessible to browser means trusting the users
browser." the details are superfluous.

The relevant xkcd on this is this one:
[https://xkcd.com/2217/](https://xkcd.com/2217/)

Where "check my math" means the same thing.

The browser isn't trustworthy.

