84 comments

[ 2.8 ms ] story [ 166 ms ] thread
Client side cryptography is almost always about providing a solution that doesn't require server trust. This article mentions end-to-end encrypted messaging, for instance, which provides the nice property that not even the messaging server can read the message contents.

The problem with webapp-based javascript cryptography is that if the crypto code is delivered by the server, then the client is back to trusting the server. The server operator, an attacker who can compromise the server, or an attacker who can compromise the SSL connection from the browser to the server can modify the JS to spray plaintext wherever they'd like.

Basically, the JS crypto is reducible to the strength of the SSL connection. Anyone on the other end of the SSL connection, or anyone who can break the SSL connection, can get your plaintext. This makes the JS crypto nothing but overhead. It's just hand-waving at that point.

This is not a theoretical weakness. This is exactly happened to both Lavabit and Hushmail. The experiment has been tried and the hand waving didn't amount to much. There's no need (and no excuse!) to try it again.

Is there no way to independently verify that a) the scripts are what they are, and b) that the values change before going to the server?
I have seen people point to using plugins to verify assets delivered by the server, but at that point, why not just do the crypto with the plugin.
The benefit of a plugin to verify assets is that it can work with other things besides the crypto lib. As your sibling comment mentions an attacker could deliver other JS that just traces your input or something different. Well, a user could ask a plugin to say "Hey, track the JS on this page. Alert me if any of it changes, any of it is removed, or any new JS is added." After an alert, the user can see a diff, decide to trust the new set of JS (maybe it was just a jquery update), try and run the old set instead, or don't run anything. A cool plugin could even connect with a repository of peer-reviewed changes so that non-technical users can still safely use it, so they might see "This change to blah.js has been marked as OK by X respectable users (see reasons)" or "It's a trap! Foobar.com has been compromised by (feds|anonymous|gary)."
How exactly do you use a plugin to verify the state of a Javascript runtime? You can't just verify assets; you need to verify the current bindings of every function relevant to your crypto code.
How are the bindings supposed to change without loading different assets, apart from an eval() somewhere?
List every possible way a browser Javascript application might end up rebinding a function.
Basically, the way JavaScript security currently works, browsers trust all code sent from the server you are communicating with to manipulate everything coming from or going to that server.

You could talk about ways to independently sign and verify some crypto primitive or crypto library and be confident that it was being used to encrypt your communications appropriately. But this wouldn't help at all. There's nothing stopping the person controlling the server (or MITMing your connection to it) from adding additional code that scrapes the text input boxes, or captures keystrokes, or simply follows the appropriate variables down to the ones which contain your text before its sent off, and then sending that back to the server in an XMLHTTPRequest, via a websocket, via loading an appropriate image, or even hiding it quite well among the timing of when requests are made to the server.

The fundamental problem is that the code comes from the same person providing you the connection, and it is updated every time you use the page, so it offers no additional security above just trusting them directly.

If you want good crypto and good security, you want stable client side software from a trusted source, and a different source routing your traffic, so that both of them would have to be compromised to compromise your data.

Now, there may be one small advantage in client-side crypto. That's if due to problems with TLS (in particular, the version and protocols supported by your browser), there are TLS weaknesses that can be exploited, like a MITM attacker forcibly downgrading your crypto to a weak algorithm that allows them to eavesdrop but not forge content. In this case, stronger crypto implemented in JavaScript could be used to keep your data confidential. But this is a very narrow corner case, that's probably better handled by fixing browsers so they aren't prone to protocol downgrading attacks.

This is a deck by Ben Adida (formerly of Mozilla, where he led the Persona project and now at Square) explaining how that argument is reductionistic. https://docs.google.com/presentation/d/1bLBb0EIJ0cuoAhsmI1XL...
Can you please help me find even an argument in that deck, let alone any refutation? Did I get an incomplete deck, perhaps? The version I'm seeing stops at slide 22.
There are 22 slides.

It's admittedly terse (it was part of a presentation Ben Adida gave at the first Real World Cryptography workshop).

However, I'd suggest reading the deck again, and while you do asking yourself, does JS crypto provide any security beyond what SSL does? And, can JS crypto make sense as part of a defense in depth/layered security approach?

He's presumably referring to slides 17-20. It essentially boils down to "JS crypto in the browser is better than nothing".
But it's not — at least not necessarily. That's the problem. It creates a potentially incredibly dangerous false sense of security, and nothing in the deck refutes that, or even argues against it.
> Basically, the JS crypto is reducible to the strength of the SSL connection. Anyone on the other end of the SSL connection, or anyone who can break the SSL connection, can get your plaintext. This makes the JS crypto nothing but overhead. It's just hand-waving at that point.

This is true. However, you can say the same thing about, for example, retrieving an ISO of Ubuntu. A cryptosystem is as weak as its weakest link, and that weakest link may of course be the way you downloaded the cryptosystem in the first place.

But once the cryptosystem is in place, you don't have to trust SSL any more. By default, webapps are always retrieved from the server for every new session, but application manifests and offline storage are an effective means of avoiding this. You can build a webapp that is only ever downloaded once, and from then on loads its own code from the filesystem; and which verifies new "releases" of its own source using whatever crypto it likes before overwriting the client-side stored copies of itself.

Neither Lavabit nor Hushmail implemented this sort of application-release policy, but they easily could have.

cryptocat accomplishes this by distributing itself as a browser extension
> You can build a webapp that is only ever downloaded once, and from then on loads its own code from the filesystem; and which verifies new "releases" of its own source using whatever crypto it likes before overwriting the client-side stored copies of itself.

But if you don't trust Hushmail they could force a back-doored update onto you.

At that point you've got "well, that's not worse than anything else, then" security. The NSA, for example, could MITM your computer's connection to Ubuntu's update servers, FISA a sysadmin for a copy of their package signing key, and inject a "critical security update" only for you. Auto-update systems are suspicious as a whole, now, and should only be trusted in general as a compromise to convenience, and the statistical unlikelihood of you being attacked.
If you're running a decent linux you can turn auto-update off. No browser will let you do that.
All the portable-app versions of Chrome and Firefox (for example, the Firefox that comes with the Tor bundle) have auto-update disabled, for both the browser, and included extensions.
I think that was in reference to a web app.
But this is why risk assessment is part of choosing and using crypto.

If you think the NSA is after you then all bets are off and whatever you're doing is probably not working because most people don't have an armoured bunker with armed guards. We need to be careful to differentiate between active NSA snooping (in which case anything we do is probably weak) and passive snooping (where we just want to make it expensive enough for them to not bother with our communications).

But if you think the FBI is after you then you'll want to avoid something that can be done by a court order - such as your encrypted email provider being forced to serve you a malformed client that allows law enforcement to view all your communications. This is a real risk, and is what happened to Hushmail.

People always seem to think that comparing the security of a content-controlled Javascript runtime to that of an ISO image is somehow insightful, as if there was no meaningful difference between those trust models. But I don't think anyone making those comparisons believes what they're saying; I think it's sophistry.

Obviously, you cannot simply assume that an ISO you download off the Internet is secure. That's a problem that's been well known since the mid-1990s, when projects began publishing hashes and PGP signatures of their binaries, widely, so that a discrepancy between what you saw and what someone else saw would stand a good change of being noticed.

The problem with booting up crypto in a browser is that it forces you to do that kind of checking on every page load, often at sub-second rates. And not only that, but it complicates the trust evaluation by making it just about as hard as possible to figure out all the components that you actually need to evaluate.

> The problem with booting up crypto in a browser is that it forces you to do that kind of checking on every page load, often at sub-second rates.

You ignored the second half of my statement: that by using offline storage and application manifests, URLs become effectively a reference to an application stored in the browser's cache (which can update itself from the web if it wants to), rather than something to be retrieved on each request. It then becomes exactly equivalent in security to, say, a second-party Ubuntu PPA repository, like the nginx.org PPAs. (With the difference that, even when trusted, the compromised webapp will still run in a browser sandbox, while the compromised PPA gets root access to run scripts.)

No, this doesn't work, because the user still needs to validate the DOM every time the page loads.
Also true, for the time being, in most browsers. (Sort of like how "SSL is broken because we don't have certificate pinning yet" is true, for the time being, in most browsers.)

To make sure I understand, let me expand: you're talking about web apps that ever load external assets besides their code package, and then embed those external assets directly into the DOM by giving the DOM the URL (this covers anything from an <img src=""> to a <link rel="Stylesheet" href=""> to a <script src=""></script>).

This doesn't cover, on the other hand, resources that are retrieved by the code-package into HTML5 ArrayBuffers/Blobs/Files, then validated against a cryptographic signature transmitted over the trusted crypto (SSL or code-package-custom) before the resources are allowed into the DOM through data:/blob: URIs.

These resources, of course, must be self-contained--they can't refer to other resources by URL (which would then be loaded directly by the DOM), only to other data:/blob: URIs. You basically need to pre-parse and "static-check" any HTML, CSS, or Javascript you plan to embed--transitively, spidering referenced URLs--before embedding. This runs into the Halting problem in extremis; if a script you want to embed dynamically builds URLs, you're kind of screwed.

But all this is a diversion from the real problem here, which is that web-applications are inherently not sandboxed from their own "trusted" third party code. You're pretty much "letting Jesus take the wheel" (Jesus being the SSL certificate authorities) when you stick a URL into your web-app's DOM.

The solution, obviously, is to let web-apps have another layer of sandboxing between them and their "content." And there are browsers that do this for web-apps, in specific circumstances; you just usually don't call the result a "web-app." Firefox and Chrome will treat their extensions (which are, in fact, HTML+JS+CSS) this way; Chrome will also treat its "apps" this way (which includes "apps" loaded by URL, instead of being delivered in the .crx!); as will my favorite RIA-toolkit-du-jour, node-webkit. We just need this "fully sandboxed DOM cut-point" feature for the web as a whole.

As far as I know, the only reason we don't have DOM-subtree sandboxing is the potential for iframe-based clickjacking. If we can figure out a way to avoid that specific problem, we'd likely get this feature quite immediately--the code for it is, in most cases, already there. I think we will, eventually. Until then, the data:/blob: workaround is pretty good in limited cases; you rarely need to load HTML/CSS/JS "content" (the kinds that can have transitively-embedded DOM URL references), but can instead build those locally from AJAX conversations, and just verify that the content you do want to embed (images, say) is in a benign file-format before translating it into a blob:.

---

My own favorite solution, by the by, would be something like the Chrome Web Store, but a lot more transparent: you browse to https://example.com/, and if that's registered as a domain "owned" by a web-app in this browser-service, it downloads and zero-config installs the app code-package, temporarily (not yet granting it any permissions in the process) and presents it as if that is exactly what is "at" that URL. This could be combined with storage of an initial pre-HSTS cert, if you do want to use SSL. This means you're implicitly switching from trusting CAs to trusting the browser-manufacturer... but you're doing that anyway by installing the browser in the first place.

When you come up with a browser design you like that does this, you should submit it to Mozilla or elsewhere to have it considered. But we're not talking about new browser features, or even extensions. We're talking about content-controlled Javascript delivering crypto functionality to end users, and a web page that says that's alright because some browsers have better RNGs now.
Okay, you're right here. (I said you were right the other two times, too. This time I'll emphasize it.)

Content-controlled Javascript is not alright. Content-controlled Javascript is, in fact, why browsers have sandboxes in the first place (think about this: if they could get away with less, they would; and in the current security model, you don't get to sandbox yourself from your content when you are the content, so you don't get to get away with anything.) You need some sort of stable base, living in the client, to build any sort of cryptographic security upon. That means, at the very least, Javascript that comes from a file: or blob: URI.

You can use SSL to bootstrap up to that, delivering an initial payload which will then be loaded. But you can't keep the advantages of the web-app model (refreshed from the server with every page-load! embed arbitrary DOM content by URL!) when you do this; you have to switch to thinking like a local-app developer, who downloads and sig-checks "updates", and who downloads and validates "content" (so your image doesn't turn into a script half-way through), before making use of either. Effectively, you don't have a web-app any more.

You can't take any web-app that's already been written and just "throw in" a crypto library, and consider yourself secure. You aren't. Don't listen to the article. Either trust SSL (i.e., trust your crypto provider with your plaintexts), or use some sort of locally-fixed-client implementation: if not a native app, then at least a Chrome App or something.

What about a site like Passpack? https://www.passpack.com/en/home/

- Does that mean a site like passpack is only waving its hands at its security, and that its client-side cryptography is irrelevant and basically insecure??

Yes, exactly. If Passpack (or a government agency that can force Passpack to obey them) wants to read your passwords they can serve you JavaScript that leaks your secure data as soon as your browser encrypts it.
Hi moxie! First off, I agree with what you said. But I had a question about your observation.

Don't the same problems apply to any autoupdating system (including smartphones, tablets and computers)?

I've posted once before asking that Chrome and Firefox implement certificate pinning APIs for extensions/addons so that MITM SSL attacks can be detected. Maybe they'll see it now. :)

Client side Javascript cryptography is about equivalent to SSL; however, it doesn't mean it's not worthwhile to do crypto on the client side. At least the computation load is distributed to all the browsers involved, thus lessen the demand and load on the server.
You can't securely load crypto into a browser without SSL, so the server is bearing that load anyways. All you're doing is adding additional load on the clients.
Given a client side crypto implementation with SSL as the delivery mechanism, the only load on the server is the content delivery and the SSL computation itself. Any of the application-specific crypto load can be done on the browser instead on the server.

Let's say the app is encrypting 1meg Excel file and 100K people are using it. I would rather letting the browsers do the work than beef up the servers to do the encryption on server side.

This article has long scrolled off the front page, so just a quick reply: modern crypto is fast. Look up the speed on AES-GCM with AES-NI, PCLMULQDQ; on a modern multicore server, your 100GB can be encrypted in a couple of seconds. (Or rather, the crypto isn't remotely the bottleneck.)
While these known issues are true, and still need to be worked out, I don't think stopping all work on crypto in the browser is the best course of action.

There are technical ways we could mitigate these vulnerabilities (signing of JS downloaded from a site, for example). Maybe having crypto in the browser become a thing is the way that these features get the support to be implemented.

It always comes down to this; would you prefer security, or just something that makes you feel fuzzy? Crypto in JavaScript only gives the latter.
I disagree. Javascript cryptography can provide real security, it's just important to keep in mind what is being secured, and where the vulnerabilities are. Currently, js crypto is vulnerable in that its difficult to verify that the js a browser is running is the intented code.

Every day, millions of people are sending sensitive data over very insecure channels like email and DropBox because secure tools like PGP are to difficult for them or their friends to use. Clearly some security is better than none, as long as the limitations are known.

This is like saying a sign that says "attackers keep out" provides real security, as long as you keep in mind that it only works if attackers obey the sign. After all, Dropbox doesn't have an "attackers keep out" sign!
No, it's more like an imperfect lock is still more security than no lock at all on your door.
No, it's more like people thinking they have a high grade lock on their door, when in fact they have a broken lock. They can't see it's broken, but anyone who knows about locks knows it's broken, and how to bypass it with a bobby pin.
Is this supposed to be serious, because we want javascript to be better, or sarcastic, because most people DO live behind locks that are broken and can be bypassed trivially with relatively unsophisticated tools? Everybody break out your bobby pins!
You would have extreme trouble picking a lock with a bobby pin, they're much too fat to do anything outside of a movie.
It is a little better than that. What about an enterprise application where you have control/trust of the server, but want to securely cache data in offline browser storage.

That covers common scenarios, like people who provide web based access to Microsoft Exchange.

Please note the implications of this. The signed javascript would have to be hosted on a separate third party website, and it would have to be the _only_ script content of the website.

Since code can be executed by almost every resource on a webpage, basically the entire would have to be stored on that separate third party website, the html, the css, maybe throw in the images too given their history of weird exploits.

Not saying that's a very crazy idea, but I'm saying it's way beyond the scope of these opal guys, and probably not what most people 'working out' browser crypto are after.

And yet, jsquery works that way, doesn't it? Everyone pulls jsquery in from basically one site...

Does the entire website have to be on that separate third party location, or just a self-booting kernel of crypto to enable a signed website to be downloaded from the desired source?

> And yet, jsquery works that way, doesn't it? Everyone pulls jsquery in from basically one site...

Not everyone (not even close). Many do, but if I'm running a site over SSL I'm going to be hosting my own copy of the jQuery libs.

If this were a blog post with a proposal for changes to implement a workable JS crypto mechanism, that'd be great, but it's a actually blog post about how some people are going to implement a "secure" service using a mechanism that's known to be insecure.

This isn't a new idea that we're shooting down before it has a chance to fully form. It's something that people have been trying, and making dangerous security claims about, for at least 10 years.

It's possible that the core issues are resolvable, but they would likely require substantial changes to the way the web browser works. Whenever people start thinking about a way to make a mechanism like this work correctly, the scope of what's required unravels quickly. At this point, I don't know of any defined or even partially articulated proposal that makes sense and accounts for the bulk of the gotchas.

Given that we haven't even been able to get correctly-scopable cookies yet (something the vast majority of the web wants and which has been clearly defined and articulated for many years), I'm not sure that we should hold our breath for this.

No. Crypto is a rare case where broken crypto is actually worse than no crypto at all. When a product claims to have encryption people trust that encryption. If the encryption is not actually effective, that compromises their security. In some cases (e.g. dissidents in oppressive regimes), that gets them killed.
Thanks for the reply.

Opal requires as little trust as possible, but you are correct that some server-trust is required at the moment.

I hope that apps like Opal will encourage more progress on browser/javascript cryptography. The W3C crypto spec is coming along nicely, and things like Content Security Policy address some of the concerns about delivering secure javascript.

One nice thing about web-apps is that they are by-default open source, and browsers are bundled with all sorts of diagnostic tools. Anybody who worries that their data is being "sprayed" can just open the network tab and see exactly what is being sent over the wire. Obviously we don't expect many users to do this, but it's one way to enforce our honesty until better solutions exist.

I think building something you know to be insecure and providing it to your user along with an assurance that your service takes their security seriously is a poor way to motivate other people (here, browser vendors) to build that security for you.

Meanwhile: the network tab thing only does anything if you do it every time and validate all the content. Nobody does this, ever.

> Opal requires as little trust as possible, but you are correct that some server-trust is required at the moment.

Unless there is some other mechanism at play here, it requires full server trust.

> I hope that apps like Opal will encourage more progress on browser/javascript cryptography. The W3C crypto spec is coming along nicely, and things like Content Security Policy address some of the concerns about delivering secure javascript.

I don't think you can just cross your fingers and hope for the best here. Whether or not it's coming along nicely is debatable, but one way or another the W3C crypto API has no bearing at all on this problem.

You're talking about implementing a "secure" service using a mechanism that is known to be insecure. For a mechanism like this to function correctly, it would likely require substantial changes to the way the web browser works that aren't currently on anyone's roadmap.

Again, this is not a theoretical problem. Two companies have done the exact same handwaving that you are doing now about users watching tcpdump to verify their traffic, and both of them were functionally destroyed when that handwaving didn't work. It doesn't seem prudent to knowingly put users (or yourselves!) into that position again.

So the question then is when will browsers provide access to crypto libraries as a built-in JS API? Clearly, the browser already requires crypto to function. Why can't we standardize a way to access it from the runtime and provide a way to run code against it in a sandbox that would be impervious to things like wrapping one JS function in another?

On top of that we would need some code delivery system with built-in trust verification. This way you could load an up to date copy of PGP written in JS and verify that this code comes from a source you trust.

Then again, this is starting to look a lot like a secure package management system and downloaded software vs the continuously updated web apps we have today, so it might not be worth reinventing the wheel...

How exactly does it help to provide access to built-in crypto libraries through a JS API? The code that manages those crypto primitives is still content-controlled Javascript.
It doesn't (though one might argue that as a result we will see much fewer JS implementations of AES coming out). What I am talking about is a better way to distribute the code, the ability to verify the code, the ability to sandbox it, and a proper secure crypto implementation to rest this on.

Basically, I want the contents of GMail messages (ones I compose and ones I read) to be rendered in a sandbox to which the rest of the page has no access. Moreover, I want to get the code that makes the sandbox tick to not come from Google, but from a third part I actually trust.

Once again, this starts looking a lot like normal downloaded apps with package signing, and less like the web. I am not certain there is a middle ground between the two that provides both security and convenience.

I've gone back and forth in my own head about this argument over the years, and I'm still not entirely sure where I come down. But, that said, I have seen the following problem several times, and it seems like client-side crypto provided a reasonable solution.

Challenge: I have a client (web browser) and I have a back-end server (sitting deep behind several layers of intermediate servers of varying degrees of trust) and these two entities need to exchange some sensitive piece of information (a credit card number, etc). How do I transmit this information (either from client to server or the reverse)?

Problems/Assumptions: Let's assume I trust the front end server explicitly to serve fully server-controlled data. Obviously, if we don't trust the server serving me the JS it is all for not. Now, let us also assume that, although my front end server is trusted, it, as well as all of the intermediate servers may accidentally log data that flows through them. In other words, we assume that if I pass a plaintext credit card number over a trusted SSL connection to the server, it, or any of the intermediate servers on the path to the trusted back end server, may accidentally log the sensitive data. How do you solve that problem?

Solution: You could use client-side crypto to create an end-to-end channel that transmits the sensitive data to the back end server.

So, yes, the above solution assumes a fully trusted front end server. In this case, the client side crypto is more to protect the service provider than for the user, but it does seem to provide some sort of "existence proof" in so far as it is a problem that exists in the real world, is made better using client-side crypto, and doesn't seem to have many alternative solutions that provides the same assurances.

P.S. This is more or less what BrainTree does with their client-side encryption for credit card processing (https://www.braintreepayments.com/braintrust/client-side-enc...). In this case, the front end server needs to be trusted, as it is serving up the public key to bootstrap the whole system. But, if we assume the server is trusted (even without client-side crypto we have to assume this for any security) then this approach mitigates the problem of logging credit card data by accident.

Now, maybe this use case is the only legit use of client-side crypto. But, it does make me take pause before dismissing the approach entirely.

> I've gone back and forth in my own head about this argument over the years, and I'm still not entirely sure where I come down

I think you are unfairly reframing it as some sort of debate. It's like not being totally decided on if you should log into your server over telnet from a coffee shop. Even if you don't see the weakness, attackers do.

I didn't mean to imply a debate...only that the reductionist viewpoint "it is only as secure as SSL, so just use SSL" doesn't quite sit right with me; the problem feels a bit more grey.

In the particular scenario I proposed the only attacker we are trying to protect against is a completely passive attacker than can possibly view our logs from servers along the path to our back end server. Obviously in the world of crypto that is a ridiculously weak adversary, and not one you want to hang your hat on when designing a crypto system. But, it is an adversary that plenty of companies are concerned with.

For example, because sensitive data is not something you can "unsee", it would be ideal if one could ensure that even trusted employees are never witness to the information. For example, I could be a completely trusted employee that sees an accidentally logged credit card. The bell has been rung..there is no going back. In that situation, even though there is no adversary in the malicious stance, it is a problem that can occur and many people would like to solve it.

Security is reductionist. Once your system is broken it doesn't matter how or where, it just is. If you need SSL, you must use it. You cannot hack around it, since the attacker will simply MITM you without it, or find a side channel to load the malicious code and then use one of the dozens of flexibilities in the JS runtime to get your sensitive info.

The opposite is also true: if your SSL setup is compromised (e.g. Leaked private key), client side crypto does nothing to protect you since the attacker can just MITM your crypto code inside the runtime, get data out of the DOM, etc.

There are no cases left where client side crypto provides any additional security. Some future server-browser model might change that, but not anything that exists on the web currently.

I for one agree with you. There are a few specific cases where client-side crypto has benefits regardless of the fact that you need to (at some point) trust the server. I think the best examples involve protecting history or data residing on the server up to the point of being compromised. See my other comment on here for my use case.
The Chicken-Egg problem is Problem 0 with Javascript crypto. Until you can solve that, everything else is just farting into the wind.
Progressive enhancement is a real thing and as the browsers start to implement native support for the rest of Web Cryptography API the situation will only improve. We have to start somewhere.
Assuming that browsers have implemented Web Crypto, how do you know you're using it and not an evil polyfill?
Some JS engines already disallow security-violating operations from happening (such as inserting evil hooks into document.location). These same protections could apply to any Crypto object.
Please stop upvoting this article, it's misleading at best. It links to the article everyone should read on browser cryptography, the article that says exactly why browser cryptography does not and basically never could work.

The article then picks the least important of all security problems, that there isn't (wasn't) a secure way of generating random numbers, acts as if that was an important point and then carries on as if browser cryptography has been solved.

In their about page they claim: "As a result, Opal is able to guarantee that the only people who are able to read a secret file are the sender and recipients."

This is plainly not true. The people who are able to read these secret files are always those who control the browser. They might claim that they're able to guarantee it because they control the code that is sent by the server, but recent history has shown us that if they were to be forced to break that guarantee, they would not be allowed to let anyone know.

So what is their guarantee worth to anyone? Jack shit.

Part of the problem is that the JS crypto article they linked to isn't very good, but has for some reason become emblematic of the whole argument against JS crypto. It deserves an update.
Compiling nacl to javascript is probably a very bad idea without some further analysis. There are almost certainly specialized code constructs that will be lost in the transformation, like branchless code paths, that are designed to prevent certain types of attacks.

In fact this is a pretty insidious mistake since you think you are doing the right thing by using a high-quality library.

Emscripten compiles the input source with LLVM, then converts the LLVM bytecode to JS. Most of the optimization passes are done by the LLVM compiler. Are you suggesting that LLVM (or optimizing compilers in general) should not be used to compile crypto libraries?

I completely agree that further analysis is needed on js-nacl, but I hadn't considered that compiler optimizations might lead to vulnerabilities.

That's might be a sign you don't pay enough attention cryptographic research; compiler optimization side channels are not news.

Of course, the notion that the compiler is a threat here is getting a bit ahead of ourselves, because you don't even know what side channels are in the runtime.

My primary concern is the LLVM bytecode to JS transformation.

Even on the LLVM side certain optimizations may be dangerous in crypto code. I wouldn't play with optimization settings unless I was sure I knew what I was doing. And I'd still think twice.

All browsers already have crypto. Why the fuck are people trying to invent their own when it's built in?

http://en.wikipedia.org/wiki/Network_Security_Services

https://developer.mozilla.org/en-US/docs/Mozilla_Crypto_FAQ

All you need is some kind of new "Web Standard" glue between the browser and the JS and do whatever you feel like using the native crypto functionality of the browser. You don't need to add more layers of complexity. But you can add a small bit of abstraction to what is already there.

How exactly do you think having built-in AES primitives solves a problem for browser crypto? Content-controlled Javascript still controls how those primitives are used.
The problem isn't only with primitives, as I think you've mentioned before. Even assuming a browser provides turnkey symmetric crypto for arbitrary plaintext lengths, "content-controlled JavaScript" can still subvert the ostensible encryptions in subtle ways.
First, not all JS delivery is subject to MITM. Having the ability for JS to use built-in, fast, reliable crypto code is useful in many cases. And it's going to be more reliable, and faster, and just better working in all cases by using what's in the browser VS someone's bleeding-edge library based on some other library based on etc etc.

Second, when we get down to it, if you can't trust your content, you can't trust your content. Do you second guess the crypto on your laptop because you might be subject to evil maid or other physical attacks? No, because there is some inherent trust, just like the people who do online banking and shopping. The integrity of the content is important, but not the only issue, and arguably not the highest priority.

Third, what we use the crypto for is completely subjective. Maybe someone using it doesn't care about the integrity of the instructions delivered; it depends on the case. You can't use one case as a yardstick for all of them.

People obviously want to do crypto from JS. I'm not proposing a solution for all the potential problems therein. But if you're going to do it, do it right and use the native code that already is there.

Moreover, the LLVM compiler can perform many optimizations during compilation, so the resulting JavaScript is highly optimized.

Optimization may actually be an argument against C-to-Javascript translated cryptography.

NaCl was written in C, according to the constraints and degrees of freedom of a standard C compiler -- which are not the same as those of an interpreted or JiT compiled language.

I am not a cryptographer, but source-to-source translation of cryptography is looking for trouble.

(comment deleted)
Came to this thread knowing tptacek would be here, discussing what a terrible idea this was. Got moxie and tptacek. Was not disappointed.

This is effectively a me too, but as someone who has spent considerable time researching, understanding, and explaining this problem to customers, let me just say it is a very dangerous thing to do (try to implement a "secure" system on top of JS Crypto in the browser). Moxie and Tom are completely correct and I cringe every time I see one of these projects.

And if you aren't convinced after reading this thread: http://rdist.root.org/2010/11/29/final-post-on-javascript-cr... start here. He covers the topic exhaustively. I feel like anyone arguing about if this is a good idea should do some research and come to the discussion informed. Nate wrote this article over 2.5 years ago.

Having the crypto code delivered by the server to provide real-time "end-to-end" security is surely a problem. But, I believe there is a specific use case where even not-so-perfect javascript crypto increases security in a significant way. Imagine you have a system where you want to send encrypted files that are stored on the server to be downloaded later by other users. With javascript public key crypto a la PGP, the user could encrypt this file using keys stored locally. These keys are "uploaded" to the web page when they are needed but not actually sent to the server. The cipher text only is then uploaded to the server and stored. Recipient users can then download the file and decrypt in a similar manner.

So what does this help protect against? You are mitigating the situation where the server becomes compromised. In the event your server is compromised, any previously encrypted files are protected as long as the keys are not used again after compromise (since malicious javascript could be delivered to obtain the key).

Say it with me: browser crypto is bad. But if everyone really wants to build crypto apps using front-end skillsets (which I can understand, because I've done it[0]), go for it! Who says you need a browser? Use Phonegap[1], or node-webkit[2], or appjs[3], or TideSDK[4] (well, not Tide, unless you're a masochist). If you don't want/can't use Node's crypto stuff[5], use SJCL[6] or OpenPGP.js[7] (the last two are not battle-proof libraries, though, because browser crypto is bad so few serious cryptographers have bothered to review them... hopefully that will change if enough people use them outside of the browser). Voila! The convenience of the tools you know, and automatic cross-platform access, without the badness of browser crypto.

0. https://parley.co

1. http://phonegap.com/

2. https://github.com/rogerwang/node-webkit

3. http://appjs.com/

4. http://www.tidesdk.org/

5. http://nodejs.org/api/crypto.html

6. http://crypto.stanford.edu/sjcl/

7. http://openpgpjs.org/

We implemented a system where the key used to encrypt messages is generated in the browser and never leaves the browser. This ensures even we cant decrypt messages. The downside is the end user has to remember a 'Room Secret Key'.

You can read more here: https://www.tesla.im/#encrypted_rooms

We are just a few weeks into beta and have only a few hundred users. Been working well so far. However it's too early for us to give solid validations.

The negative response to this post is over the top.

At most, you can say that they overstated their case by neglecting to talk about server trust and using the word "comfortable" in an article about security. :)

To address a few red herrings:

Saying that no solution is better than a flawed solution is absurd. There's no such thing as impenetrable security. On that basis, we shouldn't bother with HTTPS. For that matter, we shouldn't bother with passwords, either.

We do these things because they make attacks incrementally more difficult and thus redirect attackers' efforts to more vulnerable targets, or make it expensive enough not to bother. Every little bit helps.

Saying that you can't do this because you have to verify everything on every page load utterly ignores the past decade of development of rich client applications.

Saying that you shouldn't do this because it's been tried before also ignores virtually the entire history of technological innovation.

This is important problem and constructive criticism from security experts is extremely valuable. But the only "sophistry" I'm seeing here is from the people who can help the most.

This is a beta, invite-only app bootstrapped out of the proverbial garage. Their blog post on the technical details missed a few things. If you've ever been in those shoes, you know how easy that is to do. I've seen billion dollar companies do worse. Most of the article was accurate, well-written, and probably helpful to a lot of readers.

Help 'em out, don't tear 'em down.

It sounds like Lastpass is a goner, then.