50.005 Computer System Engineering
Information Systems Technology and Design
Singapore University of Technology and Design
Natalie Agus (Summer 2026)
Programming Assignment 2
Main Task
In this assignment, you will implement a secure file upload application from a client to a secure file server. You will design and code the secure File Transfer Protocol (FTP) into the application.
Secure means that it fulfiles these three requirements simultaneously:
- First, before you do your upload as the client, you should authenticate the identity of the file server so you wonβt leak your data to random entities including criminals.
- Secondly, you want to ensure that youβre talking to a live server.
- Thirdly, while carrying out the upload you should be able to protect the confidentiality of the data against eavesdropping by any curious adversaries.
You may complete this assignment in groups of 2-3 pax. Indicate your partnerβs name in the google sheet provided in our course handout.
There are three parts of this assignment:
- Authentication Protocol (AP)
- Confidentiality Protocol 1 (CP1)
- Confidentiality Protocol 2 (CP2)
These three parts form a strict Secure File Transfer protocol. You will be using socket programming (from the first half of the term) and cryptography knowledge (from the second half of the term) to complete this assignment.
Secure FTP != HTTPS
Note that you will be implementing Secure FTP as your own whole new application layer protocol. In NO WAY we are relying on HTTP/s.
There seem to be some ridiculous misunderstanding from your seniors in the past years that this assignment requires knowledge on HTTP/s and/or DNS. Itβs totally two different protocol even though they are both application layer protocol. HTTPS is not equal to our SFTP, they are unrelated, as unrelated as π fruit is to πΉ flower.
System Requirements
The starter code provided to you is written in C and uses the OpenSSL library (libssl, libcrypto) for all cryptographic operations. You need:
- A C compiler (
gccorclang) - OpenSSL development headers
- A POSIX-compliant OS (Linux or macOS)
Install the dependencies:
# Ubuntu / Debian
sudo apt-get install build-essential libssl-dev
# macOS (Homebrew) β the Makefile auto-detects the path
brew install openssl
# Fedora / RHEL
sudo dnf install gcc openssl-devel
Starter Code
You should have joined the GitHub Classroom and obtained the starter code for this assignment there. The link can be found in the Course Calendar portion of your Course Handout.
PA2 Files
Anything under source/ is where you will work for this assignment. All files in the same level as source/ are for admin purposes. Do not modify these.
.[PROJECT_DIR]
βββ files
βΒ Β βββ cbc.bmp
βΒ Β βββ file.txt
βΒ Β βββ image.ppm
βΒ Β βββ jsim.jar
βΒ Β βββ player.psd
βΒ Β βββ squeak.wav
βΒ Β βββ vscodejsim.mp4
βΒ Β βββ week9.html
βββ Makefile
βββ README.md
βββ recv_files
βββ recv_files_enc
βββ send_files_enc
βββ setup.sh
βββ source
βββ auth
βΒ Β βββ cacsertificate.crt
βΒ Β βββ generate_keys.sh
βββ ClientWithoutSecurity.c
βββ ServerWithoutSecurity.c
Run ./setup.sh
[PROJ_ROOT_DIR]/recv_files, [PROJ_ROOT_DIR]/recv_files_enc, and [PROJ_ROOT_DIR]/send_files_enc are all empty directories that are not added in .git. To create them, simply run ./setup.sh in the project root.
You should see exactly the above file structure afterwards. ./setup.sh is a bash script, in order to execute it you must chmod it to be executable first.

Custom Crypto Library common.c
All complex OpenSSL calls are wrapped for you in common.h / common.c. You call these wrapper functions and you do NOT need to write raw OpenSSL EVP_* code yourself.
Here is the mapping between the Python functions you may be familiar with and the C wrapper functions provided:
| Functionality | C function (in common.h) |
|---|---|
| Generate random bytes | RAND_bytes(buf, len) |
| Send 8-byte int | send_int(sockfd, val) |
| Send raw bytes | send_all(sockfd, buf, len) |
| Read exact bytes | read_bytes(sockfd, len), must free() |
| Convert 8B buf to int | bytes_to_int(buf) |
| Parse cert from bytes | load_cert_bytes(data, len), must X509_free() |
| Verify cert vs CA | verify_server_cert(cert, ca_path), returns 1 or 0 |
| Verify RSA-PSS signature | verify_message_pss(cert, sig, sig_len, msg, msg_len), 1/0 |
| Sign with RSA-PSS | sign_message_pss(key, msg, len, &sig_len), must free() |
| Load private key | load_private_key(path), must EVP_PKEY_free() |
| Extract pub key from cert | X509_get_pubkey(cert), must EVP_PKEY_free() |
| RSA encrypt one block | rsa_encrypt_block(key, pt, pt_len, &ct_len, use_oaep), must free() |
| RSA decrypt one block | rsa_decrypt_block(key, ct, ct_len, &pt_len, use_oaep), must free() |
| Generate session key | generate_session_key(key_buf) |
| Symmetric encrypt | session_encrypt(key, pt, pt_len, &ct_len), must free() |
| Symmetric decrypt | session_decrypt(key, ct, ct_len, &pt_len), must free() |
Memory management in C
Unlike Python, C does not have garbage collection. Every function that returns a
malloc()βd buffer (marked βmustfree()β above) requires you to callfree()on the returned pointer when you are done with it. Similarly,X509*objects must be freed withX509_free()andEVP_PKEY*withEVP_PKEY_free(). Failure to do so causes memory leaks. Readcommon.hcarefully β each functionβs documentation specifies who must free what.
The documentation for common.c library can be found here. Refer to it when completing this assignment.
Test the Starter Code
Build
Run the following command in the project root to compile:
make
The Makefile automatically detects macOS vs Linux and locates OpenSSL headers. If the build fails, ensure libssl-dev (Linux) or brew install openssl (macOS) is installed.
Using the same machine
The starter code provided to you implements a simple, non-secure file transfer protocol. We will explain in detail what the protocol is. For now, letβs just ensure that everything runs normally.
Run each of these commands in two separate shell sessions:
./ServerWithoutSecurity
./ClientWithoutSecurity
You can type in the filename you want to send, e.g files/image.ppm from the Clientβs window, and the server will receive it and store it under [PROJECT_DIR]/recv_files directory.
You can repeat the above steps multiple times for each file you want to send to the server. If the client would like to close connection to the server, key in -1.

Using different machines
You can also host the Server file in another computer:
./ServerWithoutSecurity [PORT] 0.0.0.0
You can use any high port you want, e.g: 12345.
The client computer can connect to it using the command:
./ClientWithoutSecurity [PORT] [SERVER-IP-ADDRESS]
Ensure you use the same port. The serverβs IP address (private) should be discoverable using the following if you use WiFi (en0), or en1 if you use ethernet:
# Linux
ipconfig getifaddr en0
# macOS
ipconfig getifaddr en0
To get this to work, you most probably need to be on the same subnet. Just ensure that both machines are connected to the same WiFi and subnet. If you use SUTD WiFi, thereβs a chance that you are not in the same subnet. In that case, simply use your phone hotspot and both machines shall connect to it.
Important Requirements
Do NOT Modify
common.h/common.cYou are NOT allowed to modify
common.horcommon.c. These files contain all the cryptographic wrappers and socket helpers you need. You should only#include "common.h"in your new source files and call the functions declared there.
No other cryptographic libraries allowed
You are also not allowed to use any cryptographic library other than OpenSSL (which is what
common.calready uses). You may use any standard C library headers (stdio.h,stdlib.h,string.h, etc.) as they are already included viacommon.h.
50.005 CSE