This is the fourth article in a series on the basics of cryptography:
- Cryptography 101: Hashing
- Cryptography 101: Encryption – One Time Pad
- Cryptography 101: Encryption – Symmetric Keys
- Cryptography 101: Encryption – Asymmetric Keys
- Cryptography 101: Realistic Security
DISCLAIMER: These articles are meant for educational purposes only. The methods explained here are meant only to illustrate the basic concepts of cryptography and may or may not be suitable in real world applications. For serious applications such as financial transactions, I recommend hiring security professionals and also getting a lawyer involved. Use this info and code at your own risk, I claim no responsibility!
If you want more in depth information about cryptography than these introductory articles provide, I highly recommend a book called Applied Cryptography by Bruce Schneier. That book literally almost didnt get published because the NSA didnt want the info getting out into the public. Yay for the 1st amendment!
Asymmetric Key Encryption (Public and Private Keys)
Unlike symmetric key encryption, which uses the same key for encryption and decryption, Asymmetric key encryption uses one key for encryption and a different key for decryption.
This probably sounds strange why you would want to have two passwords, but the reason is that you keep one for yourself, and give the other one out to another individual or a group.
Because you keep one to yourself (private) and give the other out (public) these are called public and private keys, and this technique is called Public Key Cryptography.
Depending on which key you keep private (the encryption or decryption key), you can get different effects.
Usage Pattern 1 – Private Encryption, Public Decryption
If you keep the encryption key secret, but publish the decryption key out to the public (or to a group of people, or to another individual), what that means is that you can encrypt data which can be read by anyone. What is useful about this is that they have to use your public key to decrypt the data, so they know it was encrypted with your private key, which means they can be reasonably sure that you were the one that wrote the message. You have effectively cryptographically signed your message so that people know it was in fact you that sent that message.
People use this technique all the time in computers, this is how you can verify that something is from a legitamate source, regardless of if we are talking about a web page (HTTPS), a valid device driver (digitally signed device drivers), or other things of that nature.
Another neat thing about this usage pattern is that getting creative, you can also be ensured that the message or data hasn’t been tampered with.
For instance, let’s say you were making a computer operating system where you only allowed the computer to run trusted (signed executables).
Re-visiting a technique mentioned in the first article in this series on hashing, a “signed executable” might look like the below:
- [Cryptographic Hash of Unencrypted Executable Data]
- [Encrypted Executable Data]
So, you as the “central signing authority” for the operating system would receive programs from people wanting to release software on your operating system.
First, you would put the software through it’s paces via analysis and testing to make sure the program worked as intended, was up to the level of quality you wanted software on your OS to be, followed any specific rules about how the software should behave and interact with the rest of the operating system, and also you would make sure the software wasn’t malicious. Also, you would have to make sure the software wasn’t insecure in any ways that could compromise the rest of your security (for instance, if it had a Buffer Overflow, that could let attackers run arbitrary, unsigned code on your operating system, causing viruses to spread and other malicious things).
Once the program is verified safe, next up you would make the hash of the unencrypted program, write that to a file, then encrypt the program with your private key and write that to the file after the hash.
You now have a trusted / signed executable to distribute.
When a user downloads this executable from your application store and tries to run it, the operating system could take the following measures to verify that the executable was trusted and unaltered from the time of it’s signing:
- Unencrypt the executable using the public key.
- Hash the unencrypted data and ensure that it matches the hash at the beginning of the file.
If the hashes match, you know that the executable was indeed signed by the central authority, and that it has not been altered in any way since it’s signing. Therefore, it is safe to run!
I am pretty sure variations of this sort of algorithm are used by things such as the xbox, playstation and iphone / ipad devices.
Usage Pattern 2 – Public Encryption, Private Decryption
The other way to use asymmetric key encryption is to publicize the encryption key, but keep the decryption key private.
What this allows is for anyone to encrypt a message that only you can read.
One thing you could do with this is would be to be able to communicate securely with people if all you had was public communication.
For instance you could post to a public forum saying “This message is for Jesse”, and then put the encrypted data after that.
Since only Jesse knows his private key, and thus only Jesse can decrypt the data, only Jesse will be able to read your message, even though it is visible to everyone.
Despite this, there are still several unknowns in this particular communication, including:
- Jesse doesn’t know that you really are who you say you are
- You don’t know that Jesse got the message
- Jesse doesn’t really know that the message wasn’t tampered with (well… if it’s a text message you are sending, and jesse unencrypts it and it’s garbage, he knows that the message was tampered with, but if the expected data was not so obvious when it was wrong, he may not be able to know that the message hadnt been tampered with).
But those problems, and others, are solvable, which leads to our next point…
A neat thing about cryptographic techniques like this one, symmetric key cryptography, and hashing is that they are basically just building blocks that you can stack together in different ways to be able to do useful and interesting things.
Once you learn some of the basic building blocks of cryptography (what this cryptography 101 series of articles is supposed to be all about), you can then learn more about how to put those building blocks together to preform useful tasks. The recipes for preforming these useful tasks are called Cryptographic Protocols and they can (and often should) contain more than just cryptographic techniques.
In the first usage pattern, I showed how combining asymmetric key encryption with hashing can provide you with a system for creating and verifying trusted executables. That series of steps for creating and using trusted executables was a cryptographic protocol that contained important steps even beyond just encryption and hashing – such as verifying that the executable was not malicious or insecure. Leaving those steps out creates a big security hole, so they are very important to the overall protocol.
For the second usage pattern, here’s some cryptographic protocols to solve the problems i called out:
- To solve the issue of Jesse not being sure that you are who you say you are, you could take the encrypted message you created, and sign it with your own private key (of which the decryption key is public… this is usage pattern 1). This way, when Jesse gets the encrypted message from you, he first unencrypts it with your public key, and then unencrypts it with his own private key. If the message comes out as garbage in the end, he knows that one of the two steps failed. Specifically, either it wasn’t YOU who sent the message, OR, you used the wrong public key when signing a message to send to him. Jesse doesn’t know which step went wrong, but he does know the message is invalid one way or another.
- To solve the problem of you not knowing that Jesse got the message, you could tell Jesse in the encrypted message “Jesse, if you get this message, respond by sending me back an encrypted message that says ‘the password is forty two'”. Then, if Jesse got the message, he could encrypt a message saying “the password is forty two” using your public key, and then post it on the board again for you to unencrypt with your private key and see that he got receipt of your message. While it’s true that anyone is able to encrypt messages meant for you, and so anyone could have written that message, there is some level of security there because the specific message you said to send was encrypted in such a way that only Jesse could have read it. This way, you can be reasonably sure that Jesse got the note.
- To solve the issue of Jesse not knowing if the message was tampered with at all or not (in the case that it’s hard to tell if you got the right data out or not), one way would be to just put a hash of the unencrypted data on the front of the message. You’d have to agree with Jesse in advance on the protocol, but using the hash again, it would let Jesse know that the data hadn’t been tampered with.
Generation of Key Pairs and Algorithm
By the very nature that these keys work in tandem means that they are somehow linked together mathematically.
I was trying to think of a really simple way to show how public and private keys work together and how they are linked, with a minimal piece of sample code. I thought i had figured out a simplified way, but unfortunately it turned out I was mistaken and my method didn’t work at all.
So, I have to refer you to this page which is pretty darn helpful for understanding how the real thing works with RSA, but unfortunately it doesn’t explain the full nitty gritty of WHY it works to my liking. Still a very good read though: http://sergematovic.tripod.com/rsa1.html
After I wrote up this article, my friend Patrick corrected me saying that the process i described is not the usual process for digitally signing data. He said:
You got signing a little mixed up for asymmetric. Traditionally the process is:
1. Alice creates a public and private key pair.
2. Alice shares her public key with the world.
3. Alice never shares her private key.
4. Bob can now encrypt messages using Alice’s public key and only Alice can unencrypt them using her private key.
5. Alice can take a hash of something she wants people to verify as coming from her. Alice then signs that hash with her private key. Now Bob can verify the item coming from Alice by taking the hash of the data and comparing it against the hash in the signature using Alice’s public key.
Some additional reference:
RSA Labs Digital Signing Explanation
There are two reasons that I can think of why that process is better that the one I described:
- You can sign data without obfuscating it via encryption.
- Public key encryption takes a lot of processing power apparently, so you want to minimize how much data you encrypt with it. This method encrypts a far smaller (and constant) amount of data.
Thanks for the correction Patrick!