It is time to move onto the next phase of the project. An important part of the project is the registering of the boards with the application. Basically, a JSON payload would be sent to the server, which contains crucial details such as its serial number, model name, RSA public key, MAC address and more. It is encrypted using the RSA public key of the server. The payload would reach a specific REST API endpoint, that merely does the job of decrypting the payload using the server’s RSA private key, parsing and extracting the data, then subsequently save it to the database.

It is decided that the board would emulate a USB human interface device (USB-HID) keyboard to type out the payload and then send it to the server. This, by the way, is being worked on by my fellow colleague, David.

To test things out on my side first, I would need to generate a pair of RSA keys, public and private, have a sample of the JSON payload, its encrypted version using the public key, and also its decrypted version for verification purposes. This can be conveniently done using the OpenSSL command line tool. Below is the list of commands that I used, which you can put it all in one Bash script:

# Private key
openssl genrsa -out server.key 4096

# Public key
openssl rsa -in server.key -pubout -out server.pem -outform PEM

# Encrypt payload with public key
openssl rsautl -encrypt -pubin -inkey server.pem -in sample.payload -out encrypted.payload

# Encode encrypted payload in base64
base64 encrypted.payload > encrypted.base64

# Decrypt payload with private key
openssl rsautl -decrypt -inkey server.key -in encrypted.payload -out decrypted.payload

Now that I have what I needed, I started working on the REST API endpoint that would handle this. It would need to work for both encrypted and non encrypted payload. Therefore, I included sending both payloads as part of my test suite. The detection of whether the payload is encrypted or not is done by checking whether the payload starts with ‘{‘, which is typically what a JSON would start with and it also means its not encrypted, otherwise it is encrypted. Decryption is easily done with the help of the Poco::Crypto API.

Path to the private key file is specified using a configuration property in the Wt configuration file. With that, I have the REST endpoint return the decrypted or even the non encrypted payload in the response body (provided the data has been successfully extracted and saved to the database of course), and save it to a file. I could compute a checksum of that file and match it with the original payload’s checksum to verify that the decryption went properly. This is just using the skills I have obtained from testing the current application as well as from testing in my previous project.

Fortunately, I was able to accomplish that task for this week. Would have to wait for David to finish up his work before we can test out the actual registration procedure. In the meantime, there are some further changes that I would need to make, involving the board. One of it would be the generation of the HMAC-based One-time Password (HOTP) that is used as authentication when sending HTTP requests to the TLS server running on the board, to delete the firmware, transmit it, etc. More to come in the following weeks.

Leave a Reply