

Bonchat - client-side encrypted web chat for the truly paranoid - nickbw
https://bonchat.org/

======
sweis
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.

~~~
nickbw
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.

~~~
sweis
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.

~~~
nickbw
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.

------
tptacek
_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.

~~~
nickbw
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_.

~~~
tptacek
"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.

~~~
nickbw
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.

~~~
tptacek
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.

~~~
nickbw
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?

~~~
tptacek
You seem intent on evading the point. Most security systems don't depend on me
being able to read the code every time I use it.

~~~
nickbw
Most _web_ security systems don't even give you the option. You sends your
data off and you trusts your server. You can't read the code at all because it
lives on a box you don't have access to.

Any security system you didn't code yourself does rely on _someone_ you trust
having read it at some point.

Is it more secure than some audited local code you compiled months ago and
haven't touched and don't have to re-download? No, of course not. Is it more
secure than chatting on Facebook? Potentially, yes. The necessary transparency
is there.

This is _not_ an innovation in protecting your data from network snoops. In
that sense it's no improvement on SSL and it's not trying or claiming to be.

What it does do better than other web apps is protect your conversations from
the middleman you can't avoid -- the web server itself.

~~~
tptacek
Nick. Please. It doesn't do this thing you keep claiming it does, because you
left out any mechanism for the client to verify the code the server sends. You
keep implying, directly and indirectly, that clients can do this by hand.
People keep telling you, no they can't. When I give a specific and unintuitive
reason why people can't manually verify your code in a browser, you throw out
a smokescreen about how Javascript is a fine language to write things in,
which of course has nothing to do with the issue at hand.

( _By the way, thing you don't want to hear from the guy offering you super-
secure communication system? "You have a superstitious paranoia about
Javascript"._ )

And, as Steve Weis took the time to point out, even if you had invented some
new system by which browsers could verify the state of a Javascript
interpreter fed by an app that, among other things, had until a few hours ago
a bunch of obvious Javascript injection flaws, you _still_ wouldn't have been
secure, because you don't really understand how CTR mode works and implemented
colliding nonces. (Why did you bother with CTR mode anyways?) You also don't
seem to understand the relation between encryption and authentication; not
having a MAC would just be an embarassing oversight if you hadn't then
_argued_ with Weis about why it wasn't necessary.

The security model behind this application is just a really bad idea, Nick. I
know that's tough to hear, since you obviously put some time and effort into
it, but you're going to need to zag instead of zig now and come up with
something cool about this chat system _other_ than the notion that it's
somehow more secure than Campfire or any other https chat.

~~~
nickbw
Actually I really appreciate Weis' comments, because they're actual concrete
problems and implementable solutions. (A bit-flipping attack is not
particularly interesting by itself, since the server can inject gibberish any
time it wants anyway, unless it can be used to insert _meaningful_ content.
But I will be happy to add both a MAC and a better nonce.)

What I don't understand is why you think any unaudited code is secure. There
is no mechanism by which code from an unknown source becomes trustworthy
without someone reading it, or _being able_ to read it.

Nowhere am I suggesting that understanding the javascript source is quick or
easy, but it is in fact _possible_ , which is the difference between
encrypting client-to-server vs. client-to-client. Source code you can view is
not automatically trustworthy. Of course not. But it is _easier_ to trust than
code you will never be allowed to see. Can we at least agree on that much?

As far as trustworthiness, I would say: local code > remote code run on the
client > remote code run on the server > closed source. This makes (a
theoretically fatal-bug-free) bonchat-like system worse than PGP, but better
than Facebook IM.

It sounds like your real complaint is with the "marketing", such as it is.
Perhaps I should do a better job labeling it as experimental, or a proof of
concept? These would be actual concrete criticisms.

Folks complaining of XSS vulnerabilities seem to be under the mistaken
impression that it somehow secures you against _the people you're talking to_
, which is not the problem it's trying to solve. Unescaped HTML chat is
vulnerable to XSS, which is why you shouldn't exchange raw HTML with random
strangers. You wouldn't open an HTML attachment from a stranger, but you'd
open one from your good web developer friend.

(A very fair complaint is that, although XSS is irrelevant to the intended
use, I should've anticipated that people would want to test/demo the basic
chat features by broadly distributing passwords. This turns it into,
essentially, a plain text chat with two URLs you have to enter. Which is
useless, but perhaps amusing, so I've added default HTML escaping.)

~~~
tptacek
Nick, "bit flipping attacks" imply that attackers can make messages say
whatever they want to. They do not simply mean attackers can inject "random
gibberish".

Furthermore, your nonce problem doesn't mean attackers can inject messages; it
means attackers can cryptanalyze messages.

It would be helpful, before trying to implement cryptographic security for
other people, for you to spend some time researching cryptography. A great way
to do that is to learn how to attack cryptosystems in other applications.
Maybe that should be your next project.

Best of luck, Nick.

~~~
nickbw
I appreciate your concern, Thomas, but you seem to be telling me that:

1\. no one will be able to gauge the integrity of a web app by reviewing the
code, and

2\. I should fix the security problems sweis found _by reviewing the code_.

I wholeheartedly agree with #2 (and I'm working on it now), but it rather
contradicts #1.

I threw this thing together because I'm a long-time open source fan and I've
been watching as more and more code people entrust their privacy to moves
behind the opaque border of the web app cloud. I'd like to find ways to deal
with that.

Bug reports are interesting and useful, and I'm extremely grateful for them.
My implementation is flawed, no doubt in ways beyond the ones sweis has
already pointed out, and discovering those flaws is one reason I posted it
somewhere like HN.

But simply declaring that javascript is an unsuitable language for encryption,
or that web clients are an unsuitable environment, doesn't add anything
factual. I think code transparency is a boon to security, and I would like
more web apps to at least try to make their security reviewable, even if
reviewing is a job for experts. If you don't think that code transparency adds
anything useful, well, fair enough. I respectfully disagree.

------
nickbw
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!

~~~
tptacek
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.

~~~
celoyd
Got a specific problem in mind? How would you attack this?

~~~
tptacek
See upthread.

------
nickbw
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>

~~~
tptacek
... and of course, XSS here means "attackers can turn the crypto off."

~~~
nickbw
... and why did you give your chat password to someone who will use it to turn
off the crypto? >_>

------
fexl
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.

~~~
nickbw
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.

~~~
fexl
Brilliant, works like a champ now!

------
JoshCole
<https://bonchat.org/cb9d007ac6e12605> pass: hacker news

~~~
Rhapso
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.

~~~
nickbw
Heehee. Nice!

------
eli
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.

~~~
celoyd
(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.

~~~
tptacek
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.

~~~
celoyd
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.

~~~
tptacek
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_.

~~~
celoyd
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.

~~~
tptacek
Nothing you just said is in the marketing material for this. Instead, it
promises to be (paraphrased generously) so secure that not even the operators
can tell what people are saying over the service.

------
kylebragger
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.

~~~
nickbw
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.)

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

