Hacker News new | ask | show | jobs
Bonchat - client-side encrypted web chat for the truly paranoid (bonchat.org)
13 points by nickbw 5861 days ago
9 comments

This is insecure. It is using Unix time as a nonce for CTR mode: https://bonchat.org/js/aes.js

Clients may send messages encrypted with the same keys and overlapping counters. This could allow the server to recover information on the message contents.

There's also no authentication on the encrypted messages. A corrupt server can alter messages sent to a valid client without detection. This is trivial to do in counter mode.

Also, as people have already mentioned, if the server is compromised, then the Javascript is compromised.

NICE.

Please consider joining our team? Pretty please? We just opened up a SF office. You're only sometimes going to have to deal with my ranting!

CTR nonce collisions are one of my most favoritest attacks. Everyone misses that. It doesn't help that CTR documentation isn't clear on how you should divide the nonce space up between counters and IV-style nonce; you'll find targets where you can induce them to wrap.

It's using millisecond precision time for the nonce, yes. Nonce collisions in a normal volume chat are unlikely. If you'd like to suggest improved counter code, however, I'm all ears. :)

A corrupted server could alter messages without the key if it had both the plain and encrypted versions of a text. But to get that, the javascript would have to be compromise, and at that point the server might as well just steal the key anyway. This has already been discussed above, and if you're worried about it, the solution is actually pretty trivial. I especially like Whimsy's suggestion of a Grease Monkey script for verification.

It's not just two messages colliding on the exact millisecond. They can collide on subsequent blocks. So if Alice sends a 10 block message that starts at T_0 and Bob sends a 5 block message that starts at T_5, then the server learns information about half of Alice's plaintext and all of Bob's. Each client should use an independently-chosen and unpredictable IV.

You are incorrect on your statement that the corrupted server needs both the plain and encrypted versions of a message to send bogus messages. Without authentication, the server can flip arbitrary bits of a CTR message. This opens up several types of attacks. You should apply a MAC to the ciphertext.

I think that the encryption needs to happen entirely in the client and you can't rely on code downloaded from an untrusted server.

Thank you for the insightful comments, and for taking the time to read the code! I really appreciate it.

I've added a pseudo-random component to the nonce, and a MAC to the messages.

I certainly agree that you can't rely on code from untrusted servers, but I think doing the encryption in the client with code that is publicly viewable, even if it can be compromised at any time by a malicious server, is the best we can do for web apps unless/until major browser vendors incorporate client-to-client encryption. Right now there is no reliable protection against a compromised server, but I would like to at least see web apps strive to be more accountable.

No, it's not as secure as your browser and AES. It's exactly as secure as Bonchat's servers and application code, because your browser is going to trust any Javascript fed to it from Bonchat.org, whether or not that code subtly destroys the security of the AES encryptor.

Why even bother with JS AES? If you're served a court order, you can be forced to transparently record everything being said on the site anyways, without anyone being the wiser.

Transparently? Without anyone being the wiser?

The javascript is there for the auditing. The server-side code is not, but you're completely free to analyze the client-side code to verify that it never sends your password to the server. I've avoided minifying any of it (save jquery.js, which you can diff against the official release to make sure I haven't modified it) to make it more auditable.

It's true that you probably won't check the javascript every time to make sure bonchat.org hasn't started serving up a compromised version. Just like I don't tcpdump my network traffic every time I boot up my OS X machine to make sure FileVault isn't secretly beaming my password home to Apple. The point is that I could. More practically (hah), I can randomly sample.

Actually, it would be pretty easy to verify the javascript each time. As long as you're satisfied that any version of the js is secure, you can save a copy to your hard drive and write a script (curl | diff?) to verify the server's copy every time you load up a bonchat.

No, it can't guarantee that the server is free from tampering. Nothing can. But I believe it's the first web chat secure/transparent enough that you can protect your data even if the server is compromised.

"The javascript is there for the auditing" doesn't mean anything. Javascript is the worst possible environment for running crypto code: it's accepting and running code delivered over a network from untrusted hosts bound in all sorts of unpredictable ways to an extremely complicated markup format optimized for display, and, on top of that, almost every single feature in the language can be overridden from the code.

Even if you were among the 0.00000001% of potential users who could possibly look at a block cipher implemented in Javascript and judge whether it was intact (and among the 0% of people who would actually do this), you can't just look at one piece of code in JS and know what it's actually going to do. You have to have a way of assuring every single bound function in the entire Javascript runtime.

That mechanism of ensuring the entire state of a Javascript context in a browser? It doesn't exist yet in any modern browser.

Your last sentence? What a huge dodge. If your server is compromised, your users lose. My browser trusts your server absolutely. If you'd like me to demonstrate this to you vividly, you can catch me offline and we can arrange terms.

Your objections seem to boil down to a superstitious distrust of javascript. The web may be a messy platform, but javascript is not a particularly difficult language to read, and (if I may say so) the relevant chunks of bonchat are written in a pretty plain style.

I'm not making any promises of 100% perfect security with no effort and no room for attacks. Bonchat is merely an experiment in securing content against servers as well as network snoops.

I trust Linux more than Windows. I haven't personally audited all the code on my Linux box, and I don't know any one person who even has the skill to do so. But the code is there to be audited, which gives me more confidence than when I use a opaque operating system. The same applies here. Bonchat isn't perfect, it's just trying to be easier to keep honest than a normal web app.

You say "po-TAY-to", I say "po-TAH-to".

You say "to-MAY-to", I say "no thank you".

You say "supersititious distrust of Javascript", I say "a day job finding, breaking, and fixing the horrible things people try to get away with doing in Javascript". (Or, less charitably: "knowing how Javascript works in browsers.")

Trust me on this one. It's a cool little hack. It's even useful if you get rid of the vanity crypto. But you are asking for someone to write a really mean blog post about you and your actual understanding of how crypto works. That's drama you don't need. Don't bother with the AES stuff.

If you would like to propose improved crypto code, I would love it. Honestly.

But "javascript is a messy language" is not inherently an attack. You can obfuscate just about any language. Do you actually have an attack in mind based on the fact that it's implemented in the browser?

It's true I don't have a deep understanding of the AES algorithms, and the AES code, as stated in the attribution, isn't even mine. Again, I'd love improved code. But you have yet to make any rational argument that javascript in the browser is inherently unsuited to encryption.

I completely agree that the many attempts to make SSL irrelevant by doing all the encryption in JS (and usually horribly naive JS) are foolish. That's not the point. Bonchat isn't a shopping cart or a mail reader. SSL is for securing communication to the server. Bonchat is an experiment in securing communication against the server. Do you have a better way than client-side encryption?

There are some solutions to this, right? For example, you could solve the problem for FireFox by writing a GreaseMonkey script to verify the JS is the same as last time, or just has the right hash.

Another way would be to make it an option to only use the GreaseMonkey encryption - trust it to rewrite the JS on the page, so the user can control updates to the JS.

  > Why even bother with JS AES? If you're served a court order,
  >  you can be forced to transparently record everything
They can try the "Warrant canary" approach. Nothing to lose (but I'm foreign and not a lawyer.)

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

Still it would be vulnerable to ISP-level MitM with SSL CERT hijacking. Aren't major government agencies (at least technically) able to control root CAs?

EDIT: (relevant discussion on the Clipperz forum) http://groups.google.com/group/clipperz/msg/c4e5f76af2e77bf6

For any HN crypto nerds: I made a little web chat that even the server can't read.

Besides boring old SSL, bonchat.org uses a javascript implementation of AES to encrypt chat client-to-client. There are no cookies, no sessions, and no account registration. You never even send your password or plaintext username to the server.

If you chat with someone who knows the same password, you get a simple HTML/Markdown web chat. If you chat with someone using a different password you get gibberish. That's it. :)

It has a number of glaring flaws and no marketability, but by golly it's secure!

It's not by-golly secure; it's insecure in a way that drives me perpetually nuts and that pushes a grevious misconception about how crypto algorithms can secure traffic in browsers.

There is perhaps no worse place in the world to do crypto than in a Javascript interpeter bound to an HTML DOM and hooked up to a network.

Got a specific problem in mind? How would you attack this?
See upthread.
"It has a number of glaring flaws and no marketability, but by golly it's secure!"

Everything has a market. Some things just have a very, very narrow market :)

In seriousness though, in its current form it may not be that appealing but the idea probably has merit to some.

No system is ever 100% secure.
Neither was that ever implied... ?
A couple folks have kindly pointed out that it's wide open to to XSS attacks, since it allows full HTML posting.

This is 100% true ... and doesn't matter one bit. The only information to steal via XSS is the password, and anyone who can submit an attack necessarily already knows the password.

You can exploit this to annoy friends you're chatting with. Try, for example, submitting:

<style>body { background: #cc3333; } a { color: #cc3333 }</style>

... and of course, XSS here means "attackers can turn the crypto off."
... and why did you give your chat password to someone who will use it to turn off the crypto? >_>
I'm having troubles with it in Firefox on two different Ubuntu machines. The page is all red, and the javascript source code is showing up inside the web page.

Then I tested it in the Epiphany web browser. It worked fine on one Ubuntu machine, showing up all nice and blue. But on the other Ubuntu machine I got the red page with the javascript source code showing up, just like Firefox.

Yikes, thanks for pointing this out! I fixed a rendering bug in MobileWebkit and wound up breaking Firefox. It should work now.

Gotta love web development.

Brilliant, works like a champ now!
as long as I am logged in, the password "new_pass" will also allow you to join this chat (abet with a messed up user list, but all text is readable) This is done by adding javascript to my username that changes the password in all those who log in normally.
Nevermind, HTML is no longer posted in such a way that we can inject javascript with the old method. I need to go turn off my troll bot that is now spewing nonsense due to the client being updated.
Heehee. Nice!
Cute, but unless you have some way to verify the client code every time you use it, it's only a bit more secure than a regular web chat site over HTTPS.
(Friend of the OP here.)

That’s true, but it’s a problem with pretty much everything. Google (or an impostor) could, once in a million requests, send you JS that posts your Gmail password to Twitter. You probably don’t trust this site as much as Google, but the JS is unobfuscated and you can dump your traffic. That’s about as much as anyone can offer.

Personally verifying the code and hashing it every time you use it (or whatever) is a big headache. But if you’re that serious about security, it applies to everything. Bonchat adds the unusual feature that, once you’ve done so, you know that the server can’t even theoretically read your chat. (Assuming AES is unbroken.) This is a step above Gmail etc.

Yes. You are right. It is the problem with pretty much everything. The issue here is that you haven't solved that problem. So your application is no more secure than anything.
No. Assuming it’s correctly implemented, it’s more secure than an identical app that sends the password over SSL to the server.

This is not an innovation in cryptographic theory, but it’s something you don’t usually see in a web app.

It's something you don't see in web apps because the idea has been roundly rejected. Because in almost every setting where you could possibly implement crypto in JS, you have to run the app over HTTPS anyways, you gain only epsilon more security than if you would without added crypto --- and that's if you get everything right.
Sure. As this is designed now, HTTPS’s prevention of malicious JS insertion is the big weak point I see. But it’s implicitly asking what you could do if you found ways of getting around that, for example by using client-side caches of the code after a strict initial check.

The real wow for me here is that JS is fast enough to do AES-128 at comfortable chat speed. That’s really suggestive. It’s an epsilon, but it’s a fertile and interesting epsilon.

And, to be precise, by "a bit more secure" we mean "resists attacks by people who don't understand either Javascript or AES".
It seems broken for me; if I go to the url, bonchat treats it like a new chat each time, prompting for a password and my name.
That's the point. :)

Your password is never sent to the server or stored in any cookies. You have to enter it every time because it only lives in browser memory while you view the page.

A cute side-effect of this is that you can chat with yourself under two different names by opening the same chat in multiple tabs. (You can also try chatting with two different passwords to watch the decryption fail.)

you can insert html/javascript anwhere try sticking code in your username.