CS 231: Computer Security

RSA keys in practice: creation, manipulation, storage

In-class exercise. Boot Mac and open a terminal.

Keep a record, maybe as an email to yourself, of the commands you use to do all of the following.

Creating RSA key pairs, encrypting, decrypting, and signing

For these exercises, you'll use the "openssl" command. Executing "man openssl" gives you a list of sub-commands openssl will allow you to execute (e.g. "openssl genrsa ...", "openssl rsa ...", "openssl rsautl ...", etc.). Then, "man genrsa" or "man rsa" will give you the more detailed specifics of the flags and parameters supported by each of these "openssl *" sub-commands.

Unfortunately, the openssl command has an enormously complicated command-line syntax, with a bewildering set of options. Fortunately, the internet has many tutorials and examples that help you ramp up your knowledge of the openssl command. For this lab, I like section 5 of this intro to openssl and section 3 of this other one. But feel free to search as you see fit.

  1. Act like Alice and make friends with the Bobs at a neighboring computer. Open two terminal windows. One of the windows will be your communication channel with the Bobs. One of you should execute "nc -l 1234" (or some other port number of your choice), while the other should execute "nc host 1234" where "host" is the IP address of the machine on which "nc -l 1234" is running. This will give you a rudimentary chat interface for sending messages back and forth.
  2. Create an RSA private key as a PEM file called cs231_rsa_private.pem. NOTES: (1) DO NOT password-protect your key; (2) Go with 512 bits instead of the 2048 a lot of the tutorials use. Yes, in practice, you'll want the longer key for greater security. But for today's exercise, it will be convenient if we keep the keys shorter.)
  3. Extract the corresponding RSA public key from the private key and save it in cs231_rsa_public.pem
  4. Wait, how could you get the public key from the private key? Isn't that supposed to be computationally intractable?
  5. Remain calm. Let's look at the numbers stored in the private key (see section 3 of the second link above for help). Does that help shed light on how one might have gotten the public key (n, e) from the private key (which you may have thought was just (n, d))?
  6. Share your public key with the Bobs vi your nc chat.
  7. Encrypt a message for the Bobs, using their public key. Deliver your message to them. NOTES: (1) To do this, you'll need to start by putting the message in a text file (message.txt, say). Then do the appropriate openssl command to create the encrypted file. Finally, since the encrypted file is binary and unlikely to be readable in a text display, you should use the base64 command to change the encrypted data to base64 before sending it to the Bobs. (2) Your message needs to be short, since the "openssl rsautl -encrypt..." command will only encrypt a message with fewer bits than the value of n in the key pair (how big is that for your key?).
  8. Decrypt and read the message the Bobs sent you.

Dissecting the private key PEM file

Now we're going to look at that cs231_rsa_private.pem file, and dig into its contents and file format.

  1. Copy the body of the cs231_rsa_private.pem file (the base64 lines between the header and footer lines) into the input box here: http://holtstrom.com/michael/tools/asn1decoder.php. Select "BASE64/PEM to ASN.1" from the drop-down list, and hit Convert. Compare the output to the "RSAPrivateKey" record shown here, and also to the output you got from the "Remain calm" question above. Can you see the integers?
  2. Now that you have a convenient hex version of n, p, q, e, and d, use a quick Python program (or just the python >>> interactive interface) to verify that this n = p*q and e*d mod (p-1)*(q-1) = 1. Those are the properties that make RSA encryption and decryption work.
  3. Great, but what magic was going on in the conversion from the PEM file to ASN.1? Step one, let's look at the bytes that are represented by your base64. So go select and copy the body of your private key file (the usual Command-C operation in whatever program you're using to look at your .pem file). Then do this: "pbpaste | base64 -D > cs231_rsa_private.der". You can take a look at the bytes via "hexdump cs231_rsa_private.der". This file, not suprisingly given the file name I specified, is in DER format. (Do you understand the roles of pbpaste, base64, and hexdump here?)
  4. Copy your base64 key body again, and paste it into the input box of this different converter and hit the "decode" button. You'll see the decoded bytes listed on the right. Compare them to your DER file. You'll also see the DER structure of the file illuminated in the upper left of the web page. Hover your mouse over the pieces of data in the upper left, and see how they're reflected in the raw bytes display on the right.
  5. Can you figure out the structure of this file by studying the Wikipedia description of the DER format? This requires a careful reading of the file format description. Most of the relevant information is in the "BER encoding" portion of the Wikipedia page.
  6. Finally, step back and think at a higher level of abstraction. The RSA private/public key pair involves five essential numbers: (n, p, q, e, d). All but one of these numbers is typically very long--in the hundreds or thousands of bits long. When you store the key pair in a file, then, you need a reproducible and parseable way of storing these large numbers. Talk to your partners to see if you can explain to each other how PEM, base64, and DER are used to create a relatively convenient way to store RSA keys. Practice explaining this to other people, too--it's pretty easy in the RSA context, and you're going to need to understand it when we take a look at the significantly more complex Public Key Infrastructure certificates in a day or two.