I've been following the Telegram story over the past week.
I couldn't get past how the team at Telegram made such odd decisions. Presumably they are a group of smart people who want to help people communicate. So how did they manage to piss off the entire crypto community?
They did it by disregarding best practices and mountains of advice. They did it by not consulting professional cryptographers. They did it by assuming they were smart enough to figure it out as they went along.
Don't make the same mistakes they did.
How to learn cryptography
So, you want to implement some sort of cryptography in your software or hardware project. Great. If you fuck this up people aren't going to be just mad like they might be with other bugs. They might be in prison or they might have been assassinated.
Cryptography in practice is engineering, not hacking, and it comes with serious responsibility. So get it right. Ask for help. Do not let users use your product until it's been vetted. Don't listen to idiots who tell you otherwise.
Learn the theoretical background
So, if you don't know much about cryptography, you should probably take a course. The Cryptography I course at Coursera is a good start, as is your local university's cryptography course.
Both Applied Cryptography and the Handbook of Applied Cryptography are great resources, although they're a little dated now.
Matthew Green also has a great list of cryptography resources
Learn how to implement it
More important than knowing how to use the Chinese remainder theorem is how to use cryptography in practice.
Step one is to read Cryptography Engineering. This is not optional. Read it. It is a fantastic book that details how to use cryptographic primitives. You'll be able to say to your crypto-ignorant friends: Yes, you encrypt your message with AES, but you used ECB! Or, you used Encrypt-and-MAC instead of Encrypt-then-MAC you dummy!
Step two is to study crypto in practice. OTR, the standard for secure messaging is a very well studied implementation of several key crypto features: key exchange, socialist millionaire's protocol, perfect forward secrecy and more. Read this presentation and maybe even the protocol spec if for nothing other than reading what a well written cryptographic protocol looks like.
Other good pieces of software to study are Tarsnap the backup utility and its crypto choices, and WhisperSystems's TextSecure app. Their blog posts are typically excellent.
Cryptography is something you'll need to keep learning for the rest of your career.
The way I do it is via blogs. Here's some to get you started:
- Schneier on Security
- A Few Thoughts on Cryptographic Engineering
- Bristol Cryptography Blog
- Daemonic Dispatches
- Outsourced Bits
There are also a few good mailing lists.
Follow best practices
The most important thing to do is to follow crypto best practices. Since you're not a professional cryptographer, you aren't really aware of the security trade-offs of, say AES-IGE verses AES-CTR and a SHA256-HMAC.
So what are the best practices?
Most applications of cryptography are not secure messaging or anonymity networks. Instead, they're "authenticate this REST API" or "encrypt this gossip protocol".
If your application fits in this area, try to steal someone else's design first.
So if you need a way to authenticate your REST API, don't roll-your-own. Adapt the AWS authentication scheme to your own purposes. This is how you can utilize the years of Amazon's experience of getting it wrong to your own benefit.
If you go this route, you will still need to vet your design.
Design and vetting
So, if your application is fairly unique, and you can't just borrow someone else's design what do you do?
Design your own.
Cryptography isn't something you can iterate on until you get it right, because you'll never know if you do. It's best if you design your protocol up front (before you write any code) and then ask people who are in the know what they think.
If you're a company, hire a professional cryptographer. She can audit your design, or (better yet) design one for you. This isn't something you can afford to get wrong.
If you're just an individual, try emailing your design to the Liberation Tech mailing list. I did this for a project and was told (rightly so) that my design wasn't good enough. Ask for feedback early and often.
You'll need to pick cryptographic primitives too.
Colin Percival has a great blog post, "Cryptographic Right Answers" which details what ciphers/modes/hashes to use. Even though it was written in 2009, it's still valid today.
Do not pick wacky modes or unknown ciphers. There is little reason to be creative when you can be correct. Choosing AES-IGE is suspicious and there's no reason to pick that when you can instead use CFB or CTR.
Explanations are paramount
You know the old saying: “Every ‘why’ has a ‘wherefore.’” Dromio of Syracuse The Comedy of Errors by William Shakespeare
Cryptographers have nothing up my sleeve numbers. These numbers are typically values that are static in the cipher, and could be anything. However, what if you chose your numbers such that they dramatically reduced the effort an attacker?
Sound implausible? It's happened.
So, to show that they have nothing to hide, they use famous numbers such as π or e.
In your design, you similarly need to show that you chose the right cipher modes, the right IV generation tactic and so on. You'll need to explain why you chose what you did.
If you've chosen standard algorithms and implementations recommended by cryptographers, your job is easy. Similarly, if you've copied a design from another service, your job is easier.
Often, attacks are easier against the implementation of the cryptography than against the cryptography itself. These are known as side channel attacks
Timing attacks are attacks you should especially watch out for.
Say you've signed your REST API with an HMAC and want to compare it against the value you computed on your server?
@post('/update/<apikey>/<hash_value>') def update(apikey, hash_value): server_hash_value = compute_hash(apikey, request) if server_hash_value != hash_value: raise HTTPError() else: # Process
This is wrong.
Because strings are checked one byte at a time (not always true, I know), they will stop at the first difference. Attackers can then test how many bytes matched by timing the comparison.
Instead, you need to use a timing attack resistant comparison function.
Cryptography is littered with seemingly minor implementation gotchas. It's a long road to writing great cryptography software. The best thing you can do is embrace the crypto community and ask for help.
People who aren't aware get this wrong.
After you've designed your software and implemented it, you need to open source your code and have people review it. Even if you're a company selling software. If it's not open source, it's not safe.
You'll also need to encourage people to look at your software. Everyone is busy and not everyone cares about your project or company.
Offer a bug bounty program. Not a contest. Actually pay people who find problems, even minor problems.
And don't make your cryptography project sound like snake oil. Saying military grade encryption or N-bits of security makes you sound like you don't know what you're talking about.
Cryptography is different
You can't just learn cryptography like you learn CSS or Erlang or MySQL. You need to study it first and then implement it. Otherwise you're dangerous.
But don't let that stop you from learning cryptography. Some people will say you shouldn't be doing crypto at all unless you're a cryptographer. That's nonsense.
More people should learn cryptography. But you should realize you're no longer shooting yourself in the foot if you mess up. You'll be hurting other people.
And you'll be responsible.