* No, I am not a cryptography expert. I've had a nascent interest in the field for awhile and this was my way of getting my feet wet while scratching an itch. I thought I'd post it on HN to get feedback and see where I might have screwed up.
* I'm here to learn. *
We all have to somehow right? A disclaimer is a good idea, I'll add it to the README.
* The project was originally motivated because I couldn't find a group chat service that provided an IRC-like experience with end-to-end encryption. The closest I could find was FiSH-irssi, an irc client plugin:
https://github.com/falsovsky/FiSH-irssi
I wanted to try implementing something that was easer to use. I ruled out IRC over SSL because the conversation is cleartext at the server.
* I should have mentioned this in the README and will update it -- The design goal for this system is to enable a group of trusted friends to communicate with each other over an insecure channel without fear of eavesdropping. It is assumed that a member of the trusted group operates the server. Forward secrecy was an additional goal facilitated by changing the room key. It sounds like my implementation did not achieve the design goal. What can I do to make it right?
* My intention was for the secret room key to be securely shared following the RSA key exchange protocol (encrypt secret with requestor's public key and sign with sender's private key, decrypt with requestor's private key and verify with sender's public key). The problem then lies in how to properly exchange users' public keys. If I trust the server but don't want the server operator to read my conversations, is it not okay to facilitate public key exchange through the server?
- The FiSH plugin for Xchat has a (possibly remote) buffer overflow in the Diffie-Hellman key exchange.
- FiSH uses ECB mode. Seriously. ECB.... ECB... might as well use no crypto.
- IIRC FiSH wastes two bytes per 8 byte block the way it does Base64, not sure about this anymore, it's been a while.
So I tried to find a better plugin and mod it a bit which I did (https://gitorious.org/fishslim/dumfish). But I didn't realize back then that FiSH uses ECB mode.
Since the DH key exchange is not authenticated it's useless. So I dropped it and hacked my own (for Xchat, https://github.com/lawl/dumfish), which doesn't offer DH key exchange but CBC mode instead of ECB, we exchanged keys manually via OTR. (And just makes me realize I also don't have a disclaimer, so I'll add this now.)
Disclaimer: Also not a cryptographer, so it's probably not secure. Do not use for anything serious.
If you want to look at a secure protocol, please look at OTR: http://www.cypherpunks.ca/otr/
> WARNING: Unable to decrypt. One of you may have changed keys or might be an imposter. Run /idexch if you trust this person.
This may very well be the worst advice you could possibly give.
Suppose Alice and Bob already have a conversation. Then Eve wants to start MITM'ing during middle of the conversation and has already missed the key exchange (where she could easily switch Alice and Bob's public keys because your application doesn't even try to authenticate). Now she just needs to corrupt the packages so your app tells them to do a key exchange again and now can easily switch alice and bobs public keys for a set of her own ones and read everything.
Key exchanging is the hardest problem your app would have to overcome to actually be secure, telling your users to just do it again over an unauthenticated connection is just ... stupid, sorry.
Plus from glancing over it it lacks things like session keys etc.? Though that might well be in the NaCl lib, so I'm not sure about this.
I'd just ask you to label this as POC or something, because no one should use this application for anything that needs to even remotely stay secret.
I'm tired of people labeling their applications as "cryptographically secure" with no proof of correctness or any kind of guarantee. It's just a blunt and stupid statement.
The author of this clearly has no cryptographic expertise and just wrongly applied a cryptographic scheme.
In the description, it reads "[..] messages are encrypted and decrypted at the end points such that malicious machines on the network cannot eavesdrop on the conversation, including the chat server," but no effort is made in the client code (client.py) to ensure the server works as it should. Yes, the server can't eavesdrop on the data as-is, but that means you have to trust the hosting provider is using exactly your server.go, thus you have to trust the server completely after all. And if you do, why bother trying to hide it from the server in the first place?
I'd feel even less safe using this than IRC over SSL.
The major problem with this is that you're trying to do something impossible. In order to have a secure connection between two or more people, you need to either have a key in place or establish one. Both of these options are extremely hard to achieve.
In the former, you have a to get a key in place (which can't get transferred through the server for obvious reasons), so that has to be established before any confidential data is being transferred. This is clearly not happening.
The latter option is a key exchange protocol such as Diffie–Hellman. This can work; you can in fact make a key exchange between two parties where an eaves-dropper will be none the wiser for listening in. But then you have another problem: authenticity. You have no guarantee that you are in fact talking to who you think you are.
Your system makes no effort to overcome either of these challenges.
deadchat implements the latter option. The secret room key is shared using the RSA key exchange protocol but you're right, there's currently no way to guarantee that you're talking to who you think you are. User authentication is on the todo list.
I think there's still value in hiding the conversation from the server even if you must still trust the server to not behave maliciously. If some three-letter agency contacts the server operator asking for a back channel to listen in, he or she could respond that it's not possible without malicious intent towards a user:
http://www.macobserver.com/tmo/article/apples-imessage-encry...
The point of criticism is to help people improve. By effectively saying, "You're not cut out for crypto, don't even bother," you do a disservice to others and contribute negativity that HN doesn't need.
"This is just a proof of concept. It's not secure. It's just a learning exercise. Don't use it for anything other than learning."
I haven't looked at this project, so maybe it does have those warnings.
The problem is not creating and releasing such applications; the problem is overclaiming their security, or putting early confidence in them.
Crypto is hard, we get it. Beginners and non-experts are going to mess it up, we get it. Even experts almost always mess it up, we get it.
Still, a good programmer of crypto software (or even just, "wise user of battle-tested crypto libraries in the proper ways") will almost always start out as a bad programmer of crypto software... who got started, and learned by failing.
To borrow an aphorism from other project/product wisdom: if your first version's crypto isn't obviously and embarassingly broken, you waited too long to release.
Broken cryptography can cause loss of money, infrastructure, and life. Imagine if a group of dissidents where to start using this program, the crypto implementation was subtly wrong somewhere, and they were disappeared by their government early one morning. Imagine if some transmitted a password through what they thought was a secure chat, and that password led to an industrial control system for, say, a subway, water treatment plant, foundry furnace, or explosive chemical storage tank. Software doesn't just move Tweets. There are massive, hot, high-voltage, fast-moving objects controlled by software also. Letting people believe information is safe when it isn't can have very real consequences.
Unless it is obviously written all over your software that "THIS IS A TOY AND YOU SHOULD NOT EXPECT IT TO ACTUALLY KEEP ANYTHING SECRET," your obviously and embarrassingly broken crypto (to a crypto expert) might look just fine to a nontechnical user with dollars and/or lives riding on your product.
More on topic - does anyone have any good reference guides for how to not suck at cryptography, preferably more "API guide for programmers in a hurry" than "maths textbook for people who want to learn the inner details of algorithms for their own sake"?
(I know that knowing the internals will make you a better programmer, but it seems there are a lot of people who don't know the internals or externals of cryptography, and having a step-by-step cookbook which can be followed blindly would make this situation slightly less bad. Sure it might give people a false sense of security - but they already have a false sense of security from rolling their own crypto, so a cookbook couldn't be worse :P)
Even using a good crypto library won't save you if you don't follow the docs or try to get creative with the API. For instance, using multiple passes of different encryption algorithms won't necessarily improve the strength of the encryption. Due to subtle mathematical interactions it can often lead to exploits that wouldn't have existed in the individual algorithms, but do exist in the combined algorithm. Similarly doing encryption quickly might seem like an important goal, but often consistency is more important lest you inadvertently create a potential timing attack.
TL;DR; Use a good crypto library, a large key size, a good source of entropy, and follow the documentation exactly, don't try to get creative with it.
The public keys are sent across the same channel, though, and I don't see any mechanism in place to prevent the server from replacing that public key with their own (man in the middle attack). Maybe I'm missing something.
> I don't see any mechanism in place to prevent the server from replacing that public key with their own
I'm not sure that's possible without exchanging the cert via peer-to-peer. In which case, you've already solved the toughest bit of the chat protocol (the handshake and coordination across the clients) so you might as well go fully peer-to-peer and do away with the server entirely.
Can anyone explain why this is necessary?
Personally though, I'd rather welcome that kind of abuse but not exclude other people from countries who don't use the Latin alphabet. As demonstrated above, it's impossible to automatically moderate username abuse entirely anyway - as you can just start using non-unicode characters or even punctuation such as periods after the username. And if the chat protocol is built in a secure way (which this is not), then there should be other mechanisms for ensuring that Bob is in fact "Bob" and not "B0b" nor "Bob."