Encryption - RSA with Arduino - part 1

· Read in about 8 min · (1698 words)

I decided to create a project for generating RSA keys directly from an embedded board. This board will generate data and display these keys to a LCD. I wanted to made this ludicrous project, because, the cryptography is a part of IT security I like very too much, and I wanted to explore how to execute application in an embedded board.

I split that project in two articles. The first one is to explain two kind of encryption can be used for securing a channel between two devices and we are going to see the hardware I use for this project and how to generate random data. In the second article, I will explain how RSA works and how I developed the application in C and uploaded to the embedded board.

Introduction

In he cryptography world, you have two kind of cryptosystem: symmetric and asymmetric encryption. The difference between these two cryptosystem is the number of the key. A key is just a value, which can encrypt or decrypt the plaintext message into the ciphertext:

Encryption

So, in symmetric encryption, you just have one key for encrypting and decrypting. So, you need to share that key to someone who you want to exchange securely with him, but, if you have another guy, you need to generate another symmetric key to exchange with him. So, the number of keys you have depends on the number of people you wish to exchange securely. DES (Data Encryption Standard) and AES (Advanced Encryption Standard) are example of symmetric encryption. DES is not used in nowadays.

Symmetric encryption

With the asymmetric encryption, you have two keys. One of the key called public key is for encrypting the plain text message to a ciphertext and the private key for decrypting the ciphertext. So, you just need to exchange your public key to anyone, and you keep your private key just for decrypting the ciphertext.

When you have two users which want to exchange message between them, and they want to encrypt the message for avoiding to be read by someone else, they need to exchange they public key. For instance, we have User, we’re calling UserA and you have the second one, calling UserB. First, they need to exchange their public key, that can be with the Diffie-Hellman algorithm, but, we won’t see it in these articles.

When they exchange their public key, UserA will wish to send a message to UserB. For doing that, UserA will encrypt the data with the UserB’s public key and when UserA has the ciphertext, he can send to UserB. When UserB receive the ciphertext from UserA, he can decrypt the message with it’s own private key. The diagram below explain how it’s works:

Asymmetric encryption

Different asymmetric encryption exist, like RSA or ECC (Elliptic Curve Cryptography).

RSA

RSA is named from the last name of three authors (Rivest, Shamir and Adleman), is an asymmetric encryption and widely used in nowadays. For generating keys, RSA implement the concept of prime number and coprime but we are going to explain them in the second part of this project.

Compare symmetric and asymmetric

Asymmetric Symmetric
One pair one keys, one for encrypting and the other for decrypting Just one key, both encrypt and decrypt
Private key need to kept in secret, but the public key can be shared with all people Need to generate a new key if you want to communicate with someone
Slower than symmetric, because the mathematical are more complex Faster than asymmetric

Entropy

The entropy which represent the randomness in a system, it’s a part really important in cryptography, because the key need to be the most random as possible to avoid to be predictable. I wrote an article regarding the entropy. So, when you generate a new key, the system use the entropy for generating random values with the PRNG (Pseudorandom Number Generator) algorithm. A PRNG algorithm get the data from the entropy pool and generate randomness data.

Under Linux, you have the device /dev/random and /dev/urandom for getting randomness data. Also, most of software or programming language as Python or R the use Mersenne Twister algorithm for PRNG.

For this project, we are going to develop a simple PRNG for generating randomness data.

Development

Hardware

Let’s go down to the business. I use the Arduino Uno for executing our code, and we are going to connect a LCD components for displaying our keys. Also, for generating our randomness data, I plugged a phototransistor component, which detect light and generate a current proportional to the light. Also, the LED will be use us when our entropy pool is full, the led is switch on. The push button is used for generating our keys. You can find the project in my gitlab account.

The diagram below show the electric scheme (I drawn with Circuit diagram website) of the embedded board:

Electric scheme

And this is what is looks like: Arduino

Program

When we develop with Arduino, we need to have a main file with the extension .ino. In this file, you can structure your code, but, you also can split it in different files, like header and C++ files. I split my project into different files:

  • RSA_arduino.ino: it’s the main file, which contain setup and loop functions.
  • prng.h: contains all functions prototypes for generating random data
  • prng.cpp: contains all functions for fill the entropy pool and to generate random data
  • rsa.h: contains all functions prototypes for generating RSA keys
  • rsa.cpp: contains all functions for implementing the RSA encryption.
  • constantes.h: contains all constantes I need in the program

In the main file called RSA_Arduino.ino, I have two functions: void setup() and void loop() which is needed by Arduino. These two functions structure the program. In the first one, I setup the value for all components and I call the function init_entropy() for generating the entropy pool. In the second function which is called when the function setup() has finished to be executed, the program generate the keys only, but the event is triggered when the user push the button.

During the process for generating RSA keys, the program will display these keys on the LCD components connected to the Arduino Board. For doing that, in the main file, I create an object LiquidCrystal (for doing that, you need to install the library):

LiquidCrystal lcd(11, 10, 5, 4, 3, 2);

For creating the LiquidCrystal object, you need to specify different parameters, they are describe in the follow:

  • The first parameter is for the RS (Register Select), connected to the pin 11, it’s used for controlling the data
  • The second argument, is for Enable, connected to the pin 10. That pin enable to writing the data.
  • And the others are for D4, D5, D6 and D7, they are connected respectively to the pins 5, 4, 3 and 2 to the Arduino board. These pins are used for the data bus.

It’s not mandatory to connect to the other pins (DB0-DB3), because we will transmit only 4 bits. If you want to transmit 8 bits, you need to connect all the data pins (DB0-DB7).

VSS and VDD are used for the ground and the power supply (+5V).

In the LCD components the pin v0 can handle the contrast of the screen, it’s connected to the potentiometer which can regulate the contrast of the LCD.

Generate entropy

Arduino provide some functions for generating random data, but, for this project, I wanted to generate mine. It’s not perfect, I can improve it. When the function init_entropy() is called, the program will generate random data and fill the entropy pool. For generating these data, I use a phototransistor, which can provide current proportional to the light captured. So, with that component, plugged in an analog pin, I can have different value, but that’s depends on the light.

So, for getting the data from the phototransistor, I read the analog pin input like that:

int sensorValue = analogRead(0); // A0 pin
if (sensorValue > 0){
	/* Fill the entropy pool */
}

When the program receive the value from the component, the value is in the range 1 to 50, it’s too small, so, for increasing the value (see the function static void generateEntropy(int)), some bits are shifted:

if(sensorValue <= 10)
  sensorValue = sensorValue << 5;
else if(sensorValue > 10 && sensorValue <= 100)
  sensorValue = sensorValue << 4;
      
s_entropy.buf[position] = sensorValue; // Store in the pool

When the program received data form the phototransistor, it fill the entropy pool, defined in a struct (prng.h). These data are stored in a buf variables. The size of that buffer is defined in the constantes.h file.

struct entropy_pool{
    unsigned long buf[BUFSIZE];
    int pool_size;
    int position;
    int pool_count;
};

The process for filling the entropy pool is stopped when the buffer has no enough space, at this moment, the program switch on the LED for indicating the user he cans generate RSA keys:

#define LED_PIN 13 // Define in the constantes.h file
digitalWrite(LED_PIN, HIGH);

During the process for generating RSA keys, we need to specify a base value called the “seed”, most of PRNG need it. For instance, if you wish to generate random data in C, you can use the function srand which take the seed in parameter. In the function static unsigned long generateSeed(), I generate a seed and the value is provided by the phototransistor. When the program generate a random data, I set the seed value to my PRNG algorithm, and the program can generate the random value.

I can use a motion sensor for generating random data, but, I didn’t have one, so, I used a phototransistor. Also, Arduino Uno used Atmel AVR microchip, we can try to generate data with AVR I/O. Maybe, that will be the subject of another article.

In conclusion

In this article, we seen two kinds of cryptosystems, called symmetric and asymmetric and the project is based on generate RSA keys which is a asymmetric encryption. Also, we seen what board I used for this project and how to generate randomness data with a phototransistor. In the second article, we are going to deep in the RSA algorithm and how to program it and we are going to upload the program to the Arduino board.