## Lab 11: Experimenting with RSA

#### Goals

• Understand how RSA works in practice: We discussed the basic security principles and one particular algorithm, RSA in class. In this lab, we will experiment with the RSA algorithm, see how it can be used in practice, and appreciate the challenges when an algorithm is put into use.
• Develop a set of functions to exchange data securely: We will develop a set of functions to exchange data across the network securely. So far in the class, we have used standard TCP/IP suite to exchange data across the network. The functions we used include `read()/write()` in TCP, and `recvfrom()/sendto()` in UDP. Those functions do not provide secure communications unless the transport layer does so. In this set of lab exercises, you are to write functions to transfer data securely at the API level.

#### Credits

The work is based on the discussion at http://hayageek.com/rsa-encryption-decryption-openssl-c/

#### Introduction

In the public/private key scheme for secure data transfer, the communicating parties share their own public key with the other party. When sent from Alice to Bob, the message m is encrypted with Bob's public key B+. The content to be sent becomes B+(m). When Bob receives the message, he decrypts the message using his private key B-. Because of the nature of the public key and private key, B-(B+ (m)) = m. That is, only the party with the proper private key B- can decipher the message.

In practice, key management is critical to the success of secure communication. If a public/private key encryption scheme such as RSA is used, the communicating parties have to exchange the public keys of each party. Because the asymmetric nature, the private key is kept secrete by each party, public key exchanges are less trouble-some today, though challenges do exist. Please read the Wikipedia article on the subject for some general information.

You will practice some of the basic operations of an RSA system in this lab. First you will generate your own public key and private key. You will then use this set of keys to encrypt and decrypt messages over a regular TCP connection. The sending party encrypts the message using the receiving party's public key and sends the data to the receiving party. The receiving party decrypts the received data to retrieve the original message using its private key.

To concentrate on the essential issues, you are given a set of programs that take care of some of the routine operations such as reading key files from local file system, establishing a regular TCP connection, among others. Your tasks are to write the core functions to encrypt and decrypt messages, and to send and receive the encrypted messages. You are also given a program example of direct use of RSA related functions to encrypt and decrypt messages to see how these functions may be used.

Your overall task is to write a few core functions such that the given set of applications `echo-server.c` and `echo-client.c` will work properly, exchanging information through secured communications. You will be given some program files that have implemented some of the routine tasks. You will need to understand how these programs work and write the required functions to complete the application.

The following descriptions reflect how I would set up the file structures. You can choose different way of organizing your files and use your own wrapper functions developed in this and other courses.

1. Change to your working CSCI 363 directory;
2. Copy the entire given directory to your directory
`cp -r ~cs363/Spring16/student/labs/lab11 .`
3. You should see two sub-directories under the `lab11` directory, one is named `rsa` which contains a working example, the other is named `rsa-app` which contains a set of program files with which you will work.
4. Go to the directory of rsa, compile and run the program test-rsa. Then read the program test-rsa.c to understand a few key points. You don't need to submit anything for this part of the exercise, but make sure you understand what is going on. Understanding how RSA works in this example will help you complete the lab exercises.
• The flow of the program : What are the steps in the program test-rsa.c that encrypt a piece of plain text? What are the steps needed to decrypt the encrypted text?
• Private key and public key : How do the public key and private keys look like in this program? When is the private key used? When is the public key used? In this sample program, the private key length is 2048 bytes. The longer the key is, the stronger the encryption is. From the theory of RSA, we know the keys are a pair of numbers with special features. In the testing program, and in all practical uses, the keys appear as plain text. This is really a text representation of binary values. (Read, for example, the manual pages for `uuencode` and `uudecode` to see how one might convert between a binary file and a piece of unique text.)
• Relation between the length of the private key and that of the data : In our test, the length of the private key is 2048. The length of the data the key can encrypt and decrypt at one time is about 245 bytes, a bit less than 2048/8 = 256. One would have encrypt the longer data in separate, multiple pieces, each about 245 bytes long.
5. Once understanding the test-rsa.c program in the rsa directory, change your working directory to rsa-app that is in parallel with the rsa directory. A pair of application programs reside in that directory, echo-server.c and echo-client.c. These two programs simply exchange a piece of text, similar to the simple echo program pair we worked with before, except that the functions that write to and read from network should now be in secure form using RSA. Currently two of the required functions, writes() and reads(), are simply implemented using the regular write() and read(). Your task is to re-write these and complete other missing functions so that the pair of application programs echo-server.c and echo-client.c work properly using the RSA algorithm to send and receive data.
6. Compile and run the programs. The programs echo-client and echo-server should work, that is, sending and receiving a piece of plain text.
```make
./echo-server [port] server-private.pem server-public.pem &
./echo-client [server-name] [server-port] client-private.pem client-public.pem
```
7. The general flow of logic for this pair of programs is as follows.

• You first should generate your own private and public keys for your server and client. You are given a set of four key files, server-public.pem, server-private.pem, client-public.pem, and client-private.pem. You can view these files with either Linux commands such as `cat`, or any text editors. Your programs can use these files. But you are asked to generate your own using the following command at the Linux command prompt.

`openssl genrsa -out new-server-private.pem 2048`
`openssl rsa -in new-server-private.pem -outform PEM -pubout -out new-server-public.pem`
`openssl genrsa -out new-client-private.pem 2048`
`openssl rsa -in new-client-private.pem -outform PEM -pubout -out new-client-public.pem`

Note that the order is import that a private key is generated first, the public key is then generated based on the value of the private key.

• Your next task is to complete the function `exchange_public_key()` of which the prototype is given in the header file tcplib-ssl.h. The three parameters for this function are the connected socket, the file name for the key, and an indicator whether this is the sender or receiver. Note that both parties can't read and send the public key in the same order. One has to send first, then receive; while the other has to receive first, then send.
• You then should revise the functions `writes()` and `reads()`. The prototypes of these two functions are also defined in the file tcplib-ssl.h. These two functions have the identical prototype as their counter part in the Linux file system, `read()` and `write()`. They take the socket as the first parameter, a buffer as the second parameter, and the length as the third parameter. Note that the buffers for writing and reading represent plain text. All the encryption and decryption details should be hiden from the application program. That is, you'd have to implement all the details in the functions writes() and reads(), possibly creating other functions as needed. One obvious and critical issue is that the data may have length longer than what the encryption function allows (e.g., in our case of 2048 byte key, the data can't be longer than 240 or so bytes.) In your implementation of writes() and reads() you'd have to consider this issue. You'd have to break the data in multiple pieces and send them separately. On the receiving side, you'd have to receive these separate pieces, decrypt them and reconstruct the original data before sending it back to the calling function.

When the three required functions are implemented properly, writes(), reads(), and exchange_public_key(), plus possible other functions you choose to implement in support of these three functions, you should be able just to compile the programs and run the server and client programs. Note that the echo-client.c contains two pieces of test messages, one a simple and short hello world, the other is a longer message generated by the function read_long_message(). Test with the simple message first. If it works fine, comment out the simple message, uncomment the longer message and try the program with the longer message, in which case, your writes() and reads() will have to break the message into multiple pieces for encryption and decryption.

Save as a text file a screen capture of compiling the programs, send and receive the simple message, and send and receive the longer message. Name this file screen-capture.txt

Clean up your directory by running the command `make clean`, and submit the entire directory to your git repository.

Congratulations! You just finished this lab.