Imagine you’re a software developer, and you share your software or its updates on the internet. How do you make sure that someone doesn’t tamper with your software and distribute that tampered copy to your customers? The solution is a software signature. The way these signatures work is utterly clever and fascinating.
What Is a Software Signature?
We use handwritten signatures for self-identification for two reasons: they’re supposed to be verifiable and impossible to forge. The same principle applies when you’re trying to make sure that the copy of a piece of software on your computer is authentic and not modified in any way. The developer will leave a digital signature on the software package (which cannot be forged) and the customers verify that signature in their copy before installing the piece of software.
This goes for software updates too. A malicious update (say malware disguised as a driver) could wreak havoc on your machine. Your operating system (be it Windows, macOS, or Linux) needs to verify that an update is coming from the original source before it installs it on the system.
Digital signatures are meant to do the same two jobs as a handwritten signature, but how they actually work could not be more different. It takes some really clever cryptography tricks to create and verify digital signatures.
How To Hide a Secret Message in Plain Sight
Say, you want to share a secret with a friend over handwritten notes. In this scenario, you also have to leave them in a public space for your friend to pick them up later. Anyone walking by could just pick the note up and read your secret. So that’s our problem: how to make sure only your friend can read the message, even if someone snooping around gets hold of the note?
A smart way would be to use a “key” to lock and unlock this shared secret. Allow me to explain.
Both you and your friend agree on a key, and you use that key to convert your secret message into gibberish noise. The key could be anything. For example, you two could agree to replace every letter of the message with the letter right next to it in the alphabet.
Then you would take your message and replace every letter in it according to the key. So the message “SECRET” becomes “TFDSFU.” You write “TFDSFU” on a note and leave it in the public space. Your friend can decode it because they have the key you both exchanged earlier. So all they have to do is shift each letter to one place in “TFDSFU” and they’ll get the original message “SECRET.” Any eavesdroppers would just see the nonsense because they need the key first to understand the message.
What we just described here is a very simple cryptography technique and the key it uses is a basic Caesar cipher.
How Computers Send Secret Messages Over the Internet
Now imagine if you’re doing the same thing over the internet, and you want your communication to be completely secure. In the real world, you can meet in advance and exchange keys with each other. You can’t exchange the key like that on the internet because it’s a public space. Anyone could pick up that key and use it to decode the rest of your communication. So, how to exchange a key without sharing it with your friend?
So you need a key to communicate securely, but you need to communicate the key securely first. This is how you get two computers to agree on the same key without sending that key over the internet.
Without getting overly technical, encryption works with mathematical equations that are easy to solve in one direction, but incredibly difficult (or even impossible) to solve in the opposite direction. So if a computer had the equation with all the right numbers that go into it, it could solve it easily. However, it would be impossible for it to reverse-engineer the equation itself if it was given the solution.
I’m oversimplifying a great deal here, otherwise we’ll be here all day. If you want to take a deeper dive into how this works, look into the Diffie-Hellman key exchange.
Here’s the scenario: there’s a computer A, a computer B, and a public space. It starts with a key sent to the public space (let’s call it the public key). Computer A creates another key and keeps it private (let’s call it the private key A). Computer B does the same.
The public key is available to everyone, but the private key A and private B are kept safely on their respective computers.
Now computer A takes the public key and combines it with its own private key to create a combination. Computer B does the same with its own private key. Both combinations are different. Instead of sending their private keys to the public space, the computers send these combinations out there.
Remember that it’s impossible to reverse-engineer these combinations to find the private key used to create them. And at no point, the two computers see each other’s private keys.
Now for the actual trick. Each computer grabs the combination the other sent to the public space. Then computer A adds its private key to that combination with its own private key to get the final key. The other computer does the same with its private key and gets the exact same final key that computer A made.
Now both computers have the same key that they can use to encrypt and decrypt all future communication. Here’s the oversimplified answer: the two computers “make” their own copy of the key without actually sharing the key itself.
This whole process is called public key cryptography. This type of public key cryptography is the basis for digital signatures like software signatures.
How Developers Hide a Secret Signature in Their Code
Signing software digitally also involves public and private keys. However, the intention is different, so the inner workings are a little different too. The idea here is not to establish a secure line of communication. We just want a one-way verification. The software developer isn’t trying to hide the contents of the software package. They’re only interested in proving the origin of the package.
So the developer creates a pair of private and public keys. Remember both these keys are different, but they’re mathematically related, and it’s impossible to reverse engineer one key from the other.
The developer uses their private key to encrypt the software package. That encrypted copy can only be decrypted by the public key they’ve already published on the internet. So when you and I use a public key to decrypt that copy, we can be absolutely sure that it was sent by the developer because they only have the private key that could have originally encrypted their software package.
Hashes Make the Work Easy
Okay, so I lied a little bit. It’s not practical to actually encrypt entire software packages because these files can get pretty massive. There’s another clever way to solve that problem through hash functions. Hash functions are math formulas that create a fixed length of digits and letters out of a file of any size.
For example, a SHA256 hash function will take any file and spit out a list of 256 digits and letters. If that file changes by even a single bit, it’ll create a completely different result. So the developer will run the software package through a SHA256 function to generate a text file. And instead of encrypting the whole package, they just encrypt this text file using a private key (just as I explained above). They attach the encrypted hash text to the software package and send it to us.
When you and I receive the software package, we’ll run it through SHA256 too, to get our own hash list. And then we’ll decrypt the encrypted message attached with the software package using the public key the developer provided. If the decrypted hash list matches the list we generated on our end, we can be absolutely certain that this package came from the developer, and it’s untampered with. Any tampering with the package in transit will result in a completely different hash text. These text files are called checksums.
In a nutshell, that’s exactly what a software signature is: the encrypted hash and the public key. A digital signature works because it’s unforgeable (the private key makes sure of that) and it’s verifiable (the related public key can decrypt the message).
Who Watches the Watchers?
If you’ve been paying attention, you might have noticed there’s still one flaw in this system that we’ve not addressed yet.
What happens if someone takes a copy of the software package, messes with it, creates a new checksum, and uses a new pair of keys to encrypt it? That threat actor could spread the related public key around or send it directly to us. We’d decrypt the tampered signature using the public key thinking the hashes matched so it must be from the original author. But the public key we used was from an impostor.
That’s where certification authorities come in. A trusted organization like that vets developers and awards them digital certificates linked to their public keys. It signs the certificate cryptographically just like the developer does for us, and an even higher certification authority vouches for this organization’s signature. It’s certification organizations all the way down.
These certificates are legally binding, and we can verify them on our own end to be absolutely sure that we got the right public keys.
All this stuff automatically happens in the background because the computer takes care of the hashing, encryption, and verification. We just see a dialog asking our permission to install the app or update. If an app is unsigned, the operating system will warn us before installing it.