I'm currently advocating the use of asymmetric cryptographic signatures in popular open source projects (WordPress and Composer to start). In many cases this will involve writing code, in others it will be reviewing a solution that other people have already developed. These are just some of my thoughts on the subject matter.
Why Bother with Asymmetric Crytographic Signatures?
Let's say that I want to publish a tool that the NSA wants to subvert. It could be a private communications platform. It could be a steganography tool. It could be LOIC. Doesn't matter.
How can you, the user, trust that the copy of the tool you are receiving is genuine? First, two incomplete answers:
- "Check to make sure that the download is over HTTPS and there are no certificate warnings."
This is a good first step, but we're operating in the assumption that the NSA has the capabilities to issue trusted TLS certificates on a whim. They can man-in-the-middle attack our website and most people will never notice.
- "Publish an MD5/SHA1 hash on the downloads page so we can verify the hash."
Didn't I just say the NSA can MitM your connection? If they're going to tamper with the download, why would they neglect tampering with the hash? That would be noisy and sloppy.
The answer is to use asymmetric cryptography.
Asymmetric cryptography involves two related numbers: a "private key" and its corresponding "public key". If it helps, visualize a signet ring and a wax imprint. Anyone with the signet ring (the private key) can seal an envelope such that anyone with the knowledge of the correct imprint (the public key) can verify.
Let's assume that you already know my public key. If I sign the package before every release with my private key, you should be able to reliably trust that the package you are receiving is a genuine copy that I authorized and distributed, given a couple of basic assumptions:
- Only I have access to the private key.
- Private keys are basically impossible to recover from a public key.
- The signature algorithm is secure.
- The software used to create and verify signatures is also secure.
I'm not going to go into them too much (maybe a future post). You want GnuPG, OpenSSL, or libsodium here rather than rolling your own RSA/ECDSA library. (DSA's 1024-bit limitation is a good reason to distrust it.)
Okay, so we chose a sane implementation of library to handle secure digital signatures. We're done here right? Not so fast.
Let's say the NSA gets smart, and they decide to request copies of the software, along with their PGP signatures, since its first release. As vulnerabilities are discovered in my project, I will intelligently publish and sign more packages with my signing key. What, then, stops them from using a man-in-the-middle attack to serve an outdated package (and associated correct signature) to targeted end users of interest? Nothing. The signatures will validate, the users probably won't notice they're still on version 1.1 when the latest is 1.7, and they will get 0wned. Unless I incorporate this into my threat model.
Interlude: A threat model is kind of an abstraction for motivated attackers with varying amounts of resources. If you're only concerned about script kiddies and carders, then your threat model is probably satisfied by using HTTPS everywhere and keeping your software updated religiously. If you model your threats, you can estimate the risk to vulnerabilities that crop up down the road. In my threat model, I've incorporated an intelligent, motivated agency with a lot of resources including the capability to defeat properly implemented TLS encryption by serving rogue certificates.
To avoid my users from getting 0wned, there are a number of strategies I can take:
- Sign weekly/monthly signing keys with my long-term private key, use the ephemeral keys to sign each current package.
This works really well, but key management becomes a bit burdensome. Users have a hard enough time with GnuPG as it is.
- When signing, include a short-term expiration date in the signed message
This works, but guarantees you will be resigning packages every month.
- Publish a weekly/monthly signed document with a short expiration date that lists the latest versions / SHA-2 hashes.
This works, and doesn't require re-signing every single package every month. I believe this is what Linux package managers generally do.
There are probably others that I failed to think of, but this changes the game so that, as long as the user's system clock is correct, adversaries cannot serve stale packages to end users.
Got another solution? Or a more exotic attack? Write a blog post and let me know.