CryptoGotchas

A collection of common (interesting) cryptographic mistakes and learning resources.

View on GitHub

Crypto Gotchas!

Background

What is this?

It has occurred to me that there are lots of counter-intuitive “gotchas” in cryptography. While some of them are relatively well-known (such as “encryption does not imply integrity”), there are many others which are less well-known and can trip up even relatively experienced people. So, this is a brain-dump which I hope will help other people who review and design cryptographic systems.

What this is not

This won’t teach you cryptography or help you get started in the field. For that, see my Getting Started and How to read a research paper pages.

This also isn’t an attempt to tell people how to do anything. There are already lots of excellent guides out there including Latacora’s Cryptographic Right Answers or libraries which do most of what you need for you such as the AWS Encryption SDK. In fact, this document isn’t really ever going to try to tell you what to do, just what not to do. This also means that the target audience for this isn’t really a junior engineer (though I hope they’ll still find it useful and will help them advance). If you are a junior engineer, you really shouldn’t be working at this level at all. Instead, please look at the earlier links in the paragraph for better guidance about what you should be doing. I also strongly endorse both Dan Boneh’s Online Cryptography Course and The Cryptopals Crypto Challenges (both of which are free). Instead, this is aimed at the more experienced person who already knows cryptography pretty well but hasn’t memorized the ins and outs of every single algorithm and quirk in the world.

Glossary

I like to joke that being pedantic is in the job description for a cryptographer. Like many jokes, there is an kernel of truth to it. As I think of it (or people ask me), I’ll add some important words here which I use in a very specific manner. So, for these terms you may want to forget their normal meanings and use the ones I have here. It’s worth noting that these are my definitions and may not perfectly match standard definitions. Still, I’ll do the best I can and I think that their subtle distictions may matter.

The Gotchas

The Basics

These are the standard things you should watch out for. Hopefully you’ve already learnt these all, but just in case, here they are.

Nonces/IVs

Nonce or Initialization Vector (IV) are two different names for essentially the same thing. While some people (myself included) try to draw a distinction between them, the fact is that this is basically a lost cause and you cannot assume anything about a Nonce/IV based on the name alone. While there is some work being done on “nonce reuse resistant” cryptography, you should still try to avoid ever reusing these values. Just to be safe.

Algorithm/Key Selection for Decryption/Verification

This section isn’t about selecting the proper algorithm or key for your design (see the introduction). It’s about how to select the correct parameters for this specific use of your design when decrypting or verifying data. Now, I know that there is a major push in the cryptographic community to eliminate as much of this negotiation as possible, and I sympathize with it, but it isn’t always possible. If you need to decrypt/verify data from some time in the past, or rotate keys, or be able to move off of a deprecated algorithm, you need some way to signal this. Of course, there are lots of gotchas here (which is the main reason the community is trying to eliminate this in the first place).

How to do this

This is one of the very few times I’ll provide advice on how to do something as opposed to simply saying what not to do. This is because it is really important to support key rotation and be able to change algorithms. So, if you are encrypting data and will need to decrypt it later I recommend the following (simple) solution.

  1. Prepend your ciphertext with a version number (4-byte integer?)
  2. Each version number corresponds to the immutable set of keys needed to decrypt that message (usually just one, but if you have multiple keys for confidentiality/encryption, this can signal both) and the exact algorithms used.
  3. Whitelist exactly which versions you’ll accept and prune this list whenever you can.

This will let you rotate your keys (by incrementing the version) and even move to new algorithms if needed (by incrementing the version) while avoiding all of the normal complexity around protocol negotiation. It still isn’t fool-proof but is a reasonable design which works for many simple cases. If this isn’t sufficient for your design, please seek out experts to talk to.

AES-GCM/GMAC

AES-GCM is a really popular mode and one of the better ones for people to select. However, it doesn’t always act intuitively.

Signatures

Digital Signatures are generally safe to use, but many people assume they have properties that they do not. At their core all they mean is that without the private key, an attacker cannot find a signature for the associated public key over an arbitrary value for which they don’t already know a signature. (a.k.a. existential unforgeability) The best overview of these additional (unpromised) security properties is in Seems Legit: Automated Analysis of Subtle Attacks on Protocols that Use Signatures and I strongly recommend that everyone at least skim that paper. (There is lots of formal verification in there which you can probably skip, but the introduction, defined properties, and case studies are critical.) For an easier read, though focused entirely on ECDSA, you should look at How Not to Use ECDSA.

That said, here are lots of “gotchas” for digital signatures:

Side-Channels

To quote SwiftOnSecurity, “Cryptography is nightmare magic math that cares what kind of pen you use.” Nowhere is this more true than in the area of side-channels. It’s not enough get the right answer and perform the correct calculation, you must do it in the correct way. I truly believe that writing good side-channel-free implementations is a specialty unto itself within the larger (highly specialized) field of cryptographic development and I am definitely not an expert. So, please take all of this advice as not only coming from that particular perspective but also aimed at other non-experts (like myself).

X.509 Certificates

Now, X.509 Certificates aren’t cryptography any more than a car is an engine. But just as people who are experts with engines will spend a lot of time worrying about and fixing cars, so too will cryptographers (unfortunately) need to deal with X.509 Certificates. Here are just a few of many gotchas related to these horrors. As always, if you actually need to work with them, you should read the specification (RFC 5280 and many others).

Contributions and Licensing

I’m always interested in receiving feedback. Issues or pull requests are probably best, but any (reasonable) way to reach out will work.

Is there a mistake? Tell me!

Am I missing something important? Please let me know!

Can you help flesh out my references or otherwise improve this? I want to hear from you!

Several people have already shared pre-publication papers or other non-public materials with me to help me in drafting accurate and helpful public documentation. If you have something you want to share in confidence with me but don’t want me to share it on, please reach out to me so we can chat.

The license I’ve attached to this document is somewhat of a placeholder and exists solely to have something well defined attached. If it causes problems for you for any reason at all please let me know and I’ll work with you to come to some mutually agreeable solution

Creative Commons License: BY This work is licensed under a Creative Commons Attribution 4.0 International License

Acknowledgements

A special thank you to the following people and groups who have helped me with this.